import { toLocalInput, localInputToISO } from '../booking-ui/dateTime'; import * as React from 'react'; import { __ } from '@wordpress/i18n'; import { formatDateTime } from '../booking-ui/dateTime'; import { ApiError } from './api'; import { scheduleFields, scheduleLabels } from './scheduleFields'; import type { Payload, Resource, ScheduleItem, SchedulePage } from './types'; export function ScheduleForm({ kind, item, resources, onSave, onCancel }: { kind: SchedulePage; item: ScheduleItem | null; resources: Resource[]; onSave: (payload: Payload) => Promise; onCancel: () => void; }): React.ReactElement { const grouped = kind !== 'opening-hours'; const fields = scheduleFields(kind).filter(f => !grouped || f.key !== 'resource_id'); const [target, setTarget] = React.useState(String(item?.target ?? (item?.resource_id === null ? 'all' : 'selected'))), [ids, setIds] = React.useState((item?.resource_ids as number[] | undefined) ?? (item?.resource_id ? [item.resource_id] : [])); const [confirmed, setConfirmed] = React.useState(false), [conflicts, setConflicts] = React.useState<{ id: number; reference: string; customer: string; resource_name: string; starts_at: string; ends_at: string; }[]>([]); const source: Payload = { resource_id: null, day_of_week: 1, opening_mode: 'fixed', opens_at: '07:00', closes_at: '21:00', sunrise_offset_minutes: 30, sunset_offset_minutes: -30, min_open_time: null, max_close_time: null, is_closed: false, exception_date: '', starts_at: '', ends_at: '', block_type: 'other', reason: null, note: null, ...item }; const [values, setValues] = React.useState>(() => Object.fromEntries(fields.map(field => { const value = source[field.key]; return [field.key, typeof value === 'boolean' ? value : field.type === 'time' ? String(value ?? '').slice(0, 5) : field.type === 'datetime-local' ? toLocalInput(String(value ?? '')) : String(value ?? '')]; }))); const [saving, setSaving] = React.useState(false); const [error, setError] = React.useState(null); const fixedTimes = ['opens_at', 'closes_at']; const sunFields = ['sunrise_offset_minutes', 'sunset_offset_minutes', 'min_open_time', 'max_close_time']; function hidden(key: string): boolean { return (fixedTimes.includes(key) && (values.is_closed === true || (kind === 'opening-hours' && values.opening_mode === 'sun'))) || (sunFields.includes(key) && (values.is_closed === true || values.opening_mode !== 'sun')); } async function submit(event: React.FormEvent): Promise { event.preventDefault(); setSaving(true); setError(null); const payload: Payload = grouped ? { target, resource_ids: ids, confirm_existing_bookings: confirmed } : {}; try { fields.forEach(field => { const value = values[field.key]; payload[field.key] = hidden(field.key) || (field.nullable && value === '') ? null : field.type === 'number' || ['resource_id', 'day_of_week'].includes(field.key) ? Number(value) : field.type === 'datetime-local' && value ? localInputToISO(String(value), String(source[field.key] ?? '')) : value; }); await onSave(payload); } catch (cause) { if (cause instanceof ApiError && cause.conflicts) { setConflicts(cause.conflicts); setConfirmed(false); } setError(cause instanceof ApiError ? cause : new ApiError(cause instanceof Error ? cause.message : __('The request failed. Please try again.', 'abece-booking'))); } finally { setSaving(false); } } return

{item ? scheduleLabels[kind].edit : scheduleLabels[kind].create}

{error &&

{error.message}

}
{ if ((e.target as unknown as HTMLInputElement).name !== 'confirm-existing') { setConfirmed(false); setConflicts([]); } }} onSubmit={event => void submit(event)}>
{grouped && ()}
{fields.filter(field => !hidden(field.key)).map(field => { const id = `asb-schedule-${field.key}`; const options = field.key === 'resource_id' ? resources.map(resource => [String(resource.id), resource.name]) : field.options ?? []; const required = field.required || (fixedTimes.includes(field.key) && values.is_closed !== true); return
{field.type === 'checkbox' ? setValues({ ...values, [field.key]: event.target.checked })}/> : field.type === 'select' ? : field.type === 'textarea' ?