aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/expense-form.tsx25
-rw-r--r--src/lib/schemas.ts3
2 files changed, 22 insertions, 6 deletions
diff --git a/src/components/expense-form.tsx b/src/components/expense-form.tsx
index a13498d..84fe7c5 100644
--- a/src/components/expense-form.tsx
+++ b/src/components/expense-form.tsx
@@ -56,6 +56,17 @@ export type Props = {
runtimeFeatureFlags: RuntimeFeatureFlags
}
+const enforceCurrencyPattern = (value: string) =>
+ value
+ // replace first comma with #
+ .replace(/[.,]/, '#')
+ // remove all other commas
+ .replace(/[.,]/g, '')
+ // change back # to dot
+ .replace(/#/, '.')
+ // remove all non-numeric and non-dot characters
+ .replace(/[^\d.]/g, '')
+
export function ExpenseForm({
group,
expense,
@@ -210,18 +221,22 @@ export function ExpenseForm({
<FormField
control={form.control}
name="amount"
- render={({ field }) => (
+ render={({ field: { onChange, ...field } }) => (
<FormItem className="sm:order-3">
<FormLabel>Amount</FormLabel>
<div className="flex items-baseline gap-2">
<span>{group.currency}</span>
<FormControl>
<Input
+ {...field}
className="text-base max-w-[120px]"
- type="number"
+ type="text"
inputMode="decimal"
step={0.01}
placeholder="0.00"
+ onChange={(event) =>
+ onChange(enforceCurrencyPattern(event.target.value))
+ }
onClick={(e) => e.currentTarget.select()}
{...field}
/>
@@ -428,7 +443,7 @@ export function ExpenseForm({
),
)}
className="text-base w-[80px] -my-2"
- type="number"
+ type="text"
disabled={
!field.value?.some(
({ participant }) =>
@@ -448,7 +463,9 @@ export function ExpenseForm({
? {
participant: id,
shares:
- event.target.value,
+ enforceCurrencyPattern(
+ event.target.value,
+ ),
}
: p,
),
diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts
index d68adf4..52b0d0d 100644
--- a/src/lib/schemas.ts
+++ b/src/lib/schemas.ts
@@ -51,8 +51,7 @@ export const expenseFormSchema = z
[
z.number(),
z.string().transform((value, ctx) => {
- const normalizedValue = value.replace(/,/g, '.')
- const valueAsNumber = Number(normalizedValue)
+ const valueAsNumber = Number(value)
if (Number.isNaN(valueAsNumber))
ctx.addIssue({
code: z.ZodIssueCode.custom,