Skip to content

refactor: tag id constants + guards against unknown tag ids - #202

Open
GlebYavorski wants to merge 4 commits into
ardov:masterfrom
GlebYavorski:chore/mixed-tag-hardening
Open

refactor: tag id constants + guards against unknown tag ids#202
GlebYavorski wants to merge 4 commits into
ardov:masterfrom
GlebYavorski:chore/mixed-tag-hardening

Conversation

@GlebYavorski

Copy link
Copy Markdown

Продолжение #201 — то, что нашлось вокруг бага из #147. Ветка построена поверх #201, поэтому его коммит входит в диff; мерджить после него (или вместо — тогда master получит и фикс, и остальное).

1. Константы вместо магических строк

'mixed' (плейсхолдер «Разные категории» в массовом редактировании) был продублирован в трёх слоях — BulkEditModal, TagChip, transaction/thunks — и ничем не отличался от настоящего id категории, что и стало причиной #147. Теперь mixedTagId и nullTagId живут в 5-entities/tag/model/constants.ts и экспортируются из публичного API сущности.

Литералы 'null' остались в остальном коде (envelope, budget, filtering и т.д.) — не стал раздувать диff, заменил только там, где трогал строки.

2. Устойчивость к неизвестному id категории

Поиск тега по id предполагал, что тег точно существует, поэтому один незнакомый id рушил весь экран:

Обе точки теперь падают обратно на null-тег. Это важно для тех, у кого 'mixed' уже записался в данные до фикса #201: без фолбэка они увидят краш и после обновления.

3. Пустой массив категорий

tag может быть [] — достаточно удалить последнюю категорию в редакторе операции. Проверка tr.tag ? tr.tag[0] : … считает это «категория есть»:

  • getMainTag возвращал undefined вместо null;
  • экспорт в CSV падал на t.tag[0].title;
  • getFacts группировал такие операции по ключу undefined вместо null-тега.

4. Починен сломанный тест

TagSelect2.test.tsx на master не загружается вообще: мок i18next без default-экспорта ломает импорт 6-shared/localization. Мок дополнен инстансом с use/init/on.

Проверки

  • npx vitest run — 30 тестов, 4 файла, всё зелёное (на master — 15 тестов и один упавший файл)
  • npx tsc --noEmit — чисто
  • npx vite build — успешно

Новые тесты: bulkEditTransactions (обычный кейс + кейс из #147) и getMainTag (null / [] / несколько тегов).

🤖 Generated with Claude Code

GlebYavorski and others added 4 commits July 30, 2026 16:53
When bulk editing transactions with different categories, the modal puts
a `mixed` placeholder in the tag list, and `modifyTags` is supposed to
expand it into each transaction's own tags. For a transaction without any
category `prevTags` is `null`, so the `id === 'mixed' && prevTags` check
fell through to the `else` branch and stored the literal `mixed` string as
a tag id.

After that `usePopulatedTags()['mixed']` is `undefined` and rendering the
transaction list crashes in `Symbol` (`tag.symbol` of undefined), taking
the whole app down.

Fixes ardov#147

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The `mixed` placeholder was a magic string duplicated across three layers
(BulkEditModal, TagChip, transaction thunks) with no hint that it is not a
real tag id. Same for the `null` tag id inside those places.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Lookups by tag id assumed the tag always exists, so a single unknown id
(e.g. the `mixed` placeholder written by the bug in ardov#147) crashed the whole
transaction list and the year review. Fall back to the null tag instead.

Transactions can also hold an empty tag array once the last category is
removed in the transaction editor, which `tr.tag ? tr.tag[0] : …` treated as
"has a category": `getMainTag` returned `undefined` instead of `null` and
CSV export crashed on `t.tag[0].title`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The mock had no default export, so importing `6-shared/localization` threw
and the whole suite failed to load on master.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

@GlebYavorski is attempting to deploy a commit to the Alexey Ardov's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant