Add service addons and manual scheduling features

Service Addons:
- Add ServiceAddon model with optional resource assignment
- Create AddonSelection component for booking flow
- Add ServiceAddonManager for service configuration
- Include addon API endpoints and serializers

Manual Scheduling:
- Add requires_manual_scheduling and capture_preferred_time to Service model
- Add preferred_datetime and preferred_time_notes to Event model
- Create ManualSchedulingRequest component for booking callback flow
- Auto-open pending sidebar when requests exist or arrive via websocket
- Show preferred times on pending items with detail modal popup
- Add interactive UnscheduledBookingDemo component for help docs

Scheduler Improvements:
- Consolidate Create/EditAppointmentModal into single AppointmentModal
- Update pending sidebar to show preferred schedule info
- Add modal for pending request details with Schedule Now action

Documentation:
- Add Manual Scheduling section to HelpScheduler with interactive demo
- Add Manual Scheduling section to HelpServices with interactive demo

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-23 21:27:24 -05:00
parent 2bfa01e0d4
commit fa7ecf16b1
31 changed files with 4955 additions and 803 deletions

View File

@@ -7,6 +7,7 @@ interface DateTimeSelectionProps {
serviceId?: number;
selectedDate: Date | null;
selectedTimeSlot: string | null;
selectedAddonIds?: number[];
onDateChange: (date: Date) => void;
onTimeChange: (time: string) => void;
}
@@ -15,6 +16,7 @@ export const DateTimeSelection: React.FC<DateTimeSelectionProps> = ({
serviceId,
selectedDate,
selectedTimeSlot,
selectedAddonIds = [],
onDateChange,
onTimeChange
}) => {
@@ -52,7 +54,12 @@ export const DateTimeSelection: React.FC<DateTimeSelectionProps> = ({
: undefined;
// Fetch availability when both serviceId and date are set
const { data: availability, isLoading: availabilityLoading, isError, error } = usePublicAvailability(serviceId, dateString);
// Pass addon IDs to check availability for addon resources too
const { data: availability, isLoading: availabilityLoading, isError, error } = usePublicAvailability(
serviceId,
dateString,
selectedAddonIds.length > 0 ? selectedAddonIds : undefined
);
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
const firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();