From 97b04e7593fcc4c8e7ca93dc8faed6b3c6cdb828 Mon Sep 17 00:00:00 2001 From: iamkiddy Date: Thu, 4 Dec 2025 10:48:14 +0000 Subject: [PATCH] Refactor appointment detail and booking components to implement time slot sorting by predefined order. Enhance the display of selected slots by grouping and sorting them by date and time, improving clarity and user experience across admin and user interfaces. --- app/(admin)/admin/booking/[id]/page.tsx | 75 ++++++++++++++-------- app/(pages)/book-now/page.tsx | 56 ++++++++-------- app/(user)/user/appointments/[id]/page.tsx | 75 ++++++++++++++-------- 3 files changed, 123 insertions(+), 83 deletions(-) diff --git a/app/(admin)/admin/booking/[id]/page.tsx b/app/(admin)/admin/booking/[id]/page.tsx index 17bdc38..36b531d 100644 --- a/app/(admin)/admin/booking/[id]/page.tsx +++ b/app/(admin)/admin/booking/[id]/page.tsx @@ -413,6 +413,13 @@ export default function AppointmentDetailPage() { evening: "Evening", }; + // Time slot order: morning, afternoon (lunchtime), evening + const timeSlotOrder: Record = { + morning: 0, + afternoon: 1, + evening: 2, + }; + // Group slots by date const slotsByDate: Record = {}; appointment.selected_slots.forEach((slot: any) => { @@ -423,36 +430,52 @@ export default function AppointmentDetailPage() { slotsByDate[date].push(slot); }); + // Sort dates and slots within each date + const sortedDates = Object.keys(slotsByDate).sort((a, b) => { + return new Date(a).getTime() - new Date(b).getTime(); + }); + return (
- {Object.entries(slotsByDate).map(([date, slots]) => ( -
-
-

- {formatShortDate(date)} -

- {slots.length > 0 && slots[0]?.day !== undefined && ( -

- {dayNames[slots[0].day] || `Day ${slots[0].day}`} + {sortedDates.map((date) => { + // Sort slots within this date by time slot order + const slots = slotsByDate[date].sort((a: any, b: any) => { + const aSlot = String(a.time_slot).toLowerCase().trim(); + const bSlot = String(b.time_slot).toLowerCase().trim(); + const aOrder = timeSlotOrder[aSlot] ?? 999; + const bOrder = timeSlotOrder[bSlot] ?? 999; + return aOrder - bOrder; + }); + + return ( +

+
+

+ {formatShortDate(date)}

- )} + {slots.length > 0 && slots[0]?.day !== undefined && ( +

+ {dayNames[slots[0].day] || `Day ${slots[0].day}`} +

+ )} +
+
+ {slots.map((slot: any, idx: number) => { + const timeSlot = String(slot.time_slot).toLowerCase().trim(); + const timeLabel = timeSlotLabels[timeSlot] || slot.time_slot; + return ( + + {timeLabel} + + ); + })} +
-
- {slots.map((slot: any, idx: number) => { - const timeSlot = String(slot.time_slot).toLowerCase().trim(); - const timeLabel = timeSlotLabels[timeSlot] || slot.time_slot; - return ( - - {timeLabel} - - ); - })} -
-
- ))} + ); + })}
); })()} diff --git a/app/(pages)/book-now/page.tsx b/app/(pages)/book-now/page.tsx index cb3656c..e75c0cf 100644 --- a/app/(pages)/book-now/page.tsx +++ b/app/(pages)/book-now/page.tsx @@ -154,12 +154,23 @@ export default function BookNowPage() { } }); - // Convert Map values to array and sort by day number + // Time slot order: morning, afternoon (lunchtime), evening + const timeSlotOrder: Record = { + morning: 0, + afternoon: 1, + evening: 2, + }; + + // Convert Map values to array, sort slots, and sort by day number return Array.from(dayMap.values()) .map(day => ({ day: day.day, dayName: day.dayName, - availableSlots: Array.from(day.availableSlots), + availableSlots: Array.from(day.availableSlots).sort((a, b) => { + const aOrder = timeSlotOrder[a.toLowerCase().trim()] ?? 999; + const bOrder = timeSlotOrder[b.toLowerCase().trim()] ?? 999; + return aOrder - bOrder; + }), })) .sort((a, b) => a.day - b.day); } @@ -172,6 +183,13 @@ export default function BookNowPage() { : (weeklyAvailability as any)?.week; if (weekArray && Array.isArray(weekArray)) { + // Time slot order: morning, afternoon (lunchtime), evening + const timeSlotOrder: Record = { + morning: 0, + afternoon: 1, + evening: 2, + }; + return weekArray .filter(day => { const dayNum = Number(day.day); @@ -186,7 +204,11 @@ export default function BookNowPage() { .map(day => ({ day: Number(day.day), dayName: day.day_name || 'Unknown', - availableSlots: day.available_slots || [], + availableSlots: (day.available_slots || []).sort((a: string, b: string) => { + const aOrder = timeSlotOrder[String(a).toLowerCase().trim()] ?? 999; + const bOrder = timeSlotOrder[String(b).toLowerCase().trim()] ?? 999; + return aOrder - bOrder; + }), })) .sort((a, b) => a.day - b.day); } @@ -752,34 +774,6 @@ export default function BookNowPage() {

