refactor: share instrument search presentation
Frontend verify / commits (pull_request) Successful in 24s
Frontend verify / security (pull_request) Failing after 9s
Frontend verify / verify (pull_request) Skipped

This commit is contained in:
2026-09-29 05:14:28 +03:00
parent 0865b35f93
commit 32a77860c8
18 changed files with 489 additions and 551 deletions
@@ -349,6 +349,12 @@ describe("CardPage", () => {
it("archives without deleting history and restores financial actions", async () => {
setup();
await screen.findByText("Перевод на «Запасная»");
server.use(http.patch("*/api/v1/bank-cards/a", () =>
HttpResponse.json({ code: "BANK_WRITE_CONFLICT" }, { status: 409 }),
));
fireEvent.click(screen.getByRole("button", { name: "Убрать в архив" }));
await screen.findByRole("alert");
expect(screen.getByRole("button", { name: "Добавить операцию" })).toBeEnabled();
let current = card;
const bodies: unknown[] = [];
server.use(
@@ -376,6 +382,7 @@ describe("CardPage", () => {
);
fireEvent.click(screen.getByRole("button", { name: "Убрать в архив" }));
await screen.findByRole("button", { name: "Вернуть из архива" });
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Добавить операцию" }),
).toBeDisabled();
+6 -13
View File
@@ -34,7 +34,6 @@ function useCardPageVm() {
const card = useBankCard(cardId);
const updateCard = useUpdateBankCard();
const [archiveError, setArchiveError] = useState<unknown>();
const cards = useBankCards(true);
const history = useBankOperations(cardId, {
@@ -94,7 +93,7 @@ function useCardPageVm() {
});
return {
archiveError,
archiveError: updateCard.isError ? updateCard.error : undefined,
archivePending: updateCard.isPending,
canAddOperation: !card.data?.archivedAt && Boolean(cards.data),
card: card.data,
@@ -149,19 +148,13 @@ function useCardPageVm() {
loading: summary.isLoading,
retry: () => void summary.refetch(),
},
toggleArchive: async () => {
toggleArchive: () => {
if (!card.data) return;
setArchiveError(undefined);
try {
await updateCard.mutateAsync({
body: { archived: !card.data.archivedAt, version: card.data.version },
id: card.data.id,
});
}
catch (error) {
setArchiveError(error);
}
updateCard.mutate({
body: { archived: !card.data.archivedAt, version: card.data.version },
id: card.data.id,
});
},
totalPages:
pageSize === "all"
@@ -4,25 +4,17 @@ import { DateInput } from "@mantine/dates";
import { useController, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import type { OperationValues } from "./OperationForm.types";
import type {
OperationFieldsProps,
OperationValues,
} from "./OperationForm.types";
type Choice = { label: string; value: string };
type OperationFieldsProps = {
cards: Choice[];
categories: Choice[];
dateInputValue: (value: string) => string;
defaultCategory: string;
editing: boolean;
kind: OperationValues["kind"];
kinds: Choice[];
maxDate: () => string;
refundCardId: string;
targets: Choice[];
validDate: (value: string) => boolean;
};
function useOperationFieldsVm(props: OperationFieldsProps) {
function useOperationFieldsVm(props: Pick<OperationFieldsProps,
"dateInputValue"
| "kind"
| "refundCardId"
| "validDate"
>) {
const { t } = useTranslation();
const {
@@ -1,5 +1,21 @@
import type { BankCard, BankOperation } from "@/entities/bank-card";
type Choice = { label: string; value: string };
type OperationFieldsProps = {
cards: Choice[];
categories: Choice[];
dateInputValue: (value: string) => string;
defaultCategory: string;
editing: boolean;
kind: OperationValues["kind"];
kinds: Choice[];
maxDate: () => string;
refundCardId: string;
targets: Choice[];
validDate: (value: string) => boolean;
};
type OperationFormProps = {
card: BankCard;
cards: BankCard[];
@@ -18,4 +34,9 @@ type OperationValues = {
targetCardId: string;
};
export type { OperationFormProps, OperationValues };
export type {
Choice,
OperationFieldsProps,
OperationFormProps,
OperationValues,
};
@@ -17,28 +17,12 @@ import type { BankOperation } from "@/entities/bank-card";
import { formatMoney } from "@/shared/lib";
import type { OperationValues } from "./OperationForm.types";
import type { Choice, OperationFieldsProps } from "./OperationForm.types";
import { useOperationFieldsVm } from "./OperationFields.vm";
import classes from "./OperationForm.module.css";
import { useRefundFieldsVm } from "./RefundFields.vm";
type Choice = { label: string; value: string };
type OperationFieldsProps = {
cards: Choice[];
categories: Choice[];
dateInputValue: (value: string) => string;
defaultCategory: string;
editing: boolean;
kind: OperationValues["kind"];
kinds: Choice[];
maxDate: () => string;
refundCardId: string;
targets: Choice[];
validDate: (value: string) => boolean;
};
const OperationFields: FC<OperationFieldsProps> = (props) => {
const {
cardIdField,