11<script setup lang="ts">
22import { Dropdown , DropdownContent , DropdownTrigger } from ' @/components/dropdown' ;
3- import { notifications } from ' @/composables/useAuth ' ;
3+ import { useGlobalProps } from ' @/composables/useGlobalProps ' ;
44import { _ } from ' @/composables/useTranslations' ;
55import { Link } from ' @inertiajs/vue3' ;
66import axios from ' axios' ;
77import { Bell } from ' lucide-vue-next' ;
88import { route as routeUri } from ' ziggy-js' ;
99
10+ const globalProps = useGlobalProps ();
11+
12+ // Computed reference to notifications from global props
13+ const notifications = computed (() => globalProps .auth ?.notifications );
14+
1015const markAsRead = (notification : Notification , close : () => void ) => {
11- if (! notification .is_read ) axios .post (routeUri (' notifications.read' , notification .id ));
16+ if (! notification .is_read ) {
17+ axios .post (routeUri (' notifications.read' , notification .id ));
18+ // Decrement unread count when marking a single notification as read
19+ if (globalProps .auth ?.notifications ) {
20+ globalProps .auth .notifications .unread = Math .max (0 , globalProps .auth .notifications .unread - 1 );
21+ }
22+ }
1223
1324 notification .is_read = true ;
1425 setTimeout (() => close (), 100 );
@@ -17,8 +28,12 @@ const markAsRead = (notification: Notification, close: () => void) => {
1728const markAllAsRead = () => {
1829 axios .post (routeUri (' notifications.readAll' ));
1930
20- // Optimistically mark all as read
21- notifications .value .recent .forEach ((n : Notification ) => (n .is_read = true ));
31+ // Optimistically mark all as read using the mutable global props copy
32+ if (globalProps .auth ?.notifications ) {
33+ globalProps .auth .notifications .recent .forEach ((n : Notification ) => (n .is_read = true ));
34+ // Reset unread count to 0
35+ globalProps .auth .notifications .unread = 0 ;
36+ }
2237};
2338 </script >
2439
@@ -32,21 +47,21 @@ const markAllAsRead = () => {
3247
3348 <!-- Unread count badge -->
3449 <span
35- v-if =" notifications.unread"
50+ v-if =" notifications? .unread"
3651 class =" absolute -top-0.5 -right-0.5 flex size-5 items-center justify-center rounded-full bg-accent-foreground text-xs font-bold text-background"
3752 >
3853 {{ notifications.unread > 9 ? '9+' : notifications.unread }}
3954 </span >
4055 </DropdownTrigger >
4156
4257 <DropdownContent
43- class="top-10 right-0 mr-3 w-80 origin-top overflow-hidden rounded-xl border border-border bg-surface-elevated shadow shadow-accent/70 backdrop-blur-2xl"
58+ class="top-10 right-0 mr-3 w-80 origin-top overflow-hidden rounded-xl border border-border bg-surface-elevated shadow shadow-accent/70 backdrop-blur-2xl max-xs: fixed max-xs: inset-x max-xs: top-16 "
4459 >
4560 <!-- Header -->
4661 <div class =" flex items-center justify-between border-b border-border/30 px-4 py-3" >
4762 <h3 class =" text-sm font-semibold text-text" >{{ _('Notifications') }}</h3 >
4863 <button
49- v-if =" notifications.unread"
64+ v-if =" notifications? .unread"
5065 class =" text-xs text-text-subtle hocus:text-text"
5166 @click =" markAllAsRead"
5267 >
@@ -57,8 +72,8 @@ const markAllAsRead = () => {
5772 <!-- Notifications list -->
5873 <div class =" max-h-96 divide-y divide-border/70 overflow-y-auto" >
5974 <component
75+ v-for =" notification in notifications?.recent || []"
6076 :is =" notification.data?.action ? Link : 'div'"
61- v-for =" notification in notifications.recent"
6277 :key =" notification.id"
6378 :href =" notification.data?.action"
6479 class =" flex items-start gap-3 px-4 py-3 transition-colors"
@@ -85,7 +100,7 @@ const markAllAsRead = () => {
85100
86101 <!-- Empty state -->
87102 <div
88- v-if =" notifications.recent.length === 0"
103+ v-if =" !notifications?.recent || notifications.recent.length === 0"
89104 class =" flex flex-col items-center justify-center py-12 text-text-subtle"
90105 >
91106 <Bell class="mb-3 size-12 opacity-30" />
0 commit comments