Procházet zdrojové kódy

fix(dashboard): Decimal values in tax rate input (#4052)

gabriellbui před 1 měsícem
rodič
revize
01a17ccb1a

+ 2 - 9
packages/dashboard/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx

@@ -1,4 +1,4 @@
-import { AffixedInput } from '@/vdb/components/data-input/affixed-input.js';
+import { NumberInput } from '@/vdb/components/data-input/number-input.js';
 import { ErrorPage } from '@/vdb/components/shared/error-page.js';
 import { ErrorPage } from '@/vdb/components/shared/error-page.js';
 import { FormFieldWrapper } from '@/vdb/components/shared/form-field-wrapper.js';
 import { FormFieldWrapper } from '@/vdb/components/shared/form-field-wrapper.js';
 import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
 import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
@@ -121,14 +121,7 @@ function TaxRateDetailPage() {
                             name="value"
                             name="value"
                             label={<Trans>Rate</Trans>}
                             label={<Trans>Rate</Trans>}
                             render={({ field }) => (
                             render={({ field }) => (
-                                <AffixedInput
-                                    {...field}
-                                    type="number"
-                                    suffix="%"
-                                    min={0}
-                                    value={field.value}
-                                    onChange={e => field.onChange(e.target.valueAsNumber)}
-                                />
+                                <NumberInput {...field} value={field.value} min={0} step={0.01} suffix="%" />
                             )}
                             )}
                         />
                         />
                         <FormFieldWrapper
                         <FormFieldWrapper

+ 24 - 5
packages/dashboard/src/lib/components/data-input/number-input.tsx

@@ -3,11 +3,14 @@ import { Input } from '@/vdb/components/ui/input.js';
 
 
 import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
 import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
 import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
 import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
+import { ReactNode } from 'react';
 
 
 export type NumberInputProps = DashboardFormComponentProps & {
 export type NumberInputProps = DashboardFormComponentProps & {
     min?: number;
     min?: number;
     max?: number;
     max?: number;
     step?: number;
     step?: number;
+    prefix?: ReactNode;
+    suffix?: ReactNode;
 };
 };
 
 
 /**
 /**
@@ -17,28 +20,43 @@ export type NumberInputProps = DashboardFormComponentProps & {
  * @docsCategory form-components
  * @docsCategory form-components
  * @docsPage NumberInput
  * @docsPage NumberInput
  */
  */
-export function NumberInput({ fieldDef, onChange, ...fieldProps }: Readonly<NumberInputProps>) {
+export function NumberInput({
+    fieldDef,
+    onChange,
+    prefix: overridePrefix,
+    suffix: overrideSuffix,
+    ...fieldProps
+}: Readonly<NumberInputProps>) {
     const readOnly = fieldProps.disabled || isReadonlyField(fieldDef);
     const readOnly = fieldProps.disabled || isReadonlyField(fieldDef);
     const isFloat = fieldDef ? fieldDef.type === 'float' : false;
     const isFloat = fieldDef ? fieldDef.type === 'float' : false;
     const min = fieldProps.min ?? fieldDef?.ui?.min;
     const min = fieldProps.min ?? fieldDef?.ui?.min;
     const max = fieldProps.max ?? fieldDef?.ui?.max;
     const max = fieldProps.max ?? fieldDef?.ui?.max;
     const step = fieldProps.step ?? (fieldDef?.ui?.step || (isFloat ? 0.01 : 1));
     const step = fieldProps.step ?? (fieldDef?.ui?.step || (isFloat ? 0.01 : 1));
-    const prefix = fieldDef?.ui?.prefix;
-    const suffix = fieldDef?.ui?.suffix;
+    const prefix = overridePrefix ?? fieldDef?.ui?.prefix;
+    const suffix = overrideSuffix ?? fieldDef?.ui?.suffix;
     const shouldUseAffixedInput = prefix || suffix;
     const shouldUseAffixedInput = prefix || suffix;
+    const value = fieldProps.value ?? '';
     const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
     const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         if (readOnly) return;
         if (readOnly) return;
-        const numValue = e.target.valueAsNumber;
+
+        let numValue = e.target.valueAsNumber;
+
+        if (Number.isNaN(numValue) && e.target.value) {
+            const normalized = e.target.value.replace(',', '.');
+            numValue = Number(normalized);
+        }
+
         if (Number.isNaN(numValue)) {
         if (Number.isNaN(numValue)) {
             onChange(null);
             onChange(null);
         } else {
         } else {
-            onChange(e.target.valueAsNumber);
+            onChange(numValue);
         }
         }
     };
     };
     if (shouldUseAffixedInput) {
     if (shouldUseAffixedInput) {
         return (
         return (
             <AffixedInput
             <AffixedInput
                 {...fieldProps}
                 {...fieldProps}
+                value={value}
                 type="number"
                 type="number"
                 onChange={handleChange}
                 onChange={handleChange}
                 min={min}
                 min={min}
@@ -57,6 +75,7 @@ export function NumberInput({ fieldDef, onChange, ...fieldProps }: Readonly<Numb
             type="number"
             type="number"
             onChange={handleChange}
             onChange={handleChange}
             {...fieldProps}
             {...fieldProps}
+            value={value}
             min={min}
             min={min}
             max={max}
             max={max}
             step={step}
             step={step}