import { methodLabel } from '../booking-ui/credit'; import * as React from 'react'; import { __ } from '@wordpress/i18n'; import { ApiError, CatalogApi } from './api'; import { commonFields, resourceFields, resourceTypes } from './fields'; import type { Config, Item, Payload, Sport } from './types'; interface Props { api: CatalogApi; kind: Extract; item: Item | null; sports: Sport[]; pricesUrl?: string; onSave: (payload: Payload) => Promise; onCancel: () => void; } export function CatalogForm({ api, kind, item, sports, pricesUrl, onSave, onCancel }: Props): React.ReactElement { const membershipEnabled = window.ABeCeBookingConfig?.membershipsEnabled !== false; const fields = (kind === 'sports' ? commonFields : [...commonFields, ...resourceFields, ...([])]).filter(f => membershipEnabled || !['access_mode', 'member_booking_days', 'public_release_hours'].includes(f.key)); const initialOverride = item && 'payment_methods_override' in item ? item.payment_methods_override : null; const [inherit, setInherit] = React.useState(initialOverride === null), [methods, setMethods] = React.useState(initialOverride ?? ['pay_on_site']); const defaults: Payload = { name: '', slug: '', description: null, is_active: true, sort_order: 0, sport_id: null, resource_type: '', surface: null, capacity: null, is_visible: true, is_bookable: true, online_booking_enabled: false, access_mode: 'public', member_booking_days: null, guest_booking_days: null, public_release_hours: null, min_booking_minutes: 30, max_booking_minutes: 120, booking_step_minutes: 30 }; const source = item ? { ...defaults, ...item } : defaults; source.resource_type = resourceTypes.find(([key]) => source.resource_type === key)?.[1] ?? source.resource_type; const [values, setValues] = React.useState>(() => Object.fromEntries(fields.map(field => [field.key, typeof source[field.key] === 'boolean' ? source[field.key] : String(source[field.key] ?? '')])) as Record); const [saving, setSaving] = React.useState(false); const [error, setError] = React.useState(null); const dirtyName = React.useRef(false), dirtyOrder = React.useRef(false); React.useEffect(() => { if (kind !== 'resources' || item) return; let alive = true; api.resourceSuggestions(String(values.sport_id)).then(s => { if (!alive) return; setValues(v => ({ ...v, ...(!dirtyOrder.current ? { sort_order: String(s.sort_order) } : {}), ...(!dirtyName.current ? { name: s.name ?? '' } : {}) })); }).catch(() => { }); return () => { alive = false; }; }, [api, kind, item, values.sport_id]); function change(key: string, value: string | boolean) { if (key === 'name') dirtyName.current = true; if (key === 'sort_order') dirtyOrder.current = true; setValues(v => ({ ...v, [key]: value })); } async function submit(event: React.FormEvent): Promise { event.preventDefault(); setSaving(true); setError(null); const payload: Payload = {}; fields.forEach(field => { const value = values[field.key]; payload[field.key] = field.nullable && value === '' ? null : field.type === 'number' || field.key === 'sport_id' ? Number(value) : value; }); if (kind === 'resources') { for (const key of ['member_booking_days', 'guest_booking_days', 'public_release_hours']) if (item && key in item && source[key] === 0 && payload[key] === 0) delete payload[key]; payload.payment_methods_override = inherit ? null : methods; payload.resource_type = resourceTypes.find(([key, label]) => payload.resource_type === label)?.[0] ?? payload.resource_type; for (const key of ['guest_booking_days', 'public_release_hours']) if ((key === 'guest_booking_days' && membershipEnabled && values.access_mode === 'members_only') || (key === 'public_release_hours' && (!membershipEnabled || values.access_mode !== 'members_priority'))) delete payload[key]; } try { await onSave(payload); } catch (cause) { setError(cause instanceof ApiError ? cause : new ApiError(__('The request failed. Please try again.', 'abece-booking'))); } finally { setSaving(false); } } const title = kind === 'sports' ? item ? __('Edit sport', 'abece-booking') : __('Create sport', 'abece-booking') : item ? __('Edit resource', 'abece-booking') : __('Create resource', 'abece-booking'); const groups = kind === 'sports' ? [{ title: __('Basic information', 'abece-booking'), fields }] : [ { title: __('Basic information', 'abece-booking'), fields: fields.filter(f => ['name', 'slug', 'description', 'sport_id', 'resource_type', 'surface', 'capacity', 'sort_order'].includes(f.key)) }, { title: __('Availability and access', 'abece-booking'), fields: fields.filter(f => ['is_active', 'is_visible', 'is_bookable', 'online_booking_enabled', 'access_mode'].includes(f.key)) }, { title: __('Booking rules', 'abece-booking'), fields: fields.filter(f => ['member_booking_days', 'guest_booking_days', 'public_release_hours', 'min_booking_minutes', 'max_booking_minutes', 'booking_step_minutes'].includes(f.key)) }, ]; return

{title}

{error &&

{error.message}

}
void submit(event)}>
{groups.map(group =>
{group.title}
{group.fields.filter(field => !(field.key === 'guest_booking_days' && membershipEnabled && values.access_mode === 'members_only') && !(field.key === 'public_release_hours' && (!membershipEnabled || values.access_mode !== 'members_priority'))).map(field => { const id = `asb-${field.key}`; const options = field.key === 'sport_id' ? sports.map(sport => [String(sport.id), `${sport.name}${sport.is_active ? '' : ` (${__('Inactive', 'abece-booking')})`}`]) : field.options ?? []; return
{field.type === 'checkbox' ? change(field.key, event.target.checked)}/> : field.type === 'textarea' ?