adding joined
This commit is contained in:
parent
13c390c5af
commit
3f9376addb
37 changed files with 1162 additions and 65 deletions
86
app/Http/Controllers/CategoryController.php
Normal file
86
app/Http/Controllers/CategoryController.php
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\StoreCategoryRequest;
|
||||||
|
use App\Http\Requests\UpdateCategoryRequest;
|
||||||
|
use App\Models\Category;
|
||||||
|
|
||||||
|
class CategoryController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\StoreCategoryRequest $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(StoreCategoryRequest $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(Category $category)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(Category $category)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\UpdateCategoryRequest $request
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(UpdateCategoryRequest $request, Category $category)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Category $category)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
62
app/Http/Controllers/JoinedController.php
Normal file
62
app/Http/Controllers/JoinedController.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\StoreJoinedRequest;
|
||||||
|
use App\Http\Requests\UpdateJoinedRequest;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\Joined;
|
||||||
|
|
||||||
|
class JoinedController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->authorizeResource(Joined::class, 'joined');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.joined.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.joined.create')->with([
|
||||||
|
'categories' => Category::all(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreJoinedRequest $request)
|
||||||
|
{
|
||||||
|
$validated = $request->safe()->only([
|
||||||
|
'categories',
|
||||||
|
'url',
|
||||||
|
'subject',
|
||||||
|
'image',
|
||||||
|
'approved',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Joined::store($validated);
|
||||||
|
return redirect()->route('joined.index')->with('success', 'Fanlisting added.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Joined $joined)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Joined $joined)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateJoinedRequest $request, Joined $joined)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Joined $joined)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/StoreCategoryRequest.php
Normal file
30
app/Http/Requests/StoreCategoryRequest.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreCategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
35
app/Http/Requests/StoreJoinedRequest.php
Normal file
35
app/Http/Requests/StoreJoinedRequest.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreJoinedRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'categories' => ['required', 'array'],
|
||||||
|
'categories.*' => [ 'numeric', 'exists:categories,id'],
|
||||||
|
'url' => ['required', 'url'],
|
||||||
|
'subject' => ['required', 'string'],
|
||||||
|
'image' => ['nullable', 'image'],
|
||||||
|
'approved' => ['nullable', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/UpdateCategoryRequest.php
Normal file
30
app/Http/Requests/UpdateCategoryRequest.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateCategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/UpdateJoinedRequest.php
Normal file
30
app/Http/Requests/UpdateJoinedRequest.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateJoinedRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
20
app/Models/Category.php
Normal file
20
app/Models/Category.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Category extends Model
|
||||||
|
{
|
||||||
|
/* --------------------------------------------------------------------------- relationships ---- */
|
||||||
|
|
||||||
|
public function parent()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(__CLASS__, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function joined()
|
||||||
|
{
|
||||||
|
return $this->morphedByMany(Joined::class, 'categorizable');
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,36 +11,35 @@ class Collective extends Authenticatable
|
||||||
{
|
{
|
||||||
use HasApiTokens, Notifiable;
|
use HasApiTokens, Notifiable;
|
||||||
|
|
||||||
/**
|
/* @var array<int, string> */
|
||||||
* The attributes that are mass assignable.
|
|
||||||
*
|
|
||||||
* @var array<int, string>
|
|
||||||
*/
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'email',
|
'email',
|
||||||
'password',
|
'password',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that should be hidden for serialization.
|
/* @var array<int, string> */
|
||||||
*
|
|
||||||
* @var array<int, string>
|
|
||||||
*/
|
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'password',
|
'password',
|
||||||
'remember_token',
|
'remember_token',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/* @var array<string, string> */
|
||||||
* The attributes that should be cast.
|
|
||||||
*
|
|
||||||
* @var array<string, string>
|
|
||||||
*/
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------- relationships ---- */
|
||||||
|
|
||||||
|
public function joined()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Joined::class);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------- password ---- */
|
/* -------------------------------------------------------------------------------- password ---- */
|
||||||
|
|
||||||
protected function password() : Attribute
|
protected function password() : Attribute
|
||||||
|
|
46
app/Models/Joined.php
Normal file
46
app/Models/Joined.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Categorizable;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class Joined extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, Categorizable;
|
||||||
|
|
||||||
|
protected $table = 'joined';
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'approved' => 'boolean',
|
||||||
|
];
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------- relationships ---- */
|
||||||
|
|
||||||
|
public function collective()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Collective::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// injected by trait: categories (morph many-to-many)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------- joined ---- */
|
||||||
|
|
||||||
|
public static function store($request) : Joined
|
||||||
|
{
|
||||||
|
$joined = new Joined();
|
||||||
|
$joined->url = $request['url'];
|
||||||
|
$joined->subject = $request['subject'];
|
||||||
|
$joined->image = Storage::putFile('joined', $request['image']);
|
||||||
|
$joined->approved = $request['approved'] ?? false;
|
||||||
|
|
||||||
|
$collective = auth_collective();
|
||||||
|
$collective->joined()->save($joined);
|
||||||
|
|
||||||
|
$joined->categories()->sync($request['categories']);
|
||||||
|
|
||||||
|
return $joined;
|
||||||
|
}
|
||||||
|
}
|
95
app/Policies/CategoryPolicy.php
Normal file
95
app/Policies/CategoryPolicy.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\Collective;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class CategoryPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function viewAny(Collective $collective)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function view(Collective $collective, Category $category)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function create(Collective $collective)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function update(Collective $collective, Category $category)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function delete(Collective $collective, Category $category)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function restore(Collective $collective, Category $category)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Category $category
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function forceDelete(Collective $collective, Category $category)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
}
|
95
app/Policies/JoinedPolicy.php
Normal file
95
app/Policies/JoinedPolicy.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\Collective;
|
||||||
|
use App\Models\Joined;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class JoinedPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function viewAny(Collective $collective)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Joined $joined
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function view(Collective $collective, Joined $joined)
|
||||||
|
{
|
||||||
|
return $collective->id === $joined->collective_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function create(Collective $collective)
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Joined $joined
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function update(Collective $collective, Joined $joined)
|
||||||
|
{
|
||||||
|
return $collective->id === $joined->collective_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Joined $joined
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function delete(Collective $collective, Joined $joined)
|
||||||
|
{
|
||||||
|
return $collective->id === $joined->collective_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Joined $joined
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function restore(Collective $collective, Joined $joined)
|
||||||
|
{
|
||||||
|
return $collective->id === $joined->collective_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Collective $collective
|
||||||
|
* @param \App\Models\Joined $joined
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function forceDelete(Collective $collective, Joined $joined)
|
||||||
|
{
|
||||||
|
return $collective->id === $joined->collective_id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
@ -23,6 +24,10 @@ public function register()
|
||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
//
|
Relation::enforceMorphMap([
|
||||||
|
'joined' => 'App\Models\Joined',
|
||||||
|
'owned' => 'App\Models\Owned',
|
||||||
|
'wish' => 'App\Models\Wish',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
app/Traits/Categorizable.php
Normal file
13
app/Traits/Categorizable.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Models\Category;
|
||||||
|
|
||||||
|
trait Categorizable
|
||||||
|
{
|
||||||
|
public function categories()
|
||||||
|
{
|
||||||
|
return $this->morphToMany(Category::class, 'categorizable');
|
||||||
|
}
|
||||||
|
}
|
14
app/helpers.php
Normal file
14
app/helpers.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- auth_collective ---- */
|
||||||
|
|
||||||
|
// returns the currently authenticated collective
|
||||||
|
|
||||||
|
use App\Models\Collective;
|
||||||
|
|
||||||
|
if (!function_exists('auth_collective')) {
|
||||||
|
function auth_collective() : Collective
|
||||||
|
{
|
||||||
|
return auth()->user();
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,9 @@
|
||||||
"spatie/laravel-ignition": "^1.0"
|
"spatie/laravel-ignition": "^1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"app/helpers.php"
|
||||||
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"App\\": "app/",
|
"App\\": "app/",
|
||||||
"Database\\Factories\\": "database/factories/",
|
"Database\\Factories\\": "database/factories/",
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
'default' => env('FILESYSTEM_DISK', 'public'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,13 +15,14 @@ public function up()
|
||||||
{
|
{
|
||||||
Schema::create('collectives', function (Blueprint $table) {
|
Schema::create('collectives', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('name');
|
|
||||||
$table->string('email')->unique();
|
|
||||||
$table->string('title');
|
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
|
||||||
$table->string('password');
|
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('email')->unique();
|
||||||
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
|
$table->string('title');
|
||||||
|
$table->string('password');
|
||||||
|
$table->integer('per_page')->unsigned()->default(15);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
37
database/migrations/10_create_categories_table.php
Normal file
37
database/migrations/10_create_categories_table.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('categories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->foreignId('parent_id')
|
||||||
|
->nullable()
|
||||||
|
->constrained('categories')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->onDelete('cascade');
|
||||||
|
$table->string('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categories');
|
||||||
|
}
|
||||||
|
};
|
39
database/migrations/10_create_joined_table.php
Normal file
39
database/migrations/10_create_joined_table.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('joined', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->foreignId('collective_id')
|
||||||
|
->constrained('collectives')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->onDelete('cascade');
|
||||||
|
$table->string('url');
|
||||||
|
$table->string('subject');
|
||||||
|
$table->string('image');
|
||||||
|
$table->boolean('approved');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('joined');
|
||||||
|
}
|
||||||
|
};
|
37
database/migrations/20_create_categorizable_table.php
Normal file
37
database/migrations/20_create_categorizable_table.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('categorizable', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->foreignId('category_id')
|
||||||
|
->constrained('categories')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->onDelete('restrict');
|
||||||
|
$table->unsignedBigInteger('categorizable_id');
|
||||||
|
$table->string('categorizable_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categorizable');
|
||||||
|
}
|
||||||
|
};
|
78
database/seeders/CategorySeeder.php
Normal file
78
database/seeders/CategorySeeder.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class CategorySeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
DB::table('categories')->insert([
|
||||||
|
['name' => 'Academia'],
|
||||||
|
['name' => 'Actors'],
|
||||||
|
['name' => 'Actresses'],
|
||||||
|
['name' => 'Adult'],
|
||||||
|
['name' => 'Advertising/TV Channels'],
|
||||||
|
['name' => 'Albums'],
|
||||||
|
['name' => 'Animals'],
|
||||||
|
['name' => 'Animation'],
|
||||||
|
['name' => 'Anime/Manga'],
|
||||||
|
['name' => 'Arts and Design'],
|
||||||
|
['name' => 'Authors/Writers'],
|
||||||
|
['name' => 'Calendar Events'],
|
||||||
|
['name' => 'Characters: Book/Movie'],
|
||||||
|
['name' => 'Characters: TV'],
|
||||||
|
['name' => 'Comics'],
|
||||||
|
['name' => 'Companies'],
|
||||||
|
['name' => 'Computer Miscellany and Internet'],
|
||||||
|
['name' => 'Directors/Producers'],
|
||||||
|
['name' => 'Episodes'],
|
||||||
|
['name' => 'Fan Works'],
|
||||||
|
['name' => 'Fashion/Beauty'],
|
||||||
|
['name' => 'Food/Drinks'],
|
||||||
|
['name' => 'Games'],
|
||||||
|
['name' => 'History/Royalty'],
|
||||||
|
['name' => 'Hobbies and Recreation'],
|
||||||
|
['name' => 'Literature'],
|
||||||
|
['name' => 'Miscellaneous'],
|
||||||
|
['name' => 'Models'],
|
||||||
|
['name' => 'Movies'],
|
||||||
|
['name' => 'Music Miscellany'],
|
||||||
|
['name' => 'Musicians: Bands/Groups'],
|
||||||
|
['name' => 'Musicians: Female'],
|
||||||
|
['name' => 'Musicians: Male'],
|
||||||
|
['name' => 'Mythology/Religion'],
|
||||||
|
['name' => 'Nature'],
|
||||||
|
['name' => 'Objects'],
|
||||||
|
['name' => 'People Miscellany'],
|
||||||
|
['name' => 'Personalities'],
|
||||||
|
['name' => 'Places'],
|
||||||
|
['name' => 'Politics and Organisations'],
|
||||||
|
['name' => 'Relationships: Book/Movie'],
|
||||||
|
['name' => 'Relationships: Real Life'],
|
||||||
|
['name' => 'Relationships: TV'],
|
||||||
|
['name' => 'Songs: Bands/Groups 0-M'],
|
||||||
|
['name' => 'Songs: Bands/Groups N-Z'],
|
||||||
|
['name' => 'Songs: Female Solo'],
|
||||||
|
['name' => 'Songs: Male Solo'],
|
||||||
|
['name' => 'Songs: Various'],
|
||||||
|
['name' => 'Sports'],
|
||||||
|
['name' => 'Sports Entertainment'],
|
||||||
|
['name' => 'Stage/Theatre'],
|
||||||
|
['name' => 'Toys/Collectibles'],
|
||||||
|
['name' => 'Transportation'],
|
||||||
|
['name' => 'TV Shows'],
|
||||||
|
['name' => 'TV/Movie/Book Miscellany'],
|
||||||
|
['name' => 'Webmasters'],
|
||||||
|
['name' => 'Websites'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ class DatabaseSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
// \App\Models\User::factory(10)->create();
|
$this->call([
|
||||||
|
CategorySeeder::class
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,53 @@
|
||||||
@import url(https://fonts.googleapis.com/css2?family=Imprima&family=Satisfy&display=swap);
|
@import url(https://fonts.googleapis.com/css2?family=Imprima&family=Satisfy&display=swap);
|
||||||
/* ------------------------------------------------------------------------------------ &BTN ---- */
|
/* ------------------------------------------------------------------------------------ &BTN ---- */
|
||||||
.form__btn {
|
.form__input--file::-webkit-file-upload-button {
|
||||||
border: 1px solid #7874ff;
|
border: 1px solid #7874ff;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
line-height: normal;
|
||||||
|
cursor: pointer;
|
||||||
border-color: #7874ff;
|
border-color: #7874ff;
|
||||||
background-color: #e4e3ff;
|
background-color: #e4e3ff;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
color: #7874ff;
|
||||||
|
-webkit-transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
.form__btn:hover {
|
.l-page-nav__link, .form__input--file::file-selector-button, .form__btn {
|
||||||
background-color: #f8e5ff;
|
border: 1px solid #7874ff;
|
||||||
|
padding: 5px 10px;
|
||||||
|
margin-right: 5px;
|
||||||
|
line-height: normal;
|
||||||
|
cursor: pointer;
|
||||||
|
border-color: #7874ff;
|
||||||
|
background-color: #e4e3ff;
|
||||||
|
color: #7874ff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--file:hover::-webkit-file-upload-button {
|
||||||
border-color: #de7cff;
|
border-color: #de7cff;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
-webkit-transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.l-page-nav__link:hover, .form__input--file:hover::file-selector-button, .form__btn:hover {
|
||||||
|
border-color: #de7cff;
|
||||||
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--file:focus::-webkit-file-upload-button {
|
||||||
|
border-color: #de7cff;
|
||||||
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
-webkit-transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.l-page-nav__link:focus, .form__input--file:focus::file-selector-button, .form__btn:focus {
|
||||||
|
border-color: #de7cff;
|
||||||
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
@ -44,6 +80,7 @@ h1 {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
margin-top: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -61,31 +98,97 @@ .form__fieldset {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__label, .form__btns {
|
.form__label, .form__btns, .form__checkbox {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
.form__label:first-of-type, .form__btns:first-of-type {
|
.form__label:first-child, .form__btns:first-child, .form__checkbox:first-child, .form__label .form__legend + .form__label, .form__btns .form__legend + .form__label, .form__label .form__legend + .form__btns, .form__btns .form__legend + .form__btns, .form__checkbox .form__legend + .form__label, .form__checkbox .form__legend + .form__btns, .form__label .form__legend + .form__checkbox, .form__btns .form__legend + .form__checkbox, .form__checkbox .form__legend + .form__checkbox {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input {
|
.form__input, .form__select {
|
||||||
border: 1px solid #7874ff;
|
border: 1px solid #7874ff;
|
||||||
background-color: #e4e3ff;
|
background-color: #e4e3ff;
|
||||||
border-color: #7874ff;
|
border-color: #7874ff;
|
||||||
background-color: #e4e3ff;
|
background-color: #e4e3ff;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
color: #7874ff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
.form__input:hover {
|
.form__input:hover, .form__select:hover {
|
||||||
background-color: #f8e5ff;
|
|
||||||
border-color: #de7cff;
|
border-color: #de7cff;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
.form__input:focus {
|
.form__input:focus, .form__select:focus {
|
||||||
background-color: #f8e5ff;
|
|
||||||
border-color: #de7cff;
|
border-color: #de7cff;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__input--file {
|
||||||
|
border: 1px solid #7874ff;
|
||||||
|
border-color: #7874ff;
|
||||||
|
color: #7874ff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
.form__input--file:hover {
|
||||||
|
border-color: #de7cff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--file:focus {
|
||||||
|
border-color: #de7cff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--checkbox {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: #e4e3ff;
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
font: inherit;
|
||||||
|
color: #7874ff;
|
||||||
|
width: 15px !important;
|
||||||
|
height: 15px;
|
||||||
|
border: 1px solid #7874ff;
|
||||||
|
display: inline-grid;
|
||||||
|
place-content: center;
|
||||||
|
border-color: #7874ff;
|
||||||
|
background-color: #e4e3ff;
|
||||||
|
color: #7874ff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--checkbox::before {
|
||||||
|
content: "";
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: transform 120ms ease-in-out;
|
||||||
|
box-shadow: inset 9px 9px #7874ff;
|
||||||
|
-webkit-clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||||
|
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||||
|
}
|
||||||
|
.form__input--checkbox:checked::before {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
.form__input--checkbox:hover {
|
||||||
|
border-color: #de7cff;
|
||||||
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
}
|
||||||
|
.form__input--checkbox:focus {
|
||||||
|
border-color: #de7cff;
|
||||||
|
background-color: #f8e5ff;
|
||||||
|
color: #de7cff;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__btns:first-of-type {
|
.form__btns:first-of-type {
|
||||||
|
@ -135,14 +238,51 @@ .l-nav__tab:last-child {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-main {
|
.l-page-nav {
|
||||||
padding: 10px 40px;
|
width: 100%;
|
||||||
|
margin: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
align-items: center;
|
||||||
|
-moz-column-gap: 20px;
|
||||||
|
column-gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.l-page-nav__links {
|
||||||
background-color: #87ff5f;
|
flex-grow: 1;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-page-nav__link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-main {
|
||||||
|
padding: 10px 40px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background-color: #b7ff9f;
|
||||||
border: 1px solid #30be00;
|
border: 1px solid #30be00;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background-color: #ffeaad;
|
||||||
|
border: 1px solid #ebb000;
|
||||||
|
padding: 10px;
|
||||||
|
width: 60%;
|
||||||
|
margin: 10px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background-color: #ffaaaa;
|
||||||
|
border: 1px solid #e20000;
|
||||||
|
padding: 10px;
|
||||||
|
width: 60%;
|
||||||
|
margin: 10px auto;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ h1 {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
margin-top: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -50,14 +51,63 @@ h1 {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
|
||||||
&:first-of-type { margin-top: 0; }
|
&:first-child, .form__legend + .form__label { margin-top: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input {
|
.form__input {
|
||||||
border: 1px solid $c-main;
|
border: 1px solid $c-main;
|
||||||
background-color: $c-main-lightest;
|
background-color: $c-main-lightest;
|
||||||
|
|
||||||
@include hover($focus: true);
|
@include hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__select {
|
||||||
|
@extend .form__input;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__input--file {
|
||||||
|
border: 1px solid $c-main;
|
||||||
|
@include hover($bg: false);
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
&::file-selector-button {
|
||||||
|
@extend %btn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__checkbox {
|
||||||
|
@extend .form__label;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__input--checkbox {
|
||||||
|
appearance: none;
|
||||||
|
background-color: $c-main-lightest;
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
font: inherit;
|
||||||
|
color: $c-main;
|
||||||
|
width: 15px !important;
|
||||||
|
height: 15px;
|
||||||
|
border: 1px solid $c-main;
|
||||||
|
display: inline-grid;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: transform 120ms ease-in-out;
|
||||||
|
box-shadow: inset 9px 9px $c-main;
|
||||||
|
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked::before {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__btns {
|
.form__btns {
|
||||||
|
|
|
@ -42,6 +42,28 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.l-page-nav {
|
||||||
|
width: 100%;
|
||||||
|
margin: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-page-nav__links {
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-page-nav__link {
|
||||||
|
@extend %btn;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.l-main {
|
.l-main {
|
||||||
padding: 10px 40px;
|
padding: 10px 40px;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
|
@ -1,11 +1,15 @@
|
||||||
@use 'vars' as *;
|
@use 'vars' as *;
|
||||||
@use 'sass:color';
|
@use 'sass:color';
|
||||||
|
|
||||||
.error {
|
@mixin msg($color) {
|
||||||
background-color: color.scale($c-green, $lightness: 50%);
|
background-color: color.scale($color, $lightness: 70%);
|
||||||
border: 1px solid $c-green;
|
border: 1px solid $color;
|
||||||
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.success { @include msg($c-green); }
|
||||||
|
.warning { @include msg($c-yellow); }
|
||||||
|
.error { @include msg($c-red); }
|
|
@ -8,10 +8,12 @@ $f-size: 16px;
|
||||||
$c-main: #7874ff;
|
$c-main: #7874ff;
|
||||||
$c-main-light: color.scale($c-main, $lightness: 70%);
|
$c-main-light: color.scale($c-main, $lightness: 70%);
|
||||||
$c-main-lightest: color.scale($c-main, $lightness: 80%);
|
$c-main-lightest: color.scale($c-main, $lightness: 80%);
|
||||||
|
$c-main-dark: color.scale($c-main, $lightness: -20%);
|
||||||
|
|
||||||
$c-accent: #de7cff;
|
$c-accent: #de7cff;
|
||||||
$c-accent-light: color.scale($c-accent, $lightness: 40%);
|
$c-accent-light: color.scale($c-accent, $lightness: 40%);
|
||||||
$c-accent-lightest: color.scale($c-accent, $lightness: 80%);
|
$c-accent-lightest: color.scale($c-accent, $lightness: 80%);
|
||||||
|
$c-accent-dark: color.scale($c-accent, $lightness: -20%);
|
||||||
|
|
||||||
$c-green: #30be00;
|
$c-green: #30be00;
|
||||||
$c-yellow: #ebb000;
|
$c-yellow: #ebb000;
|
||||||
|
@ -19,22 +21,31 @@ $c-red: #e20000;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------ &BTN ---- */
|
/* ------------------------------------------------------------------------------------ &BTN ---- */
|
||||||
|
|
||||||
@mixin hover($focus: false) {
|
@mixin hover($focus: true, $bg: true) {
|
||||||
border-color: $c-main;
|
border-color: $c-main;
|
||||||
|
@if $bg {
|
||||||
background-color: $c-main-lightest;
|
background-color: $c-main-lightest;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
}
|
||||||
|
color: $c-main;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $c-accent-lightest;
|
|
||||||
border-color: $c-accent;
|
border-color: $c-accent;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
@if $bg {
|
||||||
|
background-color: $c-accent-lightest;
|
||||||
|
}
|
||||||
|
color: $c-accent;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@if $focus {
|
@if $focus {
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: $c-accent-lightest;
|
|
||||||
border-color: $c-accent;
|
border-color: $c-accent;
|
||||||
transition: background-color 0.4s, border-color 0.4s;
|
@if $bg {
|
||||||
|
background-color: $c-accent-lightest;
|
||||||
|
}
|
||||||
|
color: $c-accent;
|
||||||
|
transition: background-color 0.4s, border-color 0.4s, color 0.4s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +54,8 @@ $c-red: #e20000;
|
||||||
border: 1px solid $c-main;
|
border: 1px solid $c-main;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
line-height: normal;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
@include hover;
|
@include hover;
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
@extends('admin.layout')
|
@extends('admin.layout')
|
||||||
|
|
||||||
|
@section('pg-title', 'Dashboard')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<h1><span>Dashboard</span></h1>
|
|
||||||
@endsection
|
@endsection
|
|
@ -1,7 +1,8 @@
|
||||||
@extends('admin.layout')
|
@extends('admin.layout')
|
||||||
|
|
||||||
|
@section('pg-title', 'Welcome to Fanatic!')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<h1><span>Welcome to Fanatic!</span></h1>
|
|
||||||
<p>This is the installation page. You will only need to complete this once, but values can be
|
<p>This is the installation page. You will only need to complete this once, but values can be
|
||||||
changed after installation.</p>
|
changed after installation.</p>
|
||||||
|
|
||||||
|
|
48
resources/views/admin/joined/create.blade.php
Normal file
48
resources/views/admin/joined/create.blade.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
@extends('admin.layout')
|
||||||
|
|
||||||
|
@section('pg-nav')
|
||||||
|
<x-admin.nav :section="'joined'" />
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('pg-title', 'Add Joined')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<form action="{{ route('joined.store') }}" method="POST" enctype="multipart/form-data"
|
||||||
|
autocomplete="off">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<fieldset class="form__fieldset">
|
||||||
|
<label for="categories" class="form__label">Categories:</label>
|
||||||
|
<x-admin.form.categories :categories="$categories" name="categories[]" id="categories"
|
||||||
|
multiple required />
|
||||||
|
@error('categories') <p class="form__error">{{ $message }}</p> @enderror
|
||||||
|
|
||||||
|
<label for="url" class="form__label">URL:</label>
|
||||||
|
<input type="url" id="url" name="url" value="{{ old('url') }}" class="form__input" required>
|
||||||
|
@error('url') <p class="form__error">{{ $message }}</p> @enderror
|
||||||
|
|
||||||
|
<label for="subject" class="form__label">Subject:</label>
|
||||||
|
<input type="text" id="subject" name="subject" value="{{ old('subject') }}"
|
||||||
|
class="form__input" required>
|
||||||
|
@error('subject') <p class="form__error">{{ $message }}</p> @enderror
|
||||||
|
|
||||||
|
<label for="image" class="form__label">Image:</label>
|
||||||
|
<input type="file" id="image" name="image" value="{{ old('image') }}" accept="image/*"
|
||||||
|
class="form__input--file">
|
||||||
|
@error('image') <p class="form__error">{{ $message }}</p> @enderror
|
||||||
|
|
||||||
|
<div class="form__checkbox">
|
||||||
|
<input type="checkbox" id="approved" name="approved" value="1"
|
||||||
|
class="form__input--checkbox" @checked(old('approved'))>
|
||||||
|
<label for="approved" class="form__label--checkbox">Approved</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form__btns">
|
||||||
|
<input type="submit" class="form__btn" value="Submit">
|
||||||
|
<input type="reset" class="form__btn" value="Reset">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@endsection
|
7
resources/views/admin/joined/index.blade.php
Normal file
7
resources/views/admin/joined/index.blade.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
@extends('admin.layout')
|
||||||
|
|
||||||
|
@section('pg-nav')
|
||||||
|
<x-admin.nav :section="'joined'" />
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('pg-title', 'Joined')
|
|
@ -14,15 +14,25 @@
|
||||||
|
|
||||||
@auth
|
@auth
|
||||||
<nav class="l-nav">
|
<nav class="l-nav">
|
||||||
<a class="l-nav__tab" href="#"><span class="l-nav__link">dashboard</span></a>
|
<a href="{{ route('dashboard') }}" class="l-nav__tab">
|
||||||
<a class="l-nav__tab" href="#"><span class="l-nav__link">joined</span></a>
|
<span class="l-nav__link">dashboard</span>
|
||||||
<a class="l-nav__tab" href="#"><span class="l-nav__link">owned</span></a>
|
</a>
|
||||||
<a class="l-nav__tab" href="#"><span class="l-nav__link">collective</span></a>
|
|
||||||
|
<a href="{{ route('joined.index') }}" class="l-nav__tab">
|
||||||
|
<span class="l-nav__link">joined</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" class="l-nav__tab"><span class="l-nav__link">owned</span></a>
|
||||||
|
<a href="#" class="l-nav__tab"><span class="l-nav__link">collective</span></a>
|
||||||
</nav>
|
</nav>
|
||||||
@endauth
|
@endauth
|
||||||
|
|
||||||
<main class="l-main">
|
<main class="l-main">
|
||||||
@yield('title')
|
<nav class="l-page-nav">
|
||||||
|
<h1><span>@yield('pg-title')</span></h1>
|
||||||
|
|
||||||
|
<div class="l-page-nav__links">@yield('pg-nav')</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
@if (session()->has('success'))
|
@if (session()->has('success'))
|
||||||
<p class="success">{{ session()->get('success') }}</p>
|
<p class="success">{{ session()->get('success') }}</p>
|
||||||
|
|
21
resources/views/components/admin/form/categories.blade.php
Normal file
21
resources/views/components/admin/form/categories.blade.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{{-- expected attributes: name, id --}}
|
||||||
|
@props(['categories', 'prevCats' => false])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$selected = null;
|
||||||
|
$name = rtrim($attributes['name'], '[]');
|
||||||
|
if (old($name) != null) {
|
||||||
|
$selected = collect(old($name));
|
||||||
|
} else if ($prevCats) {
|
||||||
|
$selected = $prevCats;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<select {{ $attributes }} class="form__select" size="6">
|
||||||
|
@foreach ($categories as $cat)
|
||||||
|
<option value="{{ $cat->id }}"
|
||||||
|
@if(isset($selected)) @selected($selected->search($cat->id) !== false) @endif>
|
||||||
|
{{ $cat->name }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
13
resources/views/components/admin/nav.blade.php
Normal file
13
resources/views/components/admin/nav.blade.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
@props(['section'])
|
||||||
|
|
||||||
|
@switch ($section)
|
||||||
|
@case('joined')
|
||||||
|
<a href="{{ route('joined.index') }}" class="l-page-nav__link">All Joined</a>
|
||||||
|
<a href="{{ route('joined.create') }}" class="l-page-nav__link">Add New</a>
|
||||||
|
@break
|
||||||
|
@case('owned')
|
||||||
|
|
||||||
|
@break
|
||||||
|
@default
|
||||||
|
|
||||||
|
@endswitch
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\CollectiveController;
|
use App\Http\Controllers\CollectiveController;
|
||||||
|
use App\Http\Controllers\JoinedController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -13,7 +14,15 @@
|
||||||
| contains the "web" middleware group. Now create something great!
|
| contains the "web" middleware group. Now create something great!
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
Route::middleware('guest')->group(function () {
|
||||||
Route::get('/fanatic', [CollectiveController::class, 'dashboard'])->name('dashboard');
|
//Route::get('/', [])
|
||||||
Route::get('/fanatic/install', [CollectiveController::class, 'create'])->name('collectives.create');
|
Route::get('/fanatic/install', [CollectiveController::class, 'create'])
|
||||||
|
->name('collectives.create');
|
||||||
Route::post('/fanatic', [CollectiveController::class, 'store'])->name('collectives.store');
|
Route::post('/fanatic', [CollectiveController::class, 'store'])->name('collectives.store');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::middleware('auth')->group(function () {
|
||||||
|
Route::get('/fanatic', [CollectiveController::class, 'dashboard'])->name('dashboard');
|
||||||
|
|
||||||
|
Route::resource('joined', JoinedController::class);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue