feat(appointment): enhance service mode to display available booking slots between appointments
This commit is contained in:
@@ -429,24 +429,45 @@ export default function AppointmentsPage() {
|
||||
}
|
||||
});
|
||||
|
||||
// حالت سرویسی: اسلات ثابت وجود ندارد — تایملاین از خودِ نوبتهای رزروشده
|
||||
// (با مدت واقعی) ساخته میشود، مرتب بر اساس زمان شروع.
|
||||
// حالت سرویسی: اسلات ثابت وجود ندارد — برای هر شیفتِ کاری، نوبتهای رزروشده
|
||||
// نمایش داده میشوند و باقیِ زمان بهصورت بازه(های) خالیِ قابلرزرو بین آنها.
|
||||
if (serviceMode) {
|
||||
const fmt = (ts: number) => new Date(ts * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
|
||||
return [...activeByStart.values()]
|
||||
.sort((a, b) => Number(a.slot_start) - Number(b.slot_start))
|
||||
.map(a => {
|
||||
const start = Number(a.slot_start);
|
||||
const end = Number(a.slot_end);
|
||||
return {
|
||||
start, end,
|
||||
start_time: fmt(start),
|
||||
end_time: fmt(end),
|
||||
is_available: false,
|
||||
appointment: a,
|
||||
cancelled_appointment: null,
|
||||
} as TimelineSlot;
|
||||
const parseHM = (t: string) => { const [h, m] = (t ?? '00:00').split(':').map(Number); return (h * 3600) + (m * 60); };
|
||||
const rawSessions: any[] = (slotsQuery.data?.data as any)?.sessions ?? [];
|
||||
const booked = [...activeByStart.values()].sort((a, b) => Number(a.slot_start) - Number(b.slot_start));
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
const out: TimelineSlot[] = [];
|
||||
// بازهٔ خالیِ قابلرزرو؛ اگر روی «اکنون» بیفتد به اکنون بریده میشود و بازههای
|
||||
// کاملاً گذشته حذف میشوند تا فقط زمان قابلرزرو باقی بماند.
|
||||
const pushFree = (start: number, end: number) => {
|
||||
const s = start < now ? now : start;
|
||||
if (end <= s) return;
|
||||
out.push({ start: s, end, start_time: fmt(s), end_time: fmt(end), is_available: true, appointment: null, cancelled_appointment: null });
|
||||
};
|
||||
|
||||
rawSessions.forEach((session: any) => {
|
||||
const slots = (session.slots as any[]) ?? [];
|
||||
if (!slots.length) return;
|
||||
const dayStart = Number(slots[0].start) - parseHM(session.start_time);
|
||||
const winStart = dayStart + parseHM(session.start_time);
|
||||
const winEnd = dayStart + parseHM(session.end_time);
|
||||
|
||||
const inWin = booked.filter(a => Number(a.slot_start) >= winStart && Number(a.slot_start) < winEnd);
|
||||
let cursor = winStart;
|
||||
inWin.forEach(a => {
|
||||
const s = Number(a.slot_start), e = Number(a.slot_end);
|
||||
if (s > cursor) pushFree(cursor, s);
|
||||
out.push({
|
||||
start: s, end: e, start_time: fmt(s), end_time: fmt(e),
|
||||
is_available: false, appointment: a, cancelled_appointment: null,
|
||||
});
|
||||
cursor = Math.max(cursor, e);
|
||||
});
|
||||
if (cursor < winEnd) pushFree(cursor, winEnd);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
const rawSessions: any[] = (slotsQuery.data?.data as any)?.sessions ?? [];
|
||||
|
||||
Reference in New Issue
Block a user