Compare commits

...

2 Commits

9 changed files with 276 additions and 181 deletions

View File

@ -4,11 +4,7 @@ import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { usePathname, useRouter } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { import {
Inbox, Inbox,
Calendar, Calendar,
@ -19,12 +15,16 @@ import {
Settings, Settings,
LogOut, LogOut,
} from "lucide-react"; } from "lucide-react";
import { useAppTheme } from "@/components/ThemeProvider";
import { ThemeToggle } from "@/components/ThemeToggle";
export function Header() { export function Header() {
const pathname = usePathname(); const pathname = usePathname();
const router = useRouter(); const router = useRouter();
const [notificationsOpen, setNotificationsOpen] = useState(false); const [notificationsOpen, setNotificationsOpen] = useState(false);
const [userMenuOpen, setUserMenuOpen] = useState(false); const [userMenuOpen, setUserMenuOpen] = useState(false);
const { theme } = useAppTheme();
const isDark = theme === "dark";
// Mock notifications data // Mock notifications data
const notifications = [ const notifications = [
@ -49,15 +49,15 @@ export function Header() {
const unreadCount = notifications.filter((n) => !n.read).length; const unreadCount = notifications.filter((n) => !n.read).length;
return ( return (
<header className="bg-white border-b border-gray-200 fixed top-0 left-0 right-0 z-50"> <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`}>
<div className="px-3 sm:px-4 md:px-6 lg:px-8"> <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"> <div className="flex items-center justify-between h-14 sm:h-16">
{/* Logo */} {/* Logo */}
<Link href="/" className="flex items-center gap-2 sm:gap-3"> <Link href="/" className="flex items-center gap-2 sm:gap-3">
<div className="flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-linear-to-r from-rose-100 to-pink-100"> <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 text-rose-600" fill="currentColor" /> <Heart className={`w-4 h-4 sm:w-6 sm:h-6 ${isDark ? "text-rose-400" : "text-rose-600"}`} fill="currentColor" />
</div> </div>
<span className="text-base sm:text-lg md:text-xl font-semibold text-gray-900 hidden sm:inline">Attune Heart</span> <span className={`text-base sm:text-lg md:text-xl font-semibold hidden sm:inline ${isDark ? "text-white" : "text-gray-900"}`}>Attune Heart</span>
</Link> </Link>
{/* Navigation Links */} {/* Navigation Links */}
@ -67,7 +67,9 @@ export function Header() {
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 ${ 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 ${
pathname === "/admin/dashboard" pathname === "/admin/dashboard"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
: "text-gray-600 hover:bg-gray-100" : isDark
? "text-gray-300 hover:bg-gray-800"
: "text-gray-600 hover:bg-gray-100"
}`} }`}
> >
<LayoutGrid className="w-4 h-4 sm:w-5 sm:h-5" /> <LayoutGrid className="w-4 h-4 sm:w-5 sm:h-5" />
@ -78,7 +80,9 @@ export function Header() {
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 ${ 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 ${
pathname === "/admin/booking" pathname === "/admin/booking"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
: "text-gray-600 hover:bg-gray-100" : isDark
? "text-gray-300 hover:bg-gray-800"
: "text-gray-600 hover:bg-gray-100"
}`} }`}
> >
<Calendar className="w-4 h-4 sm:w-5 sm:h-5" /> <Calendar className="w-4 h-4 sm:w-5 sm:h-5" />
@ -88,23 +92,24 @@ export function Header() {
{/* Right Side Actions */} {/* Right Side Actions */}
<div className="flex items-center gap-1.5 sm:gap-2 md:gap-3"> <div className="flex items-center gap-1.5 sm:gap-2 md:gap-3">
<ThemeToggle />
<Popover open={notificationsOpen} onOpenChange={setNotificationsOpen}> <Popover open={notificationsOpen} onOpenChange={setNotificationsOpen}>
<PopoverTrigger asChild> <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"> <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">
<Inbox className="w-5 h-5 sm:w-6 sm:h-6 md:w-8 md:h-8 text-gray-600" /> <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"}`} />
{unreadCount > 0 && ( {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> <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> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-[calc(100vw-2rem)] sm:w-80 md:w-96 p-0 bg-white shadow-xl border border-gray-200" align="end"> <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">
{/* Thumbtack Design at Top Right */} {/* Thumbtack Design at Top Right */}
<div className="relative"> <div className="relative">
<div className="absolute -top-2 right-8 w-4 h-4 bg-white border-l border-t border-gray-200 rotate-45"></div> <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 bg-white translate-x-1/2"></div> <div className={`absolute -top-1 right-8 w-2 h-2 translate-x-1/2 ${isDark ? "bg-gray-900" : "bg-white"}`}></div>
</div> </div>
<div className="flex items-center justify-between p-4 border-b"> <div className={`flex items-center justify-between p-4 border-b ${isDark ? "border-gray-800" : ""}`}>
<h3 className="font-semibold text-gray-900">Notifications</h3> <h3 className={`font-semibold ${isDark ? "text-white" : "text-gray-900"}`}>Notifications</h3>
{unreadCount > 0 && ( {unreadCount > 0 && (
<span className="px-2 py-1 text-xs font-medium bg-rose-100 text-rose-700 rounded-full"> <span className="px-2 py-1 text-xs font-medium bg-rose-100 text-rose-700 rounded-full">
{unreadCount} new {unreadCount} new
@ -113,24 +118,28 @@ export function Header() {
</div> </div>
<div className="max-h-96 overflow-y-auto"> <div className="max-h-96 overflow-y-auto">
{notifications.length === 0 ? ( {notifications.length === 0 ? (
<div className="p-8 text-center text-gray-500"> <div className={`p-8 text-center ${isDark ? "text-gray-400" : "text-gray-500"}`}>
<Bell className="w-12 h-12 mx-auto mb-2 text-gray-300" /> <Bell className={`w-12 h-12 mx-auto mb-2 ${isDark ? "text-gray-600" : "text-gray-300"}`} />
<p className="text-sm">No notifications</p> <p className="text-sm">No notifications</p>
</div> </div>
) : ( ) : (
<div className="divide-y"> <div className={`divide-y ${isDark ? "divide-gray-800" : ""}`}>
{notifications.map((notification) => { {notifications.map((notification) => {
return ( return (
<div <div
key={notification.id} key={notification.id}
className={`p-4 hover:bg-gray-50 transition-colors cursor-pointer ${ className={`p-4 transition-colors cursor-pointer ${
!notification.read ? "bg-rose-50/50" : "" !notification.read
? isDark
? "bg-rose-500/10"
: "bg-rose-50/50"
: ""
}`} }`}
> >
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<p <p
className={`text-sm font-medium text-gray-900 ${ className={`text-sm font-medium ${isDark ? "text-white" : "text-gray-900"} ${
!notification.read ? "font-semibold" : "" !notification.read ? "font-semibold" : ""
}`} }`}
> >
@ -140,10 +149,10 @@ export function Header() {
<span className="shrink-0 w-2 h-2 bg-green-500 rounded-full mt-1"></span> <span className="shrink-0 w-2 h-2 bg-green-500 rounded-full mt-1"></span>
)} )}
</div> </div>
<p className="text-sm text-gray-600 mt-1"> <p className={`text-sm mt-1 ${isDark ? "text-gray-400" : "text-gray-600"}`}>
{notification.message} {notification.message}
</p> </p>
<p className="text-xs text-gray-400 mt-1"> <p className={`text-xs mt-1 ${isDark ? "text-gray-500" : "text-gray-400"}`}>
{notification.time} {notification.time}
</p> </p>
</div> </div>
@ -153,11 +162,11 @@ export function Header() {
</div> </div>
)} )}
</div> </div>
<div className="p-3 border-t bg-gray-50"> <div className={`p-3 border-t ${isDark ? "border-gray-800 bg-gray-900/80" : "bg-gray-50"}`}>
<Link <Link
href="/admin/notifications" href="/admin/notifications"
onClick={() => setNotificationsOpen(false)} onClick={() => setNotificationsOpen(false)}
className="block w-full text-center text-sm font-medium text-rose-600 hover:text-rose-700 hover:underline transition-colors" 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"}`}
> >
View all notifications View all notifications
</Link> </Link>
@ -166,15 +175,23 @@ export function Header() {
</Popover> </Popover>
<Popover open={userMenuOpen} onOpenChange={setUserMenuOpen}> <Popover open={userMenuOpen} onOpenChange={setUserMenuOpen}>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button variant="ghost" size="icon" className="rounded-full bg-linear-to-r from-rose-100 to-pink-100 hover:from-rose-200 hover:to-pink-200 cursor-pointer w-8 h-8 sm:w-9 sm:h-9 md:w-10 md:h-10"> <Button
<UserCog className="w-4 h-4 sm:w-5 sm:h-5 text-rose-600" /> 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"}`} />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-56 sm:w-64 p-0 bg-white shadow-xl border border-gray-200" align="end"> <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">
{/* Thumbtack Design at Top Right */} {/* Thumbtack Design at Top Right */}
<div className="relative"> <div className="relative">
<div className="absolute -top-2 right-8 w-4 h-4 bg-white border-l border-t border-gray-200 rotate-45"></div> <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 bg-white translate-x-1/2"></div> <div className={`absolute -top-1 right-8 w-2 h-2 translate-x-1/2 ${isDark ? "bg-gray-900" : "bg-white"}`}></div>
</div> </div>
<div className="py-2"> <div className="py-2">
<Button <Button
@ -183,10 +200,12 @@ export function Header() {
setUserMenuOpen(false); setUserMenuOpen(false);
router.push("/admin/settings"); router.push("/admin/settings");
}} }}
className="w-full flex items-center gap-3 px-4 py-3 justify-start hover:bg-gray-50 transition-colors cursor-pointer" 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"
}`}
> >
<Settings className="w-5 h-5 text-gray-600" /> <Settings className={`w-5 h-5 ${isDark ? "text-gray-300" : "text-gray-600"}`} />
<span className="text-sm font-medium text-gray-900">Settings</span> <span className={`text-sm font-medium ${isDark ? "text-white" : "text-gray-900"}`}>Settings</span>
</Button> </Button>
<Button <Button
variant="ghost" variant="ghost"
@ -194,7 +213,9 @@ export function Header() {
setUserMenuOpen(false); setUserMenuOpen(false);
router.push("/"); router.push("/");
}} }}
className="w-full flex items-center gap-3 px-4 py-3 justify-start hover:bg-gray-50 transition-colors cursor-pointer" 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"
}`}
> >
<LogOut className="w-5 h-5 text-red-500" /> <LogOut className="w-5 h-5 text-red-500" />
<span className="text-sm font-medium text-red-500">Logout</span> <span className="text-sm font-medium text-red-500">Logout</span>

View File

@ -12,6 +12,7 @@ import {
Clock, Clock,
} from "lucide-react"; } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useAppTheme } from "@/components/ThemeProvider";
export interface Notification { export interface Notification {
id: string; id: string;
@ -36,30 +37,32 @@ export function Notifications({
onMarkAllAsRead, onMarkAllAsRead,
}: NotificationsProps) { }: NotificationsProps) {
const unreadCount = notifications.filter((n) => !n.read).length; const unreadCount = notifications.filter((n) => !n.read).length;
const { theme } = useAppTheme();
const isDark = theme === "dark";
const getIcon = (type: Notification["type"]) => { const getIcon = (type: Notification["type"]) => {
switch (type) { switch (type) {
case "success": case "success":
return <CheckCircle className="w-5 h-5 text-green-600" />; return <CheckCircle className={`w-5 h-5 ${isDark ? "text-green-300" : "text-green-600"}`} />;
case "warning": case "warning":
return <AlertCircle className="w-5 h-5 text-orange-600" />; return <AlertCircle className={`w-5 h-5 ${isDark ? "text-orange-300" : "text-orange-600"}`} />;
case "info": case "info":
return <Info className="w-5 h-5 text-blue-600" />; return <Info className={`w-5 h-5 ${isDark ? "text-blue-300" : "text-blue-600"}`} />;
case "appointment": case "appointment":
return <Calendar className="w-5 h-5 text-rose-600" />; return <Calendar className={`w-5 h-5 ${isDark ? "text-rose-300" : "text-rose-600"}`} />;
} }
}; };
const getBgColor = (type: Notification["type"]) => { const getBgColor = (type: Notification["type"]) => {
switch (type) { switch (type) {
case "success": case "success":
return "bg-[#4A90A4]/10 border-[#4A90A4]/30"; return isDark ? "bg-green-500/10 border-green-500/30" : "bg-[#4A90A4]/10 border-[#4A90A4]/30";
case "warning": case "warning":
return "bg-rose-100 border-rose-300"; return isDark ? "bg-rose-500/10 border-rose-400/40" : "bg-rose-100 border-rose-300";
case "info": case "info":
return "bg-pink-50 border-pink-200"; return isDark ? "bg-pink-500/10 border-pink-400/40" : "bg-pink-50 border-pink-200";
case "appointment": case "appointment":
return "bg-gradient-to-br from-rose-50 to-pink-50 border-rose-300"; return isDark ? "bg-rose-500/10 border-rose-400/40" : "bg-gradient-to-br from-rose-50 to-pink-50 border-rose-300";
} }
}; };
@ -68,8 +71,8 @@ export function Notifications({
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Bell className="w-6 h-6 text-gray-900" /> <Bell className={`w-6 h-6 ${isDark ? "text-white" : "text-gray-900"}`} />
<h2 className="text-2xl font-bold text-gray-900">Notifications</h2> <h2 className={`text-2xl font-bold ${isDark ? "text-white" : "text-gray-900"}`}>Notifications</h2>
{unreadCount > 0 && ( {unreadCount > 0 && (
<span className="px-2.5 py-0.5 bg-linear-to-r from-rose-500 to-pink-500 text-white text-sm font-medium rounded-full"> <span className="px-2.5 py-0.5 bg-linear-to-r from-rose-500 to-pink-500 text-white text-sm font-medium rounded-full">
{unreadCount} {unreadCount}
@ -77,7 +80,12 @@ export function Notifications({
)} )}
</div> </div>
{unreadCount > 0 && onMarkAllAsRead && ( {unreadCount > 0 && onMarkAllAsRead && (
<Button variant="outline" size="sm" onClick={onMarkAllAsRead}> <Button
variant="outline"
size="sm"
onClick={onMarkAllAsRead}
className={isDark ? "border-gray-700 text-gray-200 hover:bg-gray-800" : ""}
>
Mark all as read Mark all as read
</Button> </Button>
)} )}
@ -87,8 +95,8 @@ export function Notifications({
<div className="space-y-3"> <div className="space-y-3">
{notifications.length === 0 ? ( {notifications.length === 0 ? (
<div className="text-center py-12"> <div className="text-center py-12">
<Bell className="w-12 h-12 text-gray-400 mx-auto mb-4" /> <Bell className={`w-12 h-12 mx-auto mb-4 ${isDark ? "text-gray-600" : "text-gray-400"}`} />
<p className="text-gray-600">No notifications</p> <p className={isDark ? "text-gray-400" : "text-gray-600"}>No notifications</p>
</div> </div>
) : ( ) : (
notifications.map((notification) => ( notifications.map((notification) => (
@ -97,7 +105,7 @@ export function Notifications({
className={cn( className={cn(
"p-4 rounded-lg border-2 transition-all", "p-4 rounded-lg border-2 transition-all",
getBgColor(notification.type), getBgColor(notification.type),
!notification.read && "ring-2 ring-offset-2 ring-rose-300" !notification.read && (isDark ? "ring-2 ring-offset-2 ring-rose-400 ring-offset-gray-900" : "ring-2 ring-offset-2 ring-rose-300")
)} )}
> >
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@ -108,13 +116,15 @@ export function Notifications({
<h3 <h3
className={cn( className={cn(
"font-semibold mb-1", "font-semibold mb-1",
!notification.read ? "text-gray-900" : "text-gray-700" !notification.read
? isDark ? "text-white" : "text-gray-900"
: isDark ? "text-gray-300" : "text-gray-700"
)} )}
> >
{notification.title} {notification.title}
</h3> </h3>
<p className="text-sm text-gray-600 mb-2">{notification.message}</p> <p className={`text-sm mb-2 ${isDark ? "text-gray-400" : "text-gray-600"}`}>{notification.message}</p>
<div className="flex items-center gap-2 text-xs text-gray-500"> <div className={`flex items-center gap-2 text-xs ${isDark ? "text-gray-500" : "text-gray-500"}`}>
<Clock className="w-3 h-3" /> <Clock className="w-3 h-3" />
{notification.time} {notification.time}
</div> </div>
@ -125,7 +135,7 @@ export function Notifications({
variant="ghost" variant="ghost"
size="icon-sm" size="icon-sm"
onClick={() => onMarkAsRead(notification.id)} onClick={() => onMarkAsRead(notification.id)}
className="h-7 w-7" className={`h-7 w-7 ${isDark ? "text-gray-300 hover:bg-gray-800" : ""}`}
> >
<CheckCircle className="w-4 h-4" /> <CheckCircle className="w-4 h-4" />
</Button> </Button>
@ -135,7 +145,7 @@ export function Notifications({
variant="ghost" variant="ghost"
size="icon-sm" size="icon-sm"
onClick={() => onDismiss(notification.id)} onClick={() => onDismiss(notification.id)}
className="h-7 w-7" className={`h-7 w-7 ${isDark ? "text-gray-300 hover:bg-gray-800" : ""}`}
> >
<X className="w-4 h-4" /> <X className="w-4 h-4" />
</Button> </Button>

View File

@ -13,6 +13,7 @@ import {
X, X,
Heart, Heart,
} from "lucide-react"; } from "lucide-react";
import { useAppTheme } from "@/components/ThemeProvider";
const navItems = [ const navItems = [
{ label: "Dashboard", icon: LayoutGrid, href: "/admin/dashboard" }, { label: "Dashboard", icon: LayoutGrid, href: "/admin/dashboard" },
@ -23,6 +24,8 @@ export default function SideNav() {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const pathname = usePathname(); const pathname = usePathname();
const router = useRouter(); const router = useRouter();
const { theme } = useAppTheme();
const isDark = theme === "dark";
const getActiveIndex = () => { const getActiveIndex = () => {
return navItems.findIndex((item) => pathname?.includes(item.href)) ?? -1; return navItems.findIndex((item) => pathname?.includes(item.href)) ?? -1;
@ -43,12 +46,12 @@ export default function SideNav() {
return ( return (
<> <>
{/* Mobile Top Bar */} {/* Mobile Top Bar */}
<div className="flex md:hidden items-center justify-between px-4 py-3 border-b border-gray-200 bg-white z-30 fixed top-0 left-0 right-0"> <div className={`flex md:hidden items-center justify-between px-4 py-3 border-b z-30 fixed top-0 left-0 right-0 ${isDark ? "bg-gray-900 border-gray-800" : "bg-white border-gray-200"}`}>
<Link href="/" className="flex items-center gap-3"> <Link href="/" className="flex items-center gap-3">
<div className="flex items-center justify-center w-8 h-8 rounded-lg bg-linear-to-r from-rose-100 to-pink-100"> <div className={`flex items-center justify-center w-8 h-8 rounded-lg ${isDark ? "bg-gray-800" : "bg-linear-to-r from-rose-100 to-pink-100"}`}>
<Heart className="w-5 h-5 text-rose-600" fill="currentColor" /> <Heart className={`w-5 h-5 ${isDark ? "text-rose-300" : "text-rose-600"}`} fill="currentColor" />
</div> </div>
<span className="text-lg font-semibold text-gray-900">Attune Heart Therapy</span> <span className={`text-lg font-semibold ${isDark ? "text-white" : "text-gray-900"}`}>Attune Heart Therapy</span>
</Link> </Link>
<Button <Button
variant="ghost" variant="ghost"
@ -70,21 +73,21 @@ export default function SideNav() {
{/* Side Navigation */} {/* Side Navigation */}
<aside <aside
className={`fixed top-0 left-0 z-50 h-screen bg-white border-r border-gray-200 flex flex-col transition-transform duration-200 w-[85vw] max-w-[200px] min-w-[160px] md:translate-x-0 md:w-[200px] md:min-w-[200px] md:max-w-[200px] ${ className={`fixed top-0 left-0 z-50 h-screen flex flex-col transition-transform duration-200 w-[85vw] max-w-[200px] min-w-[160px] md:translate-x-0 md:w-[200px] md:min-w-[200px] md:max-w-[200px] ${isDark ? "bg-gray-900 border-r border-gray-800" : "bg-white border-r border-gray-200"} ${
open ? "translate-x-0" : "-translate-x-full" open ? "translate-x-0" : "-translate-x-full"
} md:translate-x-0`} } md:translate-x-0`}
> >
{/* Logo Section */} {/* Logo Section */}
<div className="shrink-0 px-3 pb-4 flex flex-col gap-1 md:block mb-5 pt-16 md:pt-4"> <div className="shrink-0 px-3 pb-4 flex flex-col gap-1 md:block mb-5 pt-16 md:pt-4">
<Link href="/" className="flex items-center gap-2 mb-1 ml-2 md:ml-3"> <Link href="/" className="flex items-center gap-2 mb-1 ml-2 md:ml-3">
<div className="flex items-center justify-center w-8 h-8 rounded-lg bg-linear-to-r from-rose-100 to-pink-100"> <div className={`flex items-center justify-center w-8 h-8 rounded-lg ${isDark ? "bg-gray-800" : "bg-linear-to-r from-rose-100 to-pink-100"}`}>
<Heart className="w-5 h-5 text-rose-600" fill="currentColor" /> <Heart className={`w-5 h-5 ${isDark ? "text-rose-300" : "text-rose-600"}`} fill="currentColor" />
</div> </div>
<span className="text-sm font-semibold text-gray-900">Attune Heart</span> <span className={`text-sm font-semibold ${isDark ? "text-white" : "text-gray-900"}`}>Attune Heart</span>
</Link> </Link>
</div> </div>
<hr className="shrink-0 -mt-10 mb-4 mx-3 border-gray-200 md:block hidden" /> <hr className={`shrink-0 -mt-10 mb-4 mx-3 md:block hidden ${isDark ? "border-gray-800" : "border-gray-200"}`} />
{/* Navigation Items */} {/* Navigation Items */}
<nav className="flex-1 overflow-y-auto flex flex-col gap-2 px-2 md:px-0"> <nav className="flex-1 overflow-y-auto flex flex-col gap-2 px-2 md:px-0">
@ -106,7 +109,9 @@ export default function SideNav() {
className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 focus:outline-none w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start ${ className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 focus:outline-none w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start ${
isActive isActive
? "bg-linear-to-r from-rose-500 to-pink-600 text-white border border-rose-500 rounded-[5px] shadow-sm" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white border border-rose-500 rounded-[5px] shadow-sm"
: "bg-transparent text-gray-600 hover:bg-rose-50 hover:text-rose-600 rounded-lg" : isDark
? "bg-transparent text-gray-300 hover:bg-gray-800 hover:text-rose-300 rounded-lg"
: "bg-transparent text-gray-600 hover:bg-rose-50 hover:text-rose-600 rounded-lg"
}`} }`}
style={isActive ? { height: 40 } : {}} style={isActive ? { height: 40 } : {}}
> >
@ -116,7 +121,9 @@ export default function SideNav() {
className={ className={
isActive isActive
? "text-white" ? "text-white"
: "text-gray-700 group-hover:text-rose-600" : isDark
? "text-gray-400 group-hover:text-rose-300"
: "text-gray-700 group-hover:text-rose-600"
} }
/> />
<span <span
@ -131,7 +138,7 @@ export default function SideNav() {
})} })}
{/* Bottom Actions */} {/* Bottom Actions */}
<div className="mt-auto pt-4 pb-4 border-t border-gray-200"> <div className={`mt-auto pt-4 pb-4 border-t ${isDark ? "border-gray-800" : "border-gray-200"}`}>
<div className="relative flex items-center w-full"> <div className="relative flex items-center w-full">
{pathname === "/admin/settings" && ( {pathname === "/admin/settings" && (
<span <span
@ -145,7 +152,9 @@ export default function SideNav() {
className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start rounded-lg ${ className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start rounded-lg ${
pathname === "/admin/settings" pathname === "/admin/settings"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white border border-rose-500 rounded-[5px] shadow-sm" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white border border-rose-500 rounded-[5px] shadow-sm"
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900" : isDark
? "text-gray-300 hover:bg-gray-800 hover:text-rose-300"
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
}`} }`}
style={pathname === "/admin/settings" ? { height: 40 } : {}} style={pathname === "/admin/settings" ? { height: 40 } : {}}
> >
@ -155,7 +164,9 @@ export default function SideNav() {
className={ className={
pathname === "/admin/settings" pathname === "/admin/settings"
? "text-white" ? "text-white"
: "text-gray-700 group-hover:text-gray-900" : isDark
? "text-gray-400 group-hover:text-rose-300"
: "text-gray-700 group-hover:text-gray-900"
} }
/> />
<span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}> <span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}>
@ -169,9 +180,13 @@ export default function SideNav() {
setOpen(false); setOpen(false);
router.push("/"); router.push("/");
}} }}
className="group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg" className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start rounded-lg ${
isDark
? "text-gray-300 hover:bg-gray-800 hover:text-rose-300"
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
}`}
> >
<LogOut size={18} strokeWidth={1.5} className="text-gray-700 group-hover:text-gray-900" /> <LogOut size={18} strokeWidth={1.5} className={isDark ? "text-gray-400 group-hover:text-rose-300" : "text-gray-700 group-hover:text-gray-900"} />
<span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}> <span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}>
Logout Logout
</span> </span>

View File

@ -9,6 +9,7 @@ import {
FileText, FileText,
MoreVertical, MoreVertical,
} from "lucide-react"; } from "lucide-react";
import { useAppTheme } from "@/components/ThemeProvider";
interface User { interface User {
ID: number; ID: number;
@ -54,6 +55,8 @@ export default function Booking() {
const [bookings, setBookings] = useState<Booking[]>([]); const [bookings, setBookings] = useState<Booking[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const { theme } = useAppTheme();
const isDark = theme === "dark";
useEffect(() => { useEffect(() => {
// Simulate API call // Simulate API call
@ -127,7 +130,22 @@ export default function Booking() {
}; };
const getStatusColor = (status: string) => { const getStatusColor = (status: string) => {
switch (status.toLowerCase()) { const normalized = status.toLowerCase();
if (isDark) {
switch (normalized) {
case "scheduled":
return "bg-blue-500/20 text-blue-200";
case "completed":
return "bg-green-500/20 text-green-200";
case "cancelled":
return "bg-red-500/20 text-red-200";
case "pending":
return "bg-yellow-500/20 text-yellow-200";
default:
return "bg-gray-700 text-gray-200";
}
}
switch (normalized) {
case "scheduled": case "scheduled":
return "bg-blue-100 text-blue-700"; return "bg-blue-100 text-blue-700";
case "completed": case "completed":
@ -142,7 +160,20 @@ export default function Booking() {
}; };
const getPaymentStatusColor = (status: string) => { const getPaymentStatusColor = (status: string) => {
switch (status.toLowerCase()) { const normalized = status.toLowerCase();
if (isDark) {
switch (normalized) {
case "paid":
return "bg-green-500/20 text-green-200";
case "pending":
return "bg-yellow-500/20 text-yellow-200";
case "failed":
return "bg-red-500/20 text-red-200";
default:
return "bg-gray-700 text-gray-200";
}
}
switch (normalized) {
case "paid": case "paid":
return "bg-green-100 text-green-700"; return "bg-green-100 text-green-700";
case "pending": case "pending":
@ -166,102 +197,104 @@ export default function Booking() {
); );
return ( return (
<div className="min-h-screen bg-gray-50"> <div className={`min-h-screen ${isDark ? "bg-gray-900" : "bg-gray-50"}`}>
{/* Main Content */} {/* Main Content */}
<main className="p-3 sm:p-4 md:p-6 lg:p-8"> <main className="p-3 sm:p-4 md:p-6 lg:p-8">
{/* Page Header */} {/* Page Header */}
<div className="mb-4 sm:mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4"> <div className="mb-4 sm:mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4">
<div> <div>
<h1 className="text-xl sm:text-2xl font-semibold text-gray-900 mb-1"> <h1 className={`text-xl sm:text-2xl font-semibold mb-1 ${isDark ? "text-white" : "text-gray-900"}`}>
Bookings Bookings
</h1> </h1>
<p className="text-xs sm:text-sm text-gray-500"> <p className={`text-xs sm:text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Manage and view all appointment bookings Manage and view all appointment bookings
</p> </p>
</div> </div>
<button className="w-full sm:w-auto px-3 sm:px-4 py-2 bg-gray-900 text-white rounded-lg text-xs sm:text-sm font-medium hover:bg-gray-800 transition-colors"> <button className={`w-full sm:w-auto px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
isDark ? "bg-rose-500 text-white hover:bg-rose-600" : "bg-gray-900 text-white hover:bg-gray-800"
}`}>
+ New Booking + New Booking
</button> </button>
</div> </div>
{loading ? ( {loading ? (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-400"></div> <div className={`animate-spin rounded-full h-8 w-8 border-b-2 ${isDark ? "border-gray-600" : "border-gray-400"}`}></div>
</div> </div>
) : filteredBookings.length === 0 ? ( ) : filteredBookings.length === 0 ? (
<div className="bg-white rounded-lg border border-gray-200 p-12 text-center"> <div className={`rounded-lg border p-12 text-center ${isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}`}>
<Calendar className="w-12 h-12 text-gray-400 mx-auto mb-4" /> <Calendar className={`w-12 h-12 mx-auto mb-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<p className="text-gray-600 font-medium mb-1">No bookings found</p> <p className={`font-medium mb-1 ${isDark ? "text-gray-200" : "text-gray-600"}`}>No bookings found</p>
<p className="text-sm text-gray-500"> <p className={`text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`}>
{searchTerm {searchTerm
? "Try adjusting your search terms" ? "Try adjusting your search terms"
: "Create a new booking to get started"} : "Create a new booking to get started"}
</p> </p>
</div> </div>
) : ( ) : (
<div className="bg-white rounded-lg border border-gray-200 overflow-hidden"> <div className={`rounded-lg border overflow-hidden ${isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}`}>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full"> <table className="w-full">
<thead className="bg-gray-50 border-b border-gray-200"> <thead className={`${isDark ? "bg-gray-800 border-b border-gray-700" : "bg-gray-50 border-b border-gray-200"}`}>
<tr> <tr>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Patient Patient
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden md:table-cell"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider hidden md:table-cell ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Date & Time Date & Time
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden lg:table-cell"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider hidden lg:table-cell ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Duration Duration
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Status Status
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden lg:table-cell"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider hidden lg:table-cell ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Payment Payment
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden xl:table-cell"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-left text-xs font-medium uppercase tracking-wider hidden xl:table-cell ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Amount Amount
</th> </th>
<th className="px-3 sm:px-4 md:px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className={`px-3 sm:px-4 md:px-6 py-3 text-right text-xs font-medium uppercase tracking-wider ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Actions Actions
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody className="bg-white divide-y divide-gray-200"> <tbody className={`${isDark ? "bg-gray-800 divide-gray-700" : "bg-white divide-gray-200"}`}>
{filteredBookings.map((booking) => ( {filteredBookings.map((booking) => (
<tr <tr
key={booking.ID} key={booking.ID}
className="hover:bg-gray-50 transition-colors" className={`transition-colors ${isDark ? "hover:bg-gray-700" : "hover:bg-gray-50"}`}
> >
<td className="px-3 sm:px-4 md:px-6 py-4"> <td className="px-3 sm:px-4 md:px-6 py-4">
<div className="flex items-center"> <div className="flex items-center">
<div className="shrink-0 h-8 w-8 sm:h-10 sm:w-10 rounded-full bg-gray-100 flex items-center justify-center"> <div className={`shrink-0 h-8 w-8 sm:h-10 sm:w-10 rounded-full flex items-center justify-center ${isDark ? "bg-gray-700" : "bg-gray-100"}`}>
<User className="w-4 h-4 sm:w-5 sm:h-5 text-gray-600" /> <User className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? "text-gray-200" : "text-gray-600"}`} />
</div> </div>
<div className="ml-2 sm:ml-4 min-w-0"> <div className="ml-2 sm:ml-4 min-w-0">
<div className="text-xs sm:text-sm font-medium text-gray-900 truncate"> <div className={`text-xs sm:text-sm font-medium truncate ${isDark ? "text-white" : "text-gray-900"}`}>
{booking.user.first_name} {booking.user.last_name} {booking.user.first_name} {booking.user.last_name}
</div> </div>
<div className="text-xs sm:text-sm text-gray-500 truncate hidden sm:block"> <div className={`text-xs sm:text-sm truncate hidden sm:block ${isDark ? "text-gray-400" : "text-gray-500"}`}>
{booking.user.email} {booking.user.email}
</div> </div>
<div className="text-xs text-gray-500 sm:hidden mt-0.5"> <div className={`text-xs sm:hidden mt-0.5 ${isDark ? "text-gray-400" : "text-gray-500"}`}>
{formatDate(booking.scheduled_at)} {formatDate(booking.scheduled_at)}
</div> </div>
</div> </div>
</div> </div>
</td> </td>
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap hidden md:table-cell"> <td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap hidden md:table-cell">
<div className="text-xs sm:text-sm text-gray-900"> <div className={`text-xs sm:text-sm ${isDark ? "text-white" : "text-gray-900"}`}>
{formatDate(booking.scheduled_at)} {formatDate(booking.scheduled_at)}
</div> </div>
<div className="text-xs sm:text-sm text-gray-500 flex items-center gap-1"> <div className={`text-xs sm:text-sm flex items-center gap-1 ${isDark ? "text-gray-400" : "text-gray-500"}`}>
<Clock className="w-3 h-3" /> <Clock className="w-3 h-3" />
{formatTime(booking.scheduled_at)} {formatTime(booking.scheduled_at)}
</div> </div>
</td> </td>
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-xs sm:text-sm text-gray-900 hidden lg:table-cell"> <td className={`px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-xs sm:text-sm hidden lg:table-cell ${isDark ? "text-white" : "text-gray-900"}`}>
{booking.duration} min {booking.duration} min
</td> </td>
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap"> <td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap">
@ -282,7 +315,7 @@ export default function Booking() {
{booking.payment_status} {booking.payment_status}
</span> </span>
</td> </td>
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-xs sm:text-sm font-medium text-gray-900 hidden xl:table-cell"> <td className={`px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-xs sm:text-sm font-medium hidden xl:table-cell ${isDark ? "text-white" : "text-gray-900"}`}>
${booking.amount} ${booking.amount}
</td> </td>
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> <td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
@ -292,7 +325,7 @@ export default function Booking() {
href={booking.jitsi_room_url} href={booking.jitsi_room_url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="p-1.5 sm:p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors" className={`p-1.5 sm:p-2 rounded-lg transition-colors ${isDark ? "text-gray-300 hover:text-white hover:bg-gray-700" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`}
title="Join Meeting" title="Join Meeting"
> >
<Video className="w-4 h-4" /> <Video className="w-4 h-4" />
@ -300,13 +333,13 @@ export default function Booking() {
)} )}
{booking.notes && ( {booking.notes && (
<button <button
className="p-1.5 sm:p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors" className={`p-1.5 sm:p-2 rounded-lg transition-colors ${isDark ? "text-gray-300 hover:text-white hover:bg-gray-700" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`}
title="View Notes" title="View Notes"
> >
<FileText className="w-4 h-4" /> <FileText className="w-4 h-4" />
</button> </button>
)} )}
<button className="p-1.5 sm:p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors"> <button className={`p-1.5 sm:p-2 rounded-lg transition-colors ${isDark ? "text-gray-300 hover:text-white hover:bg-gray-700" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`}>
<MoreVertical className="w-4 h-4" /> <MoreVertical className="w-4 h-4" />
</button> </button>
</div> </div>

View File

@ -19,6 +19,7 @@ import {
ArrowUpRight, ArrowUpRight,
ArrowDownRight, ArrowDownRight,
} from "lucide-react"; } from "lucide-react";
import { useAppTheme } from "@/components/ThemeProvider";
interface DashboardStats { interface DashboardStats {
total_users: number; total_users: number;
@ -35,6 +36,8 @@ export default function Dashboard() {
const [stats, setStats] = useState<DashboardStats | null>(null); const [stats, setStats] = useState<DashboardStats | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [timePeriod, setTimePeriod] = useState<string>("last_month"); const [timePeriod, setTimePeriod] = useState<string>("last_month");
const { theme } = useAppTheme();
const isDark = theme === "dark";
useEffect(() => { useEffect(() => {
// Simulate API call // Simulate API call
@ -122,36 +125,43 @@ export default function Dashboard() {
]; ];
const getTrendClasses = (trendUp: boolean) => {
if (isDark) {
return trendUp ? "bg-green-500/20 text-green-200" : "bg-red-500/20 text-red-200";
}
return trendUp ? "bg-green-50 text-green-700" : "bg-red-50 text-red-700";
};
return ( return (
<div className="min-h-screen bg-gray-50"> <div className={`min-h-screen ${isDark ? "bg-gray-900" : "bg-gray-50"}`}>
{/* Main Content */} {/* Main Content */}
<main className="p-4 sm:p-6 lg:p-8 space-y-6"> <main className="p-4 sm:p-6 lg:p-8 space-y-6">
{/* Welcome Section */} {/* Welcome Section */}
<div className="flex items-center justify-between mb-6"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div> <div>
<h1 className="text-2xl font-semibold text-gray-900 mb-1"> <h1 className={`text-2xl font-semibold mb-1 ${isDark ? "text-white" : "text-gray-900"}`}>
Welcome Back! Hammond Welcome Back! Hammond
</h1> </h1>
<p className="text-sm text-gray-500"> <p className={`text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Here's an overview of your practice today Here's an overview of your practice today
</p> </p>
</div> </div>
<Select value={timePeriod} onValueChange={setTimePeriod}> <Select value={timePeriod} onValueChange={setTimePeriod}>
<SelectTrigger className="w-[180px] cursor-pointer"> <SelectTrigger className={`w-full sm:w-[200px] cursor-pointer ${isDark ? "bg-gray-800 border-gray-700 text-gray-100" : "bg-white border-gray-200 text-gray-900"}`}>
<SelectValue placeholder="Select period" /> <SelectValue placeholder="Select period" />
</SelectTrigger> </SelectTrigger>
<SelectContent className="bg-white cursor-pointer"> <SelectContent className={`${isDark ? "bg-gray-800 border-gray-700 text-gray-100" : "bg-white border-gray-200 text-gray-900"} cursor-pointer`}>
<SelectItem value="last_week">Last Week</SelectItem> <SelectItem className={isDark ? "focus:bg-gray-700" : ""} value="last_week">Last Week</SelectItem>
<SelectItem value="last_month">Last Month</SelectItem> <SelectItem className={isDark ? "focus:bg-gray-700" : ""} value="last_month">Last Month</SelectItem>
<SelectItem value="last_year">Last Year</SelectItem> <SelectItem className={isDark ? "focus:bg-gray-700" : ""} value="last_year">Last Year</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
{loading ? ( {loading ? (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-400"></div> <div className={`animate-spin rounded-full h-8 w-8 border-b-2 ${isDark ? "border-gray-600" : "border-gray-400"}`}></div>
</div> </div>
) : ( ) : (
<> <>
@ -162,17 +172,13 @@ export default function Dashboard() {
return ( return (
<div <div
key={index} key={index}
className="bg-white rounded-lg border border-gray-200 p-4 sm:p-5 md:p-6 hover:shadow-md transition-shadow" className={`rounded-lg border p-4 sm:p-5 md:p-6 hover:shadow-md transition-shadow ${isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}`}
> >
<div className="flex items-start justify-between mb-3 sm:mb-4"> <div className="flex items-start justify-between mb-3 sm:mb-4">
<div className="p-2 sm:p-2.5 rounded-lg bg-gray-50"> <div className={`p-2 sm:p-2.5 rounded-lg ${isDark ? "bg-gray-700" : "bg-gray-50"}`}>
<Icon className="w-4 h-4 sm:w-5 sm:h-5 text-gray-600" /> <Icon className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? "text-gray-200" : "text-gray-600"}`} />
</div> </div>
<div className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${ <div className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${getTrendClasses(card.trendUp)}`}>
card.trendUp
? "bg-green-50 text-green-700"
: "bg-red-50 text-red-700"
}`}>
{card.trendUp ? ( {card.trendUp ? (
<ArrowUpRight className="w-3 h-3" /> <ArrowUpRight className="w-3 h-3" />
) : ( ) : (
@ -183,13 +189,13 @@ export default function Dashboard() {
</div> </div>
<div> <div>
<h3 className="text-xs font-medium text-rose-600 mb-1 sm:mb-2 uppercase tracking-wider"> <h3 className={`text-xs font-medium mb-1 sm:mb-2 uppercase tracking-wider ${isDark ? "text-rose-300" : "text-rose-600"}`}>
{card.title} {card.title}
</h3> </h3>
<p className="text-xl sm:text-2xl font-bold text-gray-900 mb-1"> <p className={`text-xl sm:text-2xl font-bold mb-1 ${isDark ? "text-white" : "text-gray-900"}`}>
{card.value} {card.value}
</p> </p>
<p className="text-xs text-gray-500"> <p className={`text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`}>
vs last month vs last month
</p> </p>
</div> </div>

View File

@ -2,6 +2,7 @@
import { useState } from "react"; import { useState } from "react";
import { Bell } from "lucide-react"; import { Bell } from "lucide-react";
import { useAppTheme } from "@/components/ThemeProvider";
interface Notification { interface Notification {
id: string; id: string;
@ -51,16 +52,18 @@ export default function NotificationsPage() {
]); ]);
const unreadCount = notifications.filter((n) => !n.read).length; const unreadCount = notifications.filter((n) => !n.read).length;
const { theme } = useAppTheme();
const isDark = theme === "dark";
return ( return (
<div className="min-h-screen bg-gray-50"> <div className={`min-h-screen ${isDark ? "bg-gray-900" : "bg-gray-50"}`}>
{/* Main Content */} {/* Main Content */}
<main className="p-3 sm:p-4 md:p-6 lg:p-8"> <main className="p-3 sm:p-4 md:p-6 lg:p-8">
{/* Page Header */} {/* Page Header */}
<div className="mb-4 sm:mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4"> <div className="mb-4 sm:mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Bell className="w-5 h-5 sm:w-6 sm:h-6 text-gray-900" /> <Bell className={`w-5 h-5 sm:w-6 sm:h-6 ${isDark ? "text-white" : "text-gray-900"}`} />
<h1 className="text-xl sm:text-2xl font-semibold text-gray-900"> <h1 className={`text-xl sm:text-2xl font-semibold ${isDark ? "text-white" : "text-gray-900"}`}>
Notifications Notifications
</h1> </h1>
{unreadCount > 0 && ( {unreadCount > 0 && (
@ -72,26 +75,30 @@ export default function NotificationsPage() {
</div> </div>
{/* Notifications List */} {/* Notifications List */}
<div className="bg-white rounded-lg border border-gray-200 overflow-hidden"> <div className={`rounded-lg border overflow-hidden ${isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}`}>
{notifications.length === 0 ? ( {notifications.length === 0 ? (
<div className="p-8 sm:p-12 text-center text-gray-500"> <div className={`p-8 sm:p-12 text-center ${isDark ? "text-gray-400" : "text-gray-500"}`}>
<Bell className="w-12 h-12 mx-auto mb-2 text-gray-300" /> <Bell className={`w-12 h-12 mx-auto mb-2 ${isDark ? "text-gray-600" : "text-gray-300"}`} />
<p className="text-sm">No notifications</p> <p className="text-sm">No notifications</p>
</div> </div>
) : ( ) : (
<div className="divide-y"> <div className={`divide-y ${isDark ? "divide-gray-700" : ""}`}>
{notifications.map((notification) => { {notifications.map((notification) => {
return ( return (
<div <div
key={notification.id} key={notification.id}
className={`p-4 sm:p-6 hover:bg-gray-50 transition-colors cursor-pointer ${ className={`p-4 sm:p-6 transition-colors cursor-pointer ${
!notification.read ? "bg-rose-50/50" : "" !notification.read
? isDark
? "bg-rose-500/10"
: "bg-rose-50/50"
: ""
}`} }`}
> >
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<p <p
className={`text-sm sm:text-base font-medium text-gray-900 ${ className={`text-sm sm:text-base font-medium ${isDark ? "text-white" : "text-gray-900"} ${
!notification.read ? "font-semibold" : "" !notification.read ? "font-semibold" : ""
}`} }`}
> >
@ -101,10 +108,10 @@ export default function NotificationsPage() {
<span className="shrink-0 w-2 h-2 bg-green-500 rounded-full mt-1"></span> <span className="shrink-0 w-2 h-2 bg-green-500 rounded-full mt-1"></span>
)} )}
</div> </div>
<p className="text-sm text-gray-600 mt-1"> <p className={`text-sm mt-1 ${isDark ? "text-gray-400" : "text-gray-600"}`}>
{notification.message} {notification.message}
</p> </p>
<p className="text-xs text-gray-400 mt-1"> <p className={`text-xs mt-1 ${isDark ? "text-gray-500" : "text-gray-400"}`}>
{notification.time} {notification.time}
</p> </p>
</div> </div>

View File

@ -15,6 +15,7 @@ import {
EyeOff, EyeOff,
} from "lucide-react"; } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useAppTheme } from "@/components/ThemeProvider";
export default function AdminSettingsPage() { export default function AdminSettingsPage() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -33,6 +34,8 @@ export default function AdminSettingsPage() {
new: false, new: false,
confirm: false, confirm: false,
}); });
const { theme } = useAppTheme();
const isDark = theme === "dark";
const handleInputChange = (field: string, value: string) => { const handleInputChange = (field: string, value: string) => {
setFormData((prev) => ({ setFormData((prev) => ({
@ -88,22 +91,22 @@ export default function AdminSettingsPage() {
}; };
return ( return (
<div className="min-h-screen bg-gray-50"> <div className={`min-h-screen ${isDark ? "bg-gray-900" : "bg-gray-50"}`}>
{/* Main Content */} {/* Main Content */}
<main className="p-4 sm:p-6 lg:p-8 space-y-6"> <main className="p-4 sm:p-6 lg:p-8 space-y-6">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-6"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link href="/admin/dashboard"> <Link href="/admin/dashboard">
<Button variant="ghost" size="icon" className="hover:bg-gray-100"> <Button variant="ghost" size="icon" className={isDark ? "hover:bg-gray-800 text-gray-300" : "hover:bg-gray-100"}>
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
</Button> </Button>
</Link> </Link>
<div> <div>
<h1 className="text-2xl font-semibold text-gray-900 mb-1"> <h1 className={`text-2xl font-semibold mb-1 ${isDark ? "text-white" : "text-gray-900"}`}>
Settings Settings
</h1> </h1>
<p className="text-sm text-gray-600"> <p className={`text-sm ${isDark ? "text-gray-400" : "text-gray-600"}`}>
Manage your account settings and practice information Manage your account settings and practice information
</p> </p>
</div> </div>
@ -111,7 +114,7 @@ export default function AdminSettingsPage() {
<Button <Button
onClick={handleSave} onClick={handleSave}
disabled={loading} disabled={loading}
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white" className="w-full sm:w-auto bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
> >
{loading ? ( {loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div> <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
@ -125,60 +128,60 @@ export default function AdminSettingsPage() {
<div className="max-w-4xl mx-auto"> <div className="max-w-4xl mx-auto">
<div className="space-y-6"> <div className="space-y-6">
{/* Profile Information */} {/* Profile Information */}
<Card className="bg-white border-gray-200"> <Card className={isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}>
<CardHeader> <CardHeader>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<User className="w-5 h-5 text-gray-600" /> <User className={`w-5 h-5 ${isDark ? "text-gray-300" : "text-gray-600"}`} />
<CardTitle className="text-gray-900">Profile Information</CardTitle> <CardTitle className={isDark ? "text-white" : "text-gray-900"}>Profile Information</CardTitle>
</div> </div>
<CardDescription className="text-gray-600"> <CardDescription className={isDark ? "text-gray-400" : "text-gray-600"}>
Update your personal information and contact details Update your personal information and contact details
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
Full Name Full Name
</label> </label>
<div className="relative"> <div className="relative">
<User className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <User className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type="text" type="text"
value={formData.fullName} value={formData.fullName}
onChange={(e) => handleInputChange("fullName", e.target.value)} onChange={(e) => handleInputChange("fullName", e.target.value)}
className="pl-10" className={`pl-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Enter your full name" placeholder="Enter your full name"
/> />
</div> </div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
Email Address Email Address
</label> </label>
<div className="relative"> <div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Mail className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type="email" type="email"
value={formData.email} value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)} onChange={(e) => handleInputChange("email", e.target.value)}
className="pl-10" className={`pl-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Enter your email" placeholder="Enter your email"
/> />
</div> </div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
Phone Number Phone Number
</label> </label>
<div className="relative"> <div className="relative">
<Phone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Phone className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type="tel" type="tel"
value={formData.phone} value={formData.phone}
onChange={(e) => handleInputChange("phone", e.target.value)} onChange={(e) => handleInputChange("phone", e.target.value)}
className="pl-10" className={`pl-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Enter your phone number" placeholder="Enter your phone number"
/> />
</div> </div>
@ -187,34 +190,34 @@ export default function AdminSettingsPage() {
</Card> </Card>
{/* Change Password */} {/* Change Password */}
<Card className="bg-white border-gray-200"> <Card className={isDark ? "bg-gray-800 border-gray-700" : "bg-white border-gray-200"}>
<CardHeader> <CardHeader>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Lock className="w-5 h-5 text-gray-600" /> <Lock className={`w-5 h-5 ${isDark ? "text-gray-300" : "text-gray-600"}`} />
<CardTitle className="text-gray-900">Change Password</CardTitle> <CardTitle className={isDark ? "text-white" : "text-gray-900"}>Change Password</CardTitle>
</div> </div>
<CardDescription className="text-gray-600"> <CardDescription className={isDark ? "text-gray-400" : "text-gray-600"}>
Update your password to keep your account secure Update your password to keep your account secure
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
Current Password Current Password
</label> </label>
<div className="relative"> <div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Lock className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type={showPasswords.current ? "text" : "password"} type={showPasswords.current ? "text" : "password"}
value={passwordData.currentPassword} value={passwordData.currentPassword}
onChange={(e) => handlePasswordChange("currentPassword", e.target.value)} onChange={(e) => handlePasswordChange("currentPassword", e.target.value)}
className="pl-10 pr-10" className={`pl-10 pr-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Enter your current password" placeholder="Enter your current password"
/> />
<button <button
type="button" type="button"
onClick={() => togglePasswordVisibility("current")} onClick={() => togglePasswordVisibility("current")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600" className={`absolute right-3 top-1/2 transform -translate-y-1/2 ${isDark ? "text-gray-400 hover:text-gray-300" : "text-gray-400 hover:text-gray-600"}`}
> >
{showPasswords.current ? ( {showPasswords.current ? (
<EyeOff className="w-4 h-4" /> <EyeOff className="w-4 h-4" />
@ -226,22 +229,22 @@ export default function AdminSettingsPage() {
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
New Password New Password
</label> </label>
<div className="relative"> <div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Lock className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type={showPasswords.new ? "text" : "password"} type={showPasswords.new ? "text" : "password"}
value={passwordData.newPassword} value={passwordData.newPassword}
onChange={(e) => handlePasswordChange("newPassword", e.target.value)} onChange={(e) => handlePasswordChange("newPassword", e.target.value)}
className="pl-10 pr-10" className={`pl-10 pr-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Enter your new password" placeholder="Enter your new password"
/> />
<button <button
type="button" type="button"
onClick={() => togglePasswordVisibility("new")} onClick={() => togglePasswordVisibility("new")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600" className={`absolute right-3 top-1/2 transform -translate-y-1/2 ${isDark ? "text-gray-400 hover:text-gray-300" : "text-gray-400 hover:text-gray-600"}`}
> >
{showPasswords.new ? ( {showPasswords.new ? (
<EyeOff className="w-4 h-4" /> <EyeOff className="w-4 h-4" />
@ -250,28 +253,28 @@ export default function AdminSettingsPage() {
)} )}
</button> </button>
</div> </div>
<p className="text-xs text-gray-500"> <p className={`text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`}>
Password must be at least 8 characters long Password must be at least 8 characters long
</p> </p>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium text-gray-700"> <label className={`text-sm font-medium ${isDark ? "text-gray-300" : "text-gray-700"}`}>
Confirm New Password Confirm New Password
</label> </label>
<div className="relative"> <div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Lock className={`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 ${isDark ? "text-gray-500" : "text-gray-400"}`} />
<Input <Input
type={showPasswords.confirm ? "text" : "password"} type={showPasswords.confirm ? "text" : "password"}
value={passwordData.confirmPassword} value={passwordData.confirmPassword}
onChange={(e) => handlePasswordChange("confirmPassword", e.target.value)} onChange={(e) => handlePasswordChange("confirmPassword", e.target.value)}
className="pl-10 pr-10" className={`pl-10 pr-10 ${isDark ? "bg-gray-700 border-gray-600 text-white placeholder:text-gray-400" : ""}`}
placeholder="Confirm your new password" placeholder="Confirm your new password"
/> />
<button <button
type="button" type="button"
onClick={() => togglePasswordVisibility("confirm")} onClick={() => togglePasswordVisibility("confirm")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600" className={`absolute right-3 top-1/2 transform -translate-y-1/2 ${isDark ? "text-gray-400 hover:text-gray-300" : "text-gray-400 hover:text-gray-600"}`}
> >
{showPasswords.confirm ? ( {showPasswords.confirm ? (
<EyeOff className="w-4 h-4" /> <EyeOff className="w-4 h-4" />

View File

@ -134,7 +134,7 @@ export default function UserDashboard() {
{/* Main Content */} {/* Main Content */}
<main className="container mx-auto px-4 sm:px-6 lg:px-8 space-y-6 pt-20 sm:pt-24 pb-8"> <main className="container mx-auto px-4 sm:px-6 lg:px-8 space-y-6 pt-20 sm:pt-24 pb-8">
{/* Welcome Section */} {/* Welcome Section */}
<div className="flex items-center justify-between mb-6"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div> <div>
<h1 className={`text-2xl font-semibold mb-1 ${isDark ? 'text-white' : 'text-gray-900'}`}> <h1 className={`text-2xl font-semibold mb-1 ${isDark ? 'text-white' : 'text-gray-900'}`}>
Welcome Back! Welcome Back!
@ -144,18 +144,18 @@ export default function UserDashboard() {
</p> </p>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Link href="/user/settings"> <Link href="/user/settings" className="flex-1 sm:flex-initial">
<Button <Button
variant="outline" variant="outline"
className={isDark ? 'hover:bg-gray-800 border-gray-700 text-gray-300' : 'hover:bg-gray-100'} className={`w-full sm:w-auto ${isDark ? 'hover:bg-gray-800 border-gray-700 text-gray-300' : 'hover:bg-gray-100'}`}
> >
<Settings className="w-4 h-4 mr-2" /> <Settings className="w-4 h-4 mr-2" />
Settings Settings
</Button> </Button>
</Link> </Link>
<Link href="/book-now"> <Link href="/book-now" className="flex-1 sm:flex-initial">
<Button <Button
className="bg-gradient-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white" className="w-full sm:w-auto bg-gradient-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
> >
<CalendarPlus className="w-4 h-4 mr-2" /> <CalendarPlus className="w-4 h-4 mr-2" />
Book Appointment Book Appointment

View File

@ -98,7 +98,7 @@ export default function SettingsPage() {
{/* Main Content */} {/* Main Content */}
<main className="container mx-auto px-4 sm:px-6 lg:px-8 space-y-6 pt-20 sm:pt-24 pb-8"> <main className="container mx-auto px-4 sm:px-6 lg:px-8 space-y-6 pt-20 sm:pt-24 pb-8">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-6"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link href="/user/dashboard"> <Link href="/user/dashboard">
<Button variant="ghost" size="icon" className={isDark ? 'hover:bg-gray-800 text-gray-300' : 'hover:bg-gray-100'}> <Button variant="ghost" size="icon" className={isDark ? 'hover:bg-gray-800 text-gray-300' : 'hover:bg-gray-100'}>
@ -117,7 +117,7 @@ export default function SettingsPage() {
<Button <Button
onClick={handleSave} onClick={handleSave}
disabled={loading} disabled={loading}
className="bg-gradient-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white" className="w-full sm:w-auto bg-gradient-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
> >
{loading ? ( {loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div> <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>