pcm-shared-components 2.1.388 → 2.1.390
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.
|
@@ -85,6 +85,7 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
85
85
|
onRemoveItem,
|
|
86
86
|
canAddMore,
|
|
87
87
|
maxItems,
|
|
88
|
+
showHistoricalAnswers,
|
|
88
89
|
className,
|
|
89
90
|
theme,
|
|
90
91
|
i18next
|
|
@@ -115,6 +116,28 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
115
116
|
setPendingRemoveId(null);
|
|
116
117
|
};
|
|
117
118
|
|
|
119
|
+
// Historical answers have no live field config left (see the Historical answers block below),
|
|
120
|
+
// so there's no field.type to route through a type-specific "clear" -- but classifyAnimalFieldValue
|
|
121
|
+
// treats an empty string as 'unanswered' regardless of what type the value used to be (a retired
|
|
122
|
+
// boolean/array/number all read back through the exact same generic-stringify branch above), so
|
|
123
|
+
// routing every deletion through the one existing onFieldChange callback with value '' is enough
|
|
124
|
+
// to make the entry disappear next render. No new prop needed on top of the ones this component
|
|
125
|
+
// already takes. Holds an array of keys so one dialog/confirm serves both a single delete and
|
|
126
|
+
// "Clear" (all of them at once) -- the array just has one entry for a single delete.
|
|
127
|
+
const [pendingHistoricalDelete, setPendingHistoricalDelete] = useState(null);
|
|
128
|
+
const requestDeleteHistorical = (itemId, deleteKeys) => setPendingHistoricalDelete({
|
|
129
|
+
itemId,
|
|
130
|
+
keys: deleteKeys
|
|
131
|
+
});
|
|
132
|
+
const confirmDeleteHistorical = () => {
|
|
133
|
+
const {
|
|
134
|
+
itemId,
|
|
135
|
+
keys: deleteKeys
|
|
136
|
+
} = pendingHistoricalDelete;
|
|
137
|
+
deleteKeys.forEach(k => onFieldChange(itemId, k, ''));
|
|
138
|
+
setPendingHistoricalDelete(null);
|
|
139
|
+
};
|
|
140
|
+
|
|
118
141
|
// A drifted field (its stored value no longer matches this field's current type/options -- see
|
|
119
142
|
// isFieldDrifted) renders read-only instead of feeding a mismatched value into a live
|
|
120
143
|
// type-specific control (e.g. never shove a raw string into a date picker). "Replace" reveals
|
|
@@ -280,8 +303,12 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
280
303
|
// replaceable. Not drifted (or already revealed): behaves exactly as before.
|
|
281
304
|
const value = showAsDrifted ? rawValue : wasDrifted ? field.type === 'select_multiple' ? [] : '' : rawValue;
|
|
282
305
|
const showError = field.required && !isFieldAnswered(field.type, value);
|
|
283
|
-
|
|
284
|
-
|
|
306
|
+
// No "(Optional)" suffix -- required fields already say so via the asterisk, so
|
|
307
|
+
// spelling out the alternative on every other field was redundant noise, and the
|
|
308
|
+
// extra length was long enough to wrap onto a second line in a narrow column,
|
|
309
|
+
// throwing that field's input out of vertical alignment with its paired neighbor.
|
|
310
|
+
const labelText = field.required ? `${field.label} *` : field.label;
|
|
311
|
+
const wrapperClassName = ['select', 'textarea', 'select_multiple'].includes(field.type) ? 'col-span-full' : undefined;
|
|
285
312
|
let control;
|
|
286
313
|
if (showAsDrifted) {
|
|
287
314
|
// Generic stringify -- this renders whatever type the field used to be, which
|
|
@@ -425,7 +452,8 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
425
452
|
if (val !== null) onFieldChange(selectedItem.id, field.key, val === 'yes');
|
|
426
453
|
},
|
|
427
454
|
fullWidth: true,
|
|
428
|
-
size: "small"
|
|
455
|
+
size: "small",
|
|
456
|
+
color: showError ? 'error' : 'standard'
|
|
429
457
|
}, /*#__PURE__*/React.createElement(ToggleButton, {
|
|
430
458
|
value: "yes"
|
|
431
459
|
}, i18next.t('common.app.yes')), /*#__PURE__*/React.createElement(ToggleButton, {
|
|
@@ -484,7 +512,7 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
484
512
|
color: "error",
|
|
485
513
|
className: "block mt-4"
|
|
486
514
|
}, requiredErrorText(field.type)));
|
|
487
|
-
})))), selectedItem && (() => {
|
|
515
|
+
})))), showHistoricalAnswers && selectedItem && (() => {
|
|
488
516
|
const liveKeys = new Set(fieldConfig.map(f => f.key));
|
|
489
517
|
const historicalEntries = Object.keys(selectedItem.values || {}).filter(k => !liveKeys.has(k)).map(k => ({
|
|
490
518
|
key: k,
|
|
@@ -500,11 +528,15 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
500
528
|
bgcolor: 'action.hover'
|
|
501
529
|
}
|
|
502
530
|
}, /*#__PURE__*/React.createElement("div", {
|
|
503
|
-
className: "flex items-center",
|
|
531
|
+
className: "flex items-center justify-between",
|
|
504
532
|
style: {
|
|
505
|
-
gap: 6,
|
|
506
533
|
marginBottom: 4
|
|
507
534
|
}
|
|
535
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
536
|
+
className: "flex items-center",
|
|
537
|
+
style: {
|
|
538
|
+
gap: 6
|
|
539
|
+
}
|
|
508
540
|
}, /*#__PURE__*/React.createElement(WarningAmberIcon, {
|
|
509
541
|
fontSize: "small",
|
|
510
542
|
color: "warning"
|
|
@@ -512,7 +544,15 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
512
544
|
sx: {
|
|
513
545
|
fontWeight: 700
|
|
514
546
|
}
|
|
515
|
-
}, i18next.t('animal.historical_answers_title'))), /*#__PURE__*/React.createElement(
|
|
547
|
+
}, i18next.t('animal.historical_answers_title'))), /*#__PURE__*/React.createElement(Button, {
|
|
548
|
+
size: "small",
|
|
549
|
+
color: "error",
|
|
550
|
+
onClick: () => requestDeleteHistorical(selectedItem.id, historicalEntries.map(e => e.key)),
|
|
551
|
+
sx: {
|
|
552
|
+
textTransform: 'none',
|
|
553
|
+
minWidth: 0
|
|
554
|
+
}
|
|
555
|
+
}, i18next.t('common.app.clear'))), /*#__PURE__*/React.createElement(Typography, {
|
|
516
556
|
variant: "caption",
|
|
517
557
|
color: "text.secondary",
|
|
518
558
|
sx: {
|
|
@@ -535,7 +575,15 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
535
575
|
const label = k.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
536
576
|
return /*#__PURE__*/React.createElement("div", {
|
|
537
577
|
key: k,
|
|
538
|
-
className: "flex
|
|
578
|
+
className: "flex items-start justify-between",
|
|
579
|
+
style: {
|
|
580
|
+
gap: 4
|
|
581
|
+
}
|
|
582
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
583
|
+
className: "flex flex-col",
|
|
584
|
+
style: {
|
|
585
|
+
minWidth: 0
|
|
586
|
+
}
|
|
539
587
|
}, /*#__PURE__*/React.createElement(Typography, {
|
|
540
588
|
variant: "body2",
|
|
541
589
|
sx: {
|
|
@@ -545,9 +593,21 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
545
593
|
}, label), /*#__PURE__*/React.createElement(Typography, {
|
|
546
594
|
variant: "body2",
|
|
547
595
|
sx: {
|
|
548
|
-
color: 'text.primary'
|
|
596
|
+
color: 'text.primary',
|
|
597
|
+
wordBreak: 'break-word'
|
|
598
|
+
}
|
|
599
|
+
}, displayText)), /*#__PURE__*/React.createElement(IconButton, {
|
|
600
|
+
size: "small",
|
|
601
|
+
color: "error",
|
|
602
|
+
"aria-label": i18next.t('common.app.delete'),
|
|
603
|
+
onClick: () => requestDeleteHistorical(selectedItem.id, [k]),
|
|
604
|
+
sx: {
|
|
605
|
+
flexShrink: 0,
|
|
606
|
+
mt: -0.5
|
|
549
607
|
}
|
|
550
|
-
},
|
|
608
|
+
}, /*#__PURE__*/React.createElement(DeleteOutlineIcon, {
|
|
609
|
+
fontSize: "small"
|
|
610
|
+
})));
|
|
551
611
|
})));
|
|
552
612
|
})(), (() => {
|
|
553
613
|
const incompleteCount = items.filter(item => missingRequiredFields(item).length > 0).length;
|
|
@@ -590,7 +650,18 @@ export const AnimalVehicleDetailsEditor = props => {
|
|
|
590
650
|
color: "error",
|
|
591
651
|
variant: "contained",
|
|
592
652
|
onClick: confirmRemove
|
|
593
|
-
}, i18next.t('common.app.remove'))))
|
|
653
|
+
}, i18next.t('common.app.remove')))), /*#__PURE__*/React.createElement(Dialog, {
|
|
654
|
+
open: pendingHistoricalDelete !== null,
|
|
655
|
+
onClose: () => setPendingHistoricalDelete(null),
|
|
656
|
+
maxWidth: "xs",
|
|
657
|
+
fullWidth: true
|
|
658
|
+
}, /*#__PURE__*/React.createElement(DialogTitle, null, i18next.t('common.app.delete')), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(DialogContentText, null, i18next.t('common.app.generic_delete_message'))), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
|
|
659
|
+
onClick: () => setPendingHistoricalDelete(null)
|
|
660
|
+
}, i18next.t('common.app.cancel')), /*#__PURE__*/React.createElement(Button, {
|
|
661
|
+
color: "error",
|
|
662
|
+
variant: "contained",
|
|
663
|
+
onClick: confirmDeleteHistorical
|
|
664
|
+
}, i18next.t('common.app.delete'))))));
|
|
594
665
|
};
|
|
595
666
|
AnimalVehicleDetailsEditor.defaultProps = {
|
|
596
667
|
items: [],
|
|
@@ -601,6 +672,7 @@ AnimalVehicleDetailsEditor.defaultProps = {
|
|
|
601
672
|
isFieldDrifted: () => false,
|
|
602
673
|
canAddMore: true,
|
|
603
674
|
maxItems: 0,
|
|
675
|
+
showHistoricalAnswers: true,
|
|
604
676
|
className: 'w-full',
|
|
605
677
|
theme: undefined,
|
|
606
678
|
i18next: i18nextLocal
|
|
@@ -642,6 +714,11 @@ AnimalVehicleDetailsEditor.propTypes = {
|
|
|
642
714
|
canAddMore: PropTypes.bool,
|
|
643
715
|
/** Shown in the "max reached" message once canAddMore is false. */
|
|
644
716
|
maxItems: PropTypes.number,
|
|
717
|
+
/** Whether the read-only "Historical Answers" block (retired field keys still holding a value)
|
|
718
|
+
* can render at all. Defaults to true for the admin edit screen, where reviewing/clearing a
|
|
719
|
+
* since-retired answer on an EXISTING reservation is legitimate. A guest-facing booking widget
|
|
720
|
+
* creating a brand-new reservation has no history to show and should pass false. */
|
|
721
|
+
showHistoricalAnswers: PropTypes.bool,
|
|
645
722
|
/** Classes applied to the component's own wrapper div. */
|
|
646
723
|
className: PropTypes.string,
|
|
647
724
|
/** Theme object to use on this component, if none provided then the MUI5 theme provider theme is used. */
|
|
@@ -2475,7 +2475,8 @@
|
|
|
2475
2475
|
"online_booking_title": "Animal details for online booking",
|
|
2476
2476
|
"manage_fields": "Manage fields",
|
|
2477
2477
|
"fields_configured_count_one": "{{count}} field configured",
|
|
2478
|
-
"fields_configured_count_other": "{{count}} fields configured"
|
|
2478
|
+
"fields_configured_count_other": "{{count}} fields configured",
|
|
2479
|
+
"fields_configured_count_plural": "{{count}} fields configured"
|
|
2479
2480
|
},
|
|
2480
2481
|
"edit_lot": "Edit Lot",
|
|
2481
2482
|
"lot_id_exist": "Lot number already exist",
|
|
@@ -2475,7 +2475,8 @@
|
|
|
2475
2475
|
"online_booking_title": "Detalles de los animales para la reserva en línea",
|
|
2476
2476
|
"manage_fields": "Administrar campos",
|
|
2477
2477
|
"fields_configured_count_one": "{{count}} campo configurado",
|
|
2478
|
-
"fields_configured_count_other": "{{count}} campos configurados"
|
|
2478
|
+
"fields_configured_count_other": "{{count}} campos configurados",
|
|
2479
|
+
"fields_configured_count_plural": "{{count}} campos configurados"
|
|
2479
2480
|
},
|
|
2480
2481
|
"edit_lot": "Editar lote",
|
|
2481
2482
|
"lot_id_exist": "El número de lote ya existe",
|
|
@@ -2475,7 +2475,8 @@
|
|
|
2475
2475
|
"online_booking_title": "Détails sur les animaux pour la réservation en ligne",
|
|
2476
2476
|
"manage_fields": "Gérer les champs",
|
|
2477
2477
|
"fields_configured_count_one": "{{count}} champ configuré",
|
|
2478
|
-
"fields_configured_count_other": "{{count}} champs configurés"
|
|
2478
|
+
"fields_configured_count_other": "{{count}} champs configurés",
|
|
2479
|
+
"fields_configured_count_plural": "{{count}} champs configurés"
|
|
2479
2480
|
},
|
|
2480
2481
|
"edit_lot": "Editer le lot",
|
|
2481
2482
|
"lot_id_exist": "Le numéro de lot existe déjà",
|