diff --git a/apps/admin/app/dashboard/subscribe/app/form.tsx b/apps/admin/app/dashboard/subscribe/app/form.tsx index 83d768c..b8ece81 100644 --- a/apps/admin/app/dashboard/subscribe/app/form.tsx +++ b/apps/admin/app/dashboard/subscribe/app/form.tsx @@ -232,16 +232,6 @@ export default function SubscribeAppForm< name: 'is_default', type: 'boolean', placeholder: t('defaultVersion'), - calculateValue: (value) => { - const newField = field.value?.map((item) => { - if (item.is_default) { - item.is_default = false; - } - return item; - }); - form.setValue(field.name, newField); - return value; - }, }, { name: 'url', @@ -250,12 +240,26 @@ export default function SubscribeAppForm< className: 'col-span-3', }, ]} - value={field.value} onChange={(value) => { - form.setValue( - field.name, - value.filter((item) => item.url), + const filteredValue = value.filter((item) => item.url); + + const defaultIndex = filteredValue.findIndex( + (item) => item.is_default, ); + let finalValue = filteredValue; + if (defaultIndex >= 0) { + finalValue = filteredValue.map((item, index) => ({ + ...item, + is_default: index === defaultIndex, + })); + } else if (filteredValue.length > 0) { + finalValue = filteredValue.map((item, index) => ({ + ...item, + is_default: index === 0, + })); + } + + form.setValue(field.name, finalValue as any); }} /> diff --git a/apps/admin/app/dashboard/subscribe/subscribe-form.tsx b/apps/admin/app/dashboard/subscribe/subscribe-form.tsx index e83c7f5..fa85ea8 100644 --- a/apps/admin/app/dashboard/subscribe/subscribe-form.tsx +++ b/apps/admin/app/dashboard/subscribe/subscribe-form.tsx @@ -157,6 +157,32 @@ export default function SubscribeForm>({ }); const unit_time = form.watch('unit_time'); + const unit_price = form.watch('unit_price'); + const discounts = form.watch('discount'); + + useEffect(() => { + if (!discounts?.length || !unit_price) return; + + const calculatedValues = discounts.map((item: any) => { + const result = { ...item }; + + if (item.quantity && item.discount) { + result.price = evaluateWithPrecision( + `${unit_price || 0} * ${item.quantity} * ${item.discount} / 100`, + ); + } else if (item.quantity && item.price && !item.discount) { + result.discount = evaluateWithPrecision( + `${item.price} / ${item.quantity} / ${unit_price} * 100`, + ); + } + + return result; + }); + + if (JSON.stringify(calculatedValues) !== JSON.stringify(discounts)) { + form.setValue('discount', calculatedValues); + } + }, [unit_price, discounts, form]); return ( @@ -543,7 +569,7 @@ export default function SubscribeForm>({ {t('form.discount')} - + fields={[ { name: 'quantity', @@ -559,15 +585,6 @@ export default function SubscribeForm>({ max: 100, placeholder: t('form.discountPercent'), suffix: '%', - calculateValue: function (data) { - const { unit_price } = form.getValues(); - return { - ...data, - price: evaluateWithPrecision( - `${unit_price || 0} * ${data.quantity || 0} * ${data.discount || 0} / 100`, - ), - }; - }, }, { name: 'price', @@ -575,21 +592,49 @@ export default function SubscribeForm>({ type: 'number', formatInput: (value) => unitConversion('centsToDollars', value), formatOutput: (value) => unitConversion('dollarsToCents', value), - internal: true, - calculateValue: (data) => { - const { unit_price } = form.getValues(); - return { - ...data, - discount: evaluateWithPrecision( - `${data.price || 0} / ${data.quantity || 0} / ${unit_price || 0} * 100`, - ), - }; - }, }, ]} value={field.value} - onChange={(value) => { - form.setValue(field.name, value); + onChange={(newValues) => { + const oldValues = field.value || []; + const { unit_price } = form.getValues(); + + const calculatedValues = newValues.map((newItem, index) => { + const oldItem = oldValues[index] || {}; + + const result = { ...newItem }; + + const quantityChanged = newItem.quantity !== oldItem.quantity; + const discountChanged = newItem.discount !== oldItem.discount; + const priceChanged = newItem.price !== oldItem.price; + + if ( + (quantityChanged || discountChanged) && + !priceChanged && + newItem.quantity && + newItem.discount + ) { + result.price = evaluateWithPrecision( + `${unit_price || 0} * ${newItem.quantity} * ${newItem.discount} / 100`, + ); + } + + if ( + priceChanged && + !discountChanged && + newItem.price && + newItem.quantity && + unit_price + ) { + result.discount = evaluateWithPrecision( + `${newItem.price} / ${newItem.quantity} / ${unit_price} * 100`, + ); + } + + return result; + }); + + form.setValue(field.name, calculatedValues); }} /> diff --git a/packages/ui/src/custom-components/dynamic-Inputs.tsx b/packages/ui/src/custom-components/dynamic-Inputs.tsx index 7ba7d37..0e6f99a 100644 --- a/packages/ui/src/custom-components/dynamic-Inputs.tsx +++ b/packages/ui/src/custom-components/dynamic-Inputs.tsx @@ -11,9 +11,6 @@ interface FieldConfig extends Omit { name: string; type: 'text' | 'number' | 'select' | 'time' | 'boolean'; options?: { label: string; value: string }[]; - internal?: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - calculateValue?: (value: Record) => any; } interface ObjectInputProps { @@ -33,36 +30,13 @@ export function ObjectInput>({ const [internalState, setInternalState] = useState(value); useEffect(() => { - let updatedState = { ...internalState, ...value }; - - fields.forEach((field) => { - if (field?.calculateValue) { - updatedState = field.calculateValue(updatedState); - } - }); - - setInternalState(updatedState); - }, [value, fields]); + setInternalState(value); + }, [value]); const updateField = (key: keyof T, fieldValue: string | number | boolean) => { - let updatedInternalState = { ...internalState, [key]: fieldValue }; - fields.forEach((field) => { - if (field.calculateValue && field.name === key) { - const newValue = field.calculateValue(updatedInternalState); - updatedInternalState = newValue; - } - }); + const updatedInternalState = { ...internalState, [key]: fieldValue }; setInternalState(updatedInternalState); - - const filteredValue = Object.keys(updatedInternalState).reduce((acc, fieldKey) => { - const field = fields.find((f) => f.name === fieldKey); - if (field && !field.internal) { - acc[fieldKey as keyof T] = updatedInternalState[fieldKey as keyof T]; - } - return acc; - }, {} as T); - - onChange(filteredValue); + onChange(updatedInternalState); }; const renderField = (field: FieldConfig) => { switch (field.type) {