diff --git a/app/Http/Controllers/Admin/PostCategoryController.php b/app/Http/Controllers/Admin/PostCategoryController.php index 64bd1fc..11146b8 100644 --- a/app/Http/Controllers/Admin/PostCategoryController.php +++ b/app/Http/Controllers/Admin/PostCategoryController.php @@ -58,12 +58,12 @@ public function update(Request $request, PostCategoryRepository $postCategoryRep 'meta_title' => 'nullable|string', 'meta_description' => 'nullable|string' ]); - + $postCategory = PostCategory::findOrFail($id); $postCategory->fill($request->all()); $postCategory->save(); $postCategoryRepository->uploadImage($postCategory, $request, 'image'); - + return redirect()->route('admin.postCategories.edit', $id)->with(['flash_type' => 'success', 'flash_message' => 'Post category updated successfully', 'flash_description' => $postCategory->name]); } } diff --git a/app/Http/Controllers/Admin/PostController.php b/app/Http/Controllers/Admin/PostController.php index feb4d37..53cb7bd 100644 --- a/app/Http/Controllers/Admin/PostController.php +++ b/app/Http/Controllers/Admin/PostController.php @@ -65,7 +65,9 @@ public function store(Request $request, PostRepository $postRepository) 'meta_description' => 'nullable|string', 'image' => 'nullable|image', 'category_ids' => 'required|array', - 'category_ids.*' => 'exists:post_categories,id' + 'category_ids.*' => 'exists:post_categories,id', + 'tag_ids' => 'sometimes|required|array', + 'tag_ids.*' => 'required|integer|exists:tags,id' ]); $request->merge(['user_id' => auth()->user()->id]); @@ -73,6 +75,7 @@ public function store(Request $request, PostRepository $postRepository) $post = Post::create($request->all()); $postRepository->uploadImage($post, $request, 'image'); $post->categories()->sync($request->get('category_ids')); + $post->tags()->sync($request->get('tag_ids')); return redirect()->route('admin.posts.edit', $post->id)->with(['flash_type' => 'success', 'flash_message' => 'Post created successfully', 'flash_description' => $post->title]); } @@ -88,13 +91,16 @@ public function update(Request $request, PostRepository $postRepository, $id) 'meta_description' => 'nullable|string', 'image' => 'nullable|image', 'category_ids' => 'required|array', - 'category_ids.*' => 'exists:post_categories,id' + 'category_ids.*' => 'exists:post_categories,id', + 'tag_ids' => 'sometimes|required|array', + 'tag_ids.*' => 'required|integer|exists:tags,id' ]); $post = Post::findOrFail($id); $post->fill($request->all()); $post->save(); $postRepository->uploadImage($post, $request, 'image'); $post->categories()->sync($request->get('category_ids')); + $post->tags()->sync($request->get('tag_ids')); return redirect()->route('admin.posts.edit', $id)->with(['flash_type' => 'success', 'flash_message' => 'Post updated successfully', 'flash_description' => $post->title]); } } diff --git a/app/Http/Controllers/Admin/TagController.php b/app/Http/Controllers/Admin/TagController.php new file mode 100644 index 0000000..f16c44a --- /dev/null +++ b/app/Http/Controllers/Admin/TagController.php @@ -0,0 +1,43 @@ +paginate($request->get('limit', config('app.pagination_limit')))->withQueryString(); + return Inertia::render('Admin/Tags/Tags', ['tags' => TagResource::collection($tags)]); + } + + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string', + ]); + + $tag = Tag::create($request->all()); + + return redirect()->route('admin.tags.index', $tag->id)->with(['flash_type' => 'success', 'flash_message' => 'Tag created successfully', 'flash_description' => $tag->name]); + } + + public function update(Request $request, $id) + { + $request->validate([ + 'name' => 'required|string', + ]); + + $tag = Tag::findOrFail($id); + $tag->fill($request->all()); + $tag->save(); + + return redirect()->route('admin.tags.index', $tag->id)->with(['flash_type' => 'success', 'flash_message' => 'Tag updated successfully', 'flash_description' => $tag->name]); + } +} diff --git a/app/Http/Controllers/HomepageController.php b/app/Http/Controllers/HomepageController.php index 2338aeb..0e234c5 100644 --- a/app/Http/Controllers/HomepageController.php +++ b/app/Http/Controllers/HomepageController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Models\Page; +use App\Models\Post; use Illuminate\Http\Request; use Inertia\Inertia; @@ -10,8 +11,13 @@ class HomepageController extends Controller { public function __invoke() { + $post = Post::latest()->first(); + + //$post->tags()->sync([1]); + $page = Page::slug('home')->firstOrNew(); - activity()->withoutLogs(function () use($page) { + + activity()->withoutLogs(function () use ($page) { $page->increment('views'); }); diff --git a/app/Http/Resources/TagResource.php b/app/Http/Resources/TagResource.php new file mode 100644 index 0000000..4bd712f --- /dev/null +++ b/app/Http/Resources/TagResource.php @@ -0,0 +1,20 @@ + + */ + public function toArray(Request $request): array + { + $data = parent::toArray($request); + return $data; + } +} diff --git a/app/Models/Post.php b/app/Models/Post.php index a08ea72..2ddfd09 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -4,6 +4,7 @@ use App\Traits\ActivityLoggable; use App\Traits\HasSlug; +use App\Traits\TaggableTrait; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphOne; @@ -11,7 +12,7 @@ class Post extends Model { - use HasFactory, ActivityLoggable, SoftDeletes, HasSlug; + use HasFactory, ActivityLoggable, SoftDeletes, HasSlug, TaggableTrait; protected $guarded = ['id']; diff --git a/app/Models/Tag.php b/app/Models/Tag.php new file mode 100644 index 0000000..df5440e --- /dev/null +++ b/app/Models/Tag.php @@ -0,0 +1,15 @@ +morphTo(); + } +} diff --git a/app/Repositories/TagRepository.php b/app/Repositories/TagRepository.php new file mode 100644 index 0000000..9da22d8 --- /dev/null +++ b/app/Repositories/TagRepository.php @@ -0,0 +1,16 @@ +model = $model; + } +} diff --git a/app/Traits/TaggableTrait.php b/app/Traits/TaggableTrait.php new file mode 100644 index 0000000..c22a279 --- /dev/null +++ b/app/Traits/TaggableTrait.php @@ -0,0 +1,15 @@ +morphToMany(Tag::class, 'taggable'); + } +} diff --git a/database/migrations/2024_10_13_100430_create_tags_table.php b/database/migrations/2024_10_13_100430_create_tags_table.php new file mode 100644 index 0000000..d89aafb --- /dev/null +++ b/database/migrations/2024_10_13_100430_create_tags_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('name'); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tags'); + } +}; diff --git a/database/migrations/2024_10_13_100910_create_taggables_table.php b/database/migrations/2024_10_13_100910_create_taggables_table.php new file mode 100644 index 0000000..1644092 --- /dev/null +++ b/database/migrations/2024_10_13_100910_create_taggables_table.php @@ -0,0 +1,30 @@ +id(); + $table->morphs('taggable'); + $table->foreignId('tag_id')->constrained('tags'); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('taggables'); + } +}; diff --git a/resources/js/Layouts/header.jsx b/resources/js/Layouts/Header.jsx similarity index 100% rename from resources/js/Layouts/header.jsx rename to resources/js/Layouts/Header.jsx diff --git a/resources/js/Layouts/admin/header.jsx b/resources/js/Layouts/admin/Header.jsx similarity index 100% rename from resources/js/Layouts/admin/header.jsx rename to resources/js/Layouts/admin/Header.jsx diff --git a/resources/js/Pages/Admin/PostCategories/PostCategories.jsx b/resources/js/Pages/Admin/PostCategories/PostCategories.jsx index 1e8a97c..1b33699 100644 --- a/resources/js/Pages/Admin/PostCategories/PostCategories.jsx +++ b/resources/js/Pages/Admin/PostCategories/PostCategories.jsx @@ -1,10 +1,7 @@ import { Button } from "@/shadcn/ui/button"; import { ScrollArea } from "@/shadcn/ui/scroll-area"; import { Head, Link } from "@inertiajs/react"; -import { - Pencil, - PlusCircle, -} from "lucide-react"; +import { Pencil, PlusCircle } from "lucide-react"; import { Checkbox } from "@/shadcn/ui/checkbox"; import RTable from "@/Components/RTable"; import AuthenticatedLayout from "@/Layouts/admin/AuthenticatedLayout"; diff --git a/resources/js/Pages/Admin/Tags/Tags.jsx b/resources/js/Pages/Admin/Tags/Tags.jsx new file mode 100644 index 0000000..979cc91 --- /dev/null +++ b/resources/js/Pages/Admin/Tags/Tags.jsx @@ -0,0 +1,99 @@ +import { Button } from "@/shadcn/ui/button"; +import { ScrollArea } from "@/shadcn/ui/scroll-area"; +import { Head, Link } from "@inertiajs/react"; +import { Pencil, PlusCircle } from "lucide-react"; +import { Checkbox } from "@/shadcn/ui/checkbox"; +import RTable from "@/Components/RTable"; +import AuthenticatedLayout from "@/Layouts/admin/AuthenticatedLayout"; +import PageHeading from "@/Components/PageHeading"; +import Can from "@/Components/Can"; + +export const columns = [ + { + id: "select", + header: ({ table }) => ( + + table.toggleAllPageRowsSelected(!!value) + } + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "name", + header: "Name", + }, + { + accessorKey: "created_at_string", + header: "Created At", + }, + { + accessorKey: "updated_at_string", + header: "Updated At", + }, + { + id: "actions", + header: () =>
Actions
, + enableHiding: false, + cell: ({ row }) => { + return ( +
+ + + +
+ ); + }, + }, +]; + +export default function tags({ tags }) { + return ( + + + Tags + + +
+ + + Tags ({tags.meta.total}) + + + + + + + + +
+ +
+
+
+
+ ); +} diff --git a/routes/admin.php b/routes/admin.php index b96db4a..fbed286 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -15,13 +15,14 @@ use App\Http\Controllers\Admin\PostController; use App\Http\Controllers\Admin\Role\RoleController; use App\Http\Controllers\Admin\SettingController; +use App\Http\Controllers\Admin\TagController; use App\Http\Controllers\Admin\Users\UserController; use Illuminate\Support\Facades\Route; -Route::prefix('admin')->name('admin.')->middleware(['web', 'auth'])->group(function() { +Route::prefix('admin')->name('admin.')->middleware(['web', 'auth'])->group(function () { Route::prefix('users')->name('users.')->controller(UserController::class)->group(function () { Route::post('update/{id}', 'update')->name('update')->middleware(['can:edit users']); Route::post('store', 'store')->name('store')->middleware(['can:create users']); @@ -138,7 +139,12 @@ Route::get('{groupKey?}', 'view')->name('view'); }); + Route::prefix('tags')->name('tags.')->controller(TagController::class)->group(function () { + Route::get('store', 'store')->name('store')->can('store tags'); + Route::get('', 'index')->name('index')->can('view tags'); + }); + Route::get('/dashboard', DashboardController::class)->middleware(['auth', 'verified'])->name('dashboard'); Route::redirect('/', '/dashboard'); -}); \ No newline at end of file +}); diff --git a/routes/web.php b/routes/web.php index bbb07d4..554fd10 100644 --- a/routes/web.php +++ b/routes/web.php @@ -27,11 +27,9 @@ Route::prefix('blog')->name('blog.')->controller(PostController::class)->group(function () { Route::get('/', 'index')->name('index'); Route::get('/{slug}', 'show')->name('post'); - }); Route::redirect('/home', '/'); Route::get('/', HomepageController::class)->name('homepage'); Route::get('{slug}', PageController::class)->name('page'); -