payload-reserve 1.2.0 → 1.3.2

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 CHANGED
@@ -40,7 +40,7 @@ pnpm add payload-reserve
40
40
  npm install payload-reserve
41
41
  ```
42
42
 
43
- **Peer dependencies:** `payload ^3.77.0`, `@payloadcms/ui ^3.77.0`, `@payloadcms/translations ^3.77.0`
43
+ **Peer dependencies:** `payload ^3.79.0`, `@payloadcms/ui ^3.79.0`, `@payloadcms/translations ^3.79.0`
44
44
 
45
45
  ---
46
46
 
@@ -4,6 +4,7 @@ import { onStatusChange } from '../hooks/reservations/onStatusChange.js';
4
4
  import { validateCancellation } from '../hooks/reservations/validateCancellation.js';
5
5
  import { validateConflicts } from '../hooks/reservations/validateConflicts.js';
6
6
  import { validateStatusTransition } from '../hooks/reservations/validateStatusTransition.js';
7
+ import { statusToI18nKey } from '../utilities/i18nUtils.js';
7
8
  import { makeReservationOwnerAccess } from '../utilities/ownerAccess.js';
8
9
  function createPluginHooksBeforeCreate(hooks) {
9
10
  return async ({ context, data, operation, req })=>{
@@ -119,7 +120,7 @@ export function createReservationsCollection(config) {
119
120
  label: ({ t })=>t('reservation:fieldStatus'),
120
121
  options: statusMachine.statuses.map((s)=>({
121
122
  label: ({ t })=>{
122
- const key = `reservation:status${s.charAt(0).toUpperCase() + s.slice(1)}`;
123
+ const key = statusToI18nKey(s);
123
124
  const translated = t(key);
124
125
  return translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1);
125
126
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/Reservations.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n CollectionConfig,\n CollectionSlug,\n} from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ReservationPluginHooks, ResolvedReservationPluginConfig } from '../types.js'\n\nimport { calculateEndTime } from '../hooks/reservations/calculateEndTime.js'\nimport { checkIdempotency } from '../hooks/reservations/checkIdempotency.js'\nimport { onStatusChange } from '../hooks/reservations/onStatusChange.js'\nimport { validateCancellation } from '../hooks/reservations/validateCancellation.js'\nimport { validateConflicts } from '../hooks/reservations/validateConflicts.js'\nimport { validateStatusTransition } from '../hooks/reservations/validateStatusTransition.js'\nimport { makeReservationOwnerAccess } from '../utilities/ownerAccess.js'\n\nfunction createPluginHooksBeforeCreate(\n hooks: ReservationPluginHooks,\n): CollectionBeforeChangeHook {\n return async ({ context, data, operation, req }) => {\n if (context?.skipReservationHooks) {return data}\n\n if (operation === 'create' && hooks.beforeBookingCreate) {\n let mutatedData = data\n for (const hook of hooks.beforeBookingCreate) {\n const result = await hook({ data: mutatedData, req })\n if (result) {mutatedData = result}\n }\n return mutatedData\n }\n\n return data\n }\n}\n\nfunction createPluginHooksAfterCreate(\n hooks: ReservationPluginHooks,\n): CollectionAfterChangeHook {\n return async ({ doc, operation, req }) => {\n if (operation === 'create' && hooks.afterBookingCreate) {\n const docRecord = doc as Record<string, unknown>\n for (const hook of hooks.afterBookingCreate) {\n await hook({ doc: docRecord, req })\n }\n }\n return doc\n }\n}\n\nexport function createReservationsCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n const { statusMachine } = config\n const rom = config.resourceOwnerMode\n const access =\n config.access.reservations ?? (rom ? makeReservationOwnerAccess(rom) : {})\n\n return {\n slug: config.slugs.reservations,\n access,\n admin: {\n components: {\n views: {\n list: {\n Component: 'payload-reserve/client#CalendarView',\n },\n },\n },\n group: config.adminGroup,\n listSearchableFields: ['status'],\n useAsTitle: 'startTime',\n },\n fields: [\n {\n name: 'service',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldService'),\n relationTo: config.slugs.services as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n allowCreate: true,\n allowEdit: true,\n components: {\n Field: 'payload-reserve/client#CustomerField',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldCustomer'),\n relationTo: config.slugs.customers as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'startTime',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTime'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n readOnly: true,\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTime'),\n },\n {\n name: 'status',\n type: 'select',\n defaultValue: statusMachine.defaultStatus,\n label: ({ t }) => (t as PluginT)('reservation:fieldStatus'),\n options: statusMachine.statuses.map((s) => ({\n label: ({ t }) => {\n const key = `reservation:status${s.charAt(0).toUpperCase() + s.slice(1)}`\n const translated = (t as PluginT)(key)\n return translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1)\n },\n value: s,\n })),\n },\n {\n name: 'cancellationReason',\n type: 'textarea',\n admin: {\n condition: (_, siblingData) => siblingData?.status === 'cancelled',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldCancellationReason'),\n },\n {\n name: 'guestCount',\n type: 'number',\n defaultValue: 1,\n label: ({ t }) => (t as PluginT)('reservation:fieldGuestCount'),\n min: 1,\n },\n {\n name: 'notes',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldNotes'),\n },\n {\n name: 'items',\n type: 'array',\n admin: {\n description: 'Resources included in this booking. Leave empty for single-resource bookings.',\n },\n fields: [\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'service',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldService'),\n relationTo: config.slugs.services as unknown as CollectionSlug,\n },\n {\n name: 'startTime',\n type: 'date',\n admin: { date: { pickerAppearance: 'dayAndTime' } },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTime'),\n },\n {\n name: 'endTime',\n type: 'date',\n admin: { date: { pickerAppearance: 'dayAndTime' }, readOnly: false },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTime'),\n },\n {\n name: 'guestCount',\n type: 'number',\n label: ({ t }) => (t as PluginT)('reservation:fieldGuestCount'),\n min: 1,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldItems'),\n },\n {\n name: 'idempotencyKey',\n type: 'text',\n admin: { position: 'sidebar', readOnly: true },\n index: true,\n unique: true,\n },\n ...config.extraReservationFields,\n ],\n hooks: {\n afterChange: [\n createPluginHooksAfterCreate(config.hooks),\n onStatusChange(config),\n ],\n beforeChange: [\n createPluginHooksBeforeCreate(config.hooks),\n checkIdempotency(config),\n calculateEndTime(config),\n validateConflicts(config),\n validateStatusTransition(config),\n validateCancellation(config),\n ],\n },\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionReservations'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionReservations'),\n },\n }\n}\n"],"names":["calculateEndTime","checkIdempotency","onStatusChange","validateCancellation","validateConflicts","validateStatusTransition","makeReservationOwnerAccess","createPluginHooksBeforeCreate","hooks","context","data","operation","req","skipReservationHooks","beforeBookingCreate","mutatedData","hook","result","createPluginHooksAfterCreate","doc","afterBookingCreate","docRecord","createReservationsCollection","config","statusMachine","rom","resourceOwnerMode","access","reservations","slug","slugs","admin","components","views","list","Component","group","adminGroup","listSearchableFields","useAsTitle","fields","name","type","label","t","relationTo","services","required","resources","allowCreate","allowEdit","Field","customers","date","pickerAppearance","readOnly","defaultValue","defaultStatus","options","statuses","map","s","key","charAt","toUpperCase","slice","translated","value","condition","_","siblingData","status","min","description","position","index","unique","extraReservationFields","afterChange","beforeChange","labels","plural","singular"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/collections/Reservations.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n CollectionConfig,\n CollectionSlug,\n} from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ReservationPluginHooks, ResolvedReservationPluginConfig } from '../types.js'\n\nimport { calculateEndTime } from '../hooks/reservations/calculateEndTime.js'\nimport { checkIdempotency } from '../hooks/reservations/checkIdempotency.js'\nimport { onStatusChange } from '../hooks/reservations/onStatusChange.js'\nimport { validateCancellation } from '../hooks/reservations/validateCancellation.js'\nimport { validateConflicts } from '../hooks/reservations/validateConflicts.js'\nimport { validateStatusTransition } from '../hooks/reservations/validateStatusTransition.js'\nimport { statusToI18nKey } from '../utilities/i18nUtils.js'\nimport { makeReservationOwnerAccess } from '../utilities/ownerAccess.js'\n\nfunction createPluginHooksBeforeCreate(\n hooks: ReservationPluginHooks,\n): CollectionBeforeChangeHook {\n return async ({ context, data, operation, req }) => {\n if (context?.skipReservationHooks) {return data}\n\n if (operation === 'create' && hooks.beforeBookingCreate) {\n let mutatedData = data\n for (const hook of hooks.beforeBookingCreate) {\n const result = await hook({ data: mutatedData, req })\n if (result) {mutatedData = result}\n }\n return mutatedData\n }\n\n return data\n }\n}\n\nfunction createPluginHooksAfterCreate(\n hooks: ReservationPluginHooks,\n): CollectionAfterChangeHook {\n return async ({ doc, operation, req }) => {\n if (operation === 'create' && hooks.afterBookingCreate) {\n const docRecord = doc as Record<string, unknown>\n for (const hook of hooks.afterBookingCreate) {\n await hook({ doc: docRecord, req })\n }\n }\n return doc\n }\n}\n\nexport function createReservationsCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n const { statusMachine } = config\n const rom = config.resourceOwnerMode\n const access =\n config.access.reservations ?? (rom ? makeReservationOwnerAccess(rom) : {})\n\n return {\n slug: config.slugs.reservations,\n access,\n admin: {\n components: {\n views: {\n list: {\n Component: 'payload-reserve/client#CalendarView',\n },\n },\n },\n group: config.adminGroup,\n listSearchableFields: ['status'],\n useAsTitle: 'startTime',\n },\n fields: [\n {\n name: 'service',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldService'),\n relationTo: config.slugs.services as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n allowCreate: true,\n allowEdit: true,\n components: {\n Field: 'payload-reserve/client#CustomerField',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldCustomer'),\n relationTo: config.slugs.customers as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'startTime',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTime'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n readOnly: true,\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTime'),\n },\n {\n name: 'status',\n type: 'select',\n defaultValue: statusMachine.defaultStatus,\n label: ({ t }) => (t as PluginT)('reservation:fieldStatus'),\n options: statusMachine.statuses.map((s) => ({\n label: ({ t }) => {\n const key = statusToI18nKey(s)\n const translated = (t as PluginT)(key)\n return translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1)\n },\n value: s,\n })),\n },\n {\n name: 'cancellationReason',\n type: 'textarea',\n admin: {\n condition: (_, siblingData) => siblingData?.status === 'cancelled',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldCancellationReason'),\n },\n {\n name: 'guestCount',\n type: 'number',\n defaultValue: 1,\n label: ({ t }) => (t as PluginT)('reservation:fieldGuestCount'),\n min: 1,\n },\n {\n name: 'notes',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldNotes'),\n },\n {\n name: 'items',\n type: 'array',\n admin: {\n description: 'Resources included in this booking. Leave empty for single-resource bookings.',\n },\n fields: [\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'service',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldService'),\n relationTo: config.slugs.services as unknown as CollectionSlug,\n },\n {\n name: 'startTime',\n type: 'date',\n admin: { date: { pickerAppearance: 'dayAndTime' } },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTime'),\n },\n {\n name: 'endTime',\n type: 'date',\n admin: { date: { pickerAppearance: 'dayAndTime' }, readOnly: false },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTime'),\n },\n {\n name: 'guestCount',\n type: 'number',\n label: ({ t }) => (t as PluginT)('reservation:fieldGuestCount'),\n min: 1,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldItems'),\n },\n {\n name: 'idempotencyKey',\n type: 'text',\n admin: { position: 'sidebar', readOnly: true },\n index: true,\n unique: true,\n },\n ...config.extraReservationFields,\n ],\n hooks: {\n afterChange: [\n createPluginHooksAfterCreate(config.hooks),\n onStatusChange(config),\n ],\n beforeChange: [\n createPluginHooksBeforeCreate(config.hooks),\n checkIdempotency(config),\n calculateEndTime(config),\n validateConflicts(config),\n validateStatusTransition(config),\n validateCancellation(config),\n ],\n },\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionReservations'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionReservations'),\n },\n }\n}\n"],"names":["calculateEndTime","checkIdempotency","onStatusChange","validateCancellation","validateConflicts","validateStatusTransition","statusToI18nKey","makeReservationOwnerAccess","createPluginHooksBeforeCreate","hooks","context","data","operation","req","skipReservationHooks","beforeBookingCreate","mutatedData","hook","result","createPluginHooksAfterCreate","doc","afterBookingCreate","docRecord","createReservationsCollection","config","statusMachine","rom","resourceOwnerMode","access","reservations","slug","slugs","admin","components","views","list","Component","group","adminGroup","listSearchableFields","useAsTitle","fields","name","type","label","t","relationTo","services","required","resources","allowCreate","allowEdit","Field","customers","date","pickerAppearance","readOnly","defaultValue","defaultStatus","options","statuses","map","s","key","translated","charAt","toUpperCase","slice","value","condition","_","siblingData","status","min","description","position","index","unique","extraReservationFields","afterChange","beforeChange","labels","plural","singular"],"mappings":"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"}
@@ -452,3 +452,38 @@
452
452
  color: var(--theme-elevation-400);
453
453
  font-size: 0.9375rem;
454
454
  }
455
+
456
+ /* Resource filter */
457
+ .filterBar {
458
+ display: flex;
459
+ align-items: center;
460
+ gap: 8px;
461
+ margin-bottom: 12px;
462
+ }
463
+
464
+ .resourceFilter {
465
+ appearance: none;
466
+ background: var(--theme-bg);
467
+ border: none;
468
+ border-radius: 3px;
469
+ box-shadow: inset 0 0 0 1px var(--theme-elevation-250);
470
+ padding: 6px 28px 6px 10px;
471
+ cursor: pointer;
472
+ font-family: inherit;
473
+ font-size: 0.8125rem;
474
+ color: var(--theme-text);
475
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23666'/%3E%3C/svg%3E");
476
+ background-repeat: no-repeat;
477
+ background-position: right 10px center;
478
+ min-width: 160px;
479
+ transition: box-shadow 100ms cubic-bezier(0, 0.2, 0.2, 1);
480
+ }
481
+
482
+ .resourceFilter:hover {
483
+ box-shadow: inset 0 0 0 1px var(--theme-elevation-400);
484
+ }
485
+
486
+ .resourceFilter:focus-visible {
487
+ outline: 2px solid var(--theme-text);
488
+ outline-offset: 2px;
489
+ }
@@ -2,6 +2,7 @@
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 { statusToI18nKey } from '../../utilities/i18nUtils.js';
5
6
  import styles from './CalendarView.module.css';
6
7
  // Built-in status → CSS class map (for known statuses; custom statuses use inline style)
7
8
  const STATUS_CLASS_MAP = {
@@ -84,7 +85,7 @@ export const CalendarView = ()=>{
84
85
  const labels = {};
85
86
  for (const s of statuses){
86
87
  // Attempt to look up a translation key, e.g. reservation:statusPending
87
- const key = `reservation:status${s.charAt(0).toUpperCase() + s.slice(1).replace(/-./g, (m)=>m[1].toUpperCase())}`;
88
+ const key = statusToI18nKey(s);
88
89
  const translated = t(key);
89
90
  // If translation returns the key itself, it's missing — fall back to capitalized status name
90
91
  labels[s] = translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1);
@@ -100,6 +101,9 @@ export const CalendarView = ()=>{
100
101
  const [loading, setLoading] = useState(true);
101
102
  const [drawerDocId, setDrawerDocId] = useState(null);
102
103
  const [initialData, setInitialData] = useState(undefined);
104
+ // Resource filter state
105
+ const [resources, setResources] = useState([]);
106
+ const [selectedResourceId, setSelectedResourceId] = useState('');
103
107
  // Pending tab state
104
108
  const [pendingReservations, setPendingReservations] = useState([]);
105
109
  const [pendingCount, setPendingCount] = useState(0);
@@ -117,6 +121,35 @@ export const CalendarView = ()=>{
117
121
  openDrawer();
118
122
  }
119
123
  });
124
+ // Fetch active resources for filter dropdown
125
+ useEffect(()=>{
126
+ const fetchResources = async ()=>{
127
+ try {
128
+ const resourceSlug = slugs?.resources ?? 'resources';
129
+ const params = new URLSearchParams({
130
+ depth: '0',
131
+ limit: '100',
132
+ sort: 'name',
133
+ 'where[active][equals]': 'true'
134
+ });
135
+ const url = `${config.serverURL ?? ''}${config.routes.api}/${resourceSlug}?${params}`;
136
+ const response = await fetch(url);
137
+ const result = await response.json();
138
+ const docs = result.docs ?? [];
139
+ setResources(docs.map((d)=>({
140
+ id: d.id,
141
+ name: d.name ?? ''
142
+ })));
143
+ } catch {
144
+ setResources([]);
145
+ }
146
+ };
147
+ void fetchResources();
148
+ }, [
149
+ config.routes.api,
150
+ config.serverURL,
151
+ slugs?.resources
152
+ ]);
120
153
  const { rangeEnd, rangeStart } = useMemo(()=>{
121
154
  const start = new Date(currentDate);
122
155
  const end = new Date(currentDate);
@@ -216,7 +249,36 @@ export const CalendarView = ()=>{
216
249
  viewMode,
217
250
  fetchPendingReservations
218
251
  ]);
219
- // Clear selection when leaving pending view
252
+ // Client-side resource filtering
253
+ const matchesResourceFilter = useCallback((r)=>{
254
+ if (!selectedResourceId) {
255
+ return true;
256
+ }
257
+ // Check top-level resource
258
+ const topId = typeof r.resource === 'string' ? r.resource : r.resource?.id;
259
+ if (topId === selectedResourceId) {
260
+ return true;
261
+ }
262
+ // Check items array for multi-resource bookings
263
+ if (r.items && r.items.length > 0) {
264
+ return r.items.some((item)=>{
265
+ const itemId = typeof item.resource === 'string' ? item.resource : item.resource?.id;
266
+ return itemId === selectedResourceId;
267
+ });
268
+ }
269
+ return false;
270
+ }, [
271
+ selectedResourceId
272
+ ]);
273
+ const filteredReservations = useMemo(()=>reservations.filter(matchesResourceFilter), [
274
+ reservations,
275
+ matchesResourceFilter
276
+ ]);
277
+ const filteredPendingReservations = useMemo(()=>pendingReservations.filter(matchesResourceFilter), [
278
+ pendingReservations,
279
+ matchesResourceFilter
280
+ ]);
281
+ // Clear selection when leaving pending view or changing resource filter
220
282
  useEffect(()=>{
221
283
  if (viewMode !== 'pending') {
222
284
  setSelectedIds(new Set());
@@ -225,6 +287,11 @@ export const CalendarView = ()=>{
225
287
  }, [
226
288
  viewMode
227
289
  ]);
290
+ useEffect(()=>{
291
+ setSelectedIds(new Set());
292
+ }, [
293
+ selectedResourceId
294
+ ]);
228
295
  // Auto-clear feedback toast
229
296
  useEffect(()=>{
230
297
  if (!actionFeedback) {
@@ -563,7 +630,7 @@ export const CalendarView = ()=>{
563
630
  const dayStr = `${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`;
564
631
  const isToday = dayStr === todayStr;
565
632
  const isOtherMonth = day.getMonth() !== currentDate.getMonth();
566
- const dayReservations = reservations.filter((r)=>{
633
+ const dayReservations = filteredReservations.filter((r)=>{
567
634
  const rDate = new Date(r.startTime);
568
635
  return rDate.getFullYear() === day.getFullYear() && rDate.getMonth() === day.getMonth() && rDate.getDate() === day.getDate();
569
636
  });
@@ -629,7 +696,7 @@ export const CalendarView = ()=>{
629
696
  ]
630
697
  }),
631
698
  weekDays.map((day, di)=>{
632
- const cellReservations = reservations.filter((r)=>{
699
+ const cellReservations = filteredReservations.filter((r)=>{
633
700
  const rDate = new Date(r.startTime);
634
701
  return rDate.getFullYear() === day.getFullYear() && rDate.getMonth() === day.getMonth() && rDate.getDate() === day.getDate() && rDate.getHours() === hour;
635
702
  });
@@ -664,7 +731,7 @@ export const CalendarView = ()=>{
664
731
  return /*#__PURE__*/ _jsx("div", {
665
732
  className: styles.dayView,
666
733
  children: hours.map((hour)=>{
667
- const hourReservations = reservations.filter((r)=>{
734
+ const hourReservations = filteredReservations.filter((r)=>{
668
735
  const rDate = new Date(r.startTime);
669
736
  return rDate.getFullYear() === currentDate.getFullYear() && rDate.getMonth() === currentDate.getMonth() && rDate.getDate() === currentDate.getDate() && rDate.getHours() === hour;
670
737
  });
@@ -701,18 +768,18 @@ export const CalendarView = ()=>{
701
768
  });
702
769
  };
703
770
  const renderPendingView = ()=>{
704
- if (pendingReservations.length === 0) {
771
+ if (filteredPendingReservations.length === 0) {
705
772
  return /*#__PURE__*/ _jsx("div", {
706
773
  className: styles.pendingEmpty,
707
774
  children: t('reservation:pendingEmpty')
708
775
  });
709
776
  }
710
- const allSelected = pendingReservations.length > 0 && pendingReservations.every((r)=>selectedIds.has(r.id));
777
+ const allSelected = filteredPendingReservations.length > 0 && filteredPendingReservations.every((r)=>selectedIds.has(r.id));
711
778
  const toggleSelectAll = ()=>{
712
779
  if (allSelected) {
713
780
  setSelectedIds(new Set());
714
781
  } else {
715
- setSelectedIds(new Set(pendingReservations.map((r)=>r.id)));
782
+ setSelectedIds(new Set(filteredPendingReservations.map((r)=>r.id)));
716
783
  }
717
784
  };
718
785
  const toggleSelect = (id)=>{
@@ -801,7 +868,7 @@ export const CalendarView = ()=>{
801
868
  })
802
869
  }),
803
870
  /*#__PURE__*/ _jsx("tbody", {
804
- children: pendingReservations.map((r)=>{
871
+ children: filteredPendingReservations.map((r)=>{
805
872
  const isConfirming = confirmingIds.has(r.id);
806
873
  // Show all resources from items array if present, else top-level resource
807
874
  const resourceDisplay = getResourceNames(r).join(', ') || t('reservation:calendarUnknownResource');
@@ -986,7 +1053,7 @@ export const CalendarView = ()=>{
986
1053
  label,
987
1054
  key === 'pending' && pendingCount > 0 && /*#__PURE__*/ _jsx("span", {
988
1055
  className: styles.pendingBadge,
989
- children: pendingCount
1056
+ children: selectedResourceId ? filteredPendingReservations.length : pendingCount
990
1057
  })
991
1058
  ]
992
1059
  }, key))
@@ -995,6 +1062,25 @@ export const CalendarView = ()=>{
995
1062
  ]
996
1063
  }),
997
1064
  viewMode !== 'pending' && renderStatusLegend(),
1065
+ resources.length > 1 && /*#__PURE__*/ _jsx("div", {
1066
+ className: styles.filterBar,
1067
+ children: /*#__PURE__*/ _jsxs("select", {
1068
+ "aria-label": t('reservation:filterByResource'),
1069
+ className: styles.resourceFilter,
1070
+ onChange: (e)=>setSelectedResourceId(e.target.value),
1071
+ value: selectedResourceId,
1072
+ children: [
1073
+ /*#__PURE__*/ _jsx("option", {
1074
+ value: "",
1075
+ children: t('reservation:filterAllResources')
1076
+ }),
1077
+ resources.map((r)=>/*#__PURE__*/ _jsx("option", {
1078
+ value: r.id,
1079
+ children: r.name
1080
+ }, r.id))
1081
+ ]
1082
+ })
1083
+ }),
998
1084
  loading && viewMode !== 'pending' ? /*#__PURE__*/ _jsx("div", {
999
1085
  className: styles.loading,
1000
1086
  children: t('reservation:calendarLoading')
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/CalendarView/index.tsx"],"sourcesContent":["'use client'\nimport type { AdminViewServerProps } from 'payload'\n\nimport { useConfig, useDocumentDrawer, useTranslation } from '@payloadcms/ui'\nimport React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { PluginT } from '../../translations/index.js'\n\nimport styles from './CalendarView.module.css'\n\ntype ViewMode = 'day' | 'month' | 'pending' | 'week'\n\ntype ReservationItem = {\n endTime?: string\n guestCount?: number\n resource?: { name?: string } | string\n service?: { name?: string } | string\n startTime?: string\n}\n\ntype Reservation = {\n customer?: { firstName?: string; lastName?: string; name?: string } | string\n endTime?: string\n id: string\n items?: ReservationItem[]\n resource?: { name?: string } | string\n service?: { name?: string } | string\n startTime: string\n status: string\n}\n\n// Built-in status → CSS class map (for known statuses; custom statuses use inline style)\nconst STATUS_CLASS_MAP: Record<string, string> = {\n cancelled: styles.statusCancelled,\n completed: styles.statusCompleted,\n confirmed: styles.statusConfirmed,\n 'no-show': styles.statusNoShow,\n pending: styles.statusPending,\n}\n\n// Built-in default colors for known statuses\nconst BUILTIN_STATUS_COLORS: Record<string, string> = {\n cancelled: '#e5e7eb',\n completed: '#d1fae5',\n confirmed: '#dbeafe',\n 'no-show': '#fee2e2',\n pending: '#fef3c7',\n}\n\n// Palette for auto-assigning colors to custom statuses\nconst CUSTOM_STATUS_PALETTE = ['#fde68a', '#c7d2fe', '#a7f3d0', '#fca5a5', '#fdba74']\n\nexport const CalendarView: React.FC<AdminViewServerProps> = () => {\n const { config } = useConfig()\n const { t: _t } = useTranslation()\n const t = _t as PluginT\n\n const slugs = config.admin?.custom?.reservationSlugs\n const reservationSlug = slugs?.reservations ?? 'reservations'\n const apiUrl = `${config.serverURL ?? ''}${config.routes.api}/${reservationSlug}`\n\n const statusMachine = config.admin?.custom?.reservationStatusMachine as\n | {\n blockingStatuses?: string[]\n defaultStatus?: string\n statuses?: string[]\n terminalStatuses?: string[]\n transitions?: Record<string, string[]>\n }\n | undefined\n\n // The initial/pending status (what \"pending\" view shows)\n const defaultStatus = statusMachine?.defaultStatus ?? 'pending'\n\n // Build STATUS_COLORS dynamically: built-ins first, then auto-assign palette for custom statuses\n const STATUS_COLORS = useMemo<Record<string, string>>(() => {\n const colors = { ...BUILTIN_STATUS_COLORS }\n const statuses = statusMachine?.statuses ?? []\n statuses.forEach((s, i) => {\n if (!colors[s]) {\n colors[s] = CUSTOM_STATUS_PALETTE[i % CUSTOM_STATUS_PALETTE.length]\n }\n })\n return colors\n }, [statusMachine])\n\n // Derive confirm/cancel target statuses from config transitions\n // \"confirm\" = first non-terminal transition from defaultStatus\n // \"cancel\" = first terminal transition from defaultStatus (or fallback: 'cancelled')\n const { cancelStatus, confirmStatus } = useMemo(() => {\n const terminalStatuses = statusMachine?.terminalStatuses ?? ['completed', 'cancelled', 'no-show']\n const transitions = statusMachine?.transitions ?? {}\n const defaultTransitions: string[] = transitions[defaultStatus] ?? []\n\n const nonTerminal = defaultTransitions.find((s) => !terminalStatuses.includes(s))\n const terminal = defaultTransitions.find((s) => terminalStatuses.includes(s))\n\n return {\n cancelStatus: terminal ?? 'cancelled',\n confirmStatus: nonTerminal ?? 'confirmed',\n }\n }, [statusMachine, defaultStatus])\n\n const STATUS_LABELS = useMemo<Record<string, string>>(() => {\n const statuses = statusMachine?.statuses ?? [\n 'pending',\n 'confirmed',\n 'completed',\n 'cancelled',\n 'no-show',\n ]\n const labels: Record<string, string> = {}\n for (const s of statuses) {\n // Attempt to look up a translation key, e.g. reservation:statusPending\n const key = `reservation:status${s.charAt(0).toUpperCase() + s.slice(1).replace(/-./g, (m) => m[1].toUpperCase())}`\n const translated = t(key)\n // If translation returns the key itself, it's missing — fall back to capitalized status name\n labels[s] = translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1)\n }\n return labels\n }, [statusMachine, t])\n\n const [currentDate, setCurrentDate] = useState(() => new Date())\n const [viewMode, setViewMode] = useState<ViewMode>('month')\n const [reservations, setReservations] = useState<Reservation[]>([])\n const [loading, setLoading] = useState(true)\n const [drawerDocId, setDrawerDocId] = useState<null | string>(null)\n const [initialData, setInitialData] = useState<Record<string, unknown> | undefined>(undefined)\n\n // Pending tab state\n const [pendingReservations, setPendingReservations] = useState<Reservation[]>([])\n const [pendingCount, setPendingCount] = useState(0)\n const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set())\n const [confirmingIds, setConfirmingIds] = useState<Set<string>>(() => new Set())\n const [actionFeedback, setActionFeedback] = useState<{\n message: string\n type: 'error' | 'success'\n } | null>(null)\n\n const [DocumentDrawer, , { openDrawer }] = useDocumentDrawer({\n id: drawerDocId ?? undefined,\n collectionSlug: reservationSlug,\n })\n\n const pendingDrawerOpen = useRef(false)\n\n useEffect(() => {\n if (pendingDrawerOpen.current) {\n pendingDrawerOpen.current = false\n openDrawer()\n }\n })\n\n const { rangeEnd, rangeStart } = useMemo(() => {\n const start = new Date(currentDate)\n const end = new Date(currentDate)\n\n if (viewMode === 'month') {\n start.setDate(1)\n start.setDate(start.getDate() - start.getDay())\n end.setMonth(end.getMonth() + 1, 0)\n end.setDate(end.getDate() + (6 - end.getDay()))\n } else if (viewMode === 'week') {\n const dayOfWeek = start.getDay()\n start.setDate(start.getDate() - dayOfWeek)\n end.setDate(start.getDate() + 6)\n }\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n\n return { rangeEnd: end, rangeStart: start }\n }, [currentDate, viewMode])\n\n const fetchReservations = useCallback(async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams({\n depth: '1',\n limit: '500',\n sort: 'startTime',\n 'where[startTime][greater_than_equal]': rangeStart.toISOString(),\n 'where[startTime][less_than_equal]': rangeEnd.toISOString(),\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setReservations(result.docs ?? [])\n } catch {\n setReservations([])\n }\n setLoading(false)\n }, [rangeStart, rangeEnd, apiUrl])\n\n useEffect(() => {\n void fetchReservations()\n }, [fetchReservations])\n\n // Fetch pending count (always, for badge) — uses defaultStatus from config\n const fetchPendingCount = useCallback(async () => {\n try {\n const params = new URLSearchParams({\n limit: '0',\n 'where[status][equals]': defaultStatus,\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setPendingCount(result.totalDocs ?? 0)\n } catch {\n // silently ignore\n }\n }, [apiUrl, defaultStatus])\n\n useEffect(() => {\n void fetchPendingCount()\n }, [fetchPendingCount])\n\n // Fetch pending reservations when tab is active — uses defaultStatus from config\n const fetchPendingReservations = useCallback(async () => {\n try {\n const params = new URLSearchParams({\n depth: '1',\n limit: '500',\n sort: 'startTime',\n 'where[status][equals]': defaultStatus,\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setPendingReservations(result.docs ?? [])\n } catch {\n setPendingReservations([])\n }\n }, [apiUrl, defaultStatus])\n\n useEffect(() => {\n if (viewMode === 'pending') {\n void fetchPendingReservations()\n }\n }, [viewMode, fetchPendingReservations])\n\n // Clear selection when leaving pending view\n useEffect(() => {\n if (viewMode !== 'pending') {\n setSelectedIds(new Set())\n setActionFeedback(null)\n }\n }, [viewMode])\n\n // Auto-clear feedback toast\n useEffect(() => {\n if (!actionFeedback) {return}\n const timer = setTimeout(() => setActionFeedback(null), 4000)\n return () => clearTimeout(timer)\n }, [actionFeedback])\n\n const patchReservation = useCallback(\n async (id: string, data: Record<string, unknown>): Promise<boolean> => {\n try {\n const response = await fetch(`${apiUrl}/${id}`, {\n body: JSON.stringify(data),\n headers: { 'Content-Type': 'application/json' },\n method: 'PATCH',\n })\n return response.ok\n } catch {\n return false\n }\n },\n [apiUrl],\n )\n\n // Uses confirmStatus derived from config transitions\n const handleQuickConfirm = useCallback(\n async (id: string) => {\n setConfirmingIds((prev) => new Set(prev).add(id))\n const ok = await patchReservation(id, { status: confirmStatus })\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setActionFeedback({\n type: ok ? 'success' : 'error',\n message: ok\n ? t('reservation:pendingConfirmSuccess')\n : t('reservation:pendingConfirmError'),\n })\n if (ok) {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n void fetchPendingReservations()\n void fetchPendingCount()\n }\n },\n [patchReservation, fetchPendingReservations, fetchPendingCount, t, confirmStatus],\n )\n\n // Uses cancelStatus derived from config transitions\n const handleQuickCancel = useCallback(\n async (id: string) => {\n setConfirmingIds((prev) => new Set(prev).add(id))\n const ok = await patchReservation(id, { status: cancelStatus })\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setActionFeedback({\n type: ok ? 'success' : 'error',\n message: ok\n ? t('reservation:pendingCancelSuccess')\n : t('reservation:pendingCancelError'),\n })\n if (ok) {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n void fetchPendingReservations()\n void fetchPendingCount()\n }\n },\n [patchReservation, fetchPendingReservations, fetchPendingCount, t, cancelStatus],\n )\n\n const confirmSelected = useCallback(async () => {\n const ids = Array.from(selectedIds)\n if (ids.length === 0) {return}\n\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n for (const id of ids) {next.add(id)}\n return next\n })\n\n const results = await Promise.allSettled(\n ids.map((id) => patchReservation(id, { status: confirmStatus })),\n )\n\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n for (const id of ids) {next.delete(id)}\n return next\n })\n\n const succeeded = results.filter(\n (r) => r.status === 'fulfilled' && r.value,\n ).length\n const failed = ids.length - succeeded\n\n if (failed === 0) {\n setActionFeedback({\n type: 'success',\n message: `${succeeded} ${t('reservation:pendingConfirmSuccess').toLowerCase()}`,\n })\n } else {\n setActionFeedback({\n type: failed === ids.length ? 'error' : 'success',\n message: t('reservation:pendingBulkConfirmSuccess')\n .replace('{{succeeded}}', String(succeeded))\n .replace('{{failed}}', String(failed)),\n })\n }\n\n setSelectedIds(new Set())\n void fetchPendingReservations()\n void fetchPendingCount()\n }, [selectedIds, patchReservation, fetchPendingReservations, fetchPendingCount, t, confirmStatus])\n\n const handleEventClick = useCallback((e: React.MouseEvent, id: string) => {\n e.stopPropagation()\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const handleEventKeyDown = useCallback((e: React.KeyboardEvent, id: string) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }\n }, [])\n\n const handleCreateNew = useCallback(() => {\n setDrawerDocId(null)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const handleDateClick = useCallback((date: Date) => {\n setDrawerDocId(null)\n setInitialData({ startTime: date.toISOString() })\n pendingDrawerOpen.current = true\n }, [])\n\n const openDocDrawer = useCallback((id: string) => {\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n setCurrentDate((prev) => {\n const next = new Date(prev)\n if (viewMode === 'month') {\n next.setMonth(next.getMonth() + direction)\n } else if (viewMode === 'week') {\n next.setDate(next.getDate() + 7 * direction)\n } else {\n next.setDate(next.getDate() + direction)\n }\n return next\n })\n },\n [viewMode],\n )\n\n const goToToday = useCallback(() => setCurrentDate(new Date()), [])\n\n const getResName = (field: { name?: string } | string | undefined): string => {\n if (!field) {return ''}\n if (typeof field === 'string') {return ''}\n return field.name ?? ''\n }\n\n const getCustomerName = (field: Reservation['customer']): string => {\n if (!field) {return ''}\n if (typeof field === 'string') {return ''}\n const parts = [field.firstName, field.lastName].filter(Boolean)\n return parts.length > 0 ? parts.join(' ') : (field.name ?? '')\n }\n\n const getEventLabel = (r: Reservation, compact: boolean) => {\n const time = new Date(r.startTime).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\n const serviceName = getResName(r.service)\n if (compact) {\n return `${time} ${serviceName}`.trim()\n }\n const customerName = getCustomerName(r.customer)\n const parts = [time, serviceName, customerName].filter(Boolean)\n return parts.join(' - ')\n }\n\n // Returns all resource names for a reservation — from items array if present, otherwise top-level resource\n const getResourceNames = (r: Reservation): string[] => {\n if (r.items && r.items.length > 0) {\n const names = r.items\n .map((item) => getResName(item.resource))\n .filter((name) => name.length > 0)\n if (names.length > 0) {return names}\n }\n const single = getResName(r.resource)\n return single ? [single] : []\n }\n\n const getEventTooltip = (r: Reservation): string => {\n const serviceName = getResName(r.service) || t('reservation:calendarUnknownService')\n const startStr = new Date(r.startTime).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\n const endStr = r.endTime\n ? new Date(r.endTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n : '?'\n const customerName = getCustomerName(r.customer) || t('reservation:calendarUnknownCustomer')\n const resourceNames = getResourceNames(r)\n const resourceStr =\n resourceNames.length > 0\n ? resourceNames.join(', ')\n : t('reservation:calendarUnknownResource')\n const status = STATUS_LABELS[r.status] ?? r.status\n return [\n serviceName,\n `${startStr} - ${endStr}`,\n `${t('reservation:tooltipCustomer')} ${customerName}`,\n `${t('reservation:tooltipResource')} ${resourceStr}`,\n `${t('reservation:tooltipStatus')} ${status}`,\n ].join('\\n')\n }\n\n const renderEventItem = (r: Reservation, compact: boolean) => {\n // Use CSS class for built-in statuses; also apply inline background for custom statuses\n const cssClass = STATUS_CLASS_MAP[r.status] ?? ''\n const color = STATUS_COLORS[r.status]\n // Only apply inline style when there's no CSS class (custom statuses) or as a supplement\n const inlineStyle = cssClass ? undefined : { background: color }\n return (\n <div\n className={`${styles.eventItem} ${cssClass}`}\n key={r.id}\n onClick={(e) => handleEventClick(e, r.id)}\n onKeyDown={(e) => handleEventKeyDown(e, r.id)}\n role=\"button\"\n style={inlineStyle}\n tabIndex={0}\n title={getEventTooltip(r)}\n >\n {getEventLabel(r, compact)}\n </div>\n )\n }\n\n // Dynamic legend: iterates all statuses from the status machine config\n const renderStatusLegend = () => {\n const statuses = statusMachine?.statuses ?? Object.keys(BUILTIN_STATUS_COLORS)\n return (\n <div className={styles.statusLegend}>\n {statuses.map((key) => (\n <div className={styles.legendItem} key={key}>\n <span className={styles.legendDot} style={{ background: STATUS_COLORS[key] }} />\n {STATUS_LABELS[key] ?? key}\n </div>\n ))}\n </div>\n )\n }\n\n const renderCurrentTimeLine = (cellDate: Date, cellHour: number) => {\n const now = new Date()\n if (\n now.getFullYear() !== cellDate.getFullYear() ||\n now.getMonth() !== cellDate.getMonth() ||\n now.getDate() !== cellDate.getDate() ||\n now.getHours() !== cellHour\n ) {\n return null\n }\n const topPercent = (now.getMinutes() / 60) * 100\n return <div className={styles.currentTimeLine} style={{ top: `${topPercent}%` }} />\n }\n\n const renderMonthView = () => {\n const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1)\n const startDay = new Date(firstDay)\n startDay.setDate(startDay.getDate() - startDay.getDay())\n\n const days: Date[] = []\n const d = new Date(startDay)\n for (let i = 0; i < 42; i++) {\n days.push(new Date(d))\n d.setDate(d.getDate() + 1)\n }\n\n const today = new Date()\n const todayStr = `${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`\n\n return (\n <div className={styles.monthGrid}>\n {[\n t('reservation:dayShortSun'),\n t('reservation:dayShortMon'),\n t('reservation:dayShortTue'),\n t('reservation:dayShortWed'),\n t('reservation:dayShortThu'),\n t('reservation:dayShortFri'),\n t('reservation:dayShortSat'),\n ].map((d) => (\n <div className={styles.dayHeader} key={d}>\n {d}\n </div>\n ))}\n {days.map((day, i) => {\n const dayStr = `${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`\n const isToday = dayStr === todayStr\n const isOtherMonth = day.getMonth() !== currentDate.getMonth()\n const dayReservations = reservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === day.getFullYear() &&\n rDate.getMonth() === day.getMonth() &&\n rDate.getDate() === day.getDate()\n )\n })\n\n const clickDate = new Date(day)\n clickDate.setHours(9, 0, 0, 0)\n\n return (\n <div\n className={`${styles.dayCell} ${isOtherMonth ? styles.dayCellOtherMonth : ''} ${isToday ? styles.dayCellToday : ''}`}\n key={i}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n <div className={styles.dayNumber}>{day.getDate()}</div>\n {dayReservations.map((r) => renderEventItem(r, true))}\n </div>\n )\n })}\n </div>\n )\n }\n\n const renderWeekView = () => {\n const startOfWeek = new Date(currentDate)\n startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay())\n startOfWeek.setHours(0, 0, 0, 0)\n\n const weekDays: Date[] = []\n for (let i = 0; i < 7; i++) {\n const d = new Date(startOfWeek)\n d.setDate(d.getDate() + i)\n weekDays.push(d)\n }\n\n const hours = Array.from({ length: 12 }, (_, i) => i + 7)\n\n return (\n <div className={styles.weekView}>\n <div className={styles.dayHeader} />\n {weekDays.map((d, i) => (\n <div className={styles.dayHeader} key={i}>\n {d.toLocaleDateString([], { day: 'numeric', month: 'numeric', weekday: 'short' })}\n </div>\n ))}\n {hours.map((hour) => (\n <Fragment key={`row-${hour}`}>\n <div className={styles.timeLabel}>\n {hour.toString().padStart(2, '0')}:00\n </div>\n {weekDays.map((day, di) => {\n const cellReservations = reservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === day.getFullYear() &&\n rDate.getMonth() === day.getMonth() &&\n rDate.getDate() === day.getDate() &&\n rDate.getHours() === hour\n )\n })\n const clickDate = new Date(day)\n clickDate.setHours(hour, 0, 0, 0)\n return (\n <div\n className={styles.weekCell}\n key={`cell-${hour}-${di}`}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {renderCurrentTimeLine(day, hour)}\n {cellReservations.map((r) => renderEventItem(r, false))}\n </div>\n )\n })}\n </Fragment>\n ))}\n </div>\n )\n }\n\n const renderDayView = () => {\n const hours = Array.from({ length: 14 }, (_, i) => i + 7)\n\n return (\n <div className={styles.dayView}>\n {hours.map((hour) => {\n const hourReservations = reservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === currentDate.getFullYear() &&\n rDate.getMonth() === currentDate.getMonth() &&\n rDate.getDate() === currentDate.getDate() &&\n rDate.getHours() === hour\n )\n })\n const clickDate = new Date(currentDate)\n clickDate.setHours(hour, 0, 0, 0)\n return (\n <Fragment key={`row-${hour}`}>\n <div className={styles.timeLabel}>\n {hour.toString().padStart(2, '0')}:00\n </div>\n <div\n className={styles.dayViewCell}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {renderCurrentTimeLine(currentDate, hour)}\n {hourReservations.map((r) => renderEventItem(r, false))}\n </div>\n </Fragment>\n )\n })}\n </div>\n )\n }\n\n const renderPendingView = () => {\n if (pendingReservations.length === 0) {\n return <div className={styles.pendingEmpty}>{t('reservation:pendingEmpty')}</div>\n }\n\n const allSelected =\n pendingReservations.length > 0 &&\n pendingReservations.every((r) => selectedIds.has(r.id))\n\n const toggleSelectAll = () => {\n if (allSelected) {\n setSelectedIds(new Set())\n } else {\n setSelectedIds(new Set(pendingReservations.map((r) => r.id)))\n }\n }\n\n const toggleSelect = (id: string) => {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }\n\n const formatDateTime = (iso: string) => {\n const d = new Date(iso)\n return d.toLocaleString([], {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'short',\n year: 'numeric',\n })\n }\n\n return (\n <div className={styles.pendingView}>\n <div className={styles.pendingToolbar}>\n <label className={styles.selectAllLabel}>\n <input\n aria-label={t('reservation:pendingSelectAll')}\n checked={allSelected}\n onChange={toggleSelectAll}\n type=\"checkbox\"\n />\n {t('reservation:pendingSelectAll')}\n </label>\n {selectedIds.size > 0 && (\n <button\n className={styles.bulkConfirmButton}\n disabled={confirmingIds.size > 0}\n onClick={() => void confirmSelected()}\n type=\"button\"\n >\n {confirmingIds.size > 0\n ? t('reservation:pendingConfirming')\n : t('reservation:pendingConfirmSelected').replace(\n '{{count}}',\n String(selectedIds.size),\n )}\n </button>\n )}\n </div>\n {actionFeedback && (\n <div\n className={`${styles.feedbackToast} ${actionFeedback.type === 'success' ? styles.feedbackSuccess : styles.feedbackError}`}\n >\n {actionFeedback.message}\n </div>\n )}\n <table className={styles.pendingTable}>\n <thead>\n <tr>\n <th aria-label={t('reservation:pendingSelectAll')} className={styles.pendingTh} />\n <th className={styles.pendingTh}>{t('reservation:fieldCustomer')}</th>\n <th className={styles.pendingTh}>{t('reservation:fieldService')}</th>\n <th className={styles.pendingTh}>{t('reservation:fieldResource')}</th>\n <th className={styles.pendingTh}>{t('reservation:pendingDateTime')}</th>\n <th className={styles.pendingTh}>{t('reservation:pendingActions')}</th>\n </tr>\n </thead>\n <tbody>\n {pendingReservations.map((r) => {\n const isConfirming = confirmingIds.has(r.id)\n // Show all resources from items array if present, else top-level resource\n const resourceDisplay =\n getResourceNames(r).join(', ') || t('reservation:calendarUnknownResource')\n return (\n <tr className={styles.pendingRow} key={r.id}>\n <td className={styles.pendingTd}>\n <input\n aria-label={getCustomerName(r.customer) || r.id}\n checked={selectedIds.has(r.id)}\n onChange={() => toggleSelect(r.id)}\n type=\"checkbox\"\n />\n </td>\n <td className={styles.pendingTd}>\n <span\n className={styles.pendingCustomerLink}\n onClick={() => openDocDrawer(r.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDocDrawer(r.id)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {getCustomerName(r.customer) || t('reservation:calendarUnknownCustomer')}\n </span>\n </td>\n <td className={styles.pendingTd}>\n {getResName(r.service) || t('reservation:calendarUnknownService')}\n </td>\n <td className={styles.pendingTd}>{resourceDisplay}</td>\n <td className={styles.pendingTd}>{formatDateTime(r.startTime)}</td>\n <td className={styles.pendingTd}>\n <button\n className={styles.confirmButton}\n disabled={isConfirming}\n onClick={() => void handleQuickConfirm(r.id)}\n title={t('reservation:pendingConfirm')}\n type=\"button\"\n >\n &#x2713;\n </button>\n <button\n className={styles.cancelButton}\n disabled={isConfirming}\n onClick={() => void handleQuickCancel(r.id)}\n title={t('reservation:pendingCancel')}\n type=\"button\"\n >\n &#x2717;\n </button>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n }\n\n const dateLabel = useMemo(() => {\n if (viewMode === 'month') {\n return currentDate.toLocaleDateString([], { month: 'long', year: 'numeric' })\n }\n if (viewMode === 'week') {\n const startOfWeek = new Date(currentDate)\n startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay())\n const endOfWeek = new Date(startOfWeek)\n endOfWeek.setDate(endOfWeek.getDate() + 6)\n return `${startOfWeek.toLocaleDateString([], { day: 'numeric', month: 'short' })} - ${endOfWeek.toLocaleDateString([], { day: 'numeric', month: 'short', year: 'numeric' })}`\n }\n return currentDate.toLocaleDateString([], {\n day: 'numeric',\n month: 'long',\n weekday: 'long',\n year: 'numeric',\n })\n }, [currentDate, viewMode])\n\n const handleDrawerSave = useCallback(() => {\n void fetchReservations()\n void fetchPendingCount()\n if (viewMode === 'pending') {\n void fetchPendingReservations()\n }\n }, [fetchReservations, fetchPendingCount, fetchPendingReservations, viewMode])\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n {viewMode !== 'pending' && (\n <div className={styles.navButtons}>\n <button className={styles.navButton} onClick={() => navigate(-1)} type=\"button\">\n &larr;\n </button>\n <button className={styles.navButton} onClick={goToToday} type=\"button\">\n {t('reservation:calendarToday')}\n </button>\n <button className={styles.navButton} onClick={() => navigate(1)} type=\"button\">\n &rarr;\n </button>\n <span className={styles.currentDate}>{dateLabel}</span>\n </div>\n )}\n {viewMode === 'pending' && <div />}\n <div className={styles.viewToggle}>\n <button className={styles.createButton} onClick={handleCreateNew} type=\"button\">\n {t('reservation:calendarCreateNew')}\n </button>\n {([\n { key: 'month' as ViewMode, label: t('reservation:calendarMonth') },\n { key: 'week' as ViewMode, label: t('reservation:calendarWeek') },\n { key: 'day' as ViewMode, label: t('reservation:calendarDay') },\n { key: 'pending' as ViewMode, label: t('reservation:calendarPending') },\n ]).map(({ key, label }) => (\n <button\n className={`${styles.viewToggleButton} ${viewMode === key ? styles.viewToggleButtonActive : ''}`}\n key={key}\n onClick={() => setViewMode(key)}\n type=\"button\"\n >\n {label}\n {key === 'pending' && pendingCount > 0 && (\n <span className={styles.pendingBadge}>{pendingCount}</span>\n )}\n </button>\n ))}\n </div>\n </div>\n {viewMode !== 'pending' && renderStatusLegend()}\n {loading && viewMode !== 'pending' ? (\n <div className={styles.loading}>{t('reservation:calendarLoading')}</div>\n ) : (\n <>\n {viewMode === 'month' && renderMonthView()}\n {viewMode === 'week' && renderWeekView()}\n {viewMode === 'day' && renderDayView()}\n </>\n )}\n {viewMode === 'pending' && renderPendingView()}\n <DocumentDrawer initialData={initialData} onSave={handleDrawerSave} />\n </div>\n )\n}\n"],"names":["useConfig","useDocumentDrawer","useTranslation","React","Fragment","useCallback","useEffect","useMemo","useRef","useState","styles","STATUS_CLASS_MAP","cancelled","statusCancelled","completed","statusCompleted","confirmed","statusConfirmed","statusNoShow","pending","statusPending","BUILTIN_STATUS_COLORS","CUSTOM_STATUS_PALETTE","CalendarView","config","t","_t","slugs","admin","custom","reservationSlugs","reservationSlug","reservations","apiUrl","serverURL","routes","api","statusMachine","reservationStatusMachine","defaultStatus","STATUS_COLORS","colors","statuses","forEach","s","i","length","cancelStatus","confirmStatus","terminalStatuses","transitions","defaultTransitions","nonTerminal","find","includes","terminal","STATUS_LABELS","labels","key","charAt","toUpperCase","slice","replace","m","translated","currentDate","setCurrentDate","Date","viewMode","setViewMode","setReservations","loading","setLoading","drawerDocId","setDrawerDocId","initialData","setInitialData","undefined","pendingReservations","setPendingReservations","pendingCount","setPendingCount","selectedIds","setSelectedIds","Set","confirmingIds","setConfirmingIds","actionFeedback","setActionFeedback","DocumentDrawer","openDrawer","id","collectionSlug","pendingDrawerOpen","current","rangeEnd","rangeStart","start","end","setDate","getDate","getDay","setMonth","getMonth","dayOfWeek","setHours","fetchReservations","params","URLSearchParams","depth","limit","sort","toISOString","response","fetch","result","json","docs","fetchPendingCount","totalDocs","fetchPendingReservations","timer","setTimeout","clearTimeout","patchReservation","data","body","JSON","stringify","headers","method","ok","handleQuickConfirm","prev","add","status","next","delete","type","message","handleQuickCancel","confirmSelected","ids","Array","from","results","Promise","allSettled","map","succeeded","filter","r","value","failed","toLowerCase","String","handleEventClick","e","stopPropagation","handleEventKeyDown","preventDefault","handleCreateNew","handleDateClick","date","startTime","openDocDrawer","navigate","direction","goToToday","getResName","field","name","getCustomerName","parts","firstName","lastName","Boolean","join","getEventLabel","compact","time","toLocaleTimeString","hour","minute","serviceName","service","trim","customerName","customer","getResourceNames","items","names","item","resource","single","getEventTooltip","startStr","endStr","endTime","resourceNames","resourceStr","renderEventItem","cssClass","color","inlineStyle","background","div","className","eventItem","onClick","onKeyDown","role","style","tabIndex","title","renderStatusLegend","Object","keys","statusLegend","legendItem","span","legendDot","renderCurrentTimeLine","cellDate","cellHour","now","getFullYear","getHours","topPercent","getMinutes","currentTimeLine","top","renderMonthView","firstDay","startDay","days","d","push","today","todayStr","monthGrid","dayHeader","day","dayStr","isToday","isOtherMonth","dayReservations","rDate","clickDate","dayCell","dayCellOtherMonth","dayCellToday","dayNumber","renderWeekView","startOfWeek","weekDays","hours","_","weekView","toLocaleDateString","month","weekday","timeLabel","toString","padStart","di","cellReservations","weekCell","renderDayView","dayView","hourReservations","dayViewCell","renderPendingView","pendingEmpty","allSelected","every","has","toggleSelectAll","toggleSelect","formatDateTime","iso","toLocaleString","year","pendingView","pendingToolbar","label","selectAllLabel","input","aria-label","checked","onChange","size","button","bulkConfirmButton","disabled","feedbackToast","feedbackSuccess","feedbackError","table","pendingTable","thead","tr","th","pendingTh","tbody","isConfirming","resourceDisplay","pendingRow","td","pendingTd","pendingCustomerLink","confirmButton","cancelButton","dateLabel","endOfWeek","handleDrawerSave","wrapper","header","navButtons","navButton","viewToggle","createButton","viewToggleButton","viewToggleButtonActive","pendingBadge","onSave"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/CalendarView/index.tsx"],"sourcesContent":["'use client'\nimport type { AdminViewServerProps } from 'payload'\n\nimport { useConfig, useDocumentDrawer, useTranslation } from '@payloadcms/ui'\nimport React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { PluginT } from '../../translations/index.js'\n\nimport { statusToI18nKey } from '../../utilities/i18nUtils.js'\nimport styles from './CalendarView.module.css'\n\ntype ViewMode = 'day' | 'month' | 'pending' | 'week'\n\ntype ReservationItem = {\n endTime?: string\n guestCount?: number\n resource?: { id?: string; name?: string } | string\n service?: { name?: string } | string\n startTime?: string\n}\n\ntype Reservation = {\n customer?: { firstName?: string; lastName?: string; name?: string } | string\n endTime?: string\n id: string\n items?: ReservationItem[]\n resource?: { id?: string; name?: string } | string\n service?: { name?: string } | string\n startTime: string\n status: string\n}\n\ntype ResourceOption = {\n id: string\n name: string\n}\n\n// Built-in status → CSS class map (for known statuses; custom statuses use inline style)\nconst STATUS_CLASS_MAP: Record<string, string> = {\n cancelled: styles.statusCancelled,\n completed: styles.statusCompleted,\n confirmed: styles.statusConfirmed,\n 'no-show': styles.statusNoShow,\n pending: styles.statusPending,\n}\n\n// Built-in default colors for known statuses\nconst BUILTIN_STATUS_COLORS: Record<string, string> = {\n cancelled: '#e5e7eb',\n completed: '#d1fae5',\n confirmed: '#dbeafe',\n 'no-show': '#fee2e2',\n pending: '#fef3c7',\n}\n\n// Palette for auto-assigning colors to custom statuses\nconst CUSTOM_STATUS_PALETTE = ['#fde68a', '#c7d2fe', '#a7f3d0', '#fca5a5', '#fdba74']\n\nexport const CalendarView: React.FC<AdminViewServerProps> = () => {\n const { config } = useConfig()\n const { t: _t } = useTranslation()\n const t = _t as PluginT\n\n const slugs = config.admin?.custom?.reservationSlugs\n const reservationSlug = slugs?.reservations ?? 'reservations'\n const apiUrl = `${config.serverURL ?? ''}${config.routes.api}/${reservationSlug}`\n\n const statusMachine = config.admin?.custom?.reservationStatusMachine as\n | {\n blockingStatuses?: string[]\n defaultStatus?: string\n statuses?: string[]\n terminalStatuses?: string[]\n transitions?: Record<string, string[]>\n }\n | undefined\n\n // The initial/pending status (what \"pending\" view shows)\n const defaultStatus = statusMachine?.defaultStatus ?? 'pending'\n\n // Build STATUS_COLORS dynamically: built-ins first, then auto-assign palette for custom statuses\n const STATUS_COLORS = useMemo<Record<string, string>>(() => {\n const colors = { ...BUILTIN_STATUS_COLORS }\n const statuses = statusMachine?.statuses ?? []\n statuses.forEach((s, i) => {\n if (!colors[s]) {\n colors[s] = CUSTOM_STATUS_PALETTE[i % CUSTOM_STATUS_PALETTE.length]\n }\n })\n return colors\n }, [statusMachine])\n\n // Derive confirm/cancel target statuses from config transitions\n // \"confirm\" = first non-terminal transition from defaultStatus\n // \"cancel\" = first terminal transition from defaultStatus (or fallback: 'cancelled')\n const { cancelStatus, confirmStatus } = useMemo(() => {\n const terminalStatuses = statusMachine?.terminalStatuses ?? ['completed', 'cancelled', 'no-show']\n const transitions = statusMachine?.transitions ?? {}\n const defaultTransitions: string[] = transitions[defaultStatus] ?? []\n\n const nonTerminal = defaultTransitions.find((s) => !terminalStatuses.includes(s))\n const terminal = defaultTransitions.find((s) => terminalStatuses.includes(s))\n\n return {\n cancelStatus: terminal ?? 'cancelled',\n confirmStatus: nonTerminal ?? 'confirmed',\n }\n }, [statusMachine, defaultStatus])\n\n const STATUS_LABELS = useMemo<Record<string, string>>(() => {\n const statuses = statusMachine?.statuses ?? [\n 'pending',\n 'confirmed',\n 'completed',\n 'cancelled',\n 'no-show',\n ]\n const labels: Record<string, string> = {}\n for (const s of statuses) {\n // Attempt to look up a translation key, e.g. reservation:statusPending\n const key = statusToI18nKey(s)\n const translated = t(key)\n // If translation returns the key itself, it's missing — fall back to capitalized status name\n labels[s] = translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1)\n }\n return labels\n }, [statusMachine, t])\n\n const [currentDate, setCurrentDate] = useState(() => new Date())\n const [viewMode, setViewMode] = useState<ViewMode>('month')\n const [reservations, setReservations] = useState<Reservation[]>([])\n const [loading, setLoading] = useState(true)\n const [drawerDocId, setDrawerDocId] = useState<null | string>(null)\n const [initialData, setInitialData] = useState<Record<string, unknown> | undefined>(undefined)\n\n // Resource filter state\n const [resources, setResources] = useState<ResourceOption[]>([])\n const [selectedResourceId, setSelectedResourceId] = useState<string>('')\n\n // Pending tab state\n const [pendingReservations, setPendingReservations] = useState<Reservation[]>([])\n const [pendingCount, setPendingCount] = useState(0)\n const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set())\n const [confirmingIds, setConfirmingIds] = useState<Set<string>>(() => new Set())\n const [actionFeedback, setActionFeedback] = useState<{\n message: string\n type: 'error' | 'success'\n } | null>(null)\n\n const [DocumentDrawer, , { openDrawer }] = useDocumentDrawer({\n id: drawerDocId ?? undefined,\n collectionSlug: reservationSlug,\n })\n\n const pendingDrawerOpen = useRef(false)\n\n useEffect(() => {\n if (pendingDrawerOpen.current) {\n pendingDrawerOpen.current = false\n openDrawer()\n }\n })\n\n // Fetch active resources for filter dropdown\n useEffect(() => {\n const fetchResources = async () => {\n try {\n const resourceSlug = slugs?.resources ?? 'resources'\n const params = new URLSearchParams({\n depth: '0',\n limit: '100',\n sort: 'name',\n 'where[active][equals]': 'true',\n })\n const url = `${config.serverURL ?? ''}${config.routes.api}/${resourceSlug}?${params}`\n const response = await fetch(url)\n const result = await response.json()\n const docs: Array<{ id: string; name?: string }> = result.docs ?? []\n setResources(docs.map((d) => ({ id: d.id, name: d.name ?? '' })))\n } catch {\n setResources([])\n }\n }\n void fetchResources()\n }, [config.routes.api, config.serverURL, slugs?.resources])\n\n const { rangeEnd, rangeStart } = useMemo(() => {\n const start = new Date(currentDate)\n const end = new Date(currentDate)\n\n if (viewMode === 'month') {\n start.setDate(1)\n start.setDate(start.getDate() - start.getDay())\n end.setMonth(end.getMonth() + 1, 0)\n end.setDate(end.getDate() + (6 - end.getDay()))\n } else if (viewMode === 'week') {\n const dayOfWeek = start.getDay()\n start.setDate(start.getDate() - dayOfWeek)\n end.setDate(start.getDate() + 6)\n }\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n\n return { rangeEnd: end, rangeStart: start }\n }, [currentDate, viewMode])\n\n const fetchReservations = useCallback(async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams({\n depth: '1',\n limit: '500',\n sort: 'startTime',\n 'where[startTime][greater_than_equal]': rangeStart.toISOString(),\n 'where[startTime][less_than_equal]': rangeEnd.toISOString(),\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setReservations(result.docs ?? [])\n } catch {\n setReservations([])\n }\n setLoading(false)\n }, [rangeStart, rangeEnd, apiUrl])\n\n useEffect(() => {\n void fetchReservations()\n }, [fetchReservations])\n\n // Fetch pending count (always, for badge) — uses defaultStatus from config\n const fetchPendingCount = useCallback(async () => {\n try {\n const params = new URLSearchParams({\n limit: '0',\n 'where[status][equals]': defaultStatus,\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setPendingCount(result.totalDocs ?? 0)\n } catch {\n // silently ignore\n }\n }, [apiUrl, defaultStatus])\n\n useEffect(() => {\n void fetchPendingCount()\n }, [fetchPendingCount])\n\n // Fetch pending reservations when tab is active — uses defaultStatus from config\n const fetchPendingReservations = useCallback(async () => {\n try {\n const params = new URLSearchParams({\n depth: '1',\n limit: '500',\n sort: 'startTime',\n 'where[status][equals]': defaultStatus,\n })\n const response = await fetch(`${apiUrl}?${params}`)\n const result = await response.json()\n setPendingReservations(result.docs ?? [])\n } catch {\n setPendingReservations([])\n }\n }, [apiUrl, defaultStatus])\n\n useEffect(() => {\n if (viewMode === 'pending') {\n void fetchPendingReservations()\n }\n }, [viewMode, fetchPendingReservations])\n\n // Client-side resource filtering\n const matchesResourceFilter = useCallback(\n (r: Reservation): boolean => {\n if (!selectedResourceId) {return true}\n // Check top-level resource\n const topId = typeof r.resource === 'string' ? r.resource : r.resource?.id\n if (topId === selectedResourceId) {return true}\n // Check items array for multi-resource bookings\n if (r.items && r.items.length > 0) {\n return r.items.some((item) => {\n const itemId =\n typeof item.resource === 'string' ? item.resource : item.resource?.id\n return itemId === selectedResourceId\n })\n }\n return false\n },\n [selectedResourceId],\n )\n\n const filteredReservations = useMemo(\n () => reservations.filter(matchesResourceFilter),\n [reservations, matchesResourceFilter],\n )\n\n const filteredPendingReservations = useMemo(\n () => pendingReservations.filter(matchesResourceFilter),\n [pendingReservations, matchesResourceFilter],\n )\n\n // Clear selection when leaving pending view or changing resource filter\n useEffect(() => {\n if (viewMode !== 'pending') {\n setSelectedIds(new Set())\n setActionFeedback(null)\n }\n }, [viewMode])\n\n useEffect(() => {\n setSelectedIds(new Set())\n }, [selectedResourceId])\n\n // Auto-clear feedback toast\n useEffect(() => {\n if (!actionFeedback) {return}\n const timer = setTimeout(() => setActionFeedback(null), 4000)\n return () => clearTimeout(timer)\n }, [actionFeedback])\n\n const patchReservation = useCallback(\n async (id: string, data: Record<string, unknown>): Promise<boolean> => {\n try {\n const response = await fetch(`${apiUrl}/${id}`, {\n body: JSON.stringify(data),\n headers: { 'Content-Type': 'application/json' },\n method: 'PATCH',\n })\n return response.ok\n } catch {\n return false\n }\n },\n [apiUrl],\n )\n\n // Uses confirmStatus derived from config transitions\n const handleQuickConfirm = useCallback(\n async (id: string) => {\n setConfirmingIds((prev) => new Set(prev).add(id))\n const ok = await patchReservation(id, { status: confirmStatus })\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setActionFeedback({\n type: ok ? 'success' : 'error',\n message: ok\n ? t('reservation:pendingConfirmSuccess')\n : t('reservation:pendingConfirmError'),\n })\n if (ok) {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n void fetchPendingReservations()\n void fetchPendingCount()\n }\n },\n [patchReservation, fetchPendingReservations, fetchPendingCount, t, confirmStatus],\n )\n\n // Uses cancelStatus derived from config transitions\n const handleQuickCancel = useCallback(\n async (id: string) => {\n setConfirmingIds((prev) => new Set(prev).add(id))\n const ok = await patchReservation(id, { status: cancelStatus })\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setActionFeedback({\n type: ok ? 'success' : 'error',\n message: ok\n ? t('reservation:pendingCancelSuccess')\n : t('reservation:pendingCancelError'),\n })\n if (ok) {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n void fetchPendingReservations()\n void fetchPendingCount()\n }\n },\n [patchReservation, fetchPendingReservations, fetchPendingCount, t, cancelStatus],\n )\n\n const confirmSelected = useCallback(async () => {\n const ids = Array.from(selectedIds)\n if (ids.length === 0) {return}\n\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n for (const id of ids) {next.add(id)}\n return next\n })\n\n const results = await Promise.allSettled(\n ids.map((id) => patchReservation(id, { status: confirmStatus })),\n )\n\n setConfirmingIds((prev) => {\n const next = new Set(prev)\n for (const id of ids) {next.delete(id)}\n return next\n })\n\n const succeeded = results.filter(\n (r) => r.status === 'fulfilled' && r.value,\n ).length\n const failed = ids.length - succeeded\n\n if (failed === 0) {\n setActionFeedback({\n type: 'success',\n message: `${succeeded} ${t('reservation:pendingConfirmSuccess').toLowerCase()}`,\n })\n } else {\n setActionFeedback({\n type: failed === ids.length ? 'error' : 'success',\n message: t('reservation:pendingBulkConfirmSuccess')\n .replace('{{succeeded}}', String(succeeded))\n .replace('{{failed}}', String(failed)),\n })\n }\n\n setSelectedIds(new Set())\n void fetchPendingReservations()\n void fetchPendingCount()\n }, [selectedIds, patchReservation, fetchPendingReservations, fetchPendingCount, t, confirmStatus])\n\n const handleEventClick = useCallback((e: React.MouseEvent, id: string) => {\n e.stopPropagation()\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const handleEventKeyDown = useCallback((e: React.KeyboardEvent, id: string) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }\n }, [])\n\n const handleCreateNew = useCallback(() => {\n setDrawerDocId(null)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const handleDateClick = useCallback((date: Date) => {\n setDrawerDocId(null)\n setInitialData({ startTime: date.toISOString() })\n pendingDrawerOpen.current = true\n }, [])\n\n const openDocDrawer = useCallback((id: string) => {\n setDrawerDocId(id)\n setInitialData(undefined)\n pendingDrawerOpen.current = true\n }, [])\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n setCurrentDate((prev) => {\n const next = new Date(prev)\n if (viewMode === 'month') {\n next.setMonth(next.getMonth() + direction)\n } else if (viewMode === 'week') {\n next.setDate(next.getDate() + 7 * direction)\n } else {\n next.setDate(next.getDate() + direction)\n }\n return next\n })\n },\n [viewMode],\n )\n\n const goToToday = useCallback(() => setCurrentDate(new Date()), [])\n\n const getResName = (field: { name?: string } | string | undefined): string => {\n if (!field) {return ''}\n if (typeof field === 'string') {return ''}\n return field.name ?? ''\n }\n\n const getCustomerName = (field: Reservation['customer']): string => {\n if (!field) {return ''}\n if (typeof field === 'string') {return ''}\n const parts = [field.firstName, field.lastName].filter(Boolean)\n return parts.length > 0 ? parts.join(' ') : (field.name ?? '')\n }\n\n const getEventLabel = (r: Reservation, compact: boolean) => {\n const time = new Date(r.startTime).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\n const serviceName = getResName(r.service)\n if (compact) {\n return `${time} ${serviceName}`.trim()\n }\n const customerName = getCustomerName(r.customer)\n const parts = [time, serviceName, customerName].filter(Boolean)\n return parts.join(' - ')\n }\n\n // Returns all resource names for a reservation — from items array if present, otherwise top-level resource\n const getResourceNames = (r: Reservation): string[] => {\n if (r.items && r.items.length > 0) {\n const names = r.items\n .map((item) => getResName(item.resource))\n .filter((name) => name.length > 0)\n if (names.length > 0) {return names}\n }\n const single = getResName(r.resource)\n return single ? [single] : []\n }\n\n const getEventTooltip = (r: Reservation): string => {\n const serviceName = getResName(r.service) || t('reservation:calendarUnknownService')\n const startStr = new Date(r.startTime).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\n const endStr = r.endTime\n ? new Date(r.endTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n : '?'\n const customerName = getCustomerName(r.customer) || t('reservation:calendarUnknownCustomer')\n const resourceNames = getResourceNames(r)\n const resourceStr =\n resourceNames.length > 0\n ? resourceNames.join(', ')\n : t('reservation:calendarUnknownResource')\n const status = STATUS_LABELS[r.status] ?? r.status\n return [\n serviceName,\n `${startStr} - ${endStr}`,\n `${t('reservation:tooltipCustomer')} ${customerName}`,\n `${t('reservation:tooltipResource')} ${resourceStr}`,\n `${t('reservation:tooltipStatus')} ${status}`,\n ].join('\\n')\n }\n\n const renderEventItem = (r: Reservation, compact: boolean) => {\n // Use CSS class for built-in statuses; also apply inline background for custom statuses\n const cssClass = STATUS_CLASS_MAP[r.status] ?? ''\n const color = STATUS_COLORS[r.status]\n // Only apply inline style when there's no CSS class (custom statuses) or as a supplement\n const inlineStyle = cssClass ? undefined : { background: color }\n return (\n <div\n className={`${styles.eventItem} ${cssClass}`}\n key={r.id}\n onClick={(e) => handleEventClick(e, r.id)}\n onKeyDown={(e) => handleEventKeyDown(e, r.id)}\n role=\"button\"\n style={inlineStyle}\n tabIndex={0}\n title={getEventTooltip(r)}\n >\n {getEventLabel(r, compact)}\n </div>\n )\n }\n\n // Dynamic legend: iterates all statuses from the status machine config\n const renderStatusLegend = () => {\n const statuses = statusMachine?.statuses ?? Object.keys(BUILTIN_STATUS_COLORS)\n return (\n <div className={styles.statusLegend}>\n {statuses.map((key) => (\n <div className={styles.legendItem} key={key}>\n <span className={styles.legendDot} style={{ background: STATUS_COLORS[key] }} />\n {STATUS_LABELS[key] ?? key}\n </div>\n ))}\n </div>\n )\n }\n\n const renderCurrentTimeLine = (cellDate: Date, cellHour: number) => {\n const now = new Date()\n if (\n now.getFullYear() !== cellDate.getFullYear() ||\n now.getMonth() !== cellDate.getMonth() ||\n now.getDate() !== cellDate.getDate() ||\n now.getHours() !== cellHour\n ) {\n return null\n }\n const topPercent = (now.getMinutes() / 60) * 100\n return <div className={styles.currentTimeLine} style={{ top: `${topPercent}%` }} />\n }\n\n const renderMonthView = () => {\n const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1)\n const startDay = new Date(firstDay)\n startDay.setDate(startDay.getDate() - startDay.getDay())\n\n const days: Date[] = []\n const d = new Date(startDay)\n for (let i = 0; i < 42; i++) {\n days.push(new Date(d))\n d.setDate(d.getDate() + 1)\n }\n\n const today = new Date()\n const todayStr = `${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`\n\n return (\n <div className={styles.monthGrid}>\n {[\n t('reservation:dayShortSun'),\n t('reservation:dayShortMon'),\n t('reservation:dayShortTue'),\n t('reservation:dayShortWed'),\n t('reservation:dayShortThu'),\n t('reservation:dayShortFri'),\n t('reservation:dayShortSat'),\n ].map((d) => (\n <div className={styles.dayHeader} key={d}>\n {d}\n </div>\n ))}\n {days.map((day, i) => {\n const dayStr = `${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`\n const isToday = dayStr === todayStr\n const isOtherMonth = day.getMonth() !== currentDate.getMonth()\n const dayReservations = filteredReservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === day.getFullYear() &&\n rDate.getMonth() === day.getMonth() &&\n rDate.getDate() === day.getDate()\n )\n })\n\n const clickDate = new Date(day)\n clickDate.setHours(9, 0, 0, 0)\n\n return (\n <div\n className={`${styles.dayCell} ${isOtherMonth ? styles.dayCellOtherMonth : ''} ${isToday ? styles.dayCellToday : ''}`}\n key={i}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n <div className={styles.dayNumber}>{day.getDate()}</div>\n {dayReservations.map((r) => renderEventItem(r, true))}\n </div>\n )\n })}\n </div>\n )\n }\n\n const renderWeekView = () => {\n const startOfWeek = new Date(currentDate)\n startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay())\n startOfWeek.setHours(0, 0, 0, 0)\n\n const weekDays: Date[] = []\n for (let i = 0; i < 7; i++) {\n const d = new Date(startOfWeek)\n d.setDate(d.getDate() + i)\n weekDays.push(d)\n }\n\n const hours = Array.from({ length: 12 }, (_, i) => i + 7)\n\n return (\n <div className={styles.weekView}>\n <div className={styles.dayHeader} />\n {weekDays.map((d, i) => (\n <div className={styles.dayHeader} key={i}>\n {d.toLocaleDateString([], { day: 'numeric', month: 'numeric', weekday: 'short' })}\n </div>\n ))}\n {hours.map((hour) => (\n <Fragment key={`row-${hour}`}>\n <div className={styles.timeLabel}>\n {hour.toString().padStart(2, '0')}:00\n </div>\n {weekDays.map((day, di) => {\n const cellReservations = filteredReservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === day.getFullYear() &&\n rDate.getMonth() === day.getMonth() &&\n rDate.getDate() === day.getDate() &&\n rDate.getHours() === hour\n )\n })\n const clickDate = new Date(day)\n clickDate.setHours(hour, 0, 0, 0)\n return (\n <div\n className={styles.weekCell}\n key={`cell-${hour}-${di}`}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {renderCurrentTimeLine(day, hour)}\n {cellReservations.map((r) => renderEventItem(r, false))}\n </div>\n )\n })}\n </Fragment>\n ))}\n </div>\n )\n }\n\n const renderDayView = () => {\n const hours = Array.from({ length: 14 }, (_, i) => i + 7)\n\n return (\n <div className={styles.dayView}>\n {hours.map((hour) => {\n const hourReservations = filteredReservations.filter((r) => {\n const rDate = new Date(r.startTime)\n return (\n rDate.getFullYear() === currentDate.getFullYear() &&\n rDate.getMonth() === currentDate.getMonth() &&\n rDate.getDate() === currentDate.getDate() &&\n rDate.getHours() === hour\n )\n })\n const clickDate = new Date(currentDate)\n clickDate.setHours(hour, 0, 0, 0)\n return (\n <Fragment key={`row-${hour}`}>\n <div className={styles.timeLabel}>\n {hour.toString().padStart(2, '0')}:00\n </div>\n <div\n className={styles.dayViewCell}\n onClick={() => handleDateClick(clickDate)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleDateClick(clickDate)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {renderCurrentTimeLine(currentDate, hour)}\n {hourReservations.map((r) => renderEventItem(r, false))}\n </div>\n </Fragment>\n )\n })}\n </div>\n )\n }\n\n const renderPendingView = () => {\n if (filteredPendingReservations.length === 0) {\n return <div className={styles.pendingEmpty}>{t('reservation:pendingEmpty')}</div>\n }\n\n const allSelected =\n filteredPendingReservations.length > 0 &&\n filteredPendingReservations.every((r) => selectedIds.has(r.id))\n\n const toggleSelectAll = () => {\n if (allSelected) {\n setSelectedIds(new Set())\n } else {\n setSelectedIds(new Set(filteredPendingReservations.map((r) => r.id)))\n }\n }\n\n const toggleSelect = (id: string) => {\n setSelectedIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }\n\n const formatDateTime = (iso: string) => {\n const d = new Date(iso)\n return d.toLocaleString([], {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'short',\n year: 'numeric',\n })\n }\n\n return (\n <div className={styles.pendingView}>\n <div className={styles.pendingToolbar}>\n <label className={styles.selectAllLabel}>\n <input\n aria-label={t('reservation:pendingSelectAll')}\n checked={allSelected}\n onChange={toggleSelectAll}\n type=\"checkbox\"\n />\n {t('reservation:pendingSelectAll')}\n </label>\n {selectedIds.size > 0 && (\n <button\n className={styles.bulkConfirmButton}\n disabled={confirmingIds.size > 0}\n onClick={() => void confirmSelected()}\n type=\"button\"\n >\n {confirmingIds.size > 0\n ? t('reservation:pendingConfirming')\n : t('reservation:pendingConfirmSelected').replace(\n '{{count}}',\n String(selectedIds.size),\n )}\n </button>\n )}\n </div>\n {actionFeedback && (\n <div\n className={`${styles.feedbackToast} ${actionFeedback.type === 'success' ? styles.feedbackSuccess : styles.feedbackError}`}\n >\n {actionFeedback.message}\n </div>\n )}\n <table className={styles.pendingTable}>\n <thead>\n <tr>\n <th aria-label={t('reservation:pendingSelectAll')} className={styles.pendingTh} />\n <th className={styles.pendingTh}>{t('reservation:fieldCustomer')}</th>\n <th className={styles.pendingTh}>{t('reservation:fieldService')}</th>\n <th className={styles.pendingTh}>{t('reservation:fieldResource')}</th>\n <th className={styles.pendingTh}>{t('reservation:pendingDateTime')}</th>\n <th className={styles.pendingTh}>{t('reservation:pendingActions')}</th>\n </tr>\n </thead>\n <tbody>\n {filteredPendingReservations.map((r) => {\n const isConfirming = confirmingIds.has(r.id)\n // Show all resources from items array if present, else top-level resource\n const resourceDisplay =\n getResourceNames(r).join(', ') || t('reservation:calendarUnknownResource')\n return (\n <tr className={styles.pendingRow} key={r.id}>\n <td className={styles.pendingTd}>\n <input\n aria-label={getCustomerName(r.customer) || r.id}\n checked={selectedIds.has(r.id)}\n onChange={() => toggleSelect(r.id)}\n type=\"checkbox\"\n />\n </td>\n <td className={styles.pendingTd}>\n <span\n className={styles.pendingCustomerLink}\n onClick={() => openDocDrawer(r.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDocDrawer(r.id)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {getCustomerName(r.customer) || t('reservation:calendarUnknownCustomer')}\n </span>\n </td>\n <td className={styles.pendingTd}>\n {getResName(r.service) || t('reservation:calendarUnknownService')}\n </td>\n <td className={styles.pendingTd}>{resourceDisplay}</td>\n <td className={styles.pendingTd}>{formatDateTime(r.startTime)}</td>\n <td className={styles.pendingTd}>\n <button\n className={styles.confirmButton}\n disabled={isConfirming}\n onClick={() => void handleQuickConfirm(r.id)}\n title={t('reservation:pendingConfirm')}\n type=\"button\"\n >\n &#x2713;\n </button>\n <button\n className={styles.cancelButton}\n disabled={isConfirming}\n onClick={() => void handleQuickCancel(r.id)}\n title={t('reservation:pendingCancel')}\n type=\"button\"\n >\n &#x2717;\n </button>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n }\n\n const dateLabel = useMemo(() => {\n if (viewMode === 'month') {\n return currentDate.toLocaleDateString([], { month: 'long', year: 'numeric' })\n }\n if (viewMode === 'week') {\n const startOfWeek = new Date(currentDate)\n startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay())\n const endOfWeek = new Date(startOfWeek)\n endOfWeek.setDate(endOfWeek.getDate() + 6)\n return `${startOfWeek.toLocaleDateString([], { day: 'numeric', month: 'short' })} - ${endOfWeek.toLocaleDateString([], { day: 'numeric', month: 'short', year: 'numeric' })}`\n }\n return currentDate.toLocaleDateString([], {\n day: 'numeric',\n month: 'long',\n weekday: 'long',\n year: 'numeric',\n })\n }, [currentDate, viewMode])\n\n const handleDrawerSave = useCallback(() => {\n void fetchReservations()\n void fetchPendingCount()\n if (viewMode === 'pending') {\n void fetchPendingReservations()\n }\n }, [fetchReservations, fetchPendingCount, fetchPendingReservations, viewMode])\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n {viewMode !== 'pending' && (\n <div className={styles.navButtons}>\n <button className={styles.navButton} onClick={() => navigate(-1)} type=\"button\">\n &larr;\n </button>\n <button className={styles.navButton} onClick={goToToday} type=\"button\">\n {t('reservation:calendarToday')}\n </button>\n <button className={styles.navButton} onClick={() => navigate(1)} type=\"button\">\n &rarr;\n </button>\n <span className={styles.currentDate}>{dateLabel}</span>\n </div>\n )}\n {viewMode === 'pending' && <div />}\n <div className={styles.viewToggle}>\n <button className={styles.createButton} onClick={handleCreateNew} type=\"button\">\n {t('reservation:calendarCreateNew')}\n </button>\n {([\n { key: 'month' as ViewMode, label: t('reservation:calendarMonth') },\n { key: 'week' as ViewMode, label: t('reservation:calendarWeek') },\n { key: 'day' as ViewMode, label: t('reservation:calendarDay') },\n { key: 'pending' as ViewMode, label: t('reservation:calendarPending') },\n ]).map(({ key, label }) => (\n <button\n className={`${styles.viewToggleButton} ${viewMode === key ? styles.viewToggleButtonActive : ''}`}\n key={key}\n onClick={() => setViewMode(key)}\n type=\"button\"\n >\n {label}\n {key === 'pending' && pendingCount > 0 && (\n <span className={styles.pendingBadge}>\n {selectedResourceId ? filteredPendingReservations.length : pendingCount}\n </span>\n )}\n </button>\n ))}\n </div>\n </div>\n {viewMode !== 'pending' && renderStatusLegend()}\n {resources.length > 1 && (\n <div className={styles.filterBar}>\n <select\n aria-label={t('reservation:filterByResource')}\n className={styles.resourceFilter}\n onChange={(e) => setSelectedResourceId(e.target.value)}\n value={selectedResourceId}\n >\n <option value=\"\">{t('reservation:filterAllResources')}</option>\n {resources.map((r) => (\n <option key={r.id} value={r.id}>\n {r.name}\n </option>\n ))}\n </select>\n </div>\n )}\n {loading && viewMode !== 'pending' ? (\n <div className={styles.loading}>{t('reservation:calendarLoading')}</div>\n ) : (\n <>\n {viewMode === 'month' && renderMonthView()}\n {viewMode === 'week' && renderWeekView()}\n {viewMode === 'day' && renderDayView()}\n </>\n )}\n {viewMode === 'pending' && renderPendingView()}\n <DocumentDrawer initialData={initialData} onSave={handleDrawerSave} />\n </div>\n )\n}\n"],"names":["useConfig","useDocumentDrawer","useTranslation","React","Fragment","useCallback","useEffect","useMemo","useRef","useState","statusToI18nKey","styles","STATUS_CLASS_MAP","cancelled","statusCancelled","completed","statusCompleted","confirmed","statusConfirmed","statusNoShow","pending","statusPending","BUILTIN_STATUS_COLORS","CUSTOM_STATUS_PALETTE","CalendarView","config","t","_t","slugs","admin","custom","reservationSlugs","reservationSlug","reservations","apiUrl","serverURL","routes","api","statusMachine","reservationStatusMachine","defaultStatus","STATUS_COLORS","colors","statuses","forEach","s","i","length","cancelStatus","confirmStatus","terminalStatuses","transitions","defaultTransitions","nonTerminal","find","includes","terminal","STATUS_LABELS","labels","key","translated","charAt","toUpperCase","slice","currentDate","setCurrentDate","Date","viewMode","setViewMode","setReservations","loading","setLoading","drawerDocId","setDrawerDocId","initialData","setInitialData","undefined","resources","setResources","selectedResourceId","setSelectedResourceId","pendingReservations","setPendingReservations","pendingCount","setPendingCount","selectedIds","setSelectedIds","Set","confirmingIds","setConfirmingIds","actionFeedback","setActionFeedback","DocumentDrawer","openDrawer","id","collectionSlug","pendingDrawerOpen","current","fetchResources","resourceSlug","params","URLSearchParams","depth","limit","sort","url","response","fetch","result","json","docs","map","d","name","rangeEnd","rangeStart","start","end","setDate","getDate","getDay","setMonth","getMonth","dayOfWeek","setHours","fetchReservations","toISOString","fetchPendingCount","totalDocs","fetchPendingReservations","matchesResourceFilter","r","topId","resource","items","some","item","itemId","filteredReservations","filter","filteredPendingReservations","timer","setTimeout","clearTimeout","patchReservation","data","body","JSON","stringify","headers","method","ok","handleQuickConfirm","prev","add","status","next","delete","type","message","handleQuickCancel","confirmSelected","ids","Array","from","results","Promise","allSettled","succeeded","value","failed","toLowerCase","replace","String","handleEventClick","e","stopPropagation","handleEventKeyDown","preventDefault","handleCreateNew","handleDateClick","date","startTime","openDocDrawer","navigate","direction","goToToday","getResName","field","getCustomerName","parts","firstName","lastName","Boolean","join","getEventLabel","compact","time","toLocaleTimeString","hour","minute","serviceName","service","trim","customerName","customer","getResourceNames","names","single","getEventTooltip","startStr","endStr","endTime","resourceNames","resourceStr","renderEventItem","cssClass","color","inlineStyle","background","div","className","eventItem","onClick","onKeyDown","role","style","tabIndex","title","renderStatusLegend","Object","keys","statusLegend","legendItem","span","legendDot","renderCurrentTimeLine","cellDate","cellHour","now","getFullYear","getHours","topPercent","getMinutes","currentTimeLine","top","renderMonthView","firstDay","startDay","days","push","today","todayStr","monthGrid","dayHeader","day","dayStr","isToday","isOtherMonth","dayReservations","rDate","clickDate","dayCell","dayCellOtherMonth","dayCellToday","dayNumber","renderWeekView","startOfWeek","weekDays","hours","_","weekView","toLocaleDateString","month","weekday","timeLabel","toString","padStart","di","cellReservations","weekCell","renderDayView","dayView","hourReservations","dayViewCell","renderPendingView","pendingEmpty","allSelected","every","has","toggleSelectAll","toggleSelect","formatDateTime","iso","toLocaleString","year","pendingView","pendingToolbar","label","selectAllLabel","input","aria-label","checked","onChange","size","button","bulkConfirmButton","disabled","feedbackToast","feedbackSuccess","feedbackError","table","pendingTable","thead","tr","th","pendingTh","tbody","isConfirming","resourceDisplay","pendingRow","td","pendingTd","pendingCustomerLink","confirmButton","cancelButton","dateLabel","endOfWeek","handleDrawerSave","wrapper","header","navButtons","navButton","viewToggle","createButton","viewToggleButton","viewToggleButtonActive","pendingBadge","filterBar","select","resourceFilter","target","option","onSave"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -94,7 +94,7 @@ export const payloadReserve = (pluginOptions = {})=>(config)=>{
94
94
  }
95
95
  config.admin.dashboard.widgets.push({
96
96
  slug: 'reservation-todays-reservations',
97
- ComponentPath: 'payload-reserve/rsc#DashboardWidgetServer',
97
+ Component: 'payload-reserve/rsc#DashboardWidgetServer',
98
98
  label: 'Today\'s Reservations',
99
99
  maxWidth: 'large',
100
100
  minWidth: 'medium'
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { CollectionSlug, Config, Field } from 'payload'\n\nimport { deepMergeSimple } from 'payload/shared'\n\nimport type { ReservationPluginConfig } from './types.js'\n\nimport { createCustomersCollection } from './collections/Customers.js'\nimport { createReservationsCollection } from './collections/Reservations.js'\nimport { createResourcesCollection } from './collections/Resources.js'\nimport { createSchedulesCollection } from './collections/Schedules.js'\nimport { createServicesCollection } from './collections/Services.js'\nimport { resolveConfig } from './defaults.js'\nimport { createCancelBookingEndpoint } from './endpoints/cancelBooking.js'\nimport { createCheckAvailabilityEndpoint } from './endpoints/checkAvailability.js'\nimport { createBookingEndpoint } from './endpoints/createBooking.js'\nimport { createCustomerSearchEndpoint } from './endpoints/customerSearch.js'\nimport { createGetSlotsEndpoint } from './endpoints/getSlots.js'\nimport { translations } from './translations/index.js'\n\nexport const payloadReserve =\n (pluginOptions: ReservationPluginConfig = {}) =>\n (config: Config): Config => {\n const resolved = resolveConfig(pluginOptions)\n\n // Detect localization from the Payload config\n if (config.localization) {\n resolved.localized = true\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n if (resolved.disabled) {\n return config\n }\n\n if (resolved.userCollection) {\n // Extend the existing auth collection with customer fields\n const targetCollection = config.collections.find(\n (col) => col.slug === resolved.userCollection,\n )\n\n if (targetCollection) {\n // Collect existing field names for deduplication check\n const existingFieldNames = new Set(\n targetCollection.fields\n .map((field) => ('name' in field ? field.name : undefined))\n .filter(Boolean),\n )\n\n // Fields to inject if not already present\n const fieldsToAdd: Field[] = [\n {\n name: 'phone',\n type: 'text',\n maxLength: 50,\n },\n {\n name: 'notes',\n type: 'textarea',\n },\n {\n name: 'bookings',\n type: 'join',\n collection: resolved.slugs.reservations as unknown as CollectionSlug,\n on: 'customer',\n },\n ]\n\n for (const field of fieldsToAdd) {\n const fieldName = 'name' in field ? field.name : undefined\n if (fieldName && !existingFieldNames.has(fieldName)) {\n targetCollection.fields.push(field)\n }\n }\n }\n\n // Point the customers slug at the user collection so other parts of the\n // plugin (endpoints, hooks) reference the correct collection\n resolved.slugs.customers = resolved.userCollection\n\n // Push only the 4 domain collections (no standalone Customers)\n config.collections.push(\n createServicesCollection(resolved),\n createResourcesCollection(resolved),\n createSchedulesCollection(resolved),\n createReservationsCollection(resolved),\n )\n } else {\n // Default behaviour: push all 5 collections including standalone Customers\n config.collections.push(\n createServicesCollection(resolved),\n createResourcesCollection(resolved),\n createSchedulesCollection(resolved),\n createReservationsCollection(resolved),\n createCustomersCollection(resolved),\n )\n }\n\n // Register custom endpoints\n if (!config.endpoints) {config.endpoints = []}\n config.endpoints.push(\n createCancelBookingEndpoint(resolved),\n createCheckAvailabilityEndpoint(resolved),\n createBookingEndpoint(resolved),\n createCustomerSearchEndpoint(resolved),\n createGetSlotsEndpoint(resolved),\n )\n\n // Set up admin configuration\n if (!config.admin) {config.admin = {}}\n if (!config.admin.components) {config.admin.components = {}}\n\n // Store slugs and status machine in admin custom for component access\n if (!config.admin.custom) {config.admin.custom = {}}\n config.admin.custom.reservationSlugs = {\n ...resolved.slugs,\n }\n config.admin.custom.reservationStatusMachine = resolved.statusMachine\n\n // Add dashboard widget\n if (!config.admin.dashboard) {\n config.admin.dashboard = { widgets: [] }\n }\n if (!config.admin.dashboard.widgets) {\n config.admin.dashboard.widgets = []\n }\n config.admin.dashboard.widgets.push({\n slug: 'reservation-todays-reservations',\n ComponentPath: 'payload-reserve/rsc#DashboardWidgetServer',\n label: 'Today\\'s Reservations',\n maxWidth: 'large',\n minWidth: 'medium',\n })\n\n // Add availability overview as custom admin view\n if (!config.admin.components.views) {\n config.admin.components.views = {}\n }\n ;(config.admin.components.views as Record<string, unknown>)['reservation-availability'] = {\n Component: 'payload-reserve/client#AvailabilityOverview',\n path: '/reservation-availability',\n }\n\n // Merge plugin translations (user translations take precedence)\n config.i18n = {\n ...(config.i18n ?? {}),\n translations: deepMergeSimple(\n translations,\n (config.i18n?.translations as Record<string, Record<string, unknown>>) ?? {},\n ),\n }\n\n return config\n }\n"],"names":["deepMergeSimple","createCustomersCollection","createReservationsCollection","createResourcesCollection","createSchedulesCollection","createServicesCollection","resolveConfig","createCancelBookingEndpoint","createCheckAvailabilityEndpoint","createBookingEndpoint","createCustomerSearchEndpoint","createGetSlotsEndpoint","translations","payloadReserve","pluginOptions","config","resolved","localization","localized","collections","disabled","userCollection","targetCollection","find","col","slug","existingFieldNames","Set","fields","map","field","name","undefined","filter","Boolean","fieldsToAdd","type","maxLength","collection","slugs","reservations","on","fieldName","has","push","customers","endpoints","admin","components","custom","reservationSlugs","reservationStatusMachine","statusMachine","dashboard","widgets","ComponentPath","label","maxWidth","minWidth","views","Component","path","i18n"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { CollectionSlug, Config, Field } from 'payload'\n\nimport { deepMergeSimple } from 'payload/shared'\n\nimport type { ReservationPluginConfig } from './types.js'\n\nimport { createCustomersCollection } from './collections/Customers.js'\nimport { createReservationsCollection } from './collections/Reservations.js'\nimport { createResourcesCollection } from './collections/Resources.js'\nimport { createSchedulesCollection } from './collections/Schedules.js'\nimport { createServicesCollection } from './collections/Services.js'\nimport { resolveConfig } from './defaults.js'\nimport { createCancelBookingEndpoint } from './endpoints/cancelBooking.js'\nimport { createCheckAvailabilityEndpoint } from './endpoints/checkAvailability.js'\nimport { createBookingEndpoint } from './endpoints/createBooking.js'\nimport { createCustomerSearchEndpoint } from './endpoints/customerSearch.js'\nimport { createGetSlotsEndpoint } from './endpoints/getSlots.js'\nimport { translations } from './translations/index.js'\n\nexport const payloadReserve =\n (pluginOptions: ReservationPluginConfig = {}) =>\n (config: Config): Config => {\n const resolved = resolveConfig(pluginOptions)\n\n // Detect localization from the Payload config\n if (config.localization) {\n resolved.localized = true\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n if (resolved.disabled) {\n return config\n }\n\n if (resolved.userCollection) {\n // Extend the existing auth collection with customer fields\n const targetCollection = config.collections.find(\n (col) => col.slug === resolved.userCollection,\n )\n\n if (targetCollection) {\n // Collect existing field names for deduplication check\n const existingFieldNames = new Set(\n targetCollection.fields\n .map((field) => ('name' in field ? field.name : undefined))\n .filter(Boolean),\n )\n\n // Fields to inject if not already present\n const fieldsToAdd: Field[] = [\n {\n name: 'phone',\n type: 'text',\n maxLength: 50,\n },\n {\n name: 'notes',\n type: 'textarea',\n },\n {\n name: 'bookings',\n type: 'join',\n collection: resolved.slugs.reservations as unknown as CollectionSlug,\n on: 'customer',\n },\n ]\n\n for (const field of fieldsToAdd) {\n const fieldName = 'name' in field ? field.name : undefined\n if (fieldName && !existingFieldNames.has(fieldName)) {\n targetCollection.fields.push(field)\n }\n }\n }\n\n // Point the customers slug at the user collection so other parts of the\n // plugin (endpoints, hooks) reference the correct collection\n resolved.slugs.customers = resolved.userCollection\n\n // Push only the 4 domain collections (no standalone Customers)\n config.collections.push(\n createServicesCollection(resolved),\n createResourcesCollection(resolved),\n createSchedulesCollection(resolved),\n createReservationsCollection(resolved),\n )\n } else {\n // Default behaviour: push all 5 collections including standalone Customers\n config.collections.push(\n createServicesCollection(resolved),\n createResourcesCollection(resolved),\n createSchedulesCollection(resolved),\n createReservationsCollection(resolved),\n createCustomersCollection(resolved),\n )\n }\n\n // Register custom endpoints\n if (!config.endpoints) {config.endpoints = []}\n config.endpoints.push(\n createCancelBookingEndpoint(resolved),\n createCheckAvailabilityEndpoint(resolved),\n createBookingEndpoint(resolved),\n createCustomerSearchEndpoint(resolved),\n createGetSlotsEndpoint(resolved),\n )\n\n // Set up admin configuration\n if (!config.admin) {config.admin = {}}\n if (!config.admin.components) {config.admin.components = {}}\n\n // Store slugs and status machine in admin custom for component access\n if (!config.admin.custom) {config.admin.custom = {}}\n config.admin.custom.reservationSlugs = {\n ...resolved.slugs,\n }\n config.admin.custom.reservationStatusMachine = resolved.statusMachine\n\n // Add dashboard widget\n if (!config.admin.dashboard) {\n config.admin.dashboard = { widgets: [] }\n }\n if (!config.admin.dashboard.widgets) {\n config.admin.dashboard.widgets = []\n }\n config.admin.dashboard.widgets.push({\n slug: 'reservation-todays-reservations',\n Component: 'payload-reserve/rsc#DashboardWidgetServer',\n label: 'Today\\'s Reservations',\n maxWidth: 'large',\n minWidth: 'medium',\n })\n\n // Add availability overview as custom admin view\n if (!config.admin.components.views) {\n config.admin.components.views = {}\n }\n ;(config.admin.components.views as Record<string, unknown>)['reservation-availability'] = {\n Component: 'payload-reserve/client#AvailabilityOverview',\n path: '/reservation-availability',\n }\n\n // Merge plugin translations (user translations take precedence)\n config.i18n = {\n ...(config.i18n ?? {}),\n translations: deepMergeSimple(\n translations,\n (config.i18n?.translations as Record<string, Record<string, unknown>>) ?? {},\n ),\n }\n\n return config\n }\n"],"names":["deepMergeSimple","createCustomersCollection","createReservationsCollection","createResourcesCollection","createSchedulesCollection","createServicesCollection","resolveConfig","createCancelBookingEndpoint","createCheckAvailabilityEndpoint","createBookingEndpoint","createCustomerSearchEndpoint","createGetSlotsEndpoint","translations","payloadReserve","pluginOptions","config","resolved","localization","localized","collections","disabled","userCollection","targetCollection","find","col","slug","existingFieldNames","Set","fields","map","field","name","undefined","filter","Boolean","fieldsToAdd","type","maxLength","collection","slugs","reservations","on","fieldName","has","push","customers","endpoints","admin","components","custom","reservationSlugs","reservationStatusMachine","statusMachine","dashboard","widgets","Component","label","maxWidth","minWidth","views","path","i18n"],"mappings":"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"}
@@ -119,5 +119,7 @@
119
119
  "durationFlexible": "Flexible",
120
120
  "durationFullDay": "Full Day",
121
121
  "fieldItems": "Items",
122
- "fieldGuestCount": "Guest Count"
122
+ "fieldGuestCount": "Guest Count",
123
+ "filterAllResources": "All Resources",
124
+ "filterByResource": "Filter by resource"
123
125
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a status string to its i18n translation key.
3
+ * Handles hyphenated statuses by converting to camelCase.
4
+ *
5
+ * Examples:
6
+ * 'pending' → 'reservation:statusPending'
7
+ * 'no-show' → 'reservation:statusNoShow'
8
+ */
9
+ export declare function statusToI18nKey(status: string): string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Convert a status string to its i18n translation key.
3
+ * Handles hyphenated statuses by converting to camelCase.
4
+ *
5
+ * Examples:
6
+ * 'pending' → 'reservation:statusPending'
7
+ * 'no-show' → 'reservation:statusNoShow'
8
+ */ export function statusToI18nKey(status) {
9
+ const camel = status.charAt(0).toUpperCase() + status.slice(1).replace(/-./g, (m)=>m[1].toUpperCase());
10
+ return `reservation:status${camel}`;
11
+ }
12
+
13
+ //# sourceMappingURL=i18nUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/i18nUtils.ts"],"sourcesContent":["/**\n * Convert a status string to its i18n translation key.\n * Handles hyphenated statuses by converting to camelCase.\n *\n * Examples:\n * 'pending' → 'reservation:statusPending'\n * 'no-show' → 'reservation:statusNoShow'\n */\nexport function statusToI18nKey(status: string): string {\n const camel = status.charAt(0).toUpperCase() + status.slice(1).replace(/-./g, (m) => m[1].toUpperCase())\n return `reservation:status${camel}`\n}\n"],"names":["statusToI18nKey","status","camel","charAt","toUpperCase","slice","replace","m"],"mappings":"AAAA;;;;;;;CAOC,GACD,OAAO,SAASA,gBAAgBC,MAAc;IAC5C,MAAMC,QAAQD,OAAOE,MAAM,CAAC,GAAGC,WAAW,KAAKH,OAAOI,KAAK,CAAC,GAAGC,OAAO,CAAC,OAAO,CAACC,IAAMA,CAAC,CAAC,EAAE,CAACH,WAAW;IACrG,OAAO,CAAC,kBAAkB,EAAEF,OAAO;AACrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-reserve",
3
- "version": "1.2.0",
3
+ "version": "1.3.2",
4
4
  "description": "A Payload CMS 3.x plugin for reservation and booking management with conflict detection, status workflows, and calendar UI",
5
5
  "keywords": [
6
6
  "payload",
@@ -48,14 +48,14 @@
48
48
  "devDependencies": {
49
49
  "@changesets/cli": "^2.30.0",
50
50
  "@eslint/eslintrc": "^3.2.0",
51
- "@payloadcms/db-mongodb": "3.77.0",
52
- "@payloadcms/db-postgres": "3.77.0",
53
- "@payloadcms/db-sqlite": "3.77.0",
51
+ "@payloadcms/db-mongodb": "3.79.0",
52
+ "@payloadcms/db-postgres": "3.79.0",
53
+ "@payloadcms/db-sqlite": "3.79.0",
54
54
  "@payloadcms/eslint-config": "3.9.0",
55
- "@payloadcms/next": "3.77.0",
56
- "@payloadcms/richtext-lexical": "3.77.0",
57
- "@payloadcms/translations": "3.77.0",
58
- "@payloadcms/ui": "3.77.0",
55
+ "@payloadcms/next": "3.79.0",
56
+ "@payloadcms/richtext-lexical": "3.79.0",
57
+ "@payloadcms/translations": "3.79.0",
58
+ "@payloadcms/ui": "3.79.0",
59
59
  "@playwright/test": "1.56.1",
60
60
  "@swc-node/register": "1.10.9",
61
61
  "@swc/cli": "0.6.0",
@@ -70,7 +70,7 @@
70
70
  "mongodb-memory-server": "10.1.4",
71
71
  "next": "15.4.11",
72
72
  "open": "^10.1.0",
73
- "payload": "3.77.0",
73
+ "payload": "3.79.0",
74
74
  "prettier": "^3.4.2",
75
75
  "qs-esm": "7.0.2",
76
76
  "react": "19.2.1",
@@ -83,9 +83,9 @@
83
83
  "vitest": "4.0.18"
84
84
  },
85
85
  "peerDependencies": {
86
- "@payloadcms/translations": "^3.77.0",
87
- "@payloadcms/ui": "^3.77.0",
88
- "payload": "^3.77.0"
86
+ "@payloadcms/translations": "^3.79.0",
87
+ "@payloadcms/ui": "^3.79.0",
88
+ "payload": "^3.79.0"
89
89
  },
90
90
  "engines": {
91
91
  "node": "^18.20.2 || >=20.9.0",