From 52e935b0d0e11affc84f4ea251febd81d8ce205a Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Thu, 18 Dec 2025 22:28:00 +0100 Subject: [PATCH] optional wishlist cart exam --- .../Course/CourseCartController.php | 20 +++++ app/Http/Controllers/StudentController.php | 20 +++++ .../js/layouts/navbar/partials/actions.tsx | 3 +- .../settings/system/partials/website.tsx | 42 ++++++++++ .../js/pages/student/partials/layout.tsx | 80 +++++++++++-------- resources/js/types/settings.d.ts | 3 + 6 files changed, 133 insertions(+), 35 deletions(-) diff --git a/app/Http/Controllers/Course/CourseCartController.php b/app/Http/Controllers/Course/CourseCartController.php index 408b418c..02c9ef4e 100644 --- a/app/Http/Controllers/Course/CourseCartController.php +++ b/app/Http/Controllers/Course/CourseCartController.php @@ -26,6 +26,11 @@ class CourseCartController extends Controller */ public function index(Request $request) { + $system = app('system_settings'); + if (($system?->fields['show_course_cart'] ?? true) === false) { + abort(404); + } + $coupon = null; $couponCode = $request->input('coupon'); @@ -56,6 +61,11 @@ class CourseCartController extends Controller */ public function store(Request $request) { + $system = app('system_settings'); + if (($system?->fields['show_course_cart'] ?? true) === false) { + abort(404); + } + $this->cartService->addToCart(Auth::user()->id, $request->course_id); return redirect(route('course-cart.index'))->with('success', 'Course added to cart successfully.'); @@ -66,6 +76,11 @@ class CourseCartController extends Controller */ public function update(Request $request, CourseCart $courseCart) { + $system = app('system_settings'); + if (($system?->fields['show_course_cart'] ?? true) === false) { + abort(404); + } + $this->cartService->clearCart(Auth::user()->id); return back()->with('success', 'Cart updated successfully.'); @@ -76,6 +91,11 @@ class CourseCartController extends Controller */ public function destroy($course_cart) { + $system = app('system_settings'); + if (($system?->fields['show_course_cart'] ?? true) === false) { + abort(404); + } + $this->cartService->removeFromCart(Auth::user()->id, $course_cart); return back()->with('success', 'Course removed from cart successfully.'); diff --git a/app/Http/Controllers/StudentController.php b/app/Http/Controllers/StudentController.php index 39efbd61..22b87c13 100644 --- a/app/Http/Controllers/StudentController.php +++ b/app/Http/Controllers/StudentController.php @@ -30,6 +30,19 @@ class StudentController extends Controller */ public function index(Request $request, string $tab) { + $system = app('system_settings'); + $fields = $system?->fields ?? []; + $showExams = $fields['show_student_exams'] ?? true; + $showWishlist = $fields['show_student_wishlist'] ?? true; + + if ($tab === 'exams' && !$showExams) { + abort(404); + } + + if ($tab === 'wishlist' && !$showWishlist) { + abort(404); + } + if ($tab !== 'courses' && !$request->user()->hasVerifiedEmail()) { return redirect() ->route('student.index', ['tab' => 'courses']) @@ -66,6 +79,13 @@ class StudentController extends Controller public function show_exam(Request $request, int $id, string $tab) { + $system = app('system_settings'); + $fields = $system?->fields ?? []; + + if (($fields['show_student_exams'] ?? true) === false) { + abort(404); + } + $user = Auth::user(); $exam = $this->examEnrollment->getEnrolledExam($id, $user); $attempts = $this->examAttempt->getExamAttempts(['exam_id' => $id, 'user_id' => $user->id]); diff --git a/resources/js/layouts/navbar/partials/actions.tsx b/resources/js/layouts/navbar/partials/actions.tsx index 8571be7a..c3243b76 100644 --- a/resources/js/layouts/navbar/partials/actions.tsx +++ b/resources/js/layouts/navbar/partials/actions.tsx @@ -19,6 +19,7 @@ const Actions = ({ language }: { language: boolean }) => { const { screen } = useScreen(); const [open, setOpen] = useState(false); const sortedItems = navbar.navbar_items.sort((a, b) => a.sort - b.sort); + const showCart = system.fields?.show_course_cart !== false; const actionElements = () => sortedItems.map((item) => { @@ -28,7 +29,7 @@ const Actions = ({ language }: { language: boolean }) => { return ; } else if (isLoggedIn && item.slug === 'notification') { return ; - } else if (isLoggedIn && item.slug === 'cart') { + } else if (isLoggedIn && item.slug === 'cart' && showCart) { return ; } else { return null; diff --git a/resources/js/pages/dashboard/settings/system/partials/website.tsx b/resources/js/pages/dashboard/settings/system/partials/website.tsx index f1bcde2d..53b0308a 100644 --- a/resources/js/pages/dashboard/settings/system/partials/website.tsx +++ b/resources/js/pages/dashboard/settings/system/partials/website.tsx @@ -6,6 +6,7 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; +import { Switch } from '@/components/ui/switch'; import currencies from '@/data/currencies'; import { onHandleChange } from '@/lib/inertia'; import { SharedData } from '@/types/global'; @@ -24,6 +25,12 @@ const Website = () => { const { translate } = props; const { input, settings } = translate; + const featureDefaults = { + show_course_cart: props.system.fields?.show_course_cart ?? true, + show_student_exams: props.system.fields?.show_student_exams ?? true, + show_student_wishlist: props.system.fields?.show_student_wishlist ?? true, + }; + const mediaFields: MediaFields = { new_logo_dark: null, new_logo_light: null, @@ -32,6 +39,7 @@ const Website = () => { }; const { data, setData, post, errors, processing } = useForm({ + ...featureDefaults, ...(props.system.fields as SystemFields), ...(mediaFields as MediaFields), }); @@ -271,6 +279,40 @@ const Website = () => { )} + +
+
+
+ +

Enable/disable course cart page and icon.

+
+ setData('show_course_cart', checked)} /> +
+ +
+
+ +

Toggle visibility of the student exams tab.

+
+ setData('show_student_exams', checked)} + /> +
+ +
+
+ +

Toggle visibility of the student wishlist tab.

+
+ setData('show_student_wishlist', checked)} + /> +
+
diff --git a/resources/js/pages/student/partials/layout.tsx b/resources/js/pages/student/partials/layout.tsx index 86ff24fe..737fa0be 100644 --- a/resources/js/pages/student/partials/layout.tsx +++ b/resources/js/pages/student/partials/layout.tsx @@ -16,43 +16,55 @@ const Layout = ({ children, tab }: { children: ReactNode; tab: string }) => { const { screen } = useScreen(); const [open, setOpen] = useState(false); const { props } = usePage(); - const { translate, auth } = props; + const { translate, auth, system } = props; const { button } = translate; const tabs = useMemo( - () => [ - { - id: 'courses', - name: button.courses, - slug: 'courses', - Icon: GraduationCap, - }, - { - id: 'exams', - name: 'Exams', - slug: 'exams', - Icon: FileQuestion, - }, - { - id: 'wishlist', - name: button.wishlist, - slug: 'wishlist', - Icon: Heart, - }, - { - id: 'profile', - name: button.profile, - slug: 'profile', - Icon: UserCircle, - }, - { - id: 'settings', - name: button.settings, - slug: 'settings', - Icon: SettingsIcon, - }, - ], - [], + () => { + const list = [ + { + id: 'courses', + name: button.courses, + slug: 'courses', + Icon: GraduationCap, + }, + ...(system.fields?.show_student_exams === false + ? [] + : [ + { + id: 'exams', + name: 'Exams', + slug: 'exams', + Icon: FileQuestion, + }, + ]), + ...(system.fields?.show_student_wishlist === false + ? [] + : [ + { + id: 'wishlist', + name: button.wishlist, + slug: 'wishlist', + Icon: Heart, + }, + ]), + { + id: 'profile', + name: button.profile, + slug: 'profile', + Icon: UserCircle, + }, + { + id: 'settings', + name: button.settings, + slug: 'settings', + Icon: SettingsIcon, + }, + ]; + + return list; + }, + [button.courses, button.wishlist, button.profile, button.settings, system.fields?.show_student_exams, system.fields?.show_student_wishlist], ); const { post, processing } = useForm({}); diff --git a/resources/js/types/settings.d.ts b/resources/js/types/settings.d.ts index acbb2c92..9b282ec9 100644 --- a/resources/js/types/settings.d.ts +++ b/resources/js/types/settings.d.ts @@ -36,6 +36,9 @@ interface SystemFields { direction: string; language_selector: boolean; theme: Appearance; + show_course_cart?: boolean; + show_student_exams?: boolean; + show_student_wishlist?: boolean; } interface GoogleAuthFields {