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) {
|
if (serviceMode) {
|
||||||
const fmt = (ts: number) => new Date(ts * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
|
const fmt = (ts: number) => new Date(ts * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
|
||||||
return [...activeByStart.values()]
|
const parseHM = (t: string) => { const [h, m] = (t ?? '00:00').split(':').map(Number); return (h * 3600) + (m * 60); };
|
||||||
.sort((a, b) => Number(a.slot_start) - Number(b.slot_start))
|
const rawSessions: any[] = (slotsQuery.data?.data as any)?.sessions ?? [];
|
||||||
.map(a => {
|
const booked = [...activeByStart.values()].sort((a, b) => Number(a.slot_start) - Number(b.slot_start));
|
||||||
const start = Number(a.slot_start);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
const end = Number(a.slot_end);
|
|
||||||
return {
|
const out: TimelineSlot[] = [];
|
||||||
start, end,
|
// بازهٔ خالیِ قابلرزرو؛ اگر روی «اکنون» بیفتد به اکنون بریده میشود و بازههای
|
||||||
start_time: fmt(start),
|
// کاملاً گذشته حذف میشوند تا فقط زمان قابلرزرو باقی بماند.
|
||||||
end_time: fmt(end),
|
const pushFree = (start: number, end: number) => {
|
||||||
is_available: false,
|
const s = start < now ? now : start;
|
||||||
appointment: a,
|
if (end <= s) return;
|
||||||
cancelled_appointment: null,
|
out.push({ start: s, end, start_time: fmt(s), end_time: fmt(end), is_available: true, appointment: null, cancelled_appointment: null });
|
||||||
} as TimelineSlot;
|
};
|
||||||
|
|
||||||
|
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 ?? [];
|
const rawSessions: any[] = (slotsQuery.data?.data as any)?.sessions ?? [];
|
||||||
|
|||||||
Reference in New Issue
Block a user