2025-11-07 13:45:14 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import { usePathname, useRouter } from "next/navigation";
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
2025-11-13 11:42:56 +00:00
|
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
2025-11-07 13:45:14 +00:00
|
|
|
import {
|
|
|
|
|
Inbox,
|
|
|
|
|
Calendar,
|
|
|
|
|
LayoutGrid,
|
|
|
|
|
Heart,
|
|
|
|
|
UserCog,
|
|
|
|
|
Bell,
|
|
|
|
|
Settings,
|
|
|
|
|
LogOut,
|
|
|
|
|
} from "lucide-react";
|
2025-11-13 11:42:56 +00:00
|
|
|
import { useAppTheme } from "@/components/ThemeProvider";
|
|
|
|
|
import { ThemeToggle } from "@/components/ThemeToggle";
|
2025-11-07 13:45:14 +00:00
|
|
|
|
|
|
|
|
export function Header() {
|
|
|
|
|
const pathname = usePathname();
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const [notificationsOpen, setNotificationsOpen] = useState(false);
|
|
|
|
|
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
2025-11-13 11:42:56 +00:00
|
|
|
const { theme } = useAppTheme();
|
|
|
|
|
const isDark = theme === "dark";
|
2025-11-07 13:45:14 +00:00
|
|
|
|
|
|
|
|
// Mock notifications data
|
|
|
|
|
const notifications = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
title: "New appointment scheduled",
|
|
|
|
|
message: "John Smith booked an appointment for tomorrow",
|
|
|
|
|
time: "2 hours ago",
|
|
|
|
|
type: "info",
|
|
|
|
|
read: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
title: "Payment received",
|
|
|
|
|
message: "Payment of $150 received from Jane Doe",
|
|
|
|
|
time: "5 hours ago",
|
|
|
|
|
type: "success",
|
|
|
|
|
read: false,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const unreadCount = notifications.filter((n) => !n.read).length;
|
|
|
|
|
|
|
|
|
|
return (
|
2025-11-13 11:42:56 +00:00
|
|
|
<header className={`fixed top-0 left-0 right-0 z-50 ${isDark ? "bg-gray-900 border-gray-800" : "bg-white border-gray-200"} border-b`}>
|
2025-11-07 13:45:14 +00:00
|
|
|
<div className="px-3 sm:px-4 md:px-6 lg:px-8">
|
|
|
|
|
<div className="flex items-center justify-between h-14 sm:h-16">
|
|
|
|
|
{/* Logo */}
|
2025-11-12 12:33:36 +00:00
|
|
|
<Link href="/" className="flex items-center gap-2 sm:gap-3">
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-lg ${isDark ? "bg-gray-800" : "bg-linear-to-r from-rose-100 to-pink-100"}`}>
|
|
|
|
|
<Heart className={`w-4 h-4 sm:w-6 sm:h-6 ${isDark ? "text-rose-400" : "text-rose-600"}`} fill="currentColor" />
|
2025-11-07 13:45:14 +00:00
|
|
|
</div>
|
2025-11-13 11:42:56 +00:00
|
|
|
<span className={`text-base sm:text-lg md:text-xl font-semibold hidden sm:inline ${isDark ? "text-white" : "text-gray-900"}`}>Attune Heart</span>
|
2025-11-07 13:45:14 +00:00
|
|
|
</Link>
|
|
|
|
|
|
|
|
|
|
{/* Navigation Links */}
|
|
|
|
|
<nav className="flex items-center gap-0.5 sm:gap-1">
|
|
|
|
|
<Link
|
2025-11-12 00:28:29 +00:00
|
|
|
href="/admin/dashboard"
|
2025-11-07 13:45:14 +00:00
|
|
|
className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
|
2025-11-12 00:28:29 +00:00
|
|
|
pathname === "/admin/dashboard"
|
2025-11-07 13:45:14 +00:00
|
|
|
? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
|
2025-11-13 11:42:56 +00:00
|
|
|
: isDark
|
|
|
|
|
? "text-gray-300 hover:bg-gray-800"
|
|
|
|
|
: "text-gray-600 hover:bg-gray-100"
|
2025-11-07 13:45:14 +00:00
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<LayoutGrid className="w-4 h-4 sm:w-5 sm:h-5" />
|
|
|
|
|
<span className="hidden sm:inline">Dashboard</span>
|
|
|
|
|
</Link>
|
|
|
|
|
<Link
|
2025-11-12 00:28:29 +00:00
|
|
|
href="/admin/booking"
|
2025-11-07 13:45:14 +00:00
|
|
|
className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
|
2025-11-12 00:28:29 +00:00
|
|
|
pathname === "/admin/booking"
|
2025-11-07 13:45:14 +00:00
|
|
|
? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
|
2025-11-13 11:42:56 +00:00
|
|
|
: isDark
|
|
|
|
|
? "text-gray-300 hover:bg-gray-800"
|
|
|
|
|
: "text-gray-600 hover:bg-gray-100"
|
2025-11-07 13:45:14 +00:00
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<Calendar className="w-4 h-4 sm:w-5 sm:h-5" />
|
|
|
|
|
<span className="hidden sm:inline">Book Appointment</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
{/* Right Side Actions */}
|
|
|
|
|
<div className="flex items-center gap-1.5 sm:gap-2 md:gap-3">
|
2025-11-13 11:42:56 +00:00
|
|
|
<ThemeToggle />
|
2025-11-07 13:45:14 +00:00
|
|
|
<Popover open={notificationsOpen} onOpenChange={setNotificationsOpen}>
|
|
|
|
|
<PopoverTrigger asChild>
|
|
|
|
|
<Button variant="ghost" size="icon" className="relative w-8 h-8 sm:w-9 sm:h-9 md:w-10 md:h-10 cursor-pointer">
|
2025-11-13 11:42:56 +00:00
|
|
|
<Inbox className={`w-5 h-5 sm:w-6 sm:h-6 md:w-8 md:h-8 ${isDark ? "text-gray-300" : "text-gray-600"}`} />
|
2025-11-07 13:45:14 +00:00
|
|
|
{unreadCount > 0 && (
|
|
|
|
|
<span className="absolute top-0.5 right-0.5 sm:top-1 sm:right-1 w-1.5 h-1.5 sm:w-2 sm:h-2 bg-green-500 rounded-full"></span>
|
|
|
|
|
)}
|
|
|
|
|
</Button>
|
|
|
|
|
</PopoverTrigger>
|
2025-11-13 11:42:56 +00:00
|
|
|
<PopoverContent className={`w-[calc(100vw-2rem)] sm:w-80 md:w-96 p-0 shadow-xl border ${isDark ? "bg-gray-900 border-gray-800" : "bg-white border-gray-200"}`} align="end">
|
2025-11-07 13:45:14 +00:00
|
|
|
{/* Thumbtack Design at Top Right */}
|
|
|
|
|
<div className="relative">
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`absolute -top-2 right-8 w-4 h-4 rotate-45 ${isDark ? "bg-gray-900 border-l border-t border-gray-800" : "bg-white border-l border-t border-gray-200"}`}></div>
|
|
|
|
|
<div className={`absolute -top-1 right-8 w-2 h-2 translate-x-1/2 ${isDark ? "bg-gray-900" : "bg-white"}`}></div>
|
2025-11-07 13:45:14 +00:00
|
|
|
</div>
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`flex items-center justify-between p-4 border-b ${isDark ? "border-gray-800" : ""}`}>
|
|
|
|
|
<h3 className={`font-semibold ${isDark ? "text-white" : "text-gray-900"}`}>Notifications</h3>
|
2025-11-07 13:45:14 +00:00
|
|
|
{unreadCount > 0 && (
|
|
|
|
|
<span className="px-2 py-1 text-xs font-medium bg-rose-100 text-rose-700 rounded-full">
|
|
|
|
|
{unreadCount} new
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="max-h-96 overflow-y-auto">
|
|
|
|
|
{notifications.length === 0 ? (
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`p-8 text-center ${isDark ? "text-gray-400" : "text-gray-500"}`}>
|
|
|
|
|
<Bell className={`w-12 h-12 mx-auto mb-2 ${isDark ? "text-gray-600" : "text-gray-300"}`} />
|
2025-11-07 13:45:14 +00:00
|
|
|
<p className="text-sm">No notifications</p>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`divide-y ${isDark ? "divide-gray-800" : ""}`}>
|
2025-11-07 13:45:14 +00:00
|
|
|
{notifications.map((notification) => {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
key={notification.id}
|
2025-11-13 11:42:56 +00:00
|
|
|
className={`p-4 transition-colors cursor-pointer ${
|
|
|
|
|
!notification.read
|
|
|
|
|
? isDark
|
|
|
|
|
? "bg-rose-500/10"
|
|
|
|
|
: "bg-rose-50/50"
|
|
|
|
|
: ""
|
2025-11-07 13:45:14 +00:00
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex-1 min-w-0">
|
|
|
|
|
<div className="flex items-start justify-between gap-2">
|
|
|
|
|
<p
|
2025-11-13 11:42:56 +00:00
|
|
|
className={`text-sm font-medium ${isDark ? "text-white" : "text-gray-900"} ${
|
2025-11-07 13:45:14 +00:00
|
|
|
!notification.read ? "font-semibold" : ""
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{notification.title}
|
|
|
|
|
</p>
|
|
|
|
|
{!notification.read && (
|
|
|
|
|
<span className="shrink-0 w-2 h-2 bg-green-500 rounded-full mt-1"></span>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-11-13 11:42:56 +00:00
|
|
|
<p className={`text-sm mt-1 ${isDark ? "text-gray-400" : "text-gray-600"}`}>
|
2025-11-07 13:45:14 +00:00
|
|
|
{notification.message}
|
|
|
|
|
</p>
|
2025-11-13 11:42:56 +00:00
|
|
|
<p className={`text-xs mt-1 ${isDark ? "text-gray-500" : "text-gray-400"}`}>
|
2025-11-07 13:45:14 +00:00
|
|
|
{notification.time}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`p-3 border-t ${isDark ? "border-gray-800 bg-gray-900/80" : "bg-gray-50"}`}>
|
2025-11-07 13:45:14 +00:00
|
|
|
<Link
|
2025-11-12 00:28:29 +00:00
|
|
|
href="/admin/notifications"
|
2025-11-07 13:45:14 +00:00
|
|
|
onClick={() => setNotificationsOpen(false)}
|
2025-11-13 11:42:56 +00:00
|
|
|
className={`block w-full text-center text-sm font-medium hover:underline transition-colors ${isDark ? "text-rose-300 hover:text-rose-200" : "text-rose-600 hover:text-rose-700"}`}
|
2025-11-07 13:45:14 +00:00
|
|
|
>
|
|
|
|
|
View all notifications
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
</Popover>
|
|
|
|
|
<Popover open={userMenuOpen} onOpenChange={setUserMenuOpen}>
|
|
|
|
|
<PopoverTrigger asChild>
|
2025-11-13 11:42:56 +00:00
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
size="icon"
|
|
|
|
|
className={`rounded-full cursor-pointer w-8 h-8 sm:w-9 sm:h-9 md:w-10 md:h-10 ${
|
|
|
|
|
isDark
|
|
|
|
|
? "bg-gray-800 hover:bg-gray-700"
|
|
|
|
|
: "bg-linear-to-r from-rose-100 to-pink-100 hover:from-rose-200 hover:to-pink-200"
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<UserCog className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? "text-rose-300" : "text-rose-600"}`} />
|
2025-11-07 13:45:14 +00:00
|
|
|
</Button>
|
|
|
|
|
</PopoverTrigger>
|
2025-11-13 11:42:56 +00:00
|
|
|
<PopoverContent className={`w-56 sm:w-64 p-0 shadow-xl border ${isDark ? "bg-gray-900 border-gray-800" : "bg-white border-gray-200"}`} align="end">
|
2025-11-07 13:45:14 +00:00
|
|
|
{/* Thumbtack Design at Top Right */}
|
|
|
|
|
<div className="relative">
|
2025-11-13 11:42:56 +00:00
|
|
|
<div className={`absolute -top-2 right-8 w-4 h-4 rotate-45 ${isDark ? "bg-gray-900 border-l border-t border-gray-800" : "bg-white border-l border-t border-gray-200"}`}></div>
|
|
|
|
|
<div className={`absolute -top-1 right-8 w-2 h-2 translate-x-1/2 ${isDark ? "bg-gray-900" : "bg-white"}`}></div>
|
2025-11-07 13:45:14 +00:00
|
|
|
</div>
|
|
|
|
|
<div className="py-2">
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setUserMenuOpen(false);
|
2025-11-12 00:28:29 +00:00
|
|
|
router.push("/admin/settings");
|
2025-11-07 13:45:14 +00:00
|
|
|
}}
|
2025-11-13 11:42:56 +00:00
|
|
|
className={`w-full flex items-center gap-3 px-4 py-3 justify-start transition-colors cursor-pointer ${
|
|
|
|
|
isDark ? "hover:bg-gray-800" : "hover:bg-gray-50"
|
|
|
|
|
}`}
|
2025-11-07 13:45:14 +00:00
|
|
|
>
|
2025-11-13 11:42:56 +00:00
|
|
|
<Settings className={`w-5 h-5 ${isDark ? "text-gray-300" : "text-gray-600"}`} />
|
|
|
|
|
<span className={`text-sm font-medium ${isDark ? "text-white" : "text-gray-900"}`}>Settings</span>
|
2025-11-07 13:45:14 +00:00
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setUserMenuOpen(false);
|
|
|
|
|
router.push("/");
|
|
|
|
|
}}
|
2025-11-13 11:42:56 +00:00
|
|
|
className={`w-full flex items-center gap-3 px-4 py-3 justify-start transition-colors cursor-pointer ${
|
|
|
|
|
isDark ? "hover:bg-gray-800" : "hover:bg-gray-50"
|
|
|
|
|
}`}
|
2025-11-07 13:45:14 +00:00
|
|
|
>
|
|
|
|
|
<LogOut className="w-5 h-5 text-red-500" />
|
|
|
|
|
<span className="text-sm font-medium text-red-500">Logout</span>
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
</Popover>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|