From 941de83949a3f8adb803d0abe941f71fa726850c Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Mon, 31 Aug 2026 14:48:02 +0700 Subject: [PATCH] feat: add pending feedback count to user notifications and sidebar --- app/Http/Middleware/HandleInertiaRequests.php | 4 ++ app/Services/Admin/FeedbackService.php | 9 +++++ resources/js/components/app-sidebar.tsx | 37 ++++++++++++------- resources/js/components/nav-secondary.tsx | 7 ++++ resources/js/types/global.d.ts | 1 + 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 02b9079..15d19aa 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -2,6 +2,7 @@ namespace App\Http\Middleware; +use App\Services\Admin\FeedbackService; use App\Services\NotificationService; use Illuminate\Http\Request; use Inertia\Inertia; @@ -48,6 +49,9 @@ public function share(Request $request): array 'unreadNotificationsCount' => fn () => $request->user() ? app(NotificationService::class)->unreadCount($request->user()) : 0, + 'pendingFeedbackCount' => fn () => $request->user() + ? app(FeedbackService::class)->pendingCount($request->user()) + : 0, 'notifications' => Inertia::merge(fn () => $request->user() ? app(NotificationService::class)->paginated($request->user()) : null)->append('data', 'id'), diff --git a/app/Services/Admin/FeedbackService.php b/app/Services/Admin/FeedbackService.php index ed383e8..5053255 100644 --- a/app/Services/Admin/FeedbackService.php +++ b/app/Services/Admin/FeedbackService.php @@ -2,6 +2,7 @@ namespace App\Services\Admin; +use App\Enums\FeedbackStatus; use App\Models\Feedback; use App\Models\User; use App\Support\TextAlignAttributeSanitizer; @@ -51,6 +52,14 @@ public function paginated(User $user, int $perPage = 25, string $search = '', ?s ->paginate($perPage); } + public function pendingCount(User $user): int + { + return Feedback::query() + ->where('user_id', $user->id) + ->where('status', '!=', FeedbackStatus::Resolved) + ->count(); + } + public function create(User $user, array $data): Feedback { return Feedback::create([ diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index 283b206..ae2d1e8 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -224,21 +224,27 @@ function buildNavMain({ ]; } -const navSecondary: { title: string; url: string; icon: Icon }[] = [ - { - title: 'Kritik dan Saran', - url: feedbackRoute.url(), - icon: IconMessageDots, - }, - { - title: 'Bantuan', - url: '#', - icon: IconHelp, - }, -]; +function buildNavSecondary( + pendingFeedbackCount: number, +): { title: string; url: string; icon: Icon; badge?: number }[] { + return [ + { + title: 'Kritik dan Saran', + url: feedbackRoute.url(), + icon: IconMessageDots, + badge: pendingFeedbackCount, + }, + { + title: 'Bantuan', + url: '#', + icon: IconHelp, + }, + ]; +} export function AppSidebar({ ...props }: React.ComponentProps) { - const { name, auth } = usePage<{ auth: Auth }>().props; + const { name, auth, pendingFeedbackCount } = usePage<{ auth: Auth }>() + .props; const roleNames = auth?.user?.roles?.map((role) => role.name) ?? []; const isStaff = roleNames.some((role) => STAFF_ROLES.includes(role)); const isMahasiswa = !isStaff && roleNames.includes('mahasiswa'); @@ -273,7 +279,10 @@ export function AppSidebar({ ...props }: React.ComponentProps) { - + ); diff --git a/resources/js/components/nav-secondary.tsx b/resources/js/components/nav-secondary.tsx index 7a929b7..306c29d 100644 --- a/resources/js/components/nav-secondary.tsx +++ b/resources/js/components/nav-secondary.tsx @@ -8,6 +8,7 @@ import { SidebarGroup, SidebarGroupContent, SidebarMenu, + SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, } from '@/components/ui/sidebar'; @@ -20,6 +21,7 @@ export function NavSecondary({ title: string; url: string; icon: Icon; + badge?: number; }[]; } & React.ComponentPropsWithoutRef) { return ( @@ -34,6 +36,11 @@ export function NavSecondary({ {item.title} + {!!item.badge && ( + + {item.badge} + + )} ))} diff --git a/resources/js/types/global.d.ts b/resources/js/types/global.d.ts index 20a529b..f6f55ed 100644 --- a/resources/js/types/global.d.ts +++ b/resources/js/types/global.d.ts @@ -14,6 +14,7 @@ declare module '@inertiajs/core' { auth: Auth; sidebarOpen: boolean; unreadNotificationsCount: number; + pendingFeedbackCount: number; [key: string]: unknown; }; }