refactor: enforce frontend view model boundaries
This commit is contained in:
@@ -2,24 +2,28 @@ import type { FC } from "react";
|
||||
|
||||
import { Select, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { DateInput } from "@mantine/dates";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
type BankCardValues,
|
||||
bankDateInputValue,
|
||||
bankDateSchema,
|
||||
bankToday,
|
||||
} from "../../model/form-validation";
|
||||
import { bankToday } from "../../model/form-validation";
|
||||
import { useBankCardFieldsVm } from "./BankCardFields.vm";
|
||||
|
||||
type BankCardFieldsProps = { archived: boolean };
|
||||
|
||||
const BankCardFields: FC<BankCardFieldsProps> = (props) => {
|
||||
const {
|
||||
control,
|
||||
formState: { errors },
|
||||
dateParser,
|
||||
errors,
|
||||
onOpeningDateBlur,
|
||||
onOpeningDateChange,
|
||||
onOpeningDateInput,
|
||||
onPaymentSystemChange,
|
||||
openingDateField,
|
||||
openingDateValue,
|
||||
paymentSystemField,
|
||||
paymentSystems,
|
||||
register,
|
||||
} = useFormContext<BankCardValues>();
|
||||
const { t } = useTranslation();
|
||||
t,
|
||||
} = useBankCardFieldsVm();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<TextInput
|
||||
@@ -28,37 +32,36 @@ const BankCardFields: FC<BankCardFieldsProps> = (props) => {
|
||||
{...register("name")}
|
||||
error={errors.name?.message}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label={t("bank.bankName")}
|
||||
{...register("bankName")}
|
||||
error={errors.bankName?.message}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
inputMode="numeric"
|
||||
label={t("bank.lastFour")}
|
||||
{...register("lastFour")}
|
||||
error={errors.lastFour?.message}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="paymentSystem"
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
{...field}
|
||||
clearable
|
||||
comboboxProps={{ withinPortal: false }}
|
||||
data={["mir", "visa", "mastercard"].map(value => ({
|
||||
label: t(`bank.paymentSystems.${value}`),
|
||||
value,
|
||||
}))}
|
||||
error={errors.paymentSystem?.message}
|
||||
label={t("bank.paymentSystem")}
|
||||
onChange={value => field.onChange(value ?? "")}
|
||||
placeholder={t("bank.paymentSystemUnknown")}
|
||||
value={field.value || /* eslint-disable-line unicorn/no-null -- Mantine represents an empty controlled field as null. */ null}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Select
|
||||
{...paymentSystemField}
|
||||
clearable
|
||||
comboboxProps={{ withinPortal: false }}
|
||||
data={paymentSystems}
|
||||
error={errors.paymentSystem?.message}
|
||||
label={t("bank.paymentSystem")}
|
||||
onChange={onPaymentSystemChange}
|
||||
placeholder={t("bank.paymentSystemUnknown")}
|
||||
value={
|
||||
paymentSystemField.value
|
||||
// eslint-disable-next-line unicorn/no-null -- Mantine represents an empty controlled paymentSystemField as null.
|
||||
|| null
|
||||
}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
inputMode="decimal"
|
||||
label={t("bank.openingBalance")}
|
||||
@@ -67,43 +70,31 @@ const BankCardFields: FC<BankCardFieldsProps> = (props) => {
|
||||
{...register("openingBalance")}
|
||||
error={errors.openingBalance?.message}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="openingDate"
|
||||
render={({ field }) => (
|
||||
<DateInput
|
||||
{...field}
|
||||
dateParser={value =>
|
||||
bankDateSchema.safeParse(bankDateInputValue(value)).success
|
||||
? bankDateInputValue(value)
|
||||
: /* eslint-disable-line unicorn/no-null -- Mantine represents an empty controlled field as null. */ null}
|
||||
error={errors.openingDate?.message}
|
||||
fixOnBlur={false}
|
||||
label={t("bank.openingDate")}
|
||||
maxDate={bankToday()}
|
||||
onBlur={(event) => {
|
||||
field.onChange(bankDateInputValue(event.currentTarget.value));
|
||||
field.onBlur();
|
||||
}}
|
||||
onChange={value => field.onChange(value ?? "")}
|
||||
onInput={event =>
|
||||
field.onChange(bankDateInputValue(event.currentTarget.value))}
|
||||
popoverProps={{
|
||||
middlewares: { shift: { crossAxis: true } },
|
||||
withinPortal: false,
|
||||
}}
|
||||
readOnly={props.archived}
|
||||
required
|
||||
value={
|
||||
(bankDateSchema.safeParse(field.value).success) ? (field.value) : undefined
|
||||
}
|
||||
valueFormat="DD.MM.YYYY"
|
||||
/>
|
||||
)}
|
||||
|
||||
<DateInput
|
||||
{...openingDateField}
|
||||
dateParser={dateParser}
|
||||
error={errors.openingDate?.message}
|
||||
fixOnBlur={false}
|
||||
label={t("bank.openingDate")}
|
||||
maxDate={bankToday()}
|
||||
onBlur={onOpeningDateBlur}
|
||||
onChange={onOpeningDateChange}
|
||||
onInput={onOpeningDateInput}
|
||||
popoverProps={{
|
||||
middlewares: { shift: { crossAxis: true } },
|
||||
withinPortal: false,
|
||||
}}
|
||||
readOnly={props.archived}
|
||||
required
|
||||
value={openingDateValue}
|
||||
valueFormat="DD.MM.YYYY"
|
||||
/>
|
||||
|
||||
<Text c="dimmed" size="sm">
|
||||
{t("bank.openingHint")}
|
||||
</Text>
|
||||
|
||||
{props.archived && <Text>{t("bank.archiveHint")}</Text>}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user