@arquimedes.co/eureka-forms 3.0.69 → 3.0.70

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.
@@ -124,6 +124,10 @@ function MaterialBookingStep({ step, editable, fetchSlots: customFetchSlots }) {
124
124
  const personSelectionMode = usesEdge
125
125
  ? (offer?.personSelection ?? PersonSelectionMode.NONE)
126
126
  : step.personSelectionMode;
127
- return (_jsx("div", { ref: ref, style: cssVars, children: _jsx(ErkBookingPicker, { value: value, onChange: handleChange, label: step.label, description: step.description, durationMinutes: offer?.durationMinutes ?? step.durationMinutes, bufferMinutes: step.bufferMinutes, bookingMode: step.bookingMode, temporaryLockMinutes: step.temporaryLockMinutes, personSelectionMode: personSelectionMode, persons: usesEdge ? persons : step.persons, collectContact: step.collectContact, fetchSlots: usesEdge ? fetchSlots : customFetchSlots, fetchDays: usesEdge ? fetchDays : undefined, holdSlot: usesEdge ? holdSlot : undefined, disabled: usesEdge && !offer, readOnly: isReadOnly, error: error?.message ?? offerError }) }));
127
+ return (_jsx("div", { ref: ref, style: cssVars, children: _jsx(ErkBookingPicker, { value: value, onChange: handleChange, label: step.label, description: step.description, durationMinutes: offer?.durationMinutes ?? step.durationMinutes, bufferMinutes: step.bufferMinutes, bookingMode: step.bookingMode, temporaryLockMinutes: step.temporaryLockMinutes, personSelectionMode: personSelectionMode, persons: usesEdge ? persons : step.persons,
128
+ // Whoever holds a slot must be named unless the step lets strangers book; asking for the name
129
+ // whenever it is required keeps the hold from being refused for a step that never turned the
130
+ // contact fields on.
131
+ collectContact: !step.allowAnonymous || step.collectContact === true, requireContact: !step.allowAnonymous, fetchSlots: usesEdge ? fetchSlots : customFetchSlots, fetchDays: usesEdge ? fetchDays : undefined, holdSlot: usesEdge ? holdSlot : undefined, disabled: usesEdge && !offer, readOnly: isReadOnly, error: error?.message ?? offerError }) }));
128
132
  }
129
133
  export default MaterialBookingStep;
