payload-reserve 1.0.2 → 1.0.3
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 +44 -1154
- package/dist/collections/Customers.d.ts +3 -0
- package/dist/collections/Customers.js +58 -0
- package/dist/collections/Customers.js.map +1 -0
- package/dist/collections/Reservations.js +124 -34
- package/dist/collections/Reservations.js.map +1 -1
- package/dist/collections/Resources.js +39 -0
- package/dist/collections/Resources.js.map +1 -1
- package/dist/collections/Schedules.js.map +1 -1
- package/dist/collections/Services.js +27 -0
- package/dist/collections/Services.js.map +1 -1
- package/dist/components/AvailabilityOverview/AvailabilityOverview.module.css +31 -0
- package/dist/components/AvailabilityOverview/index.js +59 -8
- package/dist/components/AvailabilityOverview/index.js.map +1 -1
- package/dist/components/CalendarView/CalendarView.module.css +171 -0
- package/dist/components/CalendarView/index.js +547 -38
- package/dist/components/CalendarView/index.js.map +1 -1
- package/dist/components/CustomerField/index.js +24 -10
- package/dist/components/CustomerField/index.js.map +1 -1
- package/dist/components/DashboardWidget/DashboardWidgetServer.js +21 -11
- package/dist/components/DashboardWidget/DashboardWidgetServer.js.map +1 -1
- package/dist/defaults.d.ts +1 -2
- package/dist/defaults.js +15 -4
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/cancelBooking.d.ts +3 -0
- package/dist/endpoints/cancelBooking.js +37 -0
- package/dist/endpoints/cancelBooking.js.map +1 -0
- package/dist/endpoints/checkAvailability.d.ts +3 -0
- package/dist/endpoints/checkAvailability.js +37 -0
- package/dist/endpoints/checkAvailability.js.map +1 -0
- package/dist/endpoints/createBooking.d.ts +3 -0
- package/dist/endpoints/createBooking.js +32 -0
- package/dist/endpoints/createBooking.js.map +1 -0
- package/dist/endpoints/customerSearch.js +76 -58
- package/dist/endpoints/customerSearch.js.map +1 -1
- package/dist/endpoints/getSlots.d.ts +3 -0
- package/dist/endpoints/getSlots.js +51 -0
- package/dist/endpoints/getSlots.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/reservations/calculateEndTime.js +75 -9
- package/dist/hooks/reservations/calculateEndTime.js.map +1 -1
- package/dist/hooks/reservations/checkIdempotency.d.ts +3 -0
- package/dist/hooks/reservations/checkIdempotency.js +32 -0
- package/dist/hooks/reservations/checkIdempotency.js.map +1 -0
- package/dist/hooks/reservations/onStatusChange.d.ts +3 -0
- package/dist/hooks/reservations/onStatusChange.js +38 -0
- package/dist/hooks/reservations/onStatusChange.js.map +1 -0
- package/dist/hooks/reservations/validateCancellation.js +1 -1
- package/dist/hooks/reservations/validateCancellation.js.map +1 -1
- package/dist/hooks/reservations/validateConflicts.js +34 -56
- package/dist/hooks/reservations/validateConflicts.js.map +1 -1
- package/dist/hooks/reservations/validateStatusTransition.d.ts +2 -1
- package/dist/hooks/reservations/validateStatusTransition.js +29 -6
- package/dist/hooks/reservations/validateStatusTransition.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +49 -54
- package/dist/plugin.js.map +1 -1
- package/dist/services/AvailabilityService.d.ts +57 -0
- package/dist/services/AvailabilityService.js +232 -0
- package/dist/services/AvailabilityService.js.map +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +3 -0
- package/dist/services/index.js.map +1 -0
- package/dist/translations/en.json +33 -1
- package/dist/translations/index.d.ts +5 -0
- package/dist/translations/index.js.map +1 -1
- package/dist/types.d.ts +65 -6
- package/dist/types.js +29 -9
- package/dist/types.js.map +1 -1
- package/dist/utilities/resolveReservationItems.d.ts +18 -0
- package/dist/utilities/resolveReservationItems.js +45 -0
- package/dist/utilities/resolveReservationItems.js.map +1 -0
- package/package.json +12 -9
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export function createCustomersCollection(config) {
|
|
2
|
+
return {
|
|
3
|
+
slug: config.slugs.customers,
|
|
4
|
+
access: {
|
|
5
|
+
admin: ()=>false,
|
|
6
|
+
...config.access.customers
|
|
7
|
+
},
|
|
8
|
+
admin: {
|
|
9
|
+
group: config.adminGroup,
|
|
10
|
+
listSearchableFields: [
|
|
11
|
+
'firstName',
|
|
12
|
+
'lastName',
|
|
13
|
+
'phone',
|
|
14
|
+
'email'
|
|
15
|
+
],
|
|
16
|
+
useAsTitle: 'firstName'
|
|
17
|
+
},
|
|
18
|
+
auth: true,
|
|
19
|
+
fields: [
|
|
20
|
+
{
|
|
21
|
+
name: 'firstName',
|
|
22
|
+
type: 'text',
|
|
23
|
+
label: ({ t })=>t('reservation:fieldFirstName'),
|
|
24
|
+
maxLength: 200,
|
|
25
|
+
required: true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'lastName',
|
|
29
|
+
type: 'text',
|
|
30
|
+
label: ({ t })=>t('reservation:fieldLastName'),
|
|
31
|
+
maxLength: 200,
|
|
32
|
+
required: true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'phone',
|
|
36
|
+
type: 'text',
|
|
37
|
+
maxLength: 50
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'notes',
|
|
41
|
+
type: 'textarea',
|
|
42
|
+
label: ({ t })=>t('reservation:fieldNotes')
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'bookings',
|
|
46
|
+
type: 'join',
|
|
47
|
+
collection: config.slugs.reservations,
|
|
48
|
+
on: 'customer'
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
labels: {
|
|
52
|
+
plural: ({ t })=>t('reservation:collectionCustomers'),
|
|
53
|
+
singular: ({ t })=>t('reservation:collectionCustomer')
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=Customers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/collections/Customers.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createCustomersCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.customers,\n access: {\n admin: () => false,\n ...config.access.customers,\n },\n admin: {\n group: config.adminGroup,\n listSearchableFields: ['firstName', 'lastName', 'phone', 'email'],\n useAsTitle: 'firstName',\n },\n auth: true,\n fields: [\n {\n name: 'firstName',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldFirstName'),\n maxLength: 200,\n required: true,\n },\n {\n name: 'lastName',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldLastName'),\n maxLength: 200,\n required: true,\n },\n {\n name: 'phone',\n type: 'text',\n maxLength: 50,\n },\n {\n name: 'notes',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldNotes'),\n },\n {\n name: 'bookings',\n type: 'join',\n collection: config.slugs.reservations as unknown as CollectionSlug,\n on: 'customer',\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionCustomers'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionCustomer'),\n },\n }\n}\n"],"names":["createCustomersCollection","config","slug","slugs","customers","access","admin","group","adminGroup","listSearchableFields","useAsTitle","auth","fields","name","type","label","t","maxLength","required","collection","reservations","on","labels","plural","singular"],"mappings":"AAKA,OAAO,SAASA,0BACdC,MAAuC;IAEvC,OAAO;QACLC,MAAMD,OAAOE,KAAK,CAACC,SAAS;QAC5BC,QAAQ;YACNC,OAAO,IAAM;YACb,GAAGL,OAAOI,MAAM,CAACD,SAAS;QAC5B;QACAE,OAAO;YACLC,OAAON,OAAOO,UAAU;YACxBC,sBAAsB;gBAAC;gBAAa;gBAAY;gBAAS;aAAQ;YACjEC,YAAY;QACd;QACAC,MAAM;QACNC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCC,WAAW;gBACXC,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCC,WAAW;gBACXC,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNG,WAAW;YACb;YACA;gBACEJ,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;YACnC;YACA;gBACEH,MAAM;gBACNC,MAAM;gBACNK,YAAYlB,OAAOE,KAAK,CAACiB,YAAY;gBACrCC,IAAI;YACN;SACD;QACDC,QAAQ;YACNC,QAAQ,CAAC,EAAEP,CAAC,EAAE,GAAK,AAACA,EAAc;YAClCQ,UAAU,CAAC,EAAER,CAAC,EAAE,GAAK,AAACA,EAAc;QACtC;IACF;AACF"}
|
|
@@ -1,8 +1,46 @@
|
|
|
1
1
|
import { calculateEndTime } from '../hooks/reservations/calculateEndTime.js';
|
|
2
|
+
import { checkIdempotency } from '../hooks/reservations/checkIdempotency.js';
|
|
3
|
+
import { onStatusChange } from '../hooks/reservations/onStatusChange.js';
|
|
2
4
|
import { validateCancellation } from '../hooks/reservations/validateCancellation.js';
|
|
3
5
|
import { validateConflicts } from '../hooks/reservations/validateConflicts.js';
|
|
4
6
|
import { validateStatusTransition } from '../hooks/reservations/validateStatusTransition.js';
|
|
7
|
+
function createPluginHooksBeforeCreate(hooks) {
|
|
8
|
+
return async ({ context, data, operation, req })=>{
|
|
9
|
+
if (context?.skipReservationHooks) {
|
|
10
|
+
return data;
|
|
11
|
+
}
|
|
12
|
+
if (operation === 'create' && hooks.beforeBookingCreate) {
|
|
13
|
+
let mutatedData = data;
|
|
14
|
+
for (const hook of hooks.beforeBookingCreate){
|
|
15
|
+
const result = await hook({
|
|
16
|
+
data: mutatedData,
|
|
17
|
+
req
|
|
18
|
+
});
|
|
19
|
+
if (result) {
|
|
20
|
+
mutatedData = result;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return mutatedData;
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createPluginHooksAfterCreate(hooks) {
|
|
29
|
+
return async ({ doc, operation, req })=>{
|
|
30
|
+
if (operation === 'create' && hooks.afterBookingCreate) {
|
|
31
|
+
const docRecord = doc;
|
|
32
|
+
for (const hook of hooks.afterBookingCreate){
|
|
33
|
+
await hook({
|
|
34
|
+
doc: docRecord,
|
|
35
|
+
req
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return doc;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
5
42
|
export function createReservationsCollection(config) {
|
|
43
|
+
const { statusMachine } = config;
|
|
6
44
|
return {
|
|
7
45
|
slug: config.slugs.reservations,
|
|
8
46
|
access: config.access.reservations ?? {},
|
|
@@ -38,23 +76,16 @@ export function createReservationsCollection(config) {
|
|
|
38
76
|
{
|
|
39
77
|
name: 'customer',
|
|
40
78
|
type: 'relationship',
|
|
41
|
-
label: ({ t })=>t('reservation:fieldCustomer'),
|
|
42
|
-
relationTo: config.userCollection,
|
|
43
|
-
required: true,
|
|
44
|
-
...config.customerRole ? {
|
|
45
|
-
filterOptions: ()=>({
|
|
46
|
-
role: {
|
|
47
|
-
equals: config.customerRole
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
} : {},
|
|
51
79
|
admin: {
|
|
52
80
|
allowCreate: true,
|
|
53
81
|
allowEdit: true,
|
|
54
82
|
components: {
|
|
55
83
|
Field: 'payload-reserve/client#CustomerField'
|
|
56
84
|
}
|
|
57
|
-
}
|
|
85
|
+
},
|
|
86
|
+
label: ({ t })=>t('reservation:fieldCustomer'),
|
|
87
|
+
relationTo: config.slugs.customers,
|
|
88
|
+
required: true
|
|
58
89
|
},
|
|
59
90
|
{
|
|
60
91
|
name: 'startTime',
|
|
@@ -81,50 +112,109 @@ export function createReservationsCollection(config) {
|
|
|
81
112
|
{
|
|
82
113
|
name: 'status',
|
|
83
114
|
type: 'select',
|
|
84
|
-
defaultValue:
|
|
115
|
+
defaultValue: statusMachine.defaultStatus,
|
|
85
116
|
label: ({ t })=>t('reservation:fieldStatus'),
|
|
86
|
-
options:
|
|
117
|
+
options: statusMachine.statuses.map((s)=>({
|
|
118
|
+
label: ({ t })=>{
|
|
119
|
+
const key = `reservation:status${s.charAt(0).toUpperCase() + s.slice(1)}`;
|
|
120
|
+
const translated = t(key);
|
|
121
|
+
return translated !== key ? translated : s.charAt(0).toUpperCase() + s.slice(1);
|
|
122
|
+
},
|
|
123
|
+
value: s
|
|
124
|
+
}))
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'cancellationReason',
|
|
128
|
+
type: 'textarea',
|
|
129
|
+
admin: {
|
|
130
|
+
condition: (_, siblingData)=>siblingData?.status === 'cancelled'
|
|
131
|
+
},
|
|
132
|
+
label: ({ t })=>t('reservation:fieldCancellationReason')
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: 'guestCount',
|
|
136
|
+
type: 'number',
|
|
137
|
+
defaultValue: 1,
|
|
138
|
+
label: ({ t })=>t('reservation:fieldGuestCount'),
|
|
139
|
+
min: 1
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'notes',
|
|
143
|
+
type: 'textarea',
|
|
144
|
+
label: ({ t })=>t('reservation:fieldNotes')
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'items',
|
|
148
|
+
type: 'array',
|
|
149
|
+
admin: {
|
|
150
|
+
description: 'Resources included in this booking. Leave empty for single-resource bookings.'
|
|
151
|
+
},
|
|
152
|
+
fields: [
|
|
87
153
|
{
|
|
88
|
-
|
|
89
|
-
|
|
154
|
+
name: 'resource',
|
|
155
|
+
type: 'relationship',
|
|
156
|
+
label: ({ t })=>t('reservation:fieldResource'),
|
|
157
|
+
relationTo: config.slugs.resources,
|
|
158
|
+
required: true
|
|
90
159
|
},
|
|
91
160
|
{
|
|
92
|
-
|
|
93
|
-
|
|
161
|
+
name: 'service',
|
|
162
|
+
type: 'relationship',
|
|
163
|
+
label: ({ t })=>t('reservation:fieldService'),
|
|
164
|
+
relationTo: config.slugs.services
|
|
94
165
|
},
|
|
95
166
|
{
|
|
96
|
-
|
|
97
|
-
|
|
167
|
+
name: 'startTime',
|
|
168
|
+
type: 'date',
|
|
169
|
+
admin: {
|
|
170
|
+
date: {
|
|
171
|
+
pickerAppearance: 'dayAndTime'
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
label: ({ t })=>t('reservation:fieldStartTime')
|
|
98
175
|
},
|
|
99
176
|
{
|
|
100
|
-
|
|
101
|
-
|
|
177
|
+
name: 'endTime',
|
|
178
|
+
type: 'date',
|
|
179
|
+
admin: {
|
|
180
|
+
date: {
|
|
181
|
+
pickerAppearance: 'dayAndTime'
|
|
182
|
+
},
|
|
183
|
+
readOnly: false
|
|
184
|
+
},
|
|
185
|
+
label: ({ t })=>t('reservation:fieldEndTime')
|
|
102
186
|
},
|
|
103
187
|
{
|
|
104
|
-
|
|
105
|
-
|
|
188
|
+
name: 'guestCount',
|
|
189
|
+
type: 'number',
|
|
190
|
+
label: ({ t })=>t('reservation:fieldGuestCount'),
|
|
191
|
+
min: 1
|
|
106
192
|
}
|
|
107
|
-
]
|
|
193
|
+
],
|
|
194
|
+
label: ({ t })=>t('reservation:fieldItems')
|
|
108
195
|
},
|
|
109
196
|
{
|
|
110
|
-
name: '
|
|
111
|
-
type: '
|
|
197
|
+
name: 'idempotencyKey',
|
|
198
|
+
type: 'text',
|
|
112
199
|
admin: {
|
|
113
|
-
|
|
200
|
+
position: 'sidebar',
|
|
201
|
+
readOnly: true
|
|
114
202
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
{
|
|
118
|
-
name: 'notes',
|
|
119
|
-
type: 'textarea',
|
|
120
|
-
label: ({ t })=>t('reservation:fieldNotes')
|
|
203
|
+
index: true,
|
|
204
|
+
unique: true
|
|
121
205
|
}
|
|
122
206
|
],
|
|
123
207
|
hooks: {
|
|
208
|
+
afterChange: [
|
|
209
|
+
createPluginHooksAfterCreate(config.hooks),
|
|
210
|
+
onStatusChange(config)
|
|
211
|
+
],
|
|
124
212
|
beforeChange: [
|
|
213
|
+
createPluginHooksBeforeCreate(config.hooks),
|
|
214
|
+
checkIdempotency(config),
|
|
125
215
|
calculateEndTime(config),
|
|
126
216
|
validateConflicts(config),
|
|
127
|
-
validateStatusTransition(),
|
|
217
|
+
validateStatusTransition(config),
|
|
128
218
|
validateCancellation(config)
|
|
129
219
|
]
|
|
130
220
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/collections/Reservations.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nimport { calculateEndTime } from '../hooks/reservations/calculateEndTime.js'\nimport { validateCancellation } from '../hooks/reservations/validateCancellation.js'\nimport { validateConflicts } from '../hooks/reservations/validateConflicts.js'\nimport { validateStatusTransition } from '../hooks/reservations/validateStatusTransition.js'\n\nexport function createReservationsCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.reservations,\n access: config.access.reservations ?? {},\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,\n required: true,\n },\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources,\n required: true,\n },\n {\n name: 'customer',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldCustomer'),\n relationTo: config.userCollection,\n required: true,\n ...(config.customerRole\n ? { filterOptions: () => ({ role: { equals: config.customerRole } }) }\n : {}),\n admin: {\n allowCreate: true,\n allowEdit: true,\n components: {\n Field: 'payload-reserve/client#CustomerField',\n },\n },\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: 'pending',\n label: ({ t }) => (t as PluginT)('reservation:fieldStatus'),\n options: [\n { label: ({ t }) => (t as PluginT)('reservation:statusPending'), value: 'pending' },\n { label: ({ t }) => (t as PluginT)('reservation:statusConfirmed'), value: 'confirmed' },\n { label: ({ t }) => (t as PluginT)('reservation:statusCompleted'), value: 'completed' },\n { label: ({ t }) => (t as PluginT)('reservation:statusCancelled'), value: 'cancelled' },\n { label: ({ t }) => (t as PluginT)('reservation:statusNoShow'), value: 'no-show' },\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: 'notes',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldNotes'),\n },\n ],\n hooks: {\n beforeChange: [\n calculateEndTime(config),\n validateConflicts(config),\n validateStatusTransition(),\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","validateCancellation","validateConflicts","validateStatusTransition","createReservationsCollection","config","slug","slugs","reservations","access","admin","components","views","list","Component","group","adminGroup","listSearchableFields","useAsTitle","fields","name","type","label","t","relationTo","services","required","resources","userCollection","customerRole","filterOptions","role","equals","allowCreate","allowEdit","Field","date","pickerAppearance","readOnly","defaultValue","options","value","condition","_","siblingData","status","hooks","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'\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\n return {\n slug: config.slugs.reservations,\n access: config.access.reservations ?? {},\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 ],\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","createPluginHooksBeforeCreate","hooks","context","data","operation","req","skipReservationHooks","beforeBookingCreate","mutatedData","hook","result","createPluginHooksAfterCreate","doc","afterBookingCreate","docRecord","createReservationsCollection","config","statusMachine","slug","slugs","reservations","access","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","afterChange","beforeChange","labels","plural","singular"],"mappings":"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"}
|
|
@@ -47,6 +47,45 @@ export function createResourcesCollection(config) {
|
|
|
47
47
|
},
|
|
48
48
|
defaultValue: true,
|
|
49
49
|
label: ({ t })=>t('reservation:fieldActive')
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'quantity',
|
|
53
|
+
type: 'number',
|
|
54
|
+
admin: {
|
|
55
|
+
position: 'sidebar'
|
|
56
|
+
},
|
|
57
|
+
defaultValue: 1,
|
|
58
|
+
label: ({ t })=>t('reservation:fieldQuantity'),
|
|
59
|
+
min: 1,
|
|
60
|
+
required: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'capacityMode',
|
|
64
|
+
type: 'select',
|
|
65
|
+
admin: {
|
|
66
|
+
condition: (data)=>(data?.quantity ?? 1) > 1,
|
|
67
|
+
position: 'sidebar'
|
|
68
|
+
},
|
|
69
|
+
defaultValue: 'per-reservation',
|
|
70
|
+
label: ({ t })=>t('reservation:fieldCapacityMode'),
|
|
71
|
+
options: [
|
|
72
|
+
{
|
|
73
|
+
label: ({ t })=>t('reservation:capacityPerReservation'),
|
|
74
|
+
value: 'per-reservation'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: ({ t })=>t('reservation:capacityPerGuest'),
|
|
78
|
+
value: 'per-guest'
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'timezone',
|
|
84
|
+
type: 'text',
|
|
85
|
+
admin: {
|
|
86
|
+
position: 'sidebar'
|
|
87
|
+
},
|
|
88
|
+
label: ({ t })=>t('reservation:fieldTimezone')
|
|
50
89
|
}
|
|
51
90
|
],
|
|
52
91
|
labels: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/collections/Resources.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createResourcesCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.resources,\n access: config.access.resources ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\n ...(config.localized ? { localized: true } : {}),\n maxLength: 200,\n required: true,\n },\n {\n name: 'image',\n type: 'upload',\n label: ({ t }) => (t as PluginT)('reservation:fieldImage'),\n relationTo: config.slugs.media,\n },\n {\n name: 'description',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldDescription'),\n ...(config.localized ? { localized: true } : {}),\n },\n {\n name: 'services',\n type: 'relationship',\n hasMany: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldServices'),\n relationTo: config.slugs.services,\n required: true,\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionResources'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionResources'),\n },\n }\n}\n"],"names":["createResourcesCollection","config","slug","slugs","resources","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","localized","maxLength","required","relationTo","media","hasMany","services","position","defaultValue","labels","plural","singular"],"mappings":"AAKA,OAAO,SAASA,0BACdC,MAAuC;IAEvC,OAAO;QACLC,MAAMD,OAAOE,KAAK,CAACC,SAAS;QAC5BC,QAAQJ,OAAOI,MAAM,CAACD,SAAS,IAAI,CAAC;QACpCE,OAAO;YACLC,OAAON,OAAOO,UAAU;YACxBC,YAAY;QACd;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;gBAC/CC,WAAW;gBACXC,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCI,YAAYjB,OAAOE,KAAK,CAACgB,KAAK;YAChC;YACA;gBACER,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;YACjD;YACA;gBACEJ,MAAM;gBACNC,MAAM;gBACNQ,SAAS;gBACTP,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCI,YAAYjB,OAAOE,KAAK,CAACkB,QAAQ;gBACjCJ,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLgB,UAAU;gBACZ;gBACAC,cAAc;gBACdV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;YACnC;SACD;
|
|
1
|
+
{"version":3,"sources":["../../src/collections/Resources.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createResourcesCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.resources,\n access: config.access.resources ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\n ...(config.localized ? { localized: true } : {}),\n maxLength: 200,\n required: true,\n },\n {\n name: 'image',\n type: 'upload',\n label: ({ t }) => (t as PluginT)('reservation:fieldImage'),\n relationTo: config.slugs.media as unknown as CollectionSlug,\n },\n {\n name: 'description',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldDescription'),\n ...(config.localized ? { localized: true } : {}),\n },\n {\n name: 'services',\n type: 'relationship',\n hasMany: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldServices'),\n relationTo: config.slugs.services as unknown as CollectionSlug,\n required: true,\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n {\n name: 'quantity',\n type: 'number',\n admin: {\n position: 'sidebar',\n },\n defaultValue: 1,\n label: ({ t }) => (t as PluginT)('reservation:fieldQuantity'),\n min: 1,\n required: true,\n },\n {\n name: 'capacityMode',\n type: 'select',\n admin: {\n condition: (data) => (data?.quantity ?? 1) > 1,\n position: 'sidebar',\n },\n defaultValue: 'per-reservation',\n label: ({ t }) => (t as PluginT)('reservation:fieldCapacityMode'),\n options: [\n {\n label: ({ t }) => (t as PluginT)('reservation:capacityPerReservation'),\n value: 'per-reservation',\n },\n {\n label: ({ t }) => (t as PluginT)('reservation:capacityPerGuest'),\n value: 'per-guest',\n },\n ],\n },\n {\n name: 'timezone',\n type: 'text',\n admin: {\n position: 'sidebar',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldTimezone'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionResources'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionResources'),\n },\n }\n}\n"],"names":["createResourcesCollection","config","slug","slugs","resources","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","localized","maxLength","required","relationTo","media","hasMany","services","position","defaultValue","min","condition","data","quantity","options","value","labels","plural","singular"],"mappings":"AAKA,OAAO,SAASA,0BACdC,MAAuC;IAEvC,OAAO;QACLC,MAAMD,OAAOE,KAAK,CAACC,SAAS;QAC5BC,QAAQJ,OAAOI,MAAM,CAACD,SAAS,IAAI,CAAC;QACpCE,OAAO;YACLC,OAAON,OAAOO,UAAU;YACxBC,YAAY;QACd;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;gBAC/CC,WAAW;gBACXC,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCI,YAAYjB,OAAOE,KAAK,CAACgB,KAAK;YAChC;YACA;gBACER,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;YACjD;YACA;gBACEJ,MAAM;gBACNC,MAAM;gBACNQ,SAAS;gBACTP,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCI,YAAYjB,OAAOE,KAAK,CAACkB,QAAQ;gBACjCJ,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLgB,UAAU;gBACZ;gBACAC,cAAc;gBACdV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;YACnC;YACA;gBACEH,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLgB,UAAU;gBACZ;gBACAC,cAAc;gBACdV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCU,KAAK;gBACLP,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLmB,WAAW,CAACC,OAAS,AAACA,CAAAA,MAAMC,YAAY,CAAA,IAAK;oBAC7CL,UAAU;gBACZ;gBACAC,cAAc;gBACdV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCc,SAAS;oBACP;wBACEf,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;wBACjCe,OAAO;oBACT;oBACA;wBACEhB,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;wBACjCe,OAAO;oBACT;iBACD;YACH;YACA;gBACElB,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLgB,UAAU;gBACZ;gBACAT,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;YACnC;SACD;QACDgB,QAAQ;YACNC,QAAQ,CAAC,EAAEjB,CAAC,EAAE,GAAK,AAACA,EAAc;YAClCkB,UAAU,CAAC,EAAElB,CAAC,EAAE,GAAK,AAACA,EAAc;QACtC;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/collections/Schedules.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createSchedulesCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.schedules,\n access: config.access.schedules ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\n required: true,\n },\n {\n name: 'resource',\n type: 'relationship',\n label: ({ t }) => (t as PluginT)('reservation:fieldResource'),\n relationTo: config.slugs.resources,\n required: true,\n },\n {\n name: 'scheduleType',\n type: 'select',\n defaultValue: 'recurring',\n label: ({ t }) => (t as PluginT)('reservation:fieldScheduleType'),\n options: [\n {\n label: ({ t }) => (t as PluginT)('reservation:scheduleTypeRecurring'),\n value: 'recurring',\n },\n {\n label: ({ t }) => (t as PluginT)('reservation:scheduleTypeManual'),\n value: 'manual',\n },\n ],\n },\n {\n name: 'recurringSlots',\n type: 'array',\n admin: {\n condition: (_, siblingData) => siblingData?.scheduleType === 'recurring',\n },\n fields: [\n {\n name: 'day',\n type: 'select',\n label: ({ t }) => (t as PluginT)('reservation:fieldDay'),\n options: [\n { label: ({ t }) => (t as PluginT)('reservation:dayMonday'), value: 'mon' },\n { label: ({ t }) => (t as PluginT)('reservation:dayTuesday'), value: 'tue' },\n { label: ({ t }) => (t as PluginT)('reservation:dayWednesday'), value: 'wed' },\n { label: ({ t }) => (t as PluginT)('reservation:dayThursday'), value: 'thu' },\n { label: ({ t }) => (t as PluginT)('reservation:dayFriday'), value: 'fri' },\n { label: ({ t }) => (t as PluginT)('reservation:daySaturday'), value: 'sat' },\n { label: ({ t }) => (t as PluginT)('reservation:daySunday'), value: 'sun' },\n ],\n required: true,\n },\n {\n name: 'startTime',\n type: 'text',\n admin: {\n placeholder: '09:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTimeHHmm'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'text',\n admin: {\n placeholder: '17:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTimeHHmm'),\n required: true,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldRecurringSlots'),\n },\n {\n name: 'manualSlots',\n type: 'array',\n admin: {\n condition: (_, siblingData) => siblingData?.scheduleType === 'manual',\n },\n fields: [\n {\n name: 'date',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayOnly',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldDate'),\n required: true,\n },\n {\n name: 'startTime',\n type: 'text',\n admin: {\n placeholder: '09:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTimeHHmm'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'text',\n admin: {\n placeholder: '17:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTimeHHmm'),\n required: true,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldManualSlots'),\n },\n {\n name: 'exceptions',\n type: 'array',\n fields: [\n {\n name: 'date',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayOnly',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldDate'),\n required: true,\n },\n {\n name: 'reason',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldReason'),\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldExceptions'),\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionSchedules'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionSchedules'),\n },\n }\n}\n"],"names":["createSchedulesCollection","config","slug","slugs","schedules","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","required","relationTo","resources","defaultValue","options","value","condition","_","siblingData","scheduleType","placeholder","date","pickerAppearance","position","labels","plural","singular"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/collections/Schedules.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createSchedulesCollection(\n config: ResolvedReservationPluginConfig,\n): CollectionConfig {\n return {\n slug: config.slugs.schedules,\n access: config.access.schedules ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\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: 'scheduleType',\n type: 'select',\n defaultValue: 'recurring',\n label: ({ t }) => (t as PluginT)('reservation:fieldScheduleType'),\n options: [\n {\n label: ({ t }) => (t as PluginT)('reservation:scheduleTypeRecurring'),\n value: 'recurring',\n },\n {\n label: ({ t }) => (t as PluginT)('reservation:scheduleTypeManual'),\n value: 'manual',\n },\n ],\n },\n {\n name: 'recurringSlots',\n type: 'array',\n admin: {\n condition: (_, siblingData) => siblingData?.scheduleType === 'recurring',\n },\n fields: [\n {\n name: 'day',\n type: 'select',\n label: ({ t }) => (t as PluginT)('reservation:fieldDay'),\n options: [\n { label: ({ t }) => (t as PluginT)('reservation:dayMonday'), value: 'mon' },\n { label: ({ t }) => (t as PluginT)('reservation:dayTuesday'), value: 'tue' },\n { label: ({ t }) => (t as PluginT)('reservation:dayWednesday'), value: 'wed' },\n { label: ({ t }) => (t as PluginT)('reservation:dayThursday'), value: 'thu' },\n { label: ({ t }) => (t as PluginT)('reservation:dayFriday'), value: 'fri' },\n { label: ({ t }) => (t as PluginT)('reservation:daySaturday'), value: 'sat' },\n { label: ({ t }) => (t as PluginT)('reservation:daySunday'), value: 'sun' },\n ],\n required: true,\n },\n {\n name: 'startTime',\n type: 'text',\n admin: {\n placeholder: '09:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTimeHHmm'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'text',\n admin: {\n placeholder: '17:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTimeHHmm'),\n required: true,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldRecurringSlots'),\n },\n {\n name: 'manualSlots',\n type: 'array',\n admin: {\n condition: (_, siblingData) => siblingData?.scheduleType === 'manual',\n },\n fields: [\n {\n name: 'date',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayOnly',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldDate'),\n required: true,\n },\n {\n name: 'startTime',\n type: 'text',\n admin: {\n placeholder: '09:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldStartTimeHHmm'),\n required: true,\n },\n {\n name: 'endTime',\n type: 'text',\n admin: {\n placeholder: '17:00',\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldEndTimeHHmm'),\n required: true,\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldManualSlots'),\n },\n {\n name: 'exceptions',\n type: 'array',\n fields: [\n {\n name: 'date',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayOnly',\n },\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldDate'),\n required: true,\n },\n {\n name: 'reason',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldReason'),\n },\n ],\n label: ({ t }) => (t as PluginT)('reservation:fieldExceptions'),\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionSchedules'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionSchedules'),\n },\n }\n}\n"],"names":["createSchedulesCollection","config","slug","slugs","schedules","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","required","relationTo","resources","defaultValue","options","value","condition","_","siblingData","scheduleType","placeholder","date","pickerAppearance","position","labels","plural","singular"],"mappings":"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"}
|
|
@@ -17,6 +17,12 @@ export function createServicesCollection(config) {
|
|
|
17
17
|
maxLength: 200,
|
|
18
18
|
required: true
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
name: 'image',
|
|
22
|
+
type: 'upload',
|
|
23
|
+
label: ({ t })=>t('reservation:fieldImage'),
|
|
24
|
+
relationTo: config.slugs.media
|
|
25
|
+
},
|
|
20
26
|
{
|
|
21
27
|
name: 'description',
|
|
22
28
|
type: 'textarea',
|
|
@@ -32,6 +38,27 @@ export function createServicesCollection(config) {
|
|
|
32
38
|
min: 1,
|
|
33
39
|
required: true
|
|
34
40
|
},
|
|
41
|
+
{
|
|
42
|
+
name: 'durationType',
|
|
43
|
+
type: 'select',
|
|
44
|
+
defaultValue: 'fixed',
|
|
45
|
+
label: ({ t })=>t('reservation:fieldDurationType'),
|
|
46
|
+
options: [
|
|
47
|
+
{
|
|
48
|
+
label: ({ t })=>t('reservation:durationFixed'),
|
|
49
|
+
value: 'fixed'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: ({ t })=>t('reservation:durationFlexible'),
|
|
53
|
+
value: 'flexible'
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: ({ t })=>t('reservation:durationFullDay'),
|
|
57
|
+
value: 'full-day'
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
required: true
|
|
61
|
+
},
|
|
35
62
|
{
|
|
36
63
|
name: 'price',
|
|
37
64
|
type: 'number',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/collections/Services.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createServicesCollection(config: ResolvedReservationPluginConfig): CollectionConfig {\n return {\n slug: config.slugs.services,\n access: config.access.services ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\n ...(config.localized ? { localized: true } : {}),\n maxLength: 200,\n required: true,\n },\n {\n name: 'description',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldDescription'),\n ...(config.localized ? { localized: true } : {}),\n },\n {\n name: 'duration',\n type: 'number',\n label: ({ t }) => (t as PluginT)('reservation:fieldDurationMinutes'),\n min: 1,\n required: true,\n },\n {\n name: 'price',\n type: 'number',\n admin: {\n step: 0.01,\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldPrice'),\n min: 0,\n },\n {\n name: 'bufferTimeBefore',\n type: 'number',\n defaultValue: 0,\n label: ({ t }) => (t as PluginT)('reservation:fieldBufferTimeBefore'),\n min: 0,\n },\n {\n name: 'bufferTimeAfter',\n type: 'number',\n defaultValue: 0,\n label: ({ t }) => (t as PluginT)('reservation:fieldBufferTimeAfter'),\n min: 0,\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionServices'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionServices'),\n },\n }\n}\n"],"names":["createServicesCollection","config","slug","slugs","services","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","localized","maxLength","required","
|
|
1
|
+
{"version":3,"sources":["../../src/collections/Services.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug } from 'payload'\n\nimport type { PluginT } from '../translations/index.js'\nimport type { ResolvedReservationPluginConfig } from '../types.js'\n\nexport function createServicesCollection(config: ResolvedReservationPluginConfig): CollectionConfig {\n return {\n slug: config.slugs.services,\n access: config.access.services ?? {},\n admin: {\n group: config.adminGroup,\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: ({ t }) => (t as PluginT)('reservation:fieldName'),\n ...(config.localized ? { localized: true } : {}),\n maxLength: 200,\n required: true,\n },\n {\n name: 'image',\n type: 'upload',\n label: ({ t }) => (t as PluginT)('reservation:fieldImage'),\n relationTo: config.slugs.media as unknown as CollectionSlug,\n },\n {\n name: 'description',\n type: 'textarea',\n label: ({ t }) => (t as PluginT)('reservation:fieldDescription'),\n ...(config.localized ? { localized: true } : {}),\n },\n {\n name: 'duration',\n type: 'number',\n label: ({ t }) => (t as PluginT)('reservation:fieldDurationMinutes'),\n min: 1,\n required: true,\n },\n {\n name: 'durationType',\n type: 'select',\n defaultValue: 'fixed',\n label: ({ t }) => (t as PluginT)('reservation:fieldDurationType'),\n options: [\n {\n label: ({ t }) => (t as PluginT)('reservation:durationFixed'),\n value: 'fixed',\n },\n {\n label: ({ t }) => (t as PluginT)('reservation:durationFlexible'),\n value: 'flexible',\n },\n {\n label: ({ t }) => (t as PluginT)('reservation:durationFullDay'),\n value: 'full-day',\n },\n ],\n required: true,\n },\n {\n name: 'price',\n type: 'number',\n admin: {\n step: 0.01,\n },\n label: ({ t }) => (t as PluginT)('reservation:fieldPrice'),\n min: 0,\n },\n {\n name: 'bufferTimeBefore',\n type: 'number',\n defaultValue: 0,\n label: ({ t }) => (t as PluginT)('reservation:fieldBufferTimeBefore'),\n min: 0,\n },\n {\n name: 'bufferTimeAfter',\n type: 'number',\n defaultValue: 0,\n label: ({ t }) => (t as PluginT)('reservation:fieldBufferTimeAfter'),\n min: 0,\n },\n {\n name: 'active',\n type: 'checkbox',\n admin: {\n position: 'sidebar',\n },\n defaultValue: true,\n label: ({ t }) => (t as PluginT)('reservation:fieldActive'),\n },\n ],\n labels: {\n plural: ({ t }) => (t as PluginT)('reservation:collectionServices'),\n singular: ({ t }) => (t as PluginT)('reservation:collectionServices'),\n },\n }\n}\n"],"names":["createServicesCollection","config","slug","slugs","services","access","admin","group","adminGroup","useAsTitle","fields","name","type","label","t","localized","maxLength","required","relationTo","media","min","defaultValue","options","value","step","position","labels","plural","singular"],"mappings":"AAKA,OAAO,SAASA,yBAAyBC,MAAuC;IAC9E,OAAO;QACLC,MAAMD,OAAOE,KAAK,CAACC,QAAQ;QAC3BC,QAAQJ,OAAOI,MAAM,CAACD,QAAQ,IAAI,CAAC;QACnCE,OAAO;YACLC,OAAON,OAAOO,UAAU;YACxBC,YAAY;QACd;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;gBAC/CC,WAAW;gBACXC,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCI,YAAYjB,OAAOE,KAAK,CAACgB,KAAK;YAChC;YACA;gBACER,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjC,GAAIb,OAAOc,SAAS,GAAG;oBAAEA,WAAW;gBAAK,IAAI,CAAC,CAAC;YACjD;YACA;gBACEJ,MAAM;gBACNC,MAAM;gBACNC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCM,KAAK;gBACLH,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNS,cAAc;gBACdR,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCQ,SAAS;oBACP;wBACET,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;wBACjCS,OAAO;oBACT;oBACA;wBACEV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;wBACjCS,OAAO;oBACT;oBACA;wBACEV,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;wBACjCS,OAAO;oBACT;iBACD;gBACDN,UAAU;YACZ;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLkB,MAAM;gBACR;gBACAX,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCM,KAAK;YACP;YACA;gBACET,MAAM;gBACNC,MAAM;gBACNS,cAAc;gBACdR,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCM,KAAK;YACP;YACA;gBACET,MAAM;gBACNC,MAAM;gBACNS,cAAc;gBACdR,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;gBACjCM,KAAK;YACP;YACA;gBACET,MAAM;gBACNC,MAAM;gBACNN,OAAO;oBACLmB,UAAU;gBACZ;gBACAJ,cAAc;gBACdR,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAK,AAACA,EAAc;YACnC;SACD;QACDY,QAAQ;YACNC,QAAQ,CAAC,EAAEb,CAAC,EAAE,GAAK,AAACA,EAAc;YAClCc,UAAU,CAAC,EAAEd,CAAC,EAAE,GAAK,AAACA,EAAc;QACtC;IACF;AACF"}
|
|
@@ -79,6 +79,37 @@
|
|
|
79
79
|
color: #1e40af;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/* Graduated capacity colors for multi-unit resources */
|
|
83
|
+
/* Green: utilization < 50% */
|
|
84
|
+
.slotCapacityLow {
|
|
85
|
+
font-size: 0.625rem;
|
|
86
|
+
padding: 2px 4px;
|
|
87
|
+
margin-bottom: 1px;
|
|
88
|
+
border-radius: 2px;
|
|
89
|
+
background: #d1fae5;
|
|
90
|
+
color: #065f46;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Yellow: utilization 50–99% */
|
|
94
|
+
.slotCapacityMid {
|
|
95
|
+
font-size: 0.625rem;
|
|
96
|
+
padding: 2px 4px;
|
|
97
|
+
margin-bottom: 1px;
|
|
98
|
+
border-radius: 2px;
|
|
99
|
+
background: #fef3c7;
|
|
100
|
+
color: #92400e;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Red: utilization 100% (fully booked) */
|
|
104
|
+
.slotCapacityFull {
|
|
105
|
+
font-size: 0.625rem;
|
|
106
|
+
padding: 2px 4px;
|
|
107
|
+
margin-bottom: 1px;
|
|
108
|
+
border-radius: 2px;
|
|
109
|
+
background: #fee2e2;
|
|
110
|
+
color: #991b1b;
|
|
111
|
+
}
|
|
112
|
+
|
|
82
113
|
.slotException {
|
|
83
114
|
font-size: 0.625rem;
|
|
84
115
|
padding: 2px 4px;
|