"use client";
import { useMemo } from "react";
import { Button } from "@/components/ui/button";
import {
Calendar,
Clock,
User,
Mail,
Phone,
Heart,
CalendarPlus,
Video,
CheckCircle2,
XCircle,
CalendarCheck,
ArrowUpRight,
Settings,
Loader2,
} from "lucide-react";
import Link from "next/link";
import { Navbar } from "@/components/Navbar";
import { useAppTheme } from "@/components/ThemeProvider";
import { useAppointments } from "@/hooks/useAppointments";
import { useAuth } from "@/hooks/useAuth";
import type { Appointment } from "@/lib/models/appointments";
import { toast } from "sonner";
export default function UserDashboard() {
const { theme } = useAppTheme();
const isDark = theme === "dark";
const { user } = useAuth();
const {
userAppointments,
userAppointmentStats,
isLoadingUserAppointments,
isLoadingUserStats,
refetchUserAppointments,
refetchUserStats,
} = useAppointments();
const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
});
};
const formatTime = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});
};
const formatMemberSince = (dateString?: string) => {
if (!dateString) return "N/A";
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
});
};
// Filter appointments by status
const upcomingAppointments = useMemo(() => {
return userAppointments.filter(
(appointment) => appointment.status === "scheduled"
);
}, [userAppointments]);
const completedAppointments = useMemo(() => {
return userAppointments.filter(
(appointment) => appointment.status === "completed"
);
}, [userAppointments]);
const stats = userAppointmentStats || {
total_requests: 0,
pending_review: 0,
scheduled: 0,
rejected: 0,
completed: 0,
completion_rate: 0,
};
const statCards = [
{
title: "Upcoming Appointments",
value: stats.scheduled,
icon: CalendarCheck,
trend: stats.scheduled > 0 ? `+${stats.scheduled}` : "0",
trendUp: true,
},
{
title: "Completed Sessions",
value: stats.completed || 0,
icon: CheckCircle2,
trend: stats.completed > 0 ? `+${stats.completed}` : "0",
trendUp: true,
},
{
title: "Total Appointments",
value: stats.total_requests,
icon: Calendar,
trend: `${Math.round(stats.completion_rate || 0)}%`,
trendUp: true,
},
{
title: "Pending Review",
value: stats.pending_review,
icon: Calendar,
trend: stats.pending_review > 0 ? `${stats.pending_review}` : "0",
trendUp: false,
},
];
const loading = isLoadingUserAppointments || isLoadingUserStats;
return (
{/* Main Content */}
{/* Welcome Section */}
Welcome Back!
Here's an overview of your appointments
{loading ? (
) : (
<>
{/* Stats Grid */}
{statCards.map((card, index) => {
const Icon = card.icon;
return (
{card.trendUp ? (
) : (
)}
{card.trend}
{card.title}
{card.value}
vs last month
);
})}
{/* Upcoming Appointments Section */}
{upcomingAppointments.length > 0 ? (
Upcoming Appointments
{upcomingAppointments.map((appointment) => (
{appointment.scheduled_datetime && (
<>
{formatDate(appointment.scheduled_datetime)}
{formatTime(appointment.scheduled_datetime)}
{appointment.scheduled_duration && (
({appointment.scheduled_duration} minutes)
)}
>
)}
{appointment.reason && (
{appointment.reason}
)}
{appointment.status.charAt(0).toUpperCase() +
appointment.status.slice(1).replace('_', ' ')}
{appointment.jitsi_meet_url && appointment.can_join_meeting && (
Join Session
)}
))}
) : !loading && (
No Upcoming Appointments
You don't have any scheduled appointments yet. Book an appointment to get started.
)}
{/* Account Information */}
{user && (
Account Information
Full Name
{user.first_name} {user.last_name}
{user.phone_number && (
Phone
{user.phone_number}
)}
{user.date_joined && (
Member Since
{formatMemberSince(user.date_joined)}
)}
)}
>
)}
);
}