payload-reserve
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesepayload-reserve Plugin Guide
payload-reserve插件指南
Overview
概述
payload-reserve- 5 collections: Services, Resources, Schedules, Reservations, Customers
- Customers auth collection: Dedicated auth collection () with
auth: true— customers get JWT auth endpoints but cannot access the admin panelaccess.admin: () => false - 4 beforeChange hooks: Auto endTime calculation, conflict detection, status state machine, cancellation policy
- Admin components: Dashboard widget (RSC), Calendar view (client), Customer picker (client), Availability grid (client)
- Custom endpoint: for multi-field customer search
/api/reservation-customer-search
Plugin pattern: Higher-order function .
(pluginOptions) => (config) => modifiedConfigThree export paths:
- — server-side plugin function, types, and utility functions
payload-reserve - — CalendarView, AvailabilityOverview, CustomerField
payload-reserve/client - — DashboardWidgetServer
payload-reserve/rsc
payload-reserve- 5个集合:服务(Services)、资源(Resources)、日程(Schedules)、预订记录(Reservations)、客户(Customers)
- 客户认证集合:专用的认证集合(),配置
auth: true——客户可使用JWT认证端点,但无法访问管理面板access.admin: () => false - 4个beforeChange钩子:自动结束时间计算、冲突检测、状态状态机、取消政策
- 管理面板组件:仪表盘小部件(RSC)、日历视图(客户端)、客户选择器(客户端)、可用性网格(客户端)
- 自定义端点:,用于多字段客户搜索
/api/reservation-customer-search
插件模式:高阶函数
(pluginOptions) => (config) => modifiedConfig三个导出路径:
- ——服务端插件函数、类型定义和工具函数
payload-reserve - ——CalendarView、AvailabilityOverview、CustomerField
payload-reserve/client - ——DashboardWidgetServer
payload-reserve/rsc
Quick Start
快速开始
ts
import { buildConfig } from 'payload'
import { payloadReserve } from 'payload-reserve'
export default buildConfig({
collections: [/* your existing collections */],
plugins: [payloadReserve()],
})The plugin creates 5 collections (Services, Resources, Schedules, Reservations, Customers) and adds a dashboard widget, calendar list view, and availability admin view. All collections appear under the "Reservations" group in the admin panel. The plugin does not modify your existing users collection.
Peer dependency:
payload ^3.76.1ts
import { buildConfig } from 'payload'
import { payloadReserve } from 'payload-reserve'
export default buildConfig({
collections: [/* 您现有的集合 */],
plugins: [payloadReserve()],
})该插件会创建5个集合(服务、资源、日程、预订记录、客户),并添加仪表盘小部件、日历列表视图和可用性管理视图。所有集合都会显示在管理面板的**「预订」**分组下。插件不会修改您现有的用户集合。
对等依赖:
payload ^3.76.1Configuration
配置选项
All options are optional — the plugin works out of the box.
ts
payloadReserve({
disabled: false, // disable plugin (collections still registered)
slugs: {
services: 'services', // override collection slugs
resources: 'resources',
schedules: 'schedules',
reservations: 'reservations',
customers: 'customers',
media: 'media', // media collection for Resources image field
},
adminGroup: 'Reservations', // admin panel group name
defaultBufferTime: 0, // minutes between reservations (fallback)
cancellationNoticePeriod: 24, // minimum hours notice for cancellation
access: { // per-collection access control overrides
services: { read: () => true },
resources: { /* ... */ },
schedules: { /* ... */ },
reservations: { /* ... */ },
customers: { /* ... */ },
},
})| Option | Default | Description |
|---|---|---|
| | Disable plugin functionality |
| | Collection slugs |
| | Admin panel group |
| | Default buffer minutes between bookings |
| | Minimum hours notice for cancellation |
| | Per-collection access control overrides |
所有选项均为可选——插件可开箱即用。
ts
payloadReserve({
disabled: false, // 禁用插件功能(集合仍会注册)
slugs: {
services: 'services', // 覆盖集合别名
resources: 'resources',
schedules: 'schedules',
reservations: 'reservations',
customers: 'customers',
media: 'media', // 资源图片字段使用的媒体集合
},
adminGroup: 'Reservations', // 管理面板分组名称
defaultBufferTime: 0, // 预订之间的默认缓冲时间(分钟,作为 fallback)
cancellationNoticePeriod: 24, // 取消预订的最短提前通知时长(小时)
access: { // 按集合设置的访问控制覆盖规则
services: { read: () => true },
resources: { /* ... */ },
schedules: { /* ... */ },
reservations: { /* ... */ },
customers: { /* ... */ },
},
})| 选项 | 默认值 | 说明 |
|---|---|---|
| | 禁用插件功能 |
| | 集合别名 |
| | 管理面板分组名称 |
| | 预订之间的默认缓冲分钟数 |
| | 取消预订的最短提前通知小时数 |
| | 按集合设置的访问控制覆盖规则 |
Collection Relationships
集合关系
Services <--many-to-many-- Resources
|
has schedule
|
Schedules
Reservations --> Service
--> Resource
--> Customer- Resources reference Services (hasMany) — which services a resource can perform
- Schedules belong to a Resource — when the resource is available
- Reservations reference a Service, Resource, and Customer
- Customers is a dedicated auth collection — has JWT auth endpoints but no admin panel access
For full field schemas, see references/collections.md.
Services <--多对多-- Resources
|
关联日程
|
Schedules
Reservations --> Service
--> Resource
--> Customer- 资源(Resources)关联服务(Services)(多对多)——表示某一资源可提供的服务
- 日程(Schedules)属于某一资源(Resource)——定义资源的可用时间
- **预订记录(Reservations)**关联服务、资源和客户
- **客户(Customers)**是专用的认证集合——拥有JWT认证端点,但无管理面板访问权限
完整的字段架构,请查看references/collections.md。
Status State Machine
状态状态机
+-> confirmed --+-> completed
| |
pending ------+ +-> cancelled
| |
+-> cancelled +-> no-show- On create (public): Must be
pending - On create (admin): Can be or
pending(walk-in support)confirmed - Terminal states (,
completed,cancelled): No further transitionsno-show
For hook details, conflict detection algorithm, cancellation policy, and escape hatch, see references/hooks-and-status.md.
+-> confirmed --+-> completed
| |
pending ------+ +-> cancelled
| |
+-> cancelled +-> no-show- (公开创建时):状态必须为
pending - (管理员创建时):状态可以是或
pending(支持现场预约)confirmed - 终端状态(、
completed、cancelled):无法再进行状态转换no-show
钩子详情、冲突检测算法、取消政策和应急方案,请查看references/hooks-and-status.md。
Customization Patterns
自定义模式
Adding Fields After Plugin
在插件之后添加字段
Add fields to plugin collections after the plugin runs using another plugin or config manipulation:
ts
export default buildConfig({
plugins: [
payloadReserve(),
// Add fields to reservations after the plugin
(config) => {
const reservations = config.collections?.find(c => c.slug === 'reservations')
if (reservations) {
reservations.fields.push({ name: 'internalNotes', type: 'textarea' })
}
return config
},
],
})可通过其他插件或配置修改,在插件运行后为插件集合添加字段:
ts
export default buildConfig({
plugins: [
payloadReserve(),
// 在插件之后为预订记录添加字段
(config) => {
const reservations = config.collections?.find(c => c.slug === 'reservations')
if (reservations) {
reservations.fields.push({ name: 'internalNotes', type: 'textarea' })
}
return config
},
],
})Custom afterChange Hooks
自定义afterChange钩子
Add hooks to plugin collections for notifications, integrations, etc.:
ts
// In a plugin that runs after payloadReserve()
const reservations = config.collections?.find(c => c.slug === 'reservations')
if (reservations) {
if (!reservations.hooks) reservations.hooks = {}
if (!reservations.hooks.afterChange) reservations.hooks.afterChange = []
reservations.hooks.afterChange.push(myNotificationHook)
}可为插件集合添加钩子,用于通知、集成等场景:
ts
// 在payloadReserve()之后运行的插件中
const reservations = config.collections?.find(c => c.slug === 'reservations')
if (reservations) {
if (!reservations.hooks) reservations.hooks = {}
if (!reservations.hooks.afterChange) reservations.hooks.afterChange = []
reservations.hooks.afterChange.push(myNotificationHook)
}Access Control for Public Booking
公开预约的访问控制
Pass overrides in plugin config to enable public booking. See references/frontend-booking.md for a complete step-by-step guide.
access在插件配置中传入覆盖规则,以启用公开预约功能。完整的分步指南,请查看references/frontend-booking.md。
accessCustom Slug Example
自定义别名示例
ts
payloadReserve({
slugs: {
services: 'salon-services',
resources: 'stylists',
schedules: 'stylist-schedules',
reservations: 'appointments',
customers: 'clients',
},
})Components access slugs via .
config.admin.custom.reservationSlugsts
payloadReserve({
slugs: {
services: 'salon-services',
resources: 'stylists',
schedules: 'stylist-schedules',
reservations: 'appointments',
customers: 'clients',
},
})组件可通过访问别名。
config.admin.custom.reservationSlugsAdmin Components
管理面板组件
- DashboardWidget (RSC): Today's stats (total, upcoming, completed, cancelled, next appointment). Registered as modular dashboard widget with slug .
reservation-todays-reservations - CalendarView (Client): Month/week/day CSS Grid calendar replacing Reservations list view. Color-coded by status. Click-to-create, event tooltips, current time indicator.
- CustomerField (Client): Rich customer picker with multi-field search (firstName, lastName, phone, email), inline create/edit via document drawer.
- AvailabilityOverview (Client): Weekly resource availability grid at . Green=available, blue=booked, gray=exception.
/admin/reservation-availability
- DashboardWidget(RSC):今日统计数据(总数、待处理、已完成、已取消、下一个预约)。注册为模块化仪表盘小部件,别名为。
reservation-todays-reservations - CalendarView(客户端):使用CSS Grid实现的月/周/日日历,替代预订记录的列表视图。按状态颜色编码,点击可创建预约,支持事件提示和当前时间指示器。
- CustomerField(客户端):功能丰富的客户选择器,支持多字段搜索(名字、姓氏、电话、邮箱),可通过文档抽屉内联创建/编辑客户。
- AvailabilityOverview(客户端):每周资源可用性网格,位于。绿色=可用,蓝色=已预订,灰色=例外日期。
/admin/reservation-availability
Utility Exports
工具函数导出
Available from (server-side):
payload-reserve| Function | Purpose |
|---|---|
| Add minutes to a Date |
| Check time range overlap |
| Compute blocked window with buffers |
| Hours between now and future date |
| Resolve concrete time ranges for a date |
| Merge date + "HH:mm" string |
| Check if date is an exception |
可从(服务端)获取以下工具函数:
payload-reserve| 函数 | 用途 |
|---|---|
| 为日期添加指定分钟数 |
| 检查时间范围是否重叠 |
| 计算包含缓冲时间的封锁时间段 |
| 计算当前时间与未来日期的小时差 |
| 解析指定日期的具体可用时间范围 |
| 将日期与"HH:mm"格式的时间字符串合并 |
| 检查日期是否为例外日期 |
Troubleshooting
故障排除
Conflict detection not catching overlaps: Check that / are set on the Service. The plugin falls back to (default: 0) if not set.
bufferTimeBeforebufferTimeAfterdefaultBufferTimeStatus transition errors: Only valid transitions are allowed. Check the state machine diagram above. Use for migrations/seeding.
context: { skipReservationHooks: true }Cancellation rejected: The (default: 24h) blocks late cancellations. Use the escape hatch for automated cleanup.
cancellationNoticePeriodCustomer cannot log into admin panel: This is by design. The Customers collection has . Customers authenticate via REST API endpoints () for customer-facing pages.
access.admin: () => false/api/customers/loginendTime not updating: endTime is auto-calculated from . Ensure the service has a value. The field is read-only.
startTime + service.durationduration冲突检测未识别重叠:检查服务是否设置了/。如果未设置,插件会使用(默认值:0)作为 fallback。
bufferTimeBeforebufferTimeAfterdefaultBufferTime状态转换错误:仅允许有效的状态转换。请参考上方的状态机图。迁移/初始化数据时,可使用跳过钩子。
context: { skipReservationHooks: true }取消请求被拒绝:(默认值:24小时)会阻止过晚的取消请求。可使用应急方案进行自动清理。
cancellationNoticePeriod客户无法登录管理面板:这是设计如此。客户集合配置了,客户需通过REST API端点()进行认证,以访问面向客户的页面。
access.admin: () => false/api/customers/loginendTime未更新:endTime由自动计算。请确保服务已设置值,该字段为只读。
startTime + service.durationdurationDeep Dives
深度指南
- Full collection schemas: references/collections.md
- Hook details, state machine, escape hatch: references/hooks-and-status.md
- Frontend booking integration guide: references/frontend-booking.md
- Stripe, notifications, scheduled cleanup: references/integration-patterns.md
- 完整集合架构:references/collections.md
- 钩子详情、状态机、应急方案:references/hooks-and-status.md
- 前端预约集成指南:references/frontend-booking.md
- Stripe集成、通知、定时清理:references/integration-patterns.md