refactor: address frontend review feedback
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 8m54s
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 12s
Frontend verify / verify (push) Successful in 9m59s

This commit was merged in pull request #43.
This commit is contained in:
2026-09-28 19:20:32 +03:00
parent ca0ad4f824
commit a4046dbe87
139 changed files with 1549 additions and 941 deletions
+2 -7
View File
@@ -19,8 +19,6 @@ import { CardPage } from "./CardPage";
const money = (value: string) => ({ currency: "RUB", value });
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const card
= {
archivedAt: null,
@@ -34,8 +32,6 @@ const card
version: 1,
};
/* eslint-enable unicorn/no-null */
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const operation
= {
amount: money("50.01"),
@@ -55,7 +51,6 @@ const operation
version: 1,
};
/* eslint-enable unicorn/no-null */
function setup(
options: {
cardsError?: boolean;
@@ -342,13 +337,13 @@ describe("CardPage", () => {
};
bodies.push(body);
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
current
= {
...current,
archivedAt: body.archived ? "2026-09-01" : null,
version: current.version + 1,
} as /* eslint-enable unicorn/no-null */ typeof card;
} as typeof card;
return HttpResponse.json(current);
}),
+2 -6
View File
@@ -227,12 +227,8 @@ const CardPageView: FC<CardPageViewProps> = (props) => {
variant="subtle"
>
{card.archivedAt
? (
<RestoreIcon size={18} />
)
: (
<DeleteIcon size={18} strokeWidth={1.5} />
)}
? <RestoreIcon size={18} />
: <DeleteIcon size={18} strokeWidth={1.5} />}
</ActionIcon>
</Group>
</div>
+1 -1
View File
@@ -84,7 +84,7 @@ function useCardPageVm() {
otherCard:
item.kind === "transfer"
? otherCardId
: null, // eslint-disable-line unicorn/no-null -- Preserve the nullable domain value consumed by this view model.
: null,
title,
tone: isOutgoing ? ("negative" as const) : ("positive" as const),
value: `${isOutgoing ? "−" : "+"}${formatMoney(item.amount)}`,
@@ -25,7 +25,7 @@ function useCardPagePresentationVm(vm: CardPageVm) {
if (pending.scope !== scope || vm.history.isError) {
pendingPageRef.current
// eslint-disable-next-line unicorn/no-null -- Reset the pending-pagination ref to its initial null sentinel.
= null;
return;
@@ -40,7 +40,6 @@ function useCardPagePresentationVm(vm: CardPageVm) {
if (delta) window.scrollBy({ behavior: "instant", top: delta });
}
// eslint-disable-next-line unicorn/no-null -- Preserve the existing nullable validation/ref contract.
pendingPageRef.current = null;
}, [
scope,
@@ -12,8 +12,6 @@ import { server } from "@/test/server";
import { DeleteOperation } from "./DeleteOperation";
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const transfer: BankOperation
= {
amount: { currency: "RUB", value: "100" },
@@ -33,7 +31,6 @@ const transfer: BankOperation
version: 1,
};
/* eslint-enable unicorn/no-null */
describe("DeleteOperation", () => {
it("names both sides and requires a deliberate fresh version after conflict", async () => {
configureAuthClient({
@@ -59,7 +59,7 @@ function useOperationFieldsVm(props: OperationFieldsProps) {
const dateParser: ComponentProps<typeof DateInput>["dateParser"] = value =>
props.validDate(props.dateInputValue(value))
? props.dateInputValue(value)
: null; // eslint-disable-line unicorn/no-null -- Mantine represents an empty controlled dateField as null.
: null;
const onDateBlur: ComponentProps<typeof DateInput>["onBlur"] = (event) => {
dateField.onChange(props.dateInputValue(event.currentTarget.value));
@@ -20,8 +20,6 @@ import { OperationForm } from "./OperationForm";
const money = (value: string) => ({ currency: "RUB", value });
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const card: BankCard
= {
archivedAt: null,
@@ -36,7 +34,6 @@ const card: BankCard
version: 1,
};
/* eslint-enable unicorn/no-null */
async function select(label: RegExp, value: RegExp | string) {
fireEvent.click(screen.getByRole("combobox", { name: label }));
fireEvent.click(await screen.findByRole("option", { name: value }));
@@ -229,7 +226,6 @@ describe("OperationForm", () => {
expect(body).not.toHaveProperty("categoryId");
});
it("finds a previous-month purchase across pages, checks remaining refund and retains the complete-refund intent", async () => {
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const purchase: BankOperation
= {
amount: money("500"),
@@ -249,7 +245,6 @@ describe("OperationForm", () => {
version: 1,
};
/* eslint-enable unicorn/no-null */
server.use(
http.get("*/api/v1/bank-cards/a/expenses", ({ request }) => {
return HttpResponse.json({
@@ -313,7 +308,6 @@ describe("OperationForm", () => {
});
});
it("edits a full refund with its own amount excluded from the limit and immutable purchase", async () => {
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const refund: BankOperation
= {
amount: money("500"),
@@ -333,7 +327,6 @@ describe("OperationForm", () => {
version: 2,
};
/* eslint-enable unicorn/no-null */
const purchase = {
...refund,
availableRefund: money("0"),
@@ -394,7 +387,6 @@ describe("OperationForm", () => {
});
it("keeps edit draft and stale version until explicit adoption after conflict", async () => {
/* eslint-disable unicorn/no-null -- Fixture preserves the production contract’s explicit null values. */
const operation: BankOperation
= {
amount: money("100"),
@@ -414,7 +406,6 @@ describe("OperationForm", () => {
version: 1,
};
/* eslint-enable unicorn/no-null */
let readVersion = 1;
const bodies: Record<string, unknown>[] = [];
server.use(
@@ -228,9 +228,7 @@ const OperationFormView: FC<OperationFormViewProps> = (props) => {
<>
<RefundFields {...props.refund} />
{props.loadingExpenses && (
<Text role="status">{t("bank.loadingHistory")}</Text>
)}
{props.loadingExpenses && <Text role="status">{t("bank.loadingHistory")}</Text>}
{props.emptyExpenses && <Text>{t("bank.noPurchases")}</Text>}
@@ -165,13 +165,13 @@ const useOperationFormVm = (props: OperationFormProps) => {
return {
categoriesError: categories.isError
? categories.error
: null, // eslint-disable-line unicorn/no-null -- Preserve the nullable domain value consumed by this view model.
: null,
categoriesOpen,
closeCategories: () => setCategoriesOpen(false),
error,
expensesError: expenses.isError
? expenses.error
: null, // eslint-disable-line unicorn/no-null -- Preserve the nullable domain value consumed by this view model.
: null,
methods,
onCategoryCreated: (id: string) => {
methods.setValue("categoryId", id);
@@ -182,7 +182,7 @@ const useOperationFormVm = (props: OperationFormProps) => {
retrySource: () => void sourceQuery.refetch(),
sourceError: sourceQuery.isError
? sourceQuery.error
: null, // eslint-disable-line unicorn/no-null -- Preserve the nullable domain value consumed by this view model.
: null,
view: {
categoriesOpen,
editing: Boolean(props.operation),