feat(appointment): enhance service mode to display available booking slots between appointments

This commit is contained in:
hamed
2026-07-16 00:16:37 +03:30
parent 4715649fd8
commit 8cd1253b81
+36 -15
View File
@@ -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 ?? [];