Select one or more day-time combinations that work for you. You can select multiple time slots for the same day (e.g., Monday Morning and Monday Evening).

- {/* Selected Slots Summary */} - {formData.selectedSlots && formData.selectedSlots.length > 0 && ( -
-

- Selected: {formData.selectedSlots.length} time slot{formData.selectedSlots.length !== 1 ? 's' : ''} -

-
- {formData.selectedSlots.map((slot, idx) => { - const dayNames = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; - const timeSlotLabels: Record = { - morning: "Morning", - afternoon: "Lunchtime", - evening: "Evening", - }; - const dayName = dayNames[slot.day] || `Day ${slot.day}`; - const timeLabel = timeSlotLabels[String(slot.time_slot).toLowerCase()] || slot.time_slot; - return ( - - {dayName} {timeLabel} - - ); - })} -
-
- )}
{availableDaysOfWeek.map((dayInfo, dayIndex) => { // Ensure day is always a valid number (already validated in useMemo) diff --git a/app/(user)/user/appointments/[id]/page.tsx b/app/(user)/user/appointments/[id]/page.tsx index 35622a2..1064e87 100644 --- a/app/(user)/user/appointments/[id]/page.tsx +++ b/app/(user)/user/appointments/[id]/page.tsx @@ -352,6 +352,13 @@ export default function UserAppointmentDetailPage() { evening: "Evening", }; + // Time slot order: morning, afternoon (lunchtime), evening + const timeSlotOrder: Record = { + morning: 0, + afternoon: 1, + evening: 2, + }; + // Group slots by date const slotsByDate: Record = {}; appointment.selected_slots.forEach((slot: any) => { @@ -362,36 +369,52 @@ export default function UserAppointmentDetailPage() { slotsByDate[date].push(slot); }); + // Sort dates and slots within each date + const sortedDates = Object.keys(slotsByDate).sort((a, b) => { + return new Date(a).getTime() - new Date(b).getTime(); + }); + return (
- {Object.entries(slotsByDate).map(([date, slots]) => ( -
-
-

- {formatShortDate(date)} -

- {slots.length > 0 && slots[0]?.day !== undefined && ( -

- {dayNames[slots[0].day] || `Day ${slots[0].day}`} + {sortedDates.map((date) => { + // Sort slots within this date by time slot order + const slots = slotsByDate[date].sort((a: any, b: any) => { + const aSlot = String(a.time_slot).toLowerCase().trim(); + const bSlot = String(b.time_slot).toLowerCase().trim(); + const aOrder = timeSlotOrder[aSlot] ?? 999; + const bOrder = timeSlotOrder[bSlot] ?? 999; + return aOrder - bOrder; + }); + + return ( +

+
+

+ {formatShortDate(date)}

- )} + {slots.length > 0 && slots[0]?.day !== undefined && ( +

+ {dayNames[slots[0].day] || `Day ${slots[0].day}`} +

+ )} +
+
+ {slots.map((slot: any, idx: number) => { + const timeSlot = String(slot.time_slot).toLowerCase().trim(); + const timeLabel = timeSlotLabels[timeSlot] || slot.time_slot; + return ( + + {timeLabel} + + ); + })} +
-
- {slots.map((slot: any, idx: number) => { - const timeSlot = String(slot.time_slot).toLowerCase().trim(); - const timeLabel = timeSlotLabels[timeSlot] || slot.time_slot; - return ( - - {timeLabel} - - ); - })} -
-
- ))} + ); + })}
); })()}