diff --git a/components/mobile/MoreDrawer.tsx b/components/mobile/MoreDrawer.tsx new file mode 100644 index 0000000..5bf36b6 --- /dev/null +++ b/components/mobile/MoreDrawer.tsx @@ -0,0 +1,166 @@ +'use client'; + +/* MoreDrawer — phase 02 (DRAWER-01..05). + * + * shadcn Sheet (side="right") with three top-to-bottom sections: + * 1. Mobile sections — Engagement (in-shell route, no ExternalLink hint) + * 2. Full site — desktop-only routes, each with ExternalLink hint + * 3. Account — current user (read-only) + Sign out + * + * Open state is controlled by the parent so the header avatar AND the + * bottom-nav More cell can both trigger this single drawer. */ + +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { + ExternalLink, + FileText, + Server, + HardDrive, + BarChart3, + Settings, + Users, + LogOut, +} from 'lucide-react'; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, + SheetDescription, + SheetClose, +} from '@/components/ui/sheet'; +import { useSession, signOut } from '@/lib/auth-client'; +import { toast } from 'sonner'; + +const MOBILE_SECTIONS = [ + { href: '/mobile/engagement', label: 'Engagement', icon: Users }, +]; + +const DESKTOP_LINKS = [ + { href: '/quotes', label: 'Quotes', icon: FileText }, + { href: '/configuration-items', label: 'Configuration Items', icon: Server }, + { href: '/backup-status', label: 'Backup Status', icon: HardDrive }, + { href: '/admin/ticket-digest', label: 'Ticket Digest', icon: BarChart3 }, + { href: '/admin/sync', label: 'Admin / Sync', icon: Settings }, +]; + +interface MoreDrawerProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function MoreDrawer({ open, onOpenChange }: MoreDrawerProps) { + const router = useRouter(); + const { data: session } = useSession(); + const user = session?.user as + | { name?: string; email?: string; image?: string | null } + | undefined; + + const initials = (user?.name ?? user?.email ?? '?') + .split(/[\s@]/) + .filter(Boolean) + .slice(0, 2) + .map((p) => p[0]?.toUpperCase()) + .join(''); + + async function handleSignOut() { + try { + await signOut(); + router.push('/auth/sign-in'); + } catch (e) { + toast.error('Sign out failed'); + console.error('Sign out failed:', e); + } + } + + return ( + + + + Menu + + Navigation, full-site links, and account actions. + + + + {/* Section 1: Mobile sections (DRAWER-03) */} +
+

+ Mobile sections +

+
+ {MOBILE_SECTIONS.map(({ href, label, icon: Icon }) => ( + + + + {label} + + + ))} +
+
+ + {/* Section 2: Full site (DRAWER-04) */} +
+

+ Full site +

+
+ {DESKTOP_LINKS.map(({ href, label, icon: Icon }) => ( + + + + {label} + + + + ))} +
+
+ + {/* Section 3: Account (DRAWER-05) */} +
+

+ Account +

+
+ {user && ( +
+ + {initials} + +
+ {user.name && ( +

+ {user.name} +

+ )} + {user.email && ( +

+ {user.email} +

+ )} +
+
+ )} + +
+
+
+
+ ); +}