74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
'use client'
|
|
|
|
import {useFormContext} from 'react-hook-form'
|
|
import {Minus, Plus} from 'lucide-react'
|
|
import {FormField} from '@/components/ui/form'
|
|
import {Button} from '@/components/ui/button'
|
|
import {Input} from '@/components/ui/input'
|
|
import {PurchaseFormValues} from './form-values'
|
|
|
|
type PurchaseStepperFieldName = 'quota' | 'daily_limit'
|
|
|
|
type NumberStepperFieldProps = {
|
|
name: PurchaseStepperFieldName
|
|
label: string
|
|
min: number
|
|
step: number
|
|
}
|
|
|
|
export function NumberStepperField(props: NumberStepperFieldProps) {
|
|
const form = useFormContext<PurchaseFormValues>()
|
|
|
|
const setValue = (value: number) => {
|
|
form.setValue(props.name, value)
|
|
}
|
|
|
|
return (
|
|
<FormField<PurchaseFormValues, PurchaseStepperFieldName>
|
|
className="space-y-4"
|
|
name={props.name}
|
|
label={props.label}
|
|
>
|
|
{({id, field}) => {
|
|
const value = Number(field.value) || props.min
|
|
return (
|
|
<div className="flex gap-2 items-center">
|
|
<Button
|
|
theme="outline"
|
|
type="button"
|
|
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
|
|
onClick={() => setValue(Math.max(props.min, value - props.step))}
|
|
disabled={value === props.min}
|
|
>
|
|
<Minus/>
|
|
</Button>
|
|
<Input
|
|
{...field}
|
|
id={id}
|
|
type="number"
|
|
className="w-40 h-10 border border-gray-200 rounded-sm text-center"
|
|
min={props.min}
|
|
step={props.step}
|
|
onBlur={(event) => {
|
|
field.onBlur()
|
|
const nextValue = Number(event.target.value)
|
|
if (nextValue < props.min) {
|
|
setValue(props.min)
|
|
}
|
|
}}
|
|
/>
|
|
<Button
|
|
theme="outline"
|
|
type="button"
|
|
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
|
|
onClick={() => setValue(value + props.step)}
|
|
>
|
|
<Plus/>
|
|
</Button>
|
|
</div>
|
|
)
|
|
}}
|
|
</FormField>
|
|
)
|
|
}
|