Add percentage fields to appointment stats and update dashboard components to display these metrics.
- Introduced new percentage fields in the AppointmentStats and UserAppointmentStats interfaces. - Updated the admin and user dashboard components to include and display percentage metrics for scheduled, completed, pending review, and rejected appointments. - Removed commented-out percentage badges and implemented conditional rendering for displaying percentage values, enhancing the clarity of the dashboard statistics.
This commit is contained in:
parent
d6354d20d0
commit
2eea3bcc1e
@ -39,6 +39,12 @@ interface DashboardStats {
|
||||
active_upcoming_meetings: number;
|
||||
total_revenue: number;
|
||||
monthly_revenue: number;
|
||||
// Percentage fields from API
|
||||
users_pct?: number;
|
||||
scheduled_pct?: number;
|
||||
completed_pct?: number;
|
||||
pending_review_pct?: number;
|
||||
rejected_pct?: number;
|
||||
trends: {
|
||||
total_users: string;
|
||||
active_users: string;
|
||||
@ -133,6 +139,12 @@ export default function Dashboard() {
|
||||
active_upcoming_meetings: activeUpcomingMeetings,
|
||||
total_revenue: totalRevenue,
|
||||
monthly_revenue: monthlyRevenue,
|
||||
// Include percentage fields from API
|
||||
users_pct: appointmentStats?.users_pct,
|
||||
scheduled_pct: appointmentStats?.scheduled_pct,
|
||||
completed_pct: appointmentStats?.completed_pct,
|
||||
pending_review_pct: appointmentStats?.pending_review_pct,
|
||||
rejected_pct: appointmentStats?.rejected_pct,
|
||||
trends,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -148,6 +160,11 @@ export default function Dashboard() {
|
||||
active_upcoming_meetings: 0,
|
||||
total_revenue: 0,
|
||||
monthly_revenue: 0,
|
||||
users_pct: undefined,
|
||||
scheduled_pct: undefined,
|
||||
completed_pct: undefined,
|
||||
pending_review_pct: undefined,
|
||||
rejected_pct: undefined,
|
||||
trends: {
|
||||
total_users: "0%",
|
||||
active_users: "0%",
|
||||
@ -172,7 +189,7 @@ export default function Dashboard() {
|
||||
title: "Total Users",
|
||||
value: stats?.total_users ?? 0,
|
||||
icon: Users,
|
||||
trend: stats?.trends.total_users ?? "0%",
|
||||
trend: stats?.users_pct !== undefined ? `${Math.round(stats.users_pct)}%` : undefined,
|
||||
trendUp: true,
|
||||
},
|
||||
{
|
||||
@ -193,28 +210,28 @@ export default function Dashboard() {
|
||||
title: "Upcoming Bookings",
|
||||
value: stats?.upcoming_bookings ?? 0,
|
||||
icon: CalendarCheck,
|
||||
trend: stats?.trends.upcoming_bookings ?? "0",
|
||||
trend: stats?.scheduled_pct !== undefined ? `${Math.round(stats.scheduled_pct)}%` : undefined,
|
||||
trendUp: true,
|
||||
},
|
||||
{
|
||||
title: "Completed Bookings",
|
||||
value: stats?.completed_bookings ?? 0,
|
||||
icon: CalendarCheck,
|
||||
trend: stats?.trends.completed_bookings ?? "0%",
|
||||
trend: stats?.completed_pct !== undefined ? `${Math.round(stats.completed_pct)}%` : undefined,
|
||||
trendUp: true,
|
||||
},
|
||||
{
|
||||
title: "Cancelled Bookings",
|
||||
value: stats?.cancelled_bookings ?? 0,
|
||||
icon: CalendarX,
|
||||
trend: stats?.trends.cancelled_bookings ?? "0%",
|
||||
trend: stats?.rejected_pct !== undefined ? `${Math.round(stats.rejected_pct)}%` : undefined,
|
||||
trendUp: false,
|
||||
},
|
||||
{
|
||||
title: "Active Upcoming Meetings",
|
||||
value: stats?.active_upcoming_meetings ?? 0,
|
||||
icon: CalendarCheck,
|
||||
trend: "0",
|
||||
trend: undefined,
|
||||
trendUp: true,
|
||||
},
|
||||
];
|
||||
@ -284,8 +301,7 @@ export default function Dashboard() {
|
||||
<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 ${isDark ? "text-gray-200" : "text-gray-600"}`} />
|
||||
</div>
|
||||
{/* Percentage badge commented out */}
|
||||
{/* {card.trend && (
|
||||
{card.trend && (
|
||||
<div className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${getTrendClasses(card.trendUp)}`}>
|
||||
{card.trendUp ? (
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
@ -294,7 +310,7 @@ export default function Dashboard() {
|
||||
)}
|
||||
<span className="hidden sm:inline">{card.trend}</span>
|
||||
</div>
|
||||
)} */}
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@ -146,9 +146,13 @@ export default function UserDashboard() {
|
||||
if (stats) {
|
||||
return {
|
||||
scheduled: stats.scheduled || 0,
|
||||
scheduled_pct: stats.scheduled_pct,
|
||||
completed: stats.completed || 0,
|
||||
completed_pct: stats.completed_pct,
|
||||
pending_review: stats.pending_review || 0,
|
||||
pending_review_pct: stats.pending_review_pct,
|
||||
rejected: stats.rejected || 0,
|
||||
rejected_pct: stats.rejected_pct,
|
||||
total_requests: stats.total_requests || 0,
|
||||
completion_rate: stats.completion_rate || 0,
|
||||
};
|
||||
@ -223,13 +227,14 @@ export default function UserDashboard() {
|
||||
<div className={`p-2 sm:p-2.5 rounded-lg ${isDark ? 'bg-gray-700' : 'bg-gray-50'}`}>
|
||||
<CalendarCheck className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? 'text-gray-400' : 'text-gray-600'}`} />
|
||||
</div>
|
||||
{/* Percentage badge commented out */}
|
||||
{/* <div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-green-900/30 text-green-400" : "bg-green-50 text-green-700"}`}
|
||||
>
|
||||
{displayStats.scheduled_pct !== undefined && (
|
||||
<div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-green-900/30 text-green-400" : "bg-green-50 text-green-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{displayStats.scheduled > 0 ? `+${displayStats.scheduled}` : "0"}</span>
|
||||
</div> */}
|
||||
<span>{`${Math.round(displayStats.scheduled_pct)}%`}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className={`text-xs font-medium mb-1 sm:mb-2 uppercase tracking-wider ${isDark ? 'text-rose-400' : 'text-rose-600'}`}>
|
||||
@ -248,13 +253,14 @@ export default function UserDashboard() {
|
||||
<div className={`p-2 sm:p-2.5 rounded-lg ${isDark ? 'bg-gray-700' : 'bg-gray-50'}`}>
|
||||
<CheckCircle2 className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? 'text-gray-400' : 'text-gray-600'}`} />
|
||||
</div>
|
||||
{/* Percentage badge commented out */}
|
||||
{/* <div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-green-900/30 text-green-400" : "bg-green-50 text-green-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{displayStats.completed > 0 ? `+${displayStats.completed}` : "0"}</span>
|
||||
</div> */}
|
||||
{displayStats.completed_pct !== undefined && (
|
||||
<div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-green-900/30 text-green-400" : "bg-green-50 text-green-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{`${Math.round(displayStats.completed_pct)}%`}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className={`text-xs font-medium mb-1 sm:mb-2 uppercase tracking-wider ${isDark ? 'text-rose-400' : 'text-rose-600'}`}>
|
||||
@ -273,13 +279,7 @@ export default function UserDashboard() {
|
||||
<div className={`p-2 sm:p-2.5 rounded-lg ${isDark ? 'bg-gray-700' : 'bg-gray-50'}`}>
|
||||
<Calendar className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? 'text-gray-400' : 'text-gray-600'}`} />
|
||||
</div>
|
||||
{/* Percentage badge commented out */}
|
||||
{/* <div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-green-900/30 text-green-400" : "bg-green-50 text-green-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{`${Math.round(displayStats.completion_rate || 0)}%`}</span>
|
||||
</div> */}
|
||||
{/* No percentage badge for total appointments */}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className={`text-xs font-medium mb-1 sm:mb-2 uppercase tracking-wider ${isDark ? 'text-rose-400' : 'text-rose-600'}`}>
|
||||
@ -298,13 +298,14 @@ export default function UserDashboard() {
|
||||
<div className={`p-2 sm:p-2.5 rounded-lg ${isDark ? 'bg-gray-700' : 'bg-gray-50'}`}>
|
||||
<Calendar className={`w-4 h-4 sm:w-5 sm:h-5 ${isDark ? 'text-gray-400' : 'text-gray-600'}`} />
|
||||
</div>
|
||||
{/* Percentage badge commented out */}
|
||||
{/* <div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-red-900/30 text-red-400" : "bg-red-50 text-red-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{displayStats.pending_review > 0 ? `${displayStats.pending_review}` : "0"}</span>
|
||||
</div> */}
|
||||
{displayStats.pending_review_pct !== undefined && (
|
||||
<div
|
||||
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium ${isDark ? "bg-yellow-900/30 text-yellow-400" : "bg-yellow-50 text-yellow-700"}`}
|
||||
>
|
||||
<ArrowUpRight className="w-3 h-3" />
|
||||
<span>{`${Math.round(displayStats.pending_review_pct)}%`}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className={`text-xs font-medium mb-1 sm:mb-2 uppercase tracking-wider ${isDark ? 'text-rose-400' : 'text-rose-600'}`}>
|
||||
|
||||
@ -140,24 +140,36 @@ export interface MatchingAvailability {
|
||||
export interface AppointmentStats {
|
||||
total_requests: number;
|
||||
pending_review: number;
|
||||
pending_review_pct?: number;
|
||||
scheduled: number;
|
||||
scheduled_pct?: number;
|
||||
rejected: number;
|
||||
rejected_pct?: number;
|
||||
completed: number;
|
||||
completed_pct?: number;
|
||||
completion_rate: number;
|
||||
users?: number; // Total users count from API
|
||||
users_pct?: number;
|
||||
active_upcoming_meetings?: number;
|
||||
availability_coverage?: number;
|
||||
availability_coverage_pct?: number;
|
||||
available_days_count?: number;
|
||||
jitsi_meetings_created?: number;
|
||||
meetings_with_video?: number;
|
||||
meetings_with_video_pct?: number;
|
||||
video_meetings?: number;
|
||||
}
|
||||
|
||||
export interface UserAppointmentStats {
|
||||
total_requests: number;
|
||||
pending_review: number;
|
||||
pending_review_pct?: number;
|
||||
scheduled: number;
|
||||
scheduled_pct?: number;
|
||||
rejected: number;
|
||||
rejected_pct?: number;
|
||||
completed: number;
|
||||
completed_pct?: number;
|
||||
completion_rate: number;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user