From 207993075ee4239b95e1fc3c865ead5451ccc097 Mon Sep 17 00:00:00 2001 From: Maryam Mehdizadeh Date: Fri, 3 Oct 2025 14:40:19 +0800 Subject: [PATCH] fix: resolve quantity stories bug #1616 - Fix comparator selection being lost when selected before entering value - Fix unit selection being lost when selected before entering value - Always update QR item for comparator and unit changes, even with empty values - Handle empty parsedNewInput in createQuantityItemAnswer to prevent NaN - Add debug logging to track QR updates - Add test stories QuantityBasicComparator and QuantityMultiUnit Resolves: #1616 --- .../QuantityItem/QuantityItem.tsx | 96 ++++++++++++++----- .../stories/itemTypes/Quantity.stories.tsx | 28 ++++++ .../src/utils/quantity.ts | 36 ++++--- 3 files changed, 116 insertions(+), 44 deletions(-) diff --git a/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityItem.tsx b/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityItem.tsx index a4980d38b..6b01faaaa 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityItem.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityItem.tsx @@ -185,6 +185,13 @@ function QuantityItem(props: BaseItemProps) { // Event handlers function handleComparatorInputChange(newComparatorInput: Quantity['comparator'] | null) { + console.log('🔍 Comparator changed:', { + newComparatorInput, + valueInput, + hasValue: !!valueInput, + willUpdateQR: true + }); + setComparatorInput(newComparatorInput); // Only suppress feedback once (before first blur) @@ -192,21 +199,45 @@ function QuantityItem(props: BaseItemProps) { setShowFeedback(false); } - if (!valueInput) return; - - onQrItemChange({ - ...createEmptyQrItem(qItem, answerKey), - answer: createQuantityItemAnswer( - precision, - valueInput, - newComparatorInput, - unitInput, - answerKey - ) - }); + // Always update QR item, even if valueInput is empty + if (valueInput) { + const qrUpdate = { + ...createEmptyQrItem(qItem, answerKey), + answer: createQuantityItemAnswer( + precision, + valueInput, + newComparatorInput, + unitInput, + answerKey + ) + }; + console.log('✅ Updating QR with comparator (with value):', qrUpdate); + onQrItemChange(qrUpdate); + } else { + // If no value input, still update with empty quantity to preserve comparator + const qrUpdate = { + ...createEmptyQrItem(qItem, answerKey), + answer: createQuantityItemAnswer( + precision, + '', + newComparatorInput, + unitInput, + answerKey + ) + }; + console.log('✅ Updating QR with comparator (no value):', qrUpdate); + onQrItemChange(qrUpdate); + } } function handleUnitInputChange(newUnitInput: QuestionnaireItemAnswerOption | null) { + console.log('🔍 Unit changed:', { + newUnitInput: newUnitInput?.valueCoding?.display, + valueInput, + hasValue: !!valueInput, + willUpdateQR: true + }); + setUnitInput(newUnitInput); // Only suppress feedback once (before first blur) @@ -214,18 +245,35 @@ function QuantityItem(props: BaseItemProps) { setShowFeedback(false); } - if (!valueInput) return; - - onQrItemChange({ - ...createEmptyQrItem(qItem, answerKey), - answer: createQuantityItemAnswer( - precision, - valueInput, - comparatorInput, - newUnitInput, - answerKey - ) - }); + // Always update QR item, even if valueInput is empty + if (valueInput) { + const qrUpdate = { + ...createEmptyQrItem(qItem, answerKey), + answer: createQuantityItemAnswer( + precision, + valueInput, + comparatorInput, + newUnitInput, + answerKey + ) + }; + console.log('✅ Updating QR with unit (with value):', qrUpdate); + onQrItemChange(qrUpdate); + } else { + // If no value input, still update with empty quantity to preserve unit + const qrUpdate = { + ...createEmptyQrItem(qItem, answerKey), + answer: createQuantityItemAnswer( + precision, + '', + comparatorInput, + newUnitInput, + answerKey + ) + }; + console.log('✅ Updating QR with unit (no value):', qrUpdate); + onQrItemChange(qrUpdate); + } } function handleValueInputChange(newInput: string) { diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx index 4fa34e4f5..ede709878 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx @@ -69,3 +69,31 @@ export const QuantityCalculation: Story = { questionnaire: qQuantityCalculation } }; + +export const QuantityBasicComparator: Story = { + name: 'Quantity Basic Comparator', + args: { + questionnaire: qQuantityBasic + }, + parameters: { + docs: { + description: { + story: 'Test case for quantity with comparator. After filling the input, the comparator should be "<" but store returns undefined.' + } + } + } +}; + +export const QuantityMultiUnit: Story = { + name: 'Quantity Multi Unit', + args: { + questionnaire: qQuantityUnitOption + }, + parameters: { + docs: { + description: { + story: 'Test case for quantity with multiple units. After filling the input, the unit should be "Week(s)" but store returns "Day(s)".' + } + } + } +}; diff --git a/packages/smart-forms-renderer/src/utils/quantity.ts b/packages/smart-forms-renderer/src/utils/quantity.ts index 60d111103..bc8edb4d6 100644 --- a/packages/smart-forms-renderer/src/utils/quantity.ts +++ b/packages/smart-forms-renderer/src/utils/quantity.ts @@ -35,31 +35,27 @@ export function createQuantityItemAnswer( unitInput: QuestionnaireItemAnswerOption | null, answerKey: string | undefined ): QuestionnaireResponseItemAnswer[] { - if (precision) { - return [ - { - id: answerKey, - valueQuantity: { - value: parseDecimalStringToFloat(parsedNewInput, precision), - comparator: comparatorInput ?? undefined, - unit: unitInput?.valueCoding?.display, - system: unitInput?.valueCoding?.system, - code: unitInput?.valueCoding?.code - } - } - ]; + // Handle empty input - only include value if there's actual input + const valueQuantity: Quantity = { + comparator: comparatorInput ?? undefined, + unit: unitInput?.valueCoding?.display, + system: unitInput?.valueCoding?.system, + code: unitInput?.valueCoding?.code + }; + + // Only add value if there's actual input + if (parsedNewInput && parsedNewInput.trim() !== '') { + if (precision) { + valueQuantity.value = parseDecimalStringToFloat(parsedNewInput, precision); + } else { + valueQuantity.value = parseFloat(parsedNewInput); + } } return [ { id: answerKey, - valueQuantity: { - value: parseFloat(parsedNewInput), - comparator: comparatorInput ?? undefined, - unit: unitInput?.valueCoding?.display, - system: unitInput?.valueCoding?.system, - code: unitInput?.valueCoding?.code - } + valueQuantity } ]; }