@@ -12,6 +12,8 @@ export interface ErkBookingPickerProps {
12
12
  persons?: BookablePerson[];
13
13
  /** Recopila nombre/correo del que agenda. */
14
14
  collectContact?: boolean;
15
+ /** El nombre es obligatorio para confirmar: el paso no admite reservas anónimas. */
16
+ requireContact?: boolean;
15
17
  /** Provee los slots disponibles para una persona + día. */
16
18
  fetchSlots?: (args: {
17
19
  personId?: string;
@@ -48,5 +50,5 @@ export interface ErkBookingPickerProps {
48
50
  * En el paso final el panel derecho desaparece y el resumen se expande en una columna
49
51
  * centrada (cross-fade corto). Confirmar cierra el modal y deja el resumen compacto.
50
52
  */
51
- declare function ErkBookingPicker({ value, onChange, label, description, durationMinutes, bufferMinutes, bookingMode, temporaryLockMinutes, personSelectionMode, persons, collectContact, fetchSlots, fetchDays, holdSlot, disabled, readOnly, error, }: ErkBookingPickerProps): JSX.Element;
53
+ declare function ErkBookingPicker({ value, onChange, label, description, durationMinutes, bufferMinutes, bookingMode, temporaryLockMinutes, personSelectionMode, persons, collectContact, requireContact, fetchSlots, fetchDays, holdSlot, disabled, readOnly, error, }: ErkBookingPickerProps): JSX.Element;
52
54
  export default ErkBookingPicker;
@@ -59,7 +59,7 @@ function capitalize(text) {
59
59
  * En el paso final el panel derecho desaparece y el resumen se expande en una columna
60
60
  * centrada (cross-fade corto). Confirmar cierra el modal y deja el resumen compacto.
61
61
  */
62
- function ErkBookingPicker({ value, onChange, label, description, durationMinutes, bufferMinutes, bookingMode, temporaryLockMinutes, personSelectionMode, persons, collectContact = false, fetchSlots, fetchDays, holdSlot, disabled = false, readOnly = false, error, }) {
62
+ function ErkBookingPicker({ value, onChange, label, description, durationMinutes, bufferMinutes, bookingMode, temporaryLockMinutes, personSelectionMode, persons, collectContact = false, requireContact = false, fetchSlots, fetchDays, holdSlot, disabled = false, readOnly = false, error, }) {
63
63
  const needsPerson = !!personSelectionMode && personSelectionMode !== PersonSelectionMode.NONE;
64
64
  const personsOptional = personSelectionMode === PersonSelectionMode.OPTIONAL;
65
65
  const today = startOfDay(new Date());
@@ -160,6 +160,8 @@ function ErkBookingPicker({ value, onChange, label, description, durationMinutes
160
160
  return !!date;
161
161
  case 'hour':
162
162
  return !!slot;
163
+ case 'confirm':
164
+ return !requireContact || contactName.trim().length > 0;
163
165
  default:
164
166
  return true;
165
167
  }
@@ -287,6 +289,6 @@ function ErkBookingPicker({ value, onChange, label, description, durationMinutes
287
289
  ? 'Si todo está bien, completa tus datos y confirma.'
288
290
  : '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
289
291
  ? STEP_HINT[currentKey]
290
- : 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: holding ? 'Reservando…' : 'Confirmar cita', sx: ACCENT_SX, disabled: !slot || holding, onClick: () => void confirm() })) : (_jsx(ErkButton, { text: "Siguiente", disabled: !canAdvance, onClick: () => goToStep(wizStep + 1) }))] })] }) }), error && _jsx("div", { className: styles.err, children: error })] }));
292
+ : 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: holding ? 'Reservando…' : 'Confirmar cita', sx: ACCENT_SX, disabled: !slot || holding || !canAdvance, onClick: () => void confirm() })) : (_jsx(ErkButton, { text: "Siguiente", disabled: !canAdvance, onClick: () => goToStep(wizStep + 1) }))] })] }) }), error && _jsx("div", { className: styles.err, children: error })] }));
291
293
  }
292
294
  export default ErkBookingPicker;
@@ -141,6 +141,20 @@ describe('ErkBookingPicker (wizard)', () => {
141
141
  expect(fetchSlots).toHaveBeenCalledTimes(2);
142
142
  expect(onChange).not.toHaveBeenCalled();
143
143
  });
144
+ it('does not confirm without a name when the step requires one', async () => {
145
+ const user = userEvent.setup();
146
+ const onChange = vi.fn();
147
+ render(_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(ErkBookingPicker, { value: null, onChange: onChange, label: "Agendar cita", durationMinutes: 30, personSelectionMode: PersonSelectionMode.NONE, collectContact: true, requireContact: true, fetchSlots: () => Promise.resolve(SLOTS) }) }));
148
+ await user.click(screen.getByRole('button', { name: 'Agendar cita' }));
149
+ await user.click(clickableToday());
150
+ await user.click(screen.getByRole('button', { name: 'Siguiente' }));
151
+ await user.click(await screen.findByRole('button', { name: '09:00' }));
152
+ await user.click(screen.getByRole('button', { name: 'Siguiente' }));
153
+ const confirm = await screen.findByRole('button', { name: 'Confirmar cita' });
154
+ expect(confirm).toBeDisabled();
155
+ await user.type(screen.getByLabelText('Nombre'), 'Juan');
156
+ expect(confirm).toBeEnabled();
157
+ });
144
158
  it('renders the compact summary when a value exists', () => {
145
159
  render(_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(ErkBookingPicker, { value: {
146
160
  type: 'BOOKING_VALUE',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arquimedes.co/eureka-forms",
3
3
  "repository": "git://github.com/Arquimede5/Eureka-Forms.git",
4
- "version": "3.0.69",
4
+ "version": "3.0.70",
5
5
  "scripts": {
6
6
  "watch": "node node_modules/@typescript/native/bin/tsc --noEmit --watch --project tsconfig.app.json",
7
7
  "start": "vite",