gorombo-payload-appointments 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/collections/Appointments.d.ts +2 -0
  4. package/dist/collections/Appointments.js +165 -0
  5. package/dist/collections/Appointments.js.map +1 -0
  6. package/dist/collections/GuestCustomers.d.ts +2 -0
  7. package/dist/collections/GuestCustomers.js +106 -0
  8. package/dist/collections/GuestCustomers.js.map +1 -0
  9. package/dist/collections/Services.d.ts +2 -0
  10. package/dist/collections/Services.js +147 -0
  11. package/dist/collections/Services.js.map +1 -0
  12. package/dist/collections/TeamMembers.d.ts +2 -0
  13. package/dist/collections/TeamMembers.js +184 -0
  14. package/dist/collections/TeamMembers.js.map +1 -0
  15. package/dist/components/BeforeDashboardClient.d.ts +2 -0
  16. package/dist/components/BeforeDashboardClient.js +162 -0
  17. package/dist/components/BeforeDashboardClient.js.map +1 -0
  18. package/dist/components/BeforeDashboardServer.d.ts +2 -0
  19. package/dist/components/BeforeDashboardServer.js +22 -0
  20. package/dist/components/BeforeDashboardServer.js.map +1 -0
  21. package/dist/components/BeforeDashboardServer.module.css +5 -0
  22. package/dist/components/calendar/Calendar.module.css +506 -0
  23. package/dist/components/calendar/CalendarContainer.d.ts +3 -0
  24. package/dist/components/calendar/CalendarContainer.js +246 -0
  25. package/dist/components/calendar/CalendarContainer.js.map +1 -0
  26. package/dist/components/calendar/DayView.d.ts +3 -0
  27. package/dist/components/calendar/DayView.js +192 -0
  28. package/dist/components/calendar/DayView.js.map +1 -0
  29. package/dist/components/calendar/EventPopover.d.ts +3 -0
  30. package/dist/components/calendar/EventPopover.js +257 -0
  31. package/dist/components/calendar/EventPopover.js.map +1 -0
  32. package/dist/components/calendar/EventRenderer.d.ts +3 -0
  33. package/dist/components/calendar/EventRenderer.js +76 -0
  34. package/dist/components/calendar/EventRenderer.js.map +1 -0
  35. package/dist/components/calendar/WeekView.d.ts +3 -0
  36. package/dist/components/calendar/WeekView.js +203 -0
  37. package/dist/components/calendar/WeekView.js.map +1 -0
  38. package/dist/components/calendar/index.d.ts +6 -0
  39. package/dist/components/calendar/index.js +7 -0
  40. package/dist/components/calendar/index.js.map +1 -0
  41. package/dist/components/calendar/types.d.ts +69 -0
  42. package/dist/components/calendar/types.js +3 -0
  43. package/dist/components/calendar/types.js.map +1 -0
  44. package/dist/endpoints/customEndpointHandler.d.ts +2 -0
  45. package/dist/endpoints/customEndpointHandler.js +7 -0
  46. package/dist/endpoints/customEndpointHandler.js.map +1 -0
  47. package/dist/endpoints/getAvailableSlots.d.ts +12 -0
  48. package/dist/endpoints/getAvailableSlots.js +291 -0
  49. package/dist/endpoints/getAvailableSlots.js.map +1 -0
  50. package/dist/exports/client.d.ts +3 -0
  51. package/dist/exports/client.js +4 -0
  52. package/dist/exports/client.js.map +1 -0
  53. package/dist/exports/rsc.d.ts +1 -0
  54. package/dist/exports/rsc.js +3 -0
  55. package/dist/exports/rsc.js.map +1 -0
  56. package/dist/globals/OpeningTimes.d.ts +2 -0
  57. package/dist/globals/OpeningTimes.js +196 -0
  58. package/dist/globals/OpeningTimes.js.map +1 -0
  59. package/dist/hooks/addAdminTitle.d.ts +7 -0
  60. package/dist/hooks/addAdminTitle.js +86 -0
  61. package/dist/hooks/addAdminTitle.js.map +1 -0
  62. package/dist/hooks/sendCustomerEmail.d.ts +6 -0
  63. package/dist/hooks/sendCustomerEmail.js +351 -0
  64. package/dist/hooks/sendCustomerEmail.js.map +1 -0
  65. package/dist/hooks/setEndDateTime.d.ts +6 -0
  66. package/dist/hooks/setEndDateTime.js +44 -0
  67. package/dist/hooks/setEndDateTime.js.map +1 -0
  68. package/dist/hooks/validateCustomerOrGuest.d.ts +6 -0
  69. package/dist/hooks/validateCustomerOrGuest.js +21 -0
  70. package/dist/hooks/validateCustomerOrGuest.js.map +1 -0
  71. package/dist/index.d.ts +23 -0
  72. package/dist/index.js +183 -0
  73. package/dist/index.js.map +1 -0
  74. package/package.json +135 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Daniel T Sasser II
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # Gorombo Appointments Plugin
2
+
3
+ A full-featured appointments, scheduling, and booking plugin for [PayloadCMS 3.x](https://payloadcms.com).
4
+
5
+ [![CI](https://github.com/dansasser/gorombo-appointment-plugin/actions/workflows/ci.yml/badge.svg)](https://github.com/dansasser/gorombo-appointment-plugin/actions/workflows/ci.yml)
6
+ [![npm version](https://badge.fury.io/js/gorombo-payload-appointments.svg)](https://www.npmjs.com/package/gorombo-payload-appointments)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Features
10
+
11
+ - **Admin Calendar Dashboard** - Week/Day view calendar integrated into Payload admin
12
+ - **Services Management** - Define bookable services with duration, pricing, and colors
13
+ - **Team Members** - Assign appointments to team members with availability settings
14
+ - **Guest Customers** - Support for non-registered customers booking appointments
15
+ - **Automatic Scheduling** - Auto-calculates end times based on service duration
16
+ - **Business Hours** - Configure opening times, breaks, and scheduling rules
17
+ - **Email Notifications** - Automatic confirmation and update emails
18
+ - **REST API** - Full headless API for custom frontend booking flows
19
+ - **Available Slots Endpoint** - Query available booking times
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install gorombo-payload-appointments
25
+ # or
26
+ pnpm add gorombo-payload-appointments
27
+ # or
28
+ yarn add gorombo-payload-appointments
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ Add the plugin to your Payload config:
34
+
35
+ ```typescript
36
+ // payload.config.ts
37
+ import { buildConfig } from 'payload'
38
+ import { goromboAppointmentsPlugin } from 'gorombo-payload-appointments'
39
+
40
+ export default buildConfig({
41
+ // ... your config
42
+ plugins: [
43
+ goromboAppointmentsPlugin({
44
+ // Optional configuration
45
+ }),
46
+ ],
47
+ })
48
+ ```
49
+
50
+ Regenerate types and import map:
51
+
52
+ ```bash
53
+ npm run generate:types
54
+ npm run generate:importmap
55
+ ```
56
+
57
+ ## Configuration Options
58
+
59
+ ```typescript
60
+ goromboAppointmentsPlugin({
61
+ // Slug for your media collection (default: 'media')
62
+ mediaCollectionSlug: 'media',
63
+
64
+ // Slug for your users collection (default: 'users')
65
+ usersCollectionSlug: 'users',
66
+ })
67
+ ```
68
+
69
+ ## What Gets Added
70
+
71
+ ### Collections
72
+
73
+ | Collection | Slug | Description |
74
+ |------------|------|-------------|
75
+ | Services | `services` | Bookable services with duration, price, and color |
76
+ | Team Members | `team-members` | Staff who can be assigned to appointments |
77
+ | Guest Customers | `guest-customers` | Non-registered booking customers |
78
+ | Appointments | `appointments` | The bookings themselves |
79
+
80
+ ### Globals
81
+
82
+ | Global | Slug | Description |
83
+ |--------|------|-------------|
84
+ | Opening Times | `opening-times` | Business hours and scheduling settings |
85
+
86
+ ## API Reference
87
+
88
+ PayloadCMS automatically generates REST API endpoints for all collections. Here's the complete API reference:
89
+
90
+ ### Services
91
+
92
+ | Method | Endpoint | Description |
93
+ |--------|----------|-------------|
94
+ | GET | `/api/services` | List all services |
95
+ | GET | `/api/services/:id` | Get a single service |
96
+ | POST | `/api/services` | Create a service |
97
+ | PATCH | `/api/services/:id` | Update a service |
98
+ | DELETE | `/api/services/:id` | Delete a service |
99
+
100
+ **Query examples:**
101
+ ```bash
102
+ # Get all active services
103
+ GET /api/services?where[isActive][equals]=true
104
+
105
+ # Get services sorted by price
106
+ GET /api/services?sort=price
107
+ ```
108
+
109
+ ### Team Members
110
+
111
+ | Method | Endpoint | Description |
112
+ |--------|----------|-------------|
113
+ | GET | `/api/team-members` | List all team members |
114
+ | GET | `/api/team-members/:id` | Get a single team member |
115
+ | POST | `/api/team-members` | Create a team member |
116
+ | PATCH | `/api/team-members/:id` | Update a team member |
117
+ | DELETE | `/api/team-members/:id` | Delete a team member |
118
+
119
+ **Query examples:**
120
+ ```bash
121
+ # Get team members taking appointments
122
+ GET /api/team-members?where[takingAppointments][equals]=true
123
+ ```
124
+
125
+ ### Guest Customers
126
+
127
+ | Method | Endpoint | Description |
128
+ |--------|----------|-------------|
129
+ | GET | `/api/guest-customers` | List all guest customers |
130
+ | GET | `/api/guest-customers/:id` | Get a single guest customer |
131
+ | POST | `/api/guest-customers` | Create a guest customer |
132
+ | PATCH | `/api/guest-customers/:id` | Update a guest customer |
133
+ | DELETE | `/api/guest-customers/:id` | Delete a guest customer |
134
+
135
+ **Query examples:**
136
+ ```bash
137
+ # Find guest by email
138
+ GET /api/guest-customers?where[email][equals]=john@example.com
139
+ ```
140
+
141
+ ### Appointments
142
+
143
+ | Method | Endpoint | Description |
144
+ |--------|----------|-------------|
145
+ | GET | `/api/appointments` | List all appointments |
146
+ | GET | `/api/appointments/:id` | Get a single appointment |
147
+ | POST | `/api/appointments` | Create an appointment |
148
+ | PATCH | `/api/appointments/:id` | Update an appointment |
149
+ | DELETE | `/api/appointments/:id` | Delete an appointment |
150
+
151
+ **Query examples:**
152
+ ```bash
153
+ # Get appointments for a specific date range
154
+ GET /api/appointments?where[startDateTime][greater_than_equal]=2024-01-01&where[startDateTime][less_than]=2024-01-31
155
+
156
+ # Get appointments by status
157
+ GET /api/appointments?where[status][equals]=scheduled
158
+
159
+ # Get appointments with related data
160
+ GET /api/appointments?depth=1
161
+ ```
162
+
163
+ ### Available Slots (Custom Endpoint)
164
+
165
+ | Method | Endpoint | Description |
166
+ |--------|----------|-------------|
167
+ | GET | `/api/appointments/available-slots` | Query available booking times |
168
+
169
+ **Query parameters:**
170
+ - `date` (required) - ISO date string (YYYY-MM-DD)
171
+ - `serviceId` (required) - ID of the service
172
+ - `teamMemberId` (optional) - Filter by specific team member
173
+
174
+ **Example:**
175
+ ```bash
176
+ GET /api/appointments/available-slots?date=2024-01-15&serviceId=abc123
177
+ ```
178
+
179
+ **Response:**
180
+ ```json
181
+ {
182
+ "date": "2024-01-15",
183
+ "serviceId": "abc123",
184
+ "slots": [
185
+ { "start": "2024-01-15T09:00:00Z", "end": "2024-01-15T09:30:00Z", "available": true },
186
+ { "start": "2024-01-15T09:30:00Z", "end": "2024-01-15T10:00:00Z", "available": true }
187
+ ]
188
+ }
189
+ ```
190
+
191
+ ### Opening Times (Global)
192
+
193
+ | Method | Endpoint | Description |
194
+ |--------|----------|-------------|
195
+ | GET | `/api/globals/opening-times` | Get business hours settings |
196
+ | POST | `/api/globals/opening-times` | Update business hours settings |
197
+
198
+ ## Booking Flow Example
199
+
200
+ ### 1. Get Available Services
201
+
202
+ ```bash
203
+ GET /api/services?where[isActive][equals]=true
204
+ ```
205
+
206
+ ### 2. Get Available Time Slots
207
+
208
+ ```bash
209
+ GET /api/appointments/available-slots?date=2024-01-15&serviceId=SERVICE_ID
210
+ ```
211
+
212
+ ### 3. Create Guest Customer (if not registered)
213
+
214
+ ```bash
215
+ POST /api/guest-customers
216
+ Content-Type: application/json
217
+
218
+ {
219
+ "firstName": "John",
220
+ "lastName": "Doe",
221
+ "email": "john@example.com",
222
+ "phone": "+1234567890",
223
+ "source": "website"
224
+ }
225
+ ```
226
+
227
+ ### 4. Create Appointment
228
+
229
+ ```bash
230
+ POST /api/appointments
231
+ Content-Type: application/json
232
+
233
+ {
234
+ "type": "appointment",
235
+ "service": "SERVICE_ID",
236
+ "guest": "GUEST_ID",
237
+ "startDateTime": "2024-01-15T09:00:00Z",
238
+ "status": "scheduled"
239
+ }
240
+ ```
241
+
242
+ ## Frontend Integration
243
+
244
+ See the [examples/BookingWidget.tsx](./examples/BookingWidget.tsx) for a complete React booking component with:
245
+ - 3-step booking flow (service -> date/time -> details)
246
+ - Available slots display
247
+ - Guest customer creation
248
+ - Booking confirmation
249
+
250
+ ## Admin Calendar
251
+
252
+ The plugin automatically adds a calendar dashboard to your Payload admin panel showing:
253
+ - Week and day views
254
+ - Color-coded events by service
255
+ - Click to view appointment details
256
+ - Quick navigation between dates
257
+
258
+ ## Development
259
+
260
+ ```bash
261
+ # Install dependencies
262
+ npm install
263
+
264
+ # Run dev environment
265
+ npm run dev
266
+
267
+ # Run tests
268
+ npm test
269
+
270
+ # Lint code
271
+ npm run lint
272
+
273
+ # Format code
274
+ npm run format
275
+
276
+ # Build for production
277
+ npm run build
278
+ ```
279
+
280
+ ## Requirements
281
+
282
+ - PayloadCMS 3.37.0 or higher
283
+ - Node.js 18.20.2+ or 20.9.0+
284
+ - React 19.x
285
+
286
+ ## Contributing
287
+
288
+ Contributions are welcome! Please read our [contributing guidelines](./CONTRIBUTING.md) and submit a pull request.
289
+
290
+ 1. Fork the repository
291
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
292
+ 3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
293
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
294
+ 5. Open a Pull Request
295
+
296
+ ## License
297
+
298
+ MIT License - see [LICENSE](./LICENSE) for details.
299
+
300
+ ## Author
301
+
302
+ Created by [Daniel T Sasser II](https://github.com/Gorombo)
303
+
304
+ ## Links
305
+
306
+ - [PayloadCMS](https://payloadcms.com)
307
+ - [Plugin Documentation](https://payloadcms.com/docs/plugins/overview)
308
+ - [Report Issues](https://github.com/dansasser/gorombo-appointment-plugin/issues)
@@ -0,0 +1,2 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare const Appointments: CollectionConfig;
@@ -0,0 +1,165 @@
1
+ export const Appointments = {
2
+ slug: 'appointments',
3
+ access: {
4
+ create: ()=>true,
5
+ delete: ({ req })=>!!req.user,
6
+ read: ()=>true,
7
+ update: ({ req })=>!!req.user
8
+ },
9
+ admin: {
10
+ defaultColumns: [
11
+ 'title',
12
+ 'startDateTime',
13
+ 'service',
14
+ 'status'
15
+ ],
16
+ group: 'Scheduling',
17
+ useAsTitle: 'title'
18
+ },
19
+ fields: [
20
+ {
21
+ name: 'title',
22
+ type: 'text',
23
+ admin: {
24
+ description: 'Auto-generated display title',
25
+ hidden: true
26
+ }
27
+ },
28
+ {
29
+ name: 'type',
30
+ type: 'select',
31
+ admin: {
32
+ position: 'sidebar'
33
+ },
34
+ defaultValue: 'appointment',
35
+ options: [
36
+ {
37
+ label: 'Appointment',
38
+ value: 'appointment'
39
+ },
40
+ {
41
+ label: 'Blockout',
42
+ value: 'blockout'
43
+ }
44
+ ],
45
+ required: true
46
+ },
47
+ {
48
+ name: 'service',
49
+ type: 'relationship',
50
+ admin: {
51
+ condition: (data)=>data?.type === 'appointment'
52
+ },
53
+ relationTo: 'services',
54
+ validate: (value, { siblingData })=>{
55
+ if (siblingData?.type === 'appointment' && !value) {
56
+ return 'Service is required for appointments';
57
+ }
58
+ return true;
59
+ }
60
+ },
61
+ {
62
+ name: 'customer',
63
+ type: 'relationship',
64
+ admin: {
65
+ condition: (data)=>data?.type === 'appointment',
66
+ description: 'Registered user booking the appointment'
67
+ },
68
+ relationTo: 'users'
69
+ },
70
+ {
71
+ name: 'guest',
72
+ type: 'relationship',
73
+ admin: {
74
+ condition: (data)=>data?.type === 'appointment',
75
+ description: 'Guest customer (non-registered user)'
76
+ },
77
+ relationTo: 'guest-customers'
78
+ },
79
+ {
80
+ name: 'teamMember',
81
+ type: 'relationship',
82
+ admin: {
83
+ description: 'Staff member assigned to this appointment',
84
+ position: 'sidebar'
85
+ },
86
+ relationTo: 'team-members'
87
+ },
88
+ {
89
+ name: 'startDateTime',
90
+ type: 'date',
91
+ admin: {
92
+ date: {
93
+ displayFormat: 'MMM d, yyyy h:mm a',
94
+ pickerAppearance: 'dayAndTime'
95
+ }
96
+ },
97
+ required: true
98
+ },
99
+ {
100
+ name: 'endDateTime',
101
+ type: 'date',
102
+ admin: {
103
+ date: {
104
+ displayFormat: 'MMM d, yyyy h:mm a',
105
+ pickerAppearance: 'dayAndTime'
106
+ },
107
+ description: 'Auto-calculated from service duration',
108
+ readOnly: true
109
+ }
110
+ },
111
+ {
112
+ name: 'status',
113
+ type: 'select',
114
+ admin: {
115
+ position: 'sidebar'
116
+ },
117
+ defaultValue: 'scheduled',
118
+ options: [
119
+ {
120
+ label: 'Scheduled',
121
+ value: 'scheduled'
122
+ },
123
+ {
124
+ label: 'Confirmed',
125
+ value: 'confirmed'
126
+ },
127
+ {
128
+ label: 'Completed',
129
+ value: 'completed'
130
+ },
131
+ {
132
+ label: 'Cancelled',
133
+ value: 'cancelled'
134
+ },
135
+ {
136
+ label: 'No-show',
137
+ value: 'no-show'
138
+ }
139
+ ],
140
+ required: true
141
+ },
142
+ {
143
+ name: 'notes',
144
+ type: 'textarea',
145
+ admin: {
146
+ description: 'Internal notes about this appointment'
147
+ }
148
+ },
149
+ {
150
+ name: 'blockoutReason',
151
+ type: 'text',
152
+ admin: {
153
+ condition: (data)=>data?.type === 'blockout',
154
+ description: 'Reason for the blockout (e.g., lunch, meeting)'
155
+ }
156
+ }
157
+ ],
158
+ labels: {
159
+ plural: 'Appointments',
160
+ singular: 'Appointment'
161
+ },
162
+ timestamps: true
163
+ };
164
+
165
+ //# sourceMappingURL=Appointments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/Appointments.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nexport const Appointments: CollectionConfig = {\n slug: 'appointments',\n access: {\n create: () => true,\n delete: ({ req }) => !!req.user,\n read: () => true,\n update: ({ req }) => !!req.user,\n },\n admin: {\n defaultColumns: ['title', 'startDateTime', 'service', 'status'],\n group: 'Scheduling',\n useAsTitle: 'title',\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n admin: {\n description: 'Auto-generated display title',\n hidden: true,\n },\n },\n {\n name: 'type',\n type: 'select',\n admin: {\n position: 'sidebar',\n },\n defaultValue: 'appointment',\n options: [\n { label: 'Appointment', value: 'appointment' },\n { label: 'Blockout', value: 'blockout' },\n ],\n required: true,\n },\n {\n name: 'service',\n type: 'relationship',\n admin: {\n condition: (data) => data?.type === 'appointment',\n },\n relationTo: 'services',\n validate: (value: unknown, { siblingData }: { siblingData: Record<string, unknown> }) => {\n if (siblingData?.type === 'appointment' && !value) {\n return 'Service is required for appointments'\n }\n return true\n },\n },\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n condition: (data) => data?.type === 'appointment',\n description: 'Registered user booking the appointment',\n },\n relationTo: 'users',\n },\n {\n name: 'guest',\n type: 'relationship',\n admin: {\n condition: (data) => data?.type === 'appointment',\n description: 'Guest customer (non-registered user)',\n },\n relationTo: 'guest-customers',\n },\n {\n name: 'teamMember',\n type: 'relationship',\n admin: {\n description: 'Staff member assigned to this appointment',\n position: 'sidebar',\n },\n relationTo: 'team-members',\n },\n {\n name: 'startDateTime',\n type: 'date',\n admin: {\n date: {\n displayFormat: 'MMM d, yyyy h:mm a',\n pickerAppearance: 'dayAndTime',\n },\n },\n required: true,\n },\n {\n name: 'endDateTime',\n type: 'date',\n admin: {\n date: {\n displayFormat: 'MMM d, yyyy h:mm a',\n pickerAppearance: 'dayAndTime',\n },\n description: 'Auto-calculated from service duration',\n readOnly: true,\n },\n },\n {\n name: 'status',\n type: 'select',\n admin: {\n position: 'sidebar',\n },\n defaultValue: 'scheduled',\n options: [\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Confirmed', value: 'confirmed' },\n { label: 'Completed', value: 'completed' },\n { label: 'Cancelled', value: 'cancelled' },\n { label: 'No-show', value: 'no-show' },\n ],\n required: true,\n },\n {\n name: 'notes',\n type: 'textarea',\n admin: {\n description: 'Internal notes about this appointment',\n },\n },\n {\n name: 'blockoutReason',\n type: 'text',\n admin: {\n condition: (data) => data?.type === 'blockout',\n description: 'Reason for the blockout (e.g., lunch, meeting)',\n },\n },\n ],\n labels: {\n plural: 'Appointments',\n singular: 'Appointment',\n },\n timestamps: true,\n}\n"],"names":["Appointments","slug","access","create","delete","req","user","read","update","admin","defaultColumns","group","useAsTitle","fields","name","type","description","hidden","position","defaultValue","options","label","value","required","condition","data","relationTo","validate","siblingData","date","displayFormat","pickerAppearance","readOnly","labels","plural","singular","timestamps"],"mappings":"AAEA,OAAO,MAAMA,eAAiC;IAC5CC,MAAM;IACNC,QAAQ;QACNC,QAAQ,IAAM;QACdC,QAAQ,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;QAC/BC,MAAM,IAAM;QACZC,QAAQ,CAAC,EAAEH,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;IACjC;IACAG,OAAO;QACLC,gBAAgB;YAAC;YAAS;YAAiB;YAAW;SAAS;QAC/DC,OAAO;QACPC,YAAY;IACd;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLO,aAAa;gBACbC,QAAQ;YACV;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,UAAU;YACZ;YACAC,cAAc;YACdC,SAAS;gBACP;oBAAEC,OAAO;oBAAeC,OAAO;gBAAc;gBAC7C;oBAAED,OAAO;oBAAYC,OAAO;gBAAW;aACxC;YACDC,UAAU;QACZ;QACA;YACET,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLe,WAAW,CAACC,OAASA,MAAMV,SAAS;YACtC;YACAW,YAAY;YACZC,UAAU,CAACL,OAAgB,EAAEM,WAAW,EAA4C;gBAClF,IAAIA,aAAab,SAAS,iBAAiB,CAACO,OAAO;oBACjD,OAAO;gBACT;gBACA,OAAO;YACT;QACF;QACA;YACER,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLe,WAAW,CAACC,OAASA,MAAMV,SAAS;gBACpCC,aAAa;YACf;YACAU,YAAY;QACd;QACA;YACEZ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLe,WAAW,CAACC,OAASA,MAAMV,SAAS;gBACpCC,aAAa;YACf;YACAU,YAAY;QACd;QACA;YACEZ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLO,aAAa;gBACbE,UAAU;YACZ;YACAQ,YAAY;QACd;QACA;YACEZ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLoB,MAAM;oBACJC,eAAe;oBACfC,kBAAkB;gBACpB;YACF;YACAR,UAAU;QACZ;QACA;YACET,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLoB,MAAM;oBACJC,eAAe;oBACfC,kBAAkB;gBACpB;gBACAf,aAAa;gBACbgB,UAAU;YACZ;QACF;QACA;YACElB,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,UAAU;YACZ;YACAC,cAAc;YACdC,SAAS;gBACP;oBAAEC,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAWC,OAAO;gBAAU;aACtC;YACDC,UAAU;QACZ;QACA;YACET,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLO,aAAa;YACf;QACF;QACA;YACEF,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLe,WAAW,CAACC,OAASA,MAAMV,SAAS;gBACpCC,aAAa;YACf;QACF;KACD;IACDiB,QAAQ;QACNC,QAAQ;QACRC,UAAU;IACZ;IACAC,YAAY;AACd,EAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare const GuestCustomers: CollectionConfig;
@@ -0,0 +1,106 @@
1
+ export const GuestCustomers = {
2
+ slug: 'guest-customers',
3
+ access: {
4
+ create: ()=>true,
5
+ delete: ({ req })=>!!req.user,
6
+ read: ({ req })=>!!req.user,
7
+ update: ({ req })=>!!req.user
8
+ },
9
+ admin: {
10
+ defaultColumns: [
11
+ 'firstName',
12
+ 'lastName',
13
+ 'email',
14
+ 'phone',
15
+ 'createdAt'
16
+ ],
17
+ group: 'Scheduling',
18
+ useAsTitle: 'email'
19
+ },
20
+ fields: [
21
+ {
22
+ name: 'firstName',
23
+ type: 'text',
24
+ required: true
25
+ },
26
+ {
27
+ name: 'lastName',
28
+ type: 'text',
29
+ required: true
30
+ },
31
+ {
32
+ name: 'email',
33
+ type: 'email',
34
+ required: true,
35
+ unique: true
36
+ },
37
+ {
38
+ name: 'phone',
39
+ type: 'text',
40
+ admin: {
41
+ description: 'Contact phone number'
42
+ }
43
+ },
44
+ {
45
+ name: 'company',
46
+ type: 'text',
47
+ admin: {
48
+ description: 'Company or organization name'
49
+ }
50
+ },
51
+ {
52
+ name: 'notes',
53
+ type: 'textarea',
54
+ admin: {
55
+ description: 'Internal notes about this guest'
56
+ }
57
+ },
58
+ {
59
+ name: 'marketingOptIn',
60
+ type: 'checkbox',
61
+ admin: {
62
+ description: 'Opted in to marketing communications',
63
+ position: 'sidebar'
64
+ },
65
+ defaultValue: false
66
+ },
67
+ {
68
+ name: 'source',
69
+ type: 'select',
70
+ admin: {
71
+ description: 'How did they find us',
72
+ position: 'sidebar'
73
+ },
74
+ defaultValue: 'website',
75
+ options: [
76
+ {
77
+ label: 'Website',
78
+ value: 'website'
79
+ },
80
+ {
81
+ label: 'Referral',
82
+ value: 'referral'
83
+ },
84
+ {
85
+ label: 'Walk-in',
86
+ value: 'walkin'
87
+ },
88
+ {
89
+ label: 'Phone',
90
+ value: 'phone'
91
+ },
92
+ {
93
+ label: 'Other',
94
+ value: 'other'
95
+ }
96
+ ]
97
+ }
98
+ ],
99
+ labels: {
100
+ plural: 'Guest Customers',
101
+ singular: 'Guest Customer'
102
+ },
103
+ timestamps: true
104
+ };
105
+
106
+ //# sourceMappingURL=GuestCustomers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/GuestCustomers.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nexport const GuestCustomers: CollectionConfig = {\n slug: 'guest-customers',\n access: {\n create: () => true,\n delete: ({ req }) => !!req.user,\n read: ({ req }) => !!req.user,\n update: ({ req }) => !!req.user,\n },\n admin: {\n defaultColumns: ['firstName', 'lastName', 'email', 'phone', 'createdAt'],\n group: 'Scheduling',\n useAsTitle: 'email',\n },\n fields: [\n {\n name: 'firstName',\n type: 'text',\n required: true,\n },\n {\n name: 'lastName',\n type: 'text',\n required: true,\n },\n {\n name: 'email',\n type: 'email',\n required: true,\n unique: true,\n },\n {\n name: 'phone',\n type: 'text',\n admin: {\n description: 'Contact phone number',\n },\n },\n {\n name: 'company',\n type: 'text',\n admin: {\n description: 'Company or organization name',\n },\n },\n {\n name: 'notes',\n type: 'textarea',\n admin: {\n description: 'Internal notes about this guest',\n },\n },\n {\n name: 'marketingOptIn',\n type: 'checkbox',\n admin: {\n description: 'Opted in to marketing communications',\n position: 'sidebar',\n },\n defaultValue: false,\n },\n {\n name: 'source',\n type: 'select',\n admin: {\n description: 'How did they find us',\n position: 'sidebar',\n },\n defaultValue: 'website',\n options: [\n { label: 'Website', value: 'website' },\n { label: 'Referral', value: 'referral' },\n { label: 'Walk-in', value: 'walkin' },\n { label: 'Phone', value: 'phone' },\n { label: 'Other', value: 'other' },\n ],\n },\n ],\n labels: {\n plural: 'Guest Customers',\n singular: 'Guest Customer',\n },\n timestamps: true,\n}\n"],"names":["GuestCustomers","slug","access","create","delete","req","user","read","update","admin","defaultColumns","group","useAsTitle","fields","name","type","required","unique","description","position","defaultValue","options","label","value","labels","plural","singular","timestamps"],"mappings":"AAEA,OAAO,MAAMA,iBAAmC;IAC9CC,MAAM;IACNC,QAAQ;QACNC,QAAQ,IAAM;QACdC,QAAQ,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;QAC/BC,MAAM,CAAC,EAAEF,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;QAC7BE,QAAQ,CAAC,EAAEH,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;IACjC;IACAG,OAAO;QACLC,gBAAgB;YAAC;YAAa;YAAY;YAAS;YAAS;SAAY;QACxEC,OAAO;QACPC,YAAY;IACd;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNC,UAAU;QACZ;QACA;YACEF,MAAM;YACNC,MAAM;YACNC,UAAU;QACZ;QACA;YACEF,MAAM;YACNC,MAAM;YACNC,UAAU;YACVC,QAAQ;QACV;QACA;YACEH,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,aAAa;YACf;QACF;QACA;YACEJ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,aAAa;YACf;QACF;QACA;YACEJ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,aAAa;YACf;QACF;QACA;YACEJ,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,aAAa;gBACbC,UAAU;YACZ;YACAC,cAAc;QAChB;QACA;YACEN,MAAM;YACNC,MAAM;YACNN,OAAO;gBACLS,aAAa;gBACbC,UAAU;YACZ;YACAC,cAAc;YACdC,SAAS;gBACP;oBAAEC,OAAO;oBAAWC,OAAO;gBAAU;gBACrC;oBAAED,OAAO;oBAAYC,OAAO;gBAAW;gBACvC;oBAAED,OAAO;oBAAWC,OAAO;gBAAS;gBACpC;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;gBACjC;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;aAClC;QACH;KACD;IACDC,QAAQ;QACNC,QAAQ;QACRC,UAAU;IACZ;IACAC,YAAY;AACd,EAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare const Services: CollectionConfig;