diff --git a/app/Http/Controllers/Admin/NodeController.php b/app/Http/Controllers/Admin/NodeController.php index 685fef1..21beb8c 100644 --- a/app/Http/Controllers/Admin/NodeController.php +++ b/app/Http/Controllers/Admin/NodeController.php @@ -62,21 +62,30 @@ public function create(Subject $subject, Request $request) ->firstOrFail(); } + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit')) + ? $prev + : route('admin.nodes.index', ['subject' => $subject->slug]); + return Inertia::render('admin/NodeCreateOrEdit', [ 'subject' => $subject, 'parent' => $parent, - 'redirect' => url()->previous(), + 'redirect' => $redirect, ]); } public function edit(Node $node) { + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit')) + ? $prev + : route('admin.nodes.index', ['subject' => $node->subject->slug]); return Inertia::render('admin/NodeCreateOrEdit', [ 'subject' => $node->subject, 'node' => $node, 'parent' => $node->parent, - 'redirect' => url()->previous(), + 'redirect' => $redirect, ]); } @@ -118,7 +127,9 @@ public function store(StoreNodeRequest $request, Subject $subject) 'sort_order' => $validated['sort_order'] ?? 0, ]); - $redirect = $validated['redirect'] ? $validated['redirect'] : explode('/create', url()->previous())[0]; + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : route('admin.nodes.index', ['subject' => $subject->slug]); return redirect($redirect)->with('success', 'Node created successfully.'); } @@ -151,12 +162,8 @@ public function update(UpdateNodeRequest $request, Subject $subject, Node $node) $slug = Str::slug($rawSlug); - $parentId = array_key_exists('parent_id', $validated) - ? $validated['parent_id'] - : $node->parent_id; - $exists = Node::where('subject_id', $subject->id) - ->where('parent_id', $parentId) + ->where('parent_id', $node->parent_id) ->where('slug', $slug) ->where('id', '!=', $node->id) ->exists(); @@ -176,7 +183,9 @@ public function update(UpdateNodeRequest $request, Subject $subject, Node $node) $node->save(); - $redirect = $validated['redirect'] ?? explode('/edit', url()->previous())[0]; + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : route('admin.nodes.index', ['subject' => $subject->slug]); return redirect($redirect)->with('success', 'Node updated successfully.'); } diff --git a/app/Http/Controllers/Admin/ResourceController.php b/app/Http/Controllers/Admin/ResourceController.php index 6ad53f1..08429b0 100644 --- a/app/Http/Controllers/Admin/ResourceController.php +++ b/app/Http/Controllers/Admin/ResourceController.php @@ -22,8 +22,13 @@ public function create(Request $request) { $node = Node::findOrFail($request->node_id); + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit') && ! str_contains($prev, '/resources/')) + ? $prev + : '/admin/subjects'; + return Inertia::render('admin/ResourceCreateOrEdit', [ - 'redirect' => url()->previous(), + 'redirect' => $redirect, 'node' => $node, ]); } @@ -32,8 +37,13 @@ public function edit(Resource $resource) { $node = $resource->node; + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit') && ! str_contains($prev, '/resources/')) + ? $prev + : '/admin/subjects'; + return Inertia::render('admin/ResourceCreateOrEdit', [ - 'redirect' => url()->previous(), + 'redirect' => $redirect, 'node' => $node, 'resource' => $resource, ]); @@ -51,7 +61,9 @@ public function store(StoreResourceRequest $request) Resource::create($validated); - $redirect = $validated['redirect'] ?? explode('/resources', url()->previous())[0]; + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : '/admin/subjects'; return redirect($redirect)->with('success', 'Resource created successfully.'); } @@ -74,7 +86,9 @@ public function update(UpdateResourceRequest $request, Resource $resource) $resource->update($validated); - $redirect = $validated['redirect'] ?? '/admin/subjects'; + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : '/admin/subjects'; return redirect($redirect) ->with('success', 'Resource updated successfully.'); @@ -93,7 +107,13 @@ public function destroy(Resource $resource) public function createBulkImages(Request $request) { - $redirect = $request->input('redirect', url()->previous()); + $redirect = $request->input('redirect'); + if (empty($redirect) || str_contains($redirect, '/create') || str_contains($redirect, '/edit')) { + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit')) + ? $prev + : '/admin/subjects'; + } $node = Node::findOrFail($request->node_id); return Inertia::render('admin/resources/BulkImageCreate', [ @@ -118,12 +138,22 @@ public function storeBulkImages(BulkImageStoreRequest $request) } }); - return redirect($validated['redirect'])->with('success', 'Bulk images uploaded successfully.'); + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : '/admin/subjects'; + + return redirect($redirect)->with('success', 'Bulk images uploaded successfully.'); } public function createBulkVideos(Request $request) { - $redirect = $request->input('redirect', url()->previous()); + $redirect = $request->input('redirect'); + if (empty($redirect) || str_contains($redirect, '/create') || str_contains($redirect, '/edit')) { + $prev = url()->previous(); + $redirect = (! empty($prev) && ! str_contains($prev, '/create') && ! str_contains($prev, '/edit')) + ? $prev + : '/admin/subjects'; + } $node = Node::findOrFail($request->node_id); return Inertia::render('admin/resources/BulkVideoCreate', [ @@ -220,6 +250,10 @@ public function storeBulkVideos(BulkVideoStoreRequest $request) } }); - return redirect($validated['redirect'])->with('success', 'Bulk Videos uploaded successfully.'); + $redirect = (! empty($validated['redirect']) && ! str_contains($validated['redirect'], '/create') && ! str_contains($validated['redirect'], '/edit')) + ? $validated['redirect'] + : '/admin/subjects'; + + return redirect($redirect)->with('success', 'Bulk Videos uploaded successfully.'); } } diff --git a/app/Http/Requests/Subject/StoreSubjectRequest.php b/app/Http/Requests/Subject/StoreSubjectRequest.php index 2fa988b..7975107 100644 --- a/app/Http/Requests/Subject/StoreSubjectRequest.php +++ b/app/Http/Requests/Subject/StoreSubjectRequest.php @@ -18,8 +18,12 @@ public function authorize(): bool protected function prepareForValidation(): void { + $slug = $this->filled('slug') + ? Str::slug($this->slug) + : Str::slug($this->course.'-'.($this->english_name ?: $this->name)); + $this->merge([ - 'slug' => Str::slug($this->course.'-'.$this->name), + 'slug' => $slug, ]); } @@ -32,7 +36,8 @@ public function rules(): array { return [ 'name' => ['required', 'string', 'max:100', 'min:3', 'unique:subjects,name'], - 'slug' => ['required', 'string', 'unique:subjects,slug'], + 'english_name' => ['nullable', 'string', 'max:100'], + 'slug' => ['required', 'string', 'max:100', 'unique:subjects,slug'], 'tailwind_format' => ['required', 'string', 'max:100'], 'icon' => ['required', 'string', 'max:50'], 'sort_order' => ['required', 'integer'], diff --git a/app/Http/Requests/Subject/UpdateSubjectRequest.php b/app/Http/Requests/Subject/UpdateSubjectRequest.php index 1cbf8d2..7b0a070 100644 --- a/app/Http/Requests/Subject/UpdateSubjectRequest.php +++ b/app/Http/Requests/Subject/UpdateSubjectRequest.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Support\Str; use Illuminate\Validation\Rule; class UpdateSubjectRequest extends FormRequest @@ -16,6 +17,15 @@ public function authorize(): bool return true; } + protected function prepareForValidation(): void + { + if ($this->filled('slug')) { + $this->merge([ + 'slug' => Str::slug($this->slug), + ]); + } + } + /** * Get the validation rules that apply to the request. * @@ -27,10 +37,11 @@ public function rules(): array return [ 'name' => ['sometimes', 'string', 'max:100', 'min:3', Rule::unique('subjects', 'name')->ignore($subject->id)], + 'english_name' => ['nullable', 'string', 'max:100'], 'tailwind_format' => ['sometimes', 'string', 'max:100'], 'icon' => ['sometimes', 'string', 'max:50'], 'sort_order' => ['sometimes', 'integer'], - 'slug' => ['sometimes', 'string'], + 'slug' => ['sometimes', 'string', 'max:100', Rule::unique('subjects', 'slug')->ignore($subject->id)], 'course' => ['sometimes', 'string', 'in:ssc,hsc'], ]; } diff --git a/database/migrations/2026_08_27_062836_add_english_name_to_subjects_table.php b/database/migrations/2026_08_27_062836_add_english_name_to_subjects_table.php new file mode 100644 index 0000000..b9232be --- /dev/null +++ b/database/migrations/2026_08_27_062836_add_english_name_to_subjects_table.php @@ -0,0 +1,28 @@ +string('english_name', 100)->nullable()->after('name'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('subjects', function (Blueprint $table) { + $table->dropColumn('english_name'); + }); + } +}; diff --git a/resources/js/components/BlogCard.vue b/resources/js/components/BlogCard.vue index 50e58c0..7f7bd34 100644 --- a/resources/js/components/BlogCard.vue +++ b/resources/js/components/BlogCard.vue @@ -28,12 +28,12 @@ const formattedDate = computed(() => { diff --git a/resources/js/pages/User/Show.vue b/resources/js/pages/User/Show.vue index a66ca85..c799078 100644 --- a/resources/js/pages/User/Show.vue +++ b/resources/js/pages/User/Show.vue @@ -5,7 +5,6 @@ import { ArrowBigUp, ArrowRight, ArrowUpRight, - BadgeCheck, BookOpen, Calendar, CheckCircle2, diff --git a/resources/js/pages/admin/Node.vue b/resources/js/pages/admin/Node.vue index f5924bf..98bd5f8 100644 --- a/resources/js/pages/admin/Node.vue +++ b/resources/js/pages/admin/Node.vue @@ -1,5 +1,5 @@