@arquimedes.co/eureka-forms 3.0.68-test → 3.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README +33 -1
- package/dist/@Types/AvailabilityFormStep.d.ts +48 -0
- package/dist/@Types/AvailabilityFormStep.js +24 -0
- package/dist/@Types/BankAccountFormStep.d.ts +67 -0
- package/dist/@Types/BankAccountFormStep.js +14 -0
- package/dist/@Types/BookingFormStep.d.ts +187 -0
- package/dist/@Types/BookingFormStep.js +44 -0
- package/dist/@Types/CalendarFormStep.d.ts +209 -0
- package/dist/@Types/CalendarFormStep.js +55 -0
- package/dist/@Types/CommunicationChannelFormStep.d.ts +51 -0
- package/dist/@Types/CommunicationChannelFormStep.js +15 -0
- package/dist/@Types/ConsentFormStep.d.ts +36 -0
- package/dist/@Types/ConsentFormStep.js +8 -0
- package/dist/@Types/EntityFormFormStep.d.ts +66 -0
- package/dist/@Types/EntityFormFormStep.js +20 -0
- package/dist/@Types/EventFormStep.d.ts +52 -0
- package/dist/@Types/EventFormStep.js +13 -0
- package/dist/@Types/ExternalReferenceFormStep.d.ts +74 -0
- package/dist/@Types/ExternalReferenceFormStep.js +20 -0
- package/dist/@Types/FormStep.d.ts +7 -2
- package/dist/@Types/FormStep.js +2 -1
- package/dist/@Types/LocationFormStep.d.ts +159 -0
- package/dist/@Types/LocationFormStep.js +46 -0
- package/dist/@Types/NumericFormSteps.d.ts +108 -0
- package/dist/@Types/NumericFormSteps.js +20 -0
- package/dist/@Types/PredefinedSelectorFormStep.d.ts +51 -0
- package/dist/@Types/PredefinedSelectorFormStep.js +39 -0
- package/dist/@Types/StepRef.d.ts +135 -0
- package/dist/@Types/StepRef.js +49 -0
- package/dist/App/App.stories.d.ts +10 -0
- package/dist/App/App.stories.js +189 -0
- package/dist/App/AppHooks.js +8 -0
- package/dist/App/AppHooks.test.js +8 -0
- package/dist/Form/Form.js +7 -6
- package/dist/Form/FormFunctions.d.ts +17 -0
- package/dist/Form/FormFunctions.js +22 -0
- package/dist/Form/FormFunctions.test.js +28 -1
- package/dist/FormSteps/AvailabilityStep/AvailabilityStep.d.ts +7 -0
- package/dist/FormSteps/AvailabilityStep/AvailabilityStep.js +14 -0
- package/dist/FormSteps/AvailabilityStep/MaterialAvailabilityStep/MaterialAvailabilityStep.d.ts +8 -0
- package/dist/FormSteps/AvailabilityStep/MaterialAvailabilityStep/MaterialAvailabilityStep.js +32 -0
- package/dist/FormSteps/BookingStep/BookingStep.d.ts +17 -0
- package/dist/FormSteps/BookingStep/BookingStep.js +14 -0
- package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.d.ts +7 -0
- package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.js +32 -0
- package/dist/FormSteps/CheckBoxStep/CheckBoxStep.mobileLabel.test.js +20 -12
- package/dist/FormSteps/CheckBoxStep/MaterialCheckBoxStep/MaterialCheckBoxStep.js +6 -13
- package/dist/FormSteps/CheckBoxStep/MaterialCheckBoxStep/MaterialCheckBoxStep.module.css +2 -13
- package/dist/FormSteps/ClassifierSelectorStep/ClassifierSelectorStep.lateClassifiers.test.d.ts +1 -0
- package/dist/FormSteps/ClassifierSelectorStep/ClassifierSelectorStep.lateClassifiers.test.js +70 -0
- package/dist/FormSteps/ClassifierSelectorStep/MaterialClassifierSelectorStep/MaterialClassifierSelectorStep.js +3 -1
- package/dist/FormSteps/EntityValueStep/MaterialEntityValuePickerStep/MaterialEntityValuePickerStep.js +26 -26
- package/dist/FormSteps/EntityValueStep/entityValueDependencyValue.d.ts +12 -0
- package/dist/FormSteps/EntityValueStep/entityValueDependencyValue.js +35 -0
- package/dist/FormSteps/EntityValueStep/entityValueDependencyValue.test.d.ts +1 -0
- package/dist/FormSteps/EntityValueStep/entityValueDependencyValue.test.js +31 -0
- package/dist/FormSteps/EntityValueStep/entityValuePickerWatchedSteps.d.ts +27 -0
- package/dist/FormSteps/EntityValueStep/entityValuePickerWatchedSteps.js +64 -0
- package/dist/FormSteps/EntityValueStep/entityValuePickerWatchedSteps.test.d.ts +1 -0
- package/dist/FormSteps/EntityValueStep/entityValuePickerWatchedSteps.test.js +95 -0
- package/dist/FormSteps/LocationStep/LocationStep.d.ts +10 -0
- package/dist/FormSteps/LocationStep/LocationStep.js +14 -0
- package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.d.ts +3 -0
- package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.js +54 -0
- package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.module.css +18 -0
- package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.d.ts +3 -0
- package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.js +170 -0
- package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.module.css +96 -0
- package/dist/FormSteps/NumberStep/NumberStep.d.ts +10 -0
- package/dist/FormSteps/NumberStep/NumberStep.js +14 -0
- package/dist/FormSteps/Step.js +16 -0
- package/dist/FormSteps/StepFunctions.js +14 -0
- package/dist/FormSteps/StepFunctions.test.js +54 -0
- package/dist/FormSteps/StepHooks.d.ts +21 -0
- package/dist/FormSteps/StepHooks.js +55 -8
- package/dist/FormSteps/StepHooks.test.d.ts +1 -0
- package/dist/FormSteps/StepHooks.test.js +92 -0
- package/dist/FormSteps/isStepHiddenByCondition.test.d.ts +1 -0
- package/dist/FormSteps/isStepHiddenByCondition.test.js +42 -0
- package/dist/Icons/AddIcon.d.ts +3 -0
- package/dist/Icons/AddIcon.js +7 -0
- package/dist/Icons/EditIcon.d.ts +3 -0
- package/dist/Icons/EditIcon.js +7 -0
- package/dist/Icons/RemoveIcon.d.ts +3 -0
- package/dist/Icons/RemoveIcon.js +7 -0
- package/dist/Icons/ViewDayIcon.d.ts +3 -0
- package/dist/Icons/ViewDayIcon.js +7 -0
- package/dist/Icons/ViewWeekIcon.d.ts +3 -0
- package/dist/Icons/ViewWeekIcon.js +7 -0
- package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.d.ts +19 -0
- package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.js +80 -0
- package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.module.css +88 -0
- package/dist/Shared/ErkAddressAutocomplete/googlePlaces.d.ts +29 -0
- package/dist/Shared/ErkAddressAutocomplete/googlePlaces.js +139 -0
- package/dist/Shared/ErkAvailabilityPicker/ErkAvailabilityPicker.d.ts +25 -0
- package/dist/Shared/ErkAvailabilityPicker/ErkAvailabilityPicker.js +112 -0
- package/dist/Shared/ErkAvailabilityPicker/ErkAvailabilityPicker.module.css +88 -0
- package/dist/Shared/ErkAvailabilityPicker/ErkAvailabilityPicker.test.d.ts +1 -0
- package/dist/Shared/ErkAvailabilityPicker/ErkAvailabilityPicker.test.js +73 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.d.ts +31 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.js +228 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.module.css +608 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.stories.d.ts +28 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.stories.js +117 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.stories.test.d.ts +1 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.stories.test.js +49 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.test.d.ts +1 -0
- package/dist/Shared/ErkBookingPicker/ErkBookingPicker.test.js +107 -0
- package/dist/Shared/ErkDatePicker/ErkDatePicker.js +1 -3
- package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.d.ts +2 -3
- package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.js +1 -2
- package/dist/Shared/ErkIconButton/ErkIconButton.d.ts +17 -0
- package/dist/Shared/ErkIconButton/ErkIconButton.js +11 -0
- package/dist/Shared/ErkIconButton/ErkIconButton.module.css +41 -0
- package/dist/Shared/ErkLocationField/ErkLocationField.d.ts +24 -0
- package/dist/Shared/ErkLocationField/ErkLocationField.js +128 -0
- package/dist/Shared/ErkLocationField/ErkLocationField.module.css +164 -0
- package/dist/Shared/ErkLocationField/ErkLocationField.test.d.ts +1 -0
- package/dist/Shared/ErkLocationField/ErkLocationField.test.js +82 -0
- package/dist/Shared/ErkLocationField/addressFields.d.ts +12 -0
- package/dist/Shared/ErkLocationField/addressFields.js +34 -0
- package/dist/Shared/ErkLocationField/locationRestrictions.d.ts +6 -0
- package/dist/Shared/ErkLocationField/locationRestrictions.js +51 -0
- package/dist/Shared/ErkLocationInput/ErkLocationInput.d.ts +15 -0
- package/dist/Shared/ErkLocationInput/ErkLocationInput.js +502 -0
- package/dist/Shared/ErkLocationInput/ErkLocationInput.module.css +128 -0
- package/dist/Shared/ErkNumberField/ErkNumberField.d.ts +42 -0
- package/dist/Shared/ErkNumberField/ErkNumberField.js +169 -0
- package/dist/Utils/AxiosWidget.js +9 -1
- package/dist/constants/FormStepTypes.d.ts +5 -1
- package/dist/constants/FormStepTypes.js +4 -0
- package/dist/index.lib.d.ts +4 -2
- package/dist/index.lib.js +3 -1
- package/package.json +2 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { Dialog } from '@mui/material';
|
|
4
|
+
import { addDays, addMonths, format, isBefore, isSameDay, isSameMonth, startOfDay, startOfMonth, startOfWeek, } from 'date-fns';
|
|
5
|
+
import { es } from 'date-fns/locale';
|
|
6
|
+
import { BookingMode, PersonSelectionMode, } from '../../@Types/BookingFormStep';
|
|
7
|
+
import ErkButton from '../ErkButton/ErkButton';
|
|
8
|
+
import ErkTextField from '../ErkTextField/ErkTextField';
|
|
9
|
+
import styles from './ErkBookingPicker.module.css';
|
|
10
|
+
const WEEK_STARTS_ON = 1;
|
|
11
|
+
const DOW = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
|
|
12
|
+
const MODE_LABEL = {
|
|
13
|
+
[BookingMode.IN_PERSON]: 'Presencial',
|
|
14
|
+
[BookingMode.VIRTUAL]: 'Virtual',
|
|
15
|
+
[BookingMode.HYBRID]: 'Híbrida',
|
|
16
|
+
};
|
|
17
|
+
const STEP_LABEL = {
|
|
18
|
+
person: 'Persona',
|
|
19
|
+
day: 'Día',
|
|
20
|
+
hour: 'Hora',
|
|
21
|
+
confirm: 'Confirmar',
|
|
22
|
+
};
|
|
23
|
+
const STEP_HINT = {
|
|
24
|
+
person: 'Elige con quién agendar',
|
|
25
|
+
day: 'Elige un día',
|
|
26
|
+
hour: 'Elige una hora libre',
|
|
27
|
+
confirm: 'Confirma tu cita',
|
|
28
|
+
};
|
|
29
|
+
/** Duración del fade al reestructurarse el layout (entrar/salir del paso final). */
|
|
30
|
+
const XFADE_MS = 160;
|
|
31
|
+
/** El CTA de confirmar usa el acento del form (secondaryContrastColor vía --booking-accent). */
|
|
32
|
+
const ACCENT_SX = {
|
|
33
|
+
backgroundColor: 'var(--booking-accent, #ee6c4d)',
|
|
34
|
+
'&:hover': { backgroundColor: 'var(--booking-accent, #ee6c4d)', filter: 'brightness(0.95)' },
|
|
35
|
+
'&:disabled': { backgroundColor: 'var(--booking-accent, #ee6c4d)', color: '#fff' },
|
|
36
|
+
};
|
|
37
|
+
function fmtDate(date) {
|
|
38
|
+
return format(date, 'yyyy-MM-dd');
|
|
39
|
+
}
|
|
40
|
+
function longDate(date) {
|
|
41
|
+
return format(date, 'EEEE d MMM', { locale: es });
|
|
42
|
+
}
|
|
43
|
+
function initials(name) {
|
|
44
|
+
return name
|
|
45
|
+
.split(' ')
|
|
46
|
+
.map((p) => p[0])
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.slice(0, 2)
|
|
49
|
+
.join('')
|
|
50
|
+
.toUpperCase();
|
|
51
|
+
}
|
|
52
|
+
function capitalize(text) {
|
|
53
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Selector de cita: una tarjeta de entrada ("Agendar cita") abre el wizard en un modal —
|
|
57
|
+
* una decisión por pantalla (persona → día → hora → confirmar), con panel izquierdo de
|
|
58
|
+
* resumen que se va llenando, breadcrumb navegable arriba y barra inferior Atrás / Siguiente.
|
|
59
|
+
* En el paso final el panel derecho desaparece y el resumen se expande en una columna
|
|
60
|
+
* centrada (cross-fade corto). Confirmar cierra el modal y deja el resumen compacto.
|
|
61
|
+
*/
|
|
62
|
+
function ErkBookingPicker({ value, onChange, label, description, durationMinutes, bufferMinutes, bookingMode, temporaryLockMinutes, personSelectionMode, persons, collectContact = false, fetchSlots, readOnly = false, error, }) {
|
|
63
|
+
const needsPerson = !!personSelectionMode && personSelectionMode !== PersonSelectionMode.NONE;
|
|
64
|
+
const personsOptional = personSelectionMode === PersonSelectionMode.OPTIONAL;
|
|
65
|
+
const today = startOfDay(new Date());
|
|
66
|
+
const wizardKeys = useMemo(() => (needsPerson ? ['person', 'day', 'hour', 'confirm'] : ['day', 'hour', 'confirm']), [needsPerson]);
|
|
67
|
+
const finalIdx = wizardKeys.length - 1;
|
|
68
|
+
const [open, setOpen] = useState(false);
|
|
69
|
+
const [wizStep, setWizStep] = useState(0);
|
|
70
|
+
const [xfade, setXfade] = useState(false);
|
|
71
|
+
const [person, setPerson] = useState(undefined);
|
|
72
|
+
const [personTouched, setPersonTouched] = useState(false);
|
|
73
|
+
const [date, setDate] = useState(undefined);
|
|
74
|
+
const [viewMonth, setViewMonth] = useState(() => startOfMonth(today));
|
|
75
|
+
const [slot, setSlot] = useState(undefined);
|
|
76
|
+
const [slots, setSlots] = useState([]);
|
|
77
|
+
const [loading, setLoading] = useState(false);
|
|
78
|
+
const [contactName, setContactName] = useState('');
|
|
79
|
+
const [contactEmail, setContactEmail] = useState('');
|
|
80
|
+
const reduceMotion = useMemo(() => typeof window !== 'undefined' && !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches, []);
|
|
81
|
+
const monthCells = useMemo(() => {
|
|
82
|
+
const first = startOfWeek(startOfMonth(viewMonth), { weekStartsOn: WEEK_STARTS_ON });
|
|
83
|
+
return Array.from({ length: 42 }, (_, i) => addDays(first, i));
|
|
84
|
+
}, [viewMonth]);
|
|
85
|
+
const loadSlots = useCallback(async (day, personId) => {
|
|
86
|
+
if (!fetchSlots)
|
|
87
|
+
return;
|
|
88
|
+
setLoading(true);
|
|
89
|
+
setSlots([]);
|
|
90
|
+
try {
|
|
91
|
+
setSlots(await fetchSlots({ personId, date: fmtDate(day) }));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
setSlots([]);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
setLoading(false);
|
|
98
|
+
}
|
|
99
|
+
}, [fetchSlots]);
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (value || !date)
|
|
102
|
+
return;
|
|
103
|
+
// The picker synchronises with the slots API here, and `loadSlots` raises its own
|
|
104
|
+
// loading flag as it goes out — the very shape the rule asks effects to be used for.
|
|
105
|
+
// oxlint-disable-next-line react/set-state-in-effect
|
|
106
|
+
void loadSlots(date, person?.id);
|
|
107
|
+
}, [value, date, person, loadSlots]);
|
|
108
|
+
// Al entrar/salir del paso final el layout se reestructura; el reacomodo
|
|
109
|
+
// ocurre mientras la tarjeta está invisible (fade corto en dos fases).
|
|
110
|
+
const goToStep = (target) => {
|
|
111
|
+
const crossesFinal = (wizStep === finalIdx) !== (target === finalIdx);
|
|
112
|
+
if (!crossesFinal || reduceMotion) {
|
|
113
|
+
setWizStep(target);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
setXfade(true);
|
|
117
|
+
window.setTimeout(() => {
|
|
118
|
+
setWizStep(target);
|
|
119
|
+
requestAnimationFrame(() => requestAnimationFrame(() => setXfade(false)));
|
|
120
|
+
}, XFADE_MS);
|
|
121
|
+
};
|
|
122
|
+
const currentKey = wizardKeys[wizStep];
|
|
123
|
+
const canAdvance = (() => {
|
|
124
|
+
switch (currentKey) {
|
|
125
|
+
case 'person':
|
|
126
|
+
return personsOptional ? personTouched : !!person;
|
|
127
|
+
case 'day':
|
|
128
|
+
return !!date;
|
|
129
|
+
case 'hour':
|
|
130
|
+
return !!slot;
|
|
131
|
+
default:
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
})();
|
|
135
|
+
const confirm = () => {
|
|
136
|
+
if (!slot || !date)
|
|
137
|
+
return;
|
|
138
|
+
setOpen(false);
|
|
139
|
+
onChange({
|
|
140
|
+
type: 'BOOKING_VALUE',
|
|
141
|
+
slotId: slot.id,
|
|
142
|
+
date: fmtDate(date),
|
|
143
|
+
startTime: slot.startTime,
|
|
144
|
+
endTime: slot.endTime,
|
|
145
|
+
personId: person?.id,
|
|
146
|
+
personName: person?.name,
|
|
147
|
+
contactName: contactName || undefined,
|
|
148
|
+
contactEmail: contactEmail || undefined,
|
|
149
|
+
status: 'PENDING',
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
const reset = () => {
|
|
153
|
+
onChange(null);
|
|
154
|
+
setWizStep(0);
|
|
155
|
+
setPerson(undefined);
|
|
156
|
+
setPersonTouched(false);
|
|
157
|
+
setDate(undefined);
|
|
158
|
+
setSlot(undefined);
|
|
159
|
+
setContactName('');
|
|
160
|
+
setContactEmail('');
|
|
161
|
+
};
|
|
162
|
+
const pickPerson = (p) => {
|
|
163
|
+
setPerson(p);
|
|
164
|
+
setPersonTouched(true);
|
|
165
|
+
setSlot(undefined);
|
|
166
|
+
};
|
|
167
|
+
// Read-only / already booked → compact summary with the same card aesthetic
|
|
168
|
+
if (readOnly || value) {
|
|
169
|
+
return (_jsx("div", { className: styles.container, children: _jsxs("div", { className: styles.entry, children: [_jsx("div", { className: styles.bookedIcon, children: "\u2713" }), _jsxs("div", { className: styles.entryInfo, children: [_jsx("span", { className: styles.entryLabel, children: label }), _jsx("span", { className: styles.bookedMain, children: value
|
|
170
|
+
? [
|
|
171
|
+
value.personName,
|
|
172
|
+
capitalize(longDate(new Date(value.date + 'T00:00:00'))),
|
|
173
|
+
`${value.startTime}–${value.endTime}`,
|
|
174
|
+
]
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.join(' · ')
|
|
177
|
+
: 'Sin cita' })] }), value && !readOnly && _jsx(ErkButton, { text: "Cambiar", variant: "outlined", onClick: reset })] }) }));
|
|
178
|
+
}
|
|
179
|
+
const isFinal = wizStep === finalIdx;
|
|
180
|
+
const personLabel = person?.name ?? (personTouched && personsOptional ? 'Cualquiera' : undefined);
|
|
181
|
+
const dayText = date ? capitalize(longDate(date)) : undefined;
|
|
182
|
+
const hourText = slot ? `${slot.startTime} – ${slot.endTime}` : undefined;
|
|
183
|
+
const summaryRows = [
|
|
184
|
+
...(needsPerson ? [{ key: 'person', placeholder: 'Persona', text: personLabel }] : []),
|
|
185
|
+
{ key: 'day', placeholder: 'Día', text: dayText },
|
|
186
|
+
{ key: 'hour', placeholder: 'Hora', text: hourText },
|
|
187
|
+
];
|
|
188
|
+
const navParts = [];
|
|
189
|
+
if (personLabel)
|
|
190
|
+
navParts.push(_jsx("b", { children: personLabel }, "p"));
|
|
191
|
+
if (dayText)
|
|
192
|
+
navParts.push(_jsx("span", { children: dayText }, "d"));
|
|
193
|
+
if (hourText)
|
|
194
|
+
navParts.push(_jsx("span", { className: styles.navHl, children: hourText }, "h"));
|
|
195
|
+
return (_jsxs("div", { className: styles.container, children: [_jsxs("div", { className: styles.entry, children: [_jsx("div", { className: styles.avatar, children: "\uD83D\uDCC5" }), _jsxs("div", { className: styles.entryInfo, children: [_jsx("span", { className: styles.entryLabel, children: label }), _jsx("span", { className: styles.entrySub, children: description ?? 'Agenda tu cita' })] }), _jsx(ErkButton, { text: "Agendar cita", onClick: () => setOpen(true) })] }), _jsx(Dialog, { open: open, onClose: () => setOpen(false), maxWidth: "md", fullWidth: true, slotProps: { paper: { style: { borderRadius: 16, background: 'transparent', boxShadow: 'none' } } }, children: _jsxs("div", { className: `${styles.card}${isFinal ? ` ${styles.cardFinal}` : ''}${xfade ? ` ${styles.xfade}` : ''}`, children: [_jsxs("div", { className: isFinal ? `${styles.book} ${styles.bookFinal}` : styles.book, children: [_jsxs("aside", { className: styles.who, children: [_jsxs("div", { className: styles.brand, children: [_jsx("div", { className: styles.avatar, children: person ? initials(person.name) : '📅' }), _jsxs("div", { children: [_jsx("h2", { className: styles.brandName, children: person?.name ?? label }), _jsx("p", { className: styles.brandRole, children: person?.role ?? description ?? 'Agenda tu cita' })] })] }), _jsxs("div", { className: styles.meta, children: [_jsxs("div", { className: styles.row, children: [_jsx("span", { className: styles.ic, children: "\u25F7" }), durationMinutes, " min", bufferMinutes ? ` · buffer ${bufferMinutes} min` : ''] }), bookingMode && (_jsxs("div", { className: styles.row, children: [_jsx("span", { className: styles.ic, children: "\u25F1" }), _jsx("span", { className: styles.pill, children: MODE_LABEL[bookingMode] })] }))] }), _jsx("div", { className: styles.sum, "aria-live": "polite", children: summaryRows.map((r) => (_jsxs("div", { className: r.text ? `${styles.srow} ${styles.srowOn}` : styles.srow, children: [_jsx("span", { className: styles.dot, children: "\u2713" }), _jsx("span", { children: r.text ?? r.placeholder })] }, r.key))) }), isFinal && collectContact && (_jsxs("div", { className: styles.cfields, children: [_jsx(ErkTextField, { label: "Nombre", value: contactName, onChange: setContactName }), _jsx(ErkTextField, { label: "Correo", value: contactEmail, onChange: setContactEmail })] })), !!temporaryLockMinutes && (_jsxs("div", { className: styles.lock, children: ["\u23F3 Reservaremos el horario ", _jsxs("b", { children: [temporaryLockMinutes, " min"] }), " mientras confirmas."] }))] }), _jsxs("div", { className: styles.right, children: [_jsx("nav", { className: styles.stepper, "aria-label": "Progreso", children: wizardKeys.map((key, i) => (_jsxs("span", { className: styles.stepGroup, children: [_jsxs("button", { type: "button", disabled: i >= wizStep, onClick: () => goToStep(i), className: i < wizStep
|
|
196
|
+
? `${styles.stepItem} ${styles.stepDone}`
|
|
197
|
+
: i === wizStep
|
|
198
|
+
? `${styles.stepItem} ${styles.stepOn}`
|
|
199
|
+
: styles.stepItem, children: [_jsx("span", { className: styles.stepNum, children: i < wizStep ? '✓' : i + 1 }), STEP_LABEL[key]] }), i < wizardKeys.length - 1 && _jsx("span", { className: styles.stepSep })] }, key))) }), currentKey === 'person' && (_jsxs("section", { className: styles.pane, children: [_jsx("h3", { className: styles.q, children: "\u00BFCon qui\u00E9n quieres agendar?" }), _jsx("p", { className: styles.qsub, children: personsOptional
|
|
200
|
+
? 'Elige una persona o deja que el sistema asigne a quien esté disponible.'
|
|
201
|
+
: 'Elige la persona con la que quieres tu cita.' }), _jsxs("div", { className: styles.persons, children: [(persons ?? []).map((p) => (_jsxs("button", { type: "button", className: person?.id === p.id
|
|
202
|
+
? `${styles.pcard} ${styles.pcardOn}`
|
|
203
|
+
: styles.pcard, onClick: () => pickPerson(p), children: [_jsx("span", { className: styles.pav, children: initials(p.name) }), _jsxs("span", { className: styles.pinfo, children: [_jsx("span", { className: styles.pn, children: p.name }), p.role && _jsx("span", { className: styles.pr, children: p.role })] }), _jsx("span", { className: styles.chk, children: "\u2713" })] }, p.id))), personsOptional && (_jsxs("button", { type: "button", className: personTouched && !person
|
|
204
|
+
? `${styles.pcard} ${styles.pcardAny} ${styles.pcardOn}`
|
|
205
|
+
: `${styles.pcard} ${styles.pcardAny}`, onClick: () => pickPerson(undefined), children: [_jsx("span", { className: styles.pav, children: "\u2726" }), _jsxs("span", { className: styles.pinfo, children: [_jsx("span", { className: styles.pn, children: "Cualquiera" }), _jsx("span", { className: styles.pr, children: "El sistema asigna" })] }), _jsx("span", { className: styles.chk, children: "\u2713" })] }))] })] }, "person")), currentKey === 'day' && (_jsxs("section", { className: styles.pane, children: [_jsx("h3", { className: styles.q, children: "Elige un d\u00EDa" }), _jsx("p", { className: styles.qsub, children: "Solo se muestran fechas a partir de hoy." }), _jsxs("div", { className: styles.monthWrap, children: [_jsxs("div", { className: styles.monthHead, children: [_jsx("span", { className: styles.monthTitle, children: capitalize(format(viewMonth, 'MMMM yyyy', { locale: es })) }), _jsxs("span", { className: styles.monthNav, children: [_jsx("button", { type: "button", "aria-label": "Mes anterior", onClick: () => setViewMonth((m) => addMonths(m, -1)), children: "\u2039" }), _jsx("button", { type: "button", "aria-label": "Mes siguiente", onClick: () => setViewMonth((m) => addMonths(m, 1)), children: "\u203A" })] })] }), _jsxs("div", { className: styles.mgrid, children: [DOW.map((d, i) => (_jsx("span", { className: styles.mdow, children: d }, i))), monthCells.map((d) => {
|
|
206
|
+
const outside = !isSameMonth(d, viewMonth);
|
|
207
|
+
const past = isBefore(d, today);
|
|
208
|
+
const selectable = !outside && !past;
|
|
209
|
+
const cls = date && isSameDay(d, date)
|
|
210
|
+
? `${styles.mday} ${styles.mdaySel}`
|
|
211
|
+
: selectable
|
|
212
|
+
? `${styles.mday} ${styles.mdayFree}`
|
|
213
|
+
: `${styles.mday} ${styles.mdayNone}`;
|
|
214
|
+
return (_jsx("button", { type: "button", disabled: !selectable, className: cls, onClick: () => {
|
|
215
|
+
setDate(d);
|
|
216
|
+
setSlot(undefined);
|
|
217
|
+
}, children: format(d, 'd') }, d.toISOString()));
|
|
218
|
+
})] })] })] }, "day")), currentKey === 'hour' && (_jsxs("section", { className: styles.pane, children: [_jsx("h3", { className: styles.q, children: "Elige una hora" }), _jsxs("p", { className: styles.qsub, children: [dayText, " \u00B7 citas de ", durationMinutes, " min"] }), loading ? (_jsx("div", { className: styles.empty, children: "Buscando horarios\u2026" })) : slots.length === 0 ? (_jsx("div", { className: styles.empty, children: "No hay horarios disponibles ese d\u00EDa." })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.slots, children: slots.map((s) => (_jsx("button", { type: "button", disabled: !s.available, className: slot?.id === s.id
|
|
219
|
+
? `${styles.slot} ${styles.slotSel}`
|
|
220
|
+
: s.available
|
|
221
|
+
? styles.slot
|
|
222
|
+
: `${styles.slot} ${styles.slotTaken}`, onClick: () => s.available && setSlot(s), children: s.startTime }, s.id))) }), _jsx("p", { className: styles.takenNote, children: "Tachados = ocupados por otro evento o cita." })] }))] }, "hour")), currentKey === 'confirm' && (_jsxs("section", { className: `${styles.pane} ${styles.paneFinal}`, children: [_jsx("h3", { className: styles.q, children: "Revisa y confirma tu cita" }), _jsx("p", { className: styles.qsub, children: collectContact
|
|
223
|
+
? 'Si todo está bien, completa tus datos y confirma.'
|
|
224
|
+
: 'Si todo está bien, confirma tu cita.' })] }, "confirm"))] })] }), _jsxs("div", { className: styles.navbar, children: [_jsx("div", { className: styles.navSummary, children: isFinal || !canAdvance || navParts.length === 0
|
|
225
|
+
? STEP_HINT[currentKey]
|
|
226
|
+
: navParts.reduce((acc, part, i) => i === 0 ? [part] : [...acc, _jsx("span", { children: " \u00B7 " }, `s${i}`), part], []) }), wizStep > 0 && (_jsx(ErkButton, { text: "Atr\u00E1s", variant: "outlined", onClick: () => goToStep(wizStep - 1) })), isFinal ? (_jsx(ErkButton, { text: "Confirmar cita", sx: ACCENT_SX, disabled: !slot, onClick: confirm })) : (_jsx(ErkButton, { text: "Siguiente", disabled: !canAdvance, onClick: () => goToStep(wizStep + 1) }))] })] }) }), error && _jsx("div", { className: styles.err, children: error })] }));
|
|
227
|
+
}
|
|
228
|
+
export default ErkBookingPicker;
|