refactor: simplify calendar and form state
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 11s
Frontend verify / verify (pull_request) Successful in 8m43s

This commit is contained in:
2026-09-28 20:23:02 +03:00
parent a7537da344
commit 94adbafa34
20 changed files with 449 additions and 392 deletions
@@ -91,7 +91,6 @@ const OperationExample: FC<ExampleProps> = (props) => {
},
],
limit: { currency: "RUB", value: "500" },
onSelect: () => {},
}}
saveDisabled={false}
sourcePage={1}
@@ -245,14 +245,19 @@ describe("OperationForm", () => {
version: 1,
};
const recent = {
...purchase,
availableRefund: money("100"),
description: "Недавняя покупка",
id: "recent",
};
server.use(
http.get("*/api/v1/bank-cards/a/expenses", ({ request }) => {
return HttpResponse.json({
hasNext: new URL(request.url).searchParams.get("page") !== "2",
items:
new URL(request.url).searchParams.get("page") === "2"
? [purchase]
: [],
[new URL(request.url).searchParams.get("page") === "2" ? purchase : recent],
page: 1,
total: 1,
});
@@ -260,9 +265,19 @@ describe("OperationForm", () => {
http.get("*/api/v1/bank-cards/operations/purchase", () =>
HttpResponse.json(purchase),
),
http.get("*/api/v1/bank-cards/operations/recent", () =>
HttpResponse.json(recent),
),
);
const close = setup();
await select(/Вид операции/, "Возврат");
await select(/Исходная покупка/, /Недавняя покупка/);
await screen.findByText("Доступно к возврату: 100 ₽");
fireEvent.change(screen.getByLabelText(/Сумма/), {
target: { value: "150" },
});
fireEvent.click(screen.getByRole("button", { name: "Сохранить" }));
await screen.findByText("Сумма превышает доступный возврат.");
await waitFor(() =>
expect(screen.getByRole("button", { name: "Далее" })).toBeEnabled(),
);
@@ -142,12 +142,11 @@ type RefundFieldsProps = {
editing: boolean;
expenses: Choice[];
limit: BankOperation["availableRefund"] | undefined;
onSelect: (id: string) => void;
};
const RefundFields: FC<RefundFieldsProps> = (props) => {
const { errors, isSubmitting, onExpenseChange, originalExpenseIdField, t }
= useRefundFieldsVm(props);
= useRefundFieldsVm();
return (
<Stack>
@@ -35,11 +35,6 @@ const useOperationFormVm = (props: OperationFormProps) => {
const [latest, setLatest] = useState<BankOperation>();
const [sourcePage, setSourcePage] = useState(1);
const [sourceId, setSourceId] = useState(
props.operation?.originalExpenseId ?? "",
);
const sourceQuery = useBankOperation(sourceId || undefined);
const currentQuery = useBankOperation(props.operation?.id);
const [refundLimit, setRefundLimit] = useState(
@@ -64,7 +59,7 @@ const useOperationFormVm = (props: OperationFormProps) => {
originalExpenseId: props.operation?.originalExpenseId ?? "",
targetCardId: props.operation?.targetCardId ?? "",
},
resolver: zodResolver(
resolver: (values, context, options) => zodResolver(
createOperationSchema({
cards: props.cards,
categories: categories.data,
@@ -74,9 +69,16 @@ const useOperationFormVm = (props: OperationFormProps) => {
: sourceQuery.data?.availableRefund,
submittedValues,
}),
),
)(values, context, options),
});
const sourceId = useWatch({
control: methods.control,
name: "originalExpenseId",
});
const sourceQuery = useBankOperation(sourceId || undefined);
const kind = useWatch({ control: methods.control, name: "kind" });
const expenses = useBankExpenses(
@@ -242,7 +244,6 @@ const useOperationFormVm = (props: OperationFormProps) => {
limit: props.operation
? refundLimit
: sourceQuery.data?.availableRefund,
onSelect: setSourceId,
},
saveDisabled:
(kind === "expense" && !categories.data)
@@ -1,20 +1,9 @@
import { useController, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import type { BankOperation } from "@/entities/bank-card";
import type { OperationValues } from "./OperationForm.types";
type Choice = { label: string; value: string };
type RefundFieldsProps = {
editing: boolean;
expenses: Choice[];
limit: BankOperation["availableRefund"] | undefined;
onSelect: (id: string) => void;
};
function useRefundFieldsVm(props: RefundFieldsProps) {
function useRefundFieldsVm() {
const { t } = useTranslation();
const {
@@ -29,7 +18,6 @@ function useRefundFieldsVm(props: RefundFieldsProps) {
const onExpenseChange: (value: null | string) => void = (value) => {
originalExpenseIdField.onChange(value ?? "");
props.onSelect(value ?? "");
};
return { errors, isSubmitting, onExpenseChange, originalExpenseIdField, t };