feat(admin): implement full day-by-day schedule editor with live preview
## Features ### Admin Schedule Page (`packages/app/src/pages/admin/schedule.vue`) - Interactive date-based slot editor for managing daily schedules - Real-time slot editing: start/end times, capacity adjustments - Slot deletion with conflict warnings when bookings exist - Add new slots with modal dialog - Live booking status display (booked count, people names) - Publish/Save changes with sync feedback - Revert unsaved changes with confirmation - Skeleton loading states and empty state handling - Responsive design with optimized mobile UX ### Backend Enhancements - **New DTO** (`PublishDaySlotsDto`): Structured slot publishing with validation - Date string validation - Slot array with existing slot IDs for updates - Time and capacity validation per slot - **Schedule Preview API** (`getSchedulePreview`): - Check for existing published slots - Fallback to active WeekTemplates for unpublished dates - Unified response format with isPublished flag - **Publish Slots API** (`publishDaySlots`): - Atomic transaction for consistency - Update existing slots with new times/capacity - Create new slots from template data - Delete unpublished slots or set to CLOSED if bookings exist - Prevent capacity reduction below existing bookings - Returns all published slots for feedback ### State Management - Enhanced admin store with schedule state - Support for pending/unsaved slot changes - Optimistic UI updates with server sync ### Documentation - Comprehensive scheduling system architecture docs - Quick reference for admin workflows - Flow diagrams and state transitions - Implementation guide for future maintenance ## Breaking Changes None ## Testing Recommendations - Create slots for future dates via schedule editor - Verify booking prevention for locked/full slots - Test capacity adjustments with existing bookings - Confirm template-based schedule generation - Verify transaction rollback on publish failures Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,9 @@ export type {
|
||||
TimeSlot,
|
||||
TimeSlotWithBookingStatus,
|
||||
CreateManualSlotDto,
|
||||
ScheduleSlotPreview,
|
||||
PublishDaySlotItem,
|
||||
PublishDaySlotsDto,
|
||||
Booking,
|
||||
BookingWithDetails,
|
||||
CreateBookingDto,
|
||||
|
||||
@@ -2,7 +2,7 @@ export type { User, UserProfileResponse, UpdateProfileDto, UserStatsResponse } f
|
||||
export type { CardType, CreateCardTypeDto, UpdateCardTypeDto } from './card-type'
|
||||
export type { Membership, MembershipWithCardType } from './membership'
|
||||
export type { WeekTemplate, WeekTemplateInput } from './week-template'
|
||||
export type { TimeSlot, TimeSlotWithBookingStatus, CreateManualSlotDto } from './time-slot'
|
||||
export type { TimeSlot, TimeSlotWithBookingStatus, CreateManualSlotDto, ScheduleSlotPreview, PublishDaySlotItem, PublishDaySlotsDto } from './time-slot'
|
||||
export type { Booking, BookingWithDetails, CreateBookingDto } from './booking'
|
||||
export type { Order, OrderWithDetails, CreateOrderDto, PaymentParams, CreateOrderResponse } from './order'
|
||||
export type { StudioConfig, UpdateStudioConfigDto } from './studio'
|
||||
|
||||
@@ -27,3 +27,35 @@ export interface CreateManualSlotDto {
|
||||
readonly endTime: string
|
||||
readonly capacity?: number
|
||||
}
|
||||
|
||||
/** 排课预览项(已发布的 TimeSlot 或模板派生的预览) */
|
||||
export interface ScheduleSlotPreview {
|
||||
/** 已发布则有 ID,模板预览为 null */
|
||||
readonly id: string | null
|
||||
readonly date: string
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity: number
|
||||
readonly bookedCount: number
|
||||
readonly status: TimeSlotStatus
|
||||
readonly source: TimeSlotSource
|
||||
readonly templateId: string | null
|
||||
/** true = DB 中已有 TimeSlot 记录 */
|
||||
readonly isPublished: boolean
|
||||
}
|
||||
|
||||
/** 发布某天排课时的单个时段 */
|
||||
export interface PublishDaySlotItem {
|
||||
/** 保留/修改已有时段时传入 */
|
||||
readonly existingSlotId?: string
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity: number
|
||||
}
|
||||
|
||||
/** 发布某天排课的请求体 */
|
||||
export interface PublishDaySlotsDto {
|
||||
/** YYYY-MM-DD */
|
||||
readonly date: string
|
||||
readonly slots: readonly PublishDaySlotItem[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user