payload-reserve 1.3.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +185 -4
- package/dist/collections/Reservations.js +47 -2
- package/dist/collections/Reservations.js.map +1 -1
- package/dist/collections/Resources.d.ts +16 -0
- package/dist/collections/Resources.js +35 -10
- package/dist/collections/Resources.js.map +1 -1
- package/dist/collections/Schedules.js +34 -0
- package/dist/collections/Schedules.js.map +1 -1
- package/dist/collections/Services.js +34 -1
- package/dist/collections/Services.js.map +1 -1
- package/dist/components/AvailabilityTimeField/AvailabilityTimeField.module.css +7 -0
- package/dist/components/AvailabilityTimeField/index.d.ts +2 -0
- package/dist/components/AvailabilityTimeField/index.js +109 -0
- package/dist/components/AvailabilityTimeField/index.js.map +1 -0
- package/dist/components/CalendarView/CalendarView.module.css +114 -0
- package/dist/components/CalendarView/LaneTimelineView.d.ts +12 -0
- package/dist/components/CalendarView/LaneTimelineView.js +116 -0
- package/dist/components/CalendarView/LaneTimelineView.js.map +1 -0
- package/dist/components/CalendarView/index.js +224 -22
- package/dist/components/CalendarView/index.js.map +1 -1
- package/dist/components/CalendarView/useResourceAvailability.d.ts +9 -0
- package/dist/components/CalendarView/useResourceAvailability.js +40 -0
- package/dist/components/CalendarView/useResourceAvailability.js.map +1 -0
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.js +53 -0
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/cancelBooking.js +34 -21
- package/dist/endpoints/cancelBooking.js.map +1 -1
- package/dist/endpoints/checkAvailability.js +16 -1
- package/dist/endpoints/checkAvailability.js.map +1 -1
- package/dist/endpoints/createBooking.js +4 -1
- package/dist/endpoints/createBooking.js.map +1 -1
- package/dist/endpoints/customerSearch.js +24 -5
- package/dist/endpoints/customerSearch.js.map +1 -1
- package/dist/endpoints/getSlots.js +16 -1
- package/dist/endpoints/getSlots.js.map +1 -1
- package/dist/endpoints/resourceAvailability.d.ts +43 -0
- package/dist/endpoints/resourceAvailability.js +214 -0
- package/dist/endpoints/resourceAvailability.js.map +1 -0
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.js +1 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/hooks/reservations/calculateEndTime.js +21 -1
- package/dist/hooks/reservations/calculateEndTime.js.map +1 -1
- package/dist/hooks/reservations/expandRequiredResources.d.ts +9 -0
- package/dist/hooks/reservations/expandRequiredResources.js +81 -0
- package/dist/hooks/reservations/expandRequiredResources.js.map +1 -0
- package/dist/hooks/reservations/validateGuestBooking.d.ts +3 -0
- package/dist/hooks/reservations/validateGuestBooking.js +93 -0
- package/dist/hooks/reservations/validateGuestBooking.js.map +1 -0
- package/dist/hooks/reservations/validateStatusTransition.js +4 -2
- package/dist/hooks/reservations/validateStatusTransition.js.map +1 -1
- package/dist/hooks/users/provisionStaffResource.d.ts +15 -0
- package/dist/hooks/users/provisionStaffResource.js +88 -0
- package/dist/hooks/users/provisionStaffResource.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +28 -3
- package/dist/plugin.js.map +1 -1
- package/dist/services/AvailabilityService.d.ts +7 -6
- package/dist/services/AvailabilityService.js +86 -60
- package/dist/services/AvailabilityService.js.map +1 -1
- package/dist/translations/ar.json +156 -0
- package/dist/translations/de.json +156 -0
- package/dist/translations/en.json +32 -1
- package/dist/translations/es.json +156 -0
- package/dist/translations/fa.json +156 -0
- package/dist/translations/fr.json +156 -0
- package/dist/translations/hi.json +156 -0
- package/dist/translations/id.json +156 -0
- package/dist/translations/index.js +44 -0
- package/dist/translations/index.js.map +1 -1
- package/dist/translations/pl.json +156 -0
- package/dist/translations/ru.json +156 -0
- package/dist/translations/tr.json +156 -0
- package/dist/translations/zh.json +156 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.js.map +1 -1
- package/dist/utilities/computeSlotStates.d.ts +39 -0
- package/dist/utilities/computeSlotStates.js +49 -0
- package/dist/utilities/computeSlotStates.js.map +1 -0
- package/dist/utilities/guestBooking.d.ts +10 -0
- package/dist/utilities/guestBooking.js +16 -0
- package/dist/utilities/guestBooking.js.map +1 -0
- package/dist/utilities/resolveRequiredResources.d.ts +8 -0
- package/dist/utilities/resolveRequiredResources.js +27 -0
- package/dist/utilities/resolveRequiredResources.js.map +1 -0
- package/dist/utilities/resolveReservationItems.d.ts +3 -2
- package/dist/utilities/resolveReservationItems.js +19 -6
- package/dist/utilities/resolveReservationItems.js.map +1 -1
- package/dist/utilities/scheduleUtils.d.ts +3 -0
- package/dist/utilities/scheduleUtils.js +5 -3
- package/dist/utilities/scheduleUtils.js.map +1 -1
- package/dist/utilities/selectOptions.d.ts +8 -0
- package/dist/utilities/selectOptions.js +11 -0
- package/dist/utilities/selectOptions.js.map +1 -0
- package/dist/utilities/slotUtils.d.ts +19 -0
- package/dist/utilities/slotUtils.js +28 -0
- package/dist/utilities/slotUtils.js.map +1 -1
- package/dist/utilities/userRoles.d.ts +20 -0
- package/dist/utilities/userRoles.js +32 -0
- package/dist/utilities/userRoles.js.map +1 -0
- package/package.json +2 -1
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useConfig, useDocumentDrawer, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import { computeSlotStates } from '../../utilities/computeSlotStates.js';
|
|
5
6
|
import { statusToI18nKey } from '../../utilities/i18nUtils.js';
|
|
7
|
+
import { localDayKey } from '../../utilities/slotUtils.js';
|
|
6
8
|
import styles from './CalendarView.module.css';
|
|
9
|
+
import { LaneTimelineView } from './LaneTimelineView.js';
|
|
10
|
+
import { useResourceAvailability } from './useResourceAvailability.js';
|
|
7
11
|
// Built-in status → CSS class map (for known statuses; custom statuses use inline style)
|
|
8
12
|
const STATUS_CLASS_MAP = {
|
|
9
13
|
cancelled: styles.statusCancelled,
|
|
@@ -35,6 +39,7 @@ export const CalendarView = ()=>{
|
|
|
35
39
|
const slugs = config.admin?.custom?.reservationSlugs;
|
|
36
40
|
const reservationSlug = slugs?.reservations ?? 'reservations';
|
|
37
41
|
const apiUrl = `${config.serverURL ?? ''}${config.routes.api}/${reservationSlug}`;
|
|
42
|
+
const apiBase = `${config.serverURL ?? ''}${config.routes.api}`;
|
|
38
43
|
const statusMachine = config.admin?.custom?.reservationStatusMachine;
|
|
39
44
|
// The initial/pending status (what "pending" view shows)
|
|
40
45
|
const defaultStatus = statusMachine?.defaultStatus ?? 'pending';
|
|
@@ -173,6 +178,8 @@ export const CalendarView = ()=>{
|
|
|
173
178
|
currentDate,
|
|
174
179
|
viewMode
|
|
175
180
|
]);
|
|
181
|
+
// Availability data for the selected resource (null when no resource selected — grid unshaded)
|
|
182
|
+
const { data: availability } = useResourceAvailability(apiBase, selectedResourceId || undefined, rangeStart, rangeEnd);
|
|
176
183
|
const fetchReservations = useCallback(async ()=>{
|
|
177
184
|
setLoading(true);
|
|
178
185
|
try {
|
|
@@ -453,6 +460,28 @@ export const CalendarView = ()=>{
|
|
|
453
460
|
});
|
|
454
461
|
pendingDrawerOpen.current = true;
|
|
455
462
|
}, []);
|
|
463
|
+
// Click-to-book: open new-reservation drawer pre-filled with startTime + optional resource
|
|
464
|
+
const handleSlotClick = useCallback((startIso)=>{
|
|
465
|
+
setDrawerDocId(null);
|
|
466
|
+
setInitialData({
|
|
467
|
+
...selectedResourceId ? {
|
|
468
|
+
resource: selectedResourceId
|
|
469
|
+
} : {},
|
|
470
|
+
startTime: startIso
|
|
471
|
+
});
|
|
472
|
+
pendingDrawerOpen.current = true;
|
|
473
|
+
}, [
|
|
474
|
+
selectedResourceId
|
|
475
|
+
]);
|
|
476
|
+
// Lane-specific book: pre-fills both the specific resource and startTime
|
|
477
|
+
const handleLaneBook = useCallback((resourceId, startIso)=>{
|
|
478
|
+
setDrawerDocId(null);
|
|
479
|
+
setInitialData({
|
|
480
|
+
resource: resourceId,
|
|
481
|
+
startTime: startIso
|
|
482
|
+
});
|
|
483
|
+
pendingDrawerOpen.current = true;
|
|
484
|
+
}, []);
|
|
456
485
|
const openDocDrawer = useCallback((id)=>{
|
|
457
486
|
setDrawerDocId(id);
|
|
458
487
|
setInitialData(undefined);
|
|
@@ -466,6 +495,7 @@ export const CalendarView = ()=>{
|
|
|
466
495
|
} else if (viewMode === 'week') {
|
|
467
496
|
next.setDate(next.getDate() + 7 * direction);
|
|
468
497
|
} else {
|
|
498
|
+
// day, lanes: step one day at a time
|
|
469
499
|
next.setDate(next.getDate() + direction);
|
|
470
500
|
}
|
|
471
501
|
return next;
|
|
@@ -556,15 +586,28 @@ export const CalendarView = ()=>{
|
|
|
556
586
|
const inlineStyle = cssClass ? undefined : {
|
|
557
587
|
background: color
|
|
558
588
|
};
|
|
559
|
-
|
|
560
|
-
|
|
589
|
+
const hasItems = Array.isArray(r.items) && r.items.length > 0;
|
|
590
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
591
|
+
className: `${styles.eventItem} ${cssClass} ${hasItems && !compact ? styles.eventItemExpanded : ''}`,
|
|
561
592
|
onClick: (e)=>handleEventClick(e, r.id),
|
|
562
593
|
onKeyDown: (e)=>handleEventKeyDown(e, r.id),
|
|
563
594
|
role: "button",
|
|
564
595
|
style: inlineStyle,
|
|
565
596
|
tabIndex: 0,
|
|
566
597
|
title: getEventTooltip(r),
|
|
567
|
-
children:
|
|
598
|
+
children: [
|
|
599
|
+
getEventLabel(r, compact),
|
|
600
|
+
hasItems && /*#__PURE__*/ _jsx("div", {
|
|
601
|
+
className: styles.itemBadges,
|
|
602
|
+
children: r.items.map((it, i)=>{
|
|
603
|
+
const name = typeof it.resource === 'object' ? it.resource?.name : it.resource;
|
|
604
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
605
|
+
className: styles.itemBadge,
|
|
606
|
+
children: String(name ?? '')
|
|
607
|
+
}, i);
|
|
608
|
+
})
|
|
609
|
+
})
|
|
610
|
+
]
|
|
568
611
|
}, r.id);
|
|
569
612
|
};
|
|
570
613
|
// Dynamic legend: iterates all statuses from the status machine config
|
|
@@ -672,6 +715,40 @@ export const CalendarView = ()=>{
|
|
|
672
715
|
const hours = Array.from({
|
|
673
716
|
length: 12
|
|
674
717
|
}, (_, i)=>i + 7);
|
|
718
|
+
// Grid bounds: hour 7 to hour 19 (end of last slot), step 60 min
|
|
719
|
+
const gridStartHour = 7;
|
|
720
|
+
const gridEndHour = gridStartHour + hours.length // 19
|
|
721
|
+
;
|
|
722
|
+
const gridStep = 60;
|
|
723
|
+
// Build per-day slot-state maps when a resource is selected
|
|
724
|
+
const daySlotMaps = availability ? new Map(weekDays.map((day)=>{
|
|
725
|
+
const isoDay = localDayKey(day);
|
|
726
|
+
const dayAvail = availability.days.find((d)=>d.date === isoDay);
|
|
727
|
+
const dayStart = new Date(day);
|
|
728
|
+
dayStart.setHours(gridStartHour, 0, 0, 0);
|
|
729
|
+
const dayEnd = new Date(day);
|
|
730
|
+
dayEnd.setHours(gridEndHour, 0, 0, 0);
|
|
731
|
+
const slots = dayAvail ? computeSlotStates({
|
|
732
|
+
busy: availability.busy,
|
|
733
|
+
capacityMode: availability.capacityMode,
|
|
734
|
+
dayEnd,
|
|
735
|
+
dayStart,
|
|
736
|
+
quantity: availability.quantity,
|
|
737
|
+
requiredPools: availability.requiredPools,
|
|
738
|
+
shiftWindows: dayAvail.shiftWindows,
|
|
739
|
+
step: gridStep,
|
|
740
|
+
timeOff: dayAvail.timeOff
|
|
741
|
+
}) : [];
|
|
742
|
+
// Index by slot start ISO for fast lookup
|
|
743
|
+
const slotByStart = new Map(slots.map((s)=>[
|
|
744
|
+
s.start.toISOString(),
|
|
745
|
+
s
|
|
746
|
+
]));
|
|
747
|
+
return [
|
|
748
|
+
isoDay,
|
|
749
|
+
slotByStart
|
|
750
|
+
];
|
|
751
|
+
})) : null;
|
|
675
752
|
return /*#__PURE__*/ _jsxs("div", {
|
|
676
753
|
className: styles.weekView,
|
|
677
754
|
children: [
|
|
@@ -702,19 +779,62 @@ export const CalendarView = ()=>{
|
|
|
702
779
|
});
|
|
703
780
|
const clickDate = new Date(day);
|
|
704
781
|
clickDate.setHours(hour, 0, 0, 0);
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
782
|
+
// Slot state (only when a resource is selected)
|
|
783
|
+
const isoDay = localDayKey(day);
|
|
784
|
+
const slotMap = daySlotMaps?.get(isoDay);
|
|
785
|
+
const slotInfo = slotMap?.get(clickDate.toISOString()) ?? null;
|
|
786
|
+
// Derive cell CSS class and interactivity based on slot state
|
|
787
|
+
let slotClass = '';
|
|
788
|
+
let isNonInteractive = false;
|
|
789
|
+
if (slotInfo) {
|
|
790
|
+
if (slotInfo.state === 'off-shift') {
|
|
791
|
+
slotClass = styles.slotOffShift;
|
|
792
|
+
isNonInteractive = true;
|
|
793
|
+
} else if (slotInfo.state === 'time-off') {
|
|
794
|
+
slotClass = styles.slotTimeOff;
|
|
795
|
+
isNonInteractive = true;
|
|
796
|
+
} else if (slotInfo.state === 'full') {
|
|
797
|
+
slotClass = styles.slotFull;
|
|
798
|
+
isNonInteractive = true;
|
|
799
|
+
} else {
|
|
800
|
+
slotClass = styles.slotFree;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
// Time-off label: show type/reason from dayAvail when in time-off state
|
|
804
|
+
const dayAvail = availability?.days.find((d)=>d.date === isoDay);
|
|
805
|
+
const timeOffEntry = slotInfo?.state === 'time-off' ? dayAvail?.timeOff.find((to)=>new Date(to.start) <= clickDate && clickDate < new Date(to.end)) : undefined;
|
|
806
|
+
const timeOffLabel = timeOffEntry?.type ?? timeOffEntry?.reason ?? null;
|
|
807
|
+
const handleClick = isNonInteractive ? undefined : availability ? ()=>handleSlotClick(clickDate.toISOString()) : ()=>handleDateClick(clickDate);
|
|
808
|
+
const handleKeyDown = isNonInteractive ? undefined : (e)=>{
|
|
809
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
810
|
+
e.preventDefault();
|
|
811
|
+
if (availability) {
|
|
812
|
+
handleSlotClick(clickDate.toISOString());
|
|
813
|
+
} else {
|
|
711
814
|
handleDateClick(clickDate);
|
|
712
815
|
}
|
|
713
|
-
}
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
819
|
+
className: `${styles.weekCell} ${slotClass}`,
|
|
820
|
+
onClick: handleClick,
|
|
821
|
+
onKeyDown: handleKeyDown,
|
|
714
822
|
role: "button",
|
|
715
|
-
tabIndex: 0,
|
|
823
|
+
tabIndex: isNonInteractive ? -1 : 0,
|
|
716
824
|
children: [
|
|
717
825
|
renderCurrentTimeLine(day, hour),
|
|
826
|
+
timeOffLabel && /*#__PURE__*/ _jsx("span", {
|
|
827
|
+
className: styles.timeOffLabel,
|
|
828
|
+
children: timeOffLabel
|
|
829
|
+
}),
|
|
830
|
+
slotInfo && availability && availability.quantity > 1 && /*#__PURE__*/ _jsxs("span", {
|
|
831
|
+
className: styles.capacityBadge,
|
|
832
|
+
children: [
|
|
833
|
+
slotInfo.occupancy,
|
|
834
|
+
"/",
|
|
835
|
+
availability.quantity
|
|
836
|
+
]
|
|
837
|
+
}),
|
|
718
838
|
cellReservations.map((r)=>renderEventItem(r, false))
|
|
719
839
|
]
|
|
720
840
|
}, `cell-${hour}-${di}`);
|
|
@@ -728,6 +848,36 @@ export const CalendarView = ()=>{
|
|
|
728
848
|
const hours = Array.from({
|
|
729
849
|
length: 14
|
|
730
850
|
}, (_, i)=>i + 7);
|
|
851
|
+
// Grid bounds: hour 7 to hour 21 (end of last slot), step 60 min
|
|
852
|
+
const gridStartHour = 7;
|
|
853
|
+
const gridEndHour = gridStartHour + hours.length // 21
|
|
854
|
+
;
|
|
855
|
+
const gridStep = 60;
|
|
856
|
+
// Build slot-state map for the current day when a resource is selected
|
|
857
|
+
let daySlotMap = null;
|
|
858
|
+
if (availability) {
|
|
859
|
+
const isoDay = localDayKey(currentDate);
|
|
860
|
+
const dayAvail = availability.days.find((d)=>d.date === isoDay);
|
|
861
|
+
const dayStart = new Date(currentDate);
|
|
862
|
+
dayStart.setHours(gridStartHour, 0, 0, 0);
|
|
863
|
+
const dayEnd = new Date(currentDate);
|
|
864
|
+
dayEnd.setHours(gridEndHour, 0, 0, 0);
|
|
865
|
+
const slots = dayAvail ? computeSlotStates({
|
|
866
|
+
busy: availability.busy,
|
|
867
|
+
capacityMode: availability.capacityMode,
|
|
868
|
+
dayEnd,
|
|
869
|
+
dayStart,
|
|
870
|
+
quantity: availability.quantity,
|
|
871
|
+
requiredPools: availability.requiredPools,
|
|
872
|
+
shiftWindows: dayAvail.shiftWindows,
|
|
873
|
+
step: gridStep,
|
|
874
|
+
timeOff: dayAvail.timeOff
|
|
875
|
+
}) : [];
|
|
876
|
+
daySlotMap = new Map(slots.map((s)=>[
|
|
877
|
+
s.start.toISOString(),
|
|
878
|
+
s
|
|
879
|
+
]));
|
|
880
|
+
}
|
|
731
881
|
return /*#__PURE__*/ _jsx("div", {
|
|
732
882
|
className: styles.dayView,
|
|
733
883
|
children: hours.map((hour)=>{
|
|
@@ -737,6 +887,41 @@ export const CalendarView = ()=>{
|
|
|
737
887
|
});
|
|
738
888
|
const clickDate = new Date(currentDate);
|
|
739
889
|
clickDate.setHours(hour, 0, 0, 0);
|
|
890
|
+
// Slot state (only when a resource is selected)
|
|
891
|
+
const slotInfo = daySlotMap?.get(clickDate.toISOString()) ?? null;
|
|
892
|
+
// Derive cell CSS class and interactivity based on slot state
|
|
893
|
+
let slotClass = '';
|
|
894
|
+
let isNonInteractive = false;
|
|
895
|
+
if (slotInfo) {
|
|
896
|
+
if (slotInfo.state === 'off-shift') {
|
|
897
|
+
slotClass = styles.slotOffShift;
|
|
898
|
+
isNonInteractive = true;
|
|
899
|
+
} else if (slotInfo.state === 'time-off') {
|
|
900
|
+
slotClass = styles.slotTimeOff;
|
|
901
|
+
isNonInteractive = true;
|
|
902
|
+
} else if (slotInfo.state === 'full') {
|
|
903
|
+
slotClass = styles.slotFull;
|
|
904
|
+
isNonInteractive = true;
|
|
905
|
+
} else {
|
|
906
|
+
slotClass = styles.slotFree;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
// Time-off label
|
|
910
|
+
const isoDay = localDayKey(currentDate);
|
|
911
|
+
const dayAvail = availability?.days.find((d)=>d.date === isoDay);
|
|
912
|
+
const timeOffEntry = slotInfo?.state === 'time-off' ? dayAvail?.timeOff.find((to)=>new Date(to.start) <= clickDate && clickDate < new Date(to.end)) : undefined;
|
|
913
|
+
const timeOffLabel = timeOffEntry?.type ?? timeOffEntry?.reason ?? null;
|
|
914
|
+
const handleClick = isNonInteractive ? undefined : availability ? ()=>handleSlotClick(clickDate.toISOString()) : ()=>handleDateClick(clickDate);
|
|
915
|
+
const handleKeyDown = isNonInteractive ? undefined : (e)=>{
|
|
916
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
917
|
+
e.preventDefault();
|
|
918
|
+
if (availability) {
|
|
919
|
+
handleSlotClick(clickDate.toISOString());
|
|
920
|
+
} else {
|
|
921
|
+
handleDateClick(clickDate);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
};
|
|
740
925
|
return /*#__PURE__*/ _jsxs(Fragment, {
|
|
741
926
|
children: [
|
|
742
927
|
/*#__PURE__*/ _jsxs("div", {
|
|
@@ -747,18 +932,25 @@ export const CalendarView = ()=>{
|
|
|
747
932
|
]
|
|
748
933
|
}),
|
|
749
934
|
/*#__PURE__*/ _jsxs("div", {
|
|
750
|
-
className: styles.dayViewCell
|
|
751
|
-
onClick:
|
|
752
|
-
onKeyDown:
|
|
753
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
754
|
-
e.preventDefault();
|
|
755
|
-
handleDateClick(clickDate);
|
|
756
|
-
}
|
|
757
|
-
},
|
|
935
|
+
className: `${styles.dayViewCell} ${slotClass}`,
|
|
936
|
+
onClick: handleClick,
|
|
937
|
+
onKeyDown: handleKeyDown,
|
|
758
938
|
role: "button",
|
|
759
|
-
tabIndex: 0,
|
|
939
|
+
tabIndex: isNonInteractive ? -1 : 0,
|
|
760
940
|
children: [
|
|
761
941
|
renderCurrentTimeLine(currentDate, hour),
|
|
942
|
+
timeOffLabel && /*#__PURE__*/ _jsx("span", {
|
|
943
|
+
className: styles.timeOffLabel,
|
|
944
|
+
children: timeOffLabel
|
|
945
|
+
}),
|
|
946
|
+
slotInfo && availability && availability.quantity > 1 && /*#__PURE__*/ _jsxs("span", {
|
|
947
|
+
className: styles.capacityBadge,
|
|
948
|
+
children: [
|
|
949
|
+
slotInfo.occupancy,
|
|
950
|
+
"/",
|
|
951
|
+
availability.quantity
|
|
952
|
+
]
|
|
953
|
+
}),
|
|
762
954
|
hourReservations.map((r)=>renderEventItem(r, false))
|
|
763
955
|
]
|
|
764
956
|
})
|
|
@@ -1041,6 +1233,10 @@ export const CalendarView = ()=>{
|
|
|
1041
1233
|
key: 'day',
|
|
1042
1234
|
label: t('reservation:calendarDay')
|
|
1043
1235
|
},
|
|
1236
|
+
{
|
|
1237
|
+
key: 'lanes',
|
|
1238
|
+
label: t('reservation:calendarLanes')
|
|
1239
|
+
},
|
|
1044
1240
|
{
|
|
1045
1241
|
key: 'pending',
|
|
1046
1242
|
label: t('reservation:calendarPending')
|
|
@@ -1081,14 +1277,20 @@ export const CalendarView = ()=>{
|
|
|
1081
1277
|
]
|
|
1082
1278
|
})
|
|
1083
1279
|
}),
|
|
1084
|
-
loading && viewMode !== 'pending' ? /*#__PURE__*/ _jsx("div", {
|
|
1280
|
+
loading && viewMode !== 'pending' && viewMode !== 'lanes' ? /*#__PURE__*/ _jsx("div", {
|
|
1085
1281
|
className: styles.loading,
|
|
1086
1282
|
children: t('reservation:calendarLoading')
|
|
1087
1283
|
}) : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
1088
1284
|
children: [
|
|
1089
1285
|
viewMode === 'month' && renderMonthView(),
|
|
1090
1286
|
viewMode === 'week' && renderWeekView(),
|
|
1091
|
-
viewMode === 'day' && renderDayView()
|
|
1287
|
+
viewMode === 'day' && renderDayView(),
|
|
1288
|
+
viewMode === 'lanes' && /*#__PURE__*/ _jsx(LaneTimelineView, {
|
|
1289
|
+
apiBase: apiBase,
|
|
1290
|
+
day: currentDate,
|
|
1291
|
+
onBook: handleLaneBook,
|
|
1292
|
+
resources: selectedResourceId ? resources.filter((r)=>r.id === selectedResourceId) : resources
|
|
1293
|
+
})
|
|
1092
1294
|
]
|
|
1093
1295
|
}),
|
|
1094
1296
|
viewMode === 'pending' && renderPendingView(),
|