Skip to content

Substitution page filter and UI fixes#218

Merged
nemvince merged 9 commits into
mainfrom
substitution-page-filter-and-ui-fixes
May 28, 2026
Merged

Substitution page filter and UI fixes#218
nemvince merged 9 commits into
mainfrom
substitution-page-filter-and-ui-fixes

Conversation

@KoZsombat
Copy link
Copy Markdown
Contributor

@KoZsombat KoZsombat commented May 27, 2026

Summary by CodeRabbit

  • New Features

    • Added a substitution filter bar to search by class, teacher, or classroom with a searchable selector.
    • Substitution view now groups and can emit multiple cards per date to show cohort-specific and moved-lesson details.
    • Added a "Clear Filter" label.
  • Improvements

    • Substitute options prioritize nearby candidates and use locale-aware, case-insensitive ordering.
    • Lesson lists are ordered by period for consistent display.
  • Bug Fixes

    • Timetable list now reliably refreshes after import, update, or delete.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 42d70e80-16bc-4a9e-b3c3-8562ee0d9678

📥 Commits

Reviewing files that changed from the base of the PR and between 5138de3 and 7d863fc.

📒 Files selected for processing (2)
  • apps/iris/public/locales/hu/translation.json
  • apps/iris/src/components/subs.tsx
💤 Files with no reviewable changes (1)
  • apps/iris/src/components/subs.tsx
📜 Recent review details
🔇 Additional comments (1)
apps/iris/public/locales/hu/translation.json (1)

175-175: LGTM!


📝 Walkthrough

Walkthrough

Adds a filter bar and filtering helpers to SubstitutionView with per-cohort card splitting; extends SubsV to accept cohort/date props and apply cohort-scoped lesson filtering; sorts substitute-teacher options (nearby first, then locale-sorted) and sorts available lessons by period; updates timetable query key shape and usages; adds clearFilter translations.

Changes

Substitution View Filtering and Per-Cohort Display

Layer / File(s) Summary
Filter bar UI and helper functions
apps/iris/src/components/subs-view.tsx
Adds new imports and QUERY_OPTIONS, i18n-backed helper functions to build filter options/placeholders/empty messages and to filter substitutions/moved lessons, and introduces SubsFilterBar (toggle modes, searchable combobox, clear button, skeleton state).
SubstitutionView data fetching and filtering
apps/iris/src/components/subs-view.tsx
SubstitutionView computes activeSelectionId, queries timetables/cohorts/teachers/classrooms/substitutions/movedLessons (using QUERY_OPTIONS), applies filter helpers to derive filteredSubs and filteredMovedLessons, groups results by date, computes hasFutureSubstitutions, and wires SubsFilterBar.
SubsV component contract and filtering support
apps/iris/src/components/subs.tsx
TimetableProps adds optional cohortFilter and date. LessonReturn filters lessons by cohortFilter. SubsV accepts the new props, derives cardDate, gates rendering on future content, precomputes lessonRows/movedRows, and uses those for badge counts and table-body rendering.

Substitution Admin Dialog Sorting

Layer / File(s) Summary
Substitute-teacher option and lesson-period sorting
apps/iris/src/components/admin/substitution-dialog.tsx
Adds isNearby to substitute options, introduces sortedSubstituteOptions (nearby first, then localeCompare with sensitivity 'base'), switches the combobox to sortedSubstituteOptions, and sorts availableLessons by lesson.period.period (missing -> 0) before rendering checkboxes.

Query key shape and usages

Layer / File(s) Summary
queryKeys.timetables shape change
apps/iris/src/utils/query-keys.ts
Replaces timetables: () => ['timetables'] with timetables: { all: () => ['timetables'], latestValid: () => ['timetables','latestValid'] }.
Update usages to queryKeys.timetables.all()
apps/iris/src/components/timetable/index.tsx, apps/iris/src/routes/_private/admin/timetable/manage.tsx, apps/iris/src/components/admin/timetable-import-dialog.tsx
Updates queryKey and invalidate calls to use queryKeys.timetables.all() where the all-timetables key is intended.

Localization

Layer / File(s) Summary
Add clearFilter translations
apps/iris/public/locales/en/translation.json, apps/iris/public/locales/hu/translation.json
Adds timetable.clearFilter translation entries in English and Hungarian.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • filcdev/filc#196: Overlaps changes to apps/iris/src/components/admin/substitution-dialog.tsx related to substitute-teacher option construction and ordering.
  • filcdev/filc#187: Related to timetable import and query invalidation adjustments in admin/timetable-import-dialog.tsx.

Suggested reviewers

  • nemvince
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Substitution page filter and UI fixes' directly summarizes the main changes across the pull request, which focus on implementing filtering UI for the substitution view and fixing related UI components and query caching.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/iris/src/components/admin/substitution-dialog.tsx`:
- Around line 209-221: The sorting logic in sortedSubstituteOptions currently
inspects rendered text via label.includes('H1'), which breaks with translations;
change it to sort using a stable flag on the option objects (e.g., option.isH1
or option.priority on each substituteOptions entry) first, then fall back to
localeCompare on label for ties; update the comparator in useMemo to use that
flag (e.g., compare a.isH1 vs b.isH1 or a.priority vs b.priority) instead of
checking label.includes('H1') while keeping the final localeCompare for
alphabetical order.

In `@apps/iris/src/components/subs-view.tsx`:
- Around line 443-445: Replace the inline query key array
['timetables','latestValid'] used in subs-view.tsx with a centralized key from
query-keys.ts: add a new timetables.latestValid function that returns the tuple
['timetables','latestValid'] as const (matching the existing timetables keys
shape) and then update the queryKey in the hook in components/subs-view.tsx to
call queryKeys.timetables.latestValid(); this keeps key generation consistent
with other keys and enables proper cache invalidation.
- Around line 393-401: Replace the hardcoded aria-label on the Button with a
localized string using the i18n `t(...)` function (e.g., use t('clearFilter')
for the Button with onClear and XIcon) so accessibility labels are localized;
then add the key "clearFilter" to both locale trees (English and Hungarian) with
values "Clear filter" and "Szűrő törlése" respectively. Ensure the component
imports/has access to the translation hook/namespace used in this file and
update any tests or snapshots that assert the aria-label if present.

In `@apps/iris/src/components/subs.tsx`:
- Around line 267-274: The badge count is inconsistent: when cohortFilter is set
you count matching lessons, but when unset you count substitutions with any
lesson; update the fallback branch so filteredLessonCount always counts lessons
(non-null) across all subs. Modify the ternary on filteredLessonCount to, when
!cohortFilter, compute data.flatMap(sub => sub.lessons.filter((l): l is Lesson
=> l != null)).length so both branches consistently count individual lessons
(use the same sub.lessons filter predicate as the cohort branch).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b961e057-ae4a-467c-a7f9-cc79230b769e

📥 Commits

Reviewing files that changed from the base of the PR and between a0a0725 and 7355c2a.

📒 Files selected for processing (3)
  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs-view.tsx
  • apps/iris/src/components/subs.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
apps/{chronos,iris}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/filc-reuse.instructions.md)

apps/{chronos,iris}/src/**/*.{ts,tsx}: Reuse existing helpers, types, schemas, and hooks before adding new ones. Check nearby feature folders first, then shared files such as apps/chronos/src/database/helpers.ts, apps/iris/src/utils/query-keys.ts, apps/iris/src/hooks/use-has-permission.ts, apps/iris/src/components/admin/admin.types.ts, and apps/iris/src/components/doorlock/doorlock.types.ts
When a second call site needs the same logic, prefer extracting or extending the existing abstraction instead of creating a parallel helper with a slightly different name
Keep abstractions local to the narrowest shared boundary that already exists. Do not create cross-app utilities for one feature-specific use
Extend existing dialog props, response shapes, and query key families instead of re-declaring near-identical types in each file
Prefer the smallest root-cause fix that matches neighboring code over broad rewrites or speculative cleanup
Keep imports on the app alias boundary: #... for Chronos and @/... for Iris

Files:

  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs.tsx
  • apps/iris/src/components/subs-view.tsx
apps/iris/src/{routes,components}/**/*.tsx

📄 CodeRabbit inference engine (.github/instructions/iris-data-flow.instructions.md)

apps/iris/src/{routes,components}/**/*.tsx: Always use centralized keys from apps/iris/src/utils/query-keys.ts for React Query. Do not introduce inline array query keys for existing domains
Use parseResponse(...) and the generated Hono client from apps/iris/src/utils/hc.ts for API requests when that is the local pattern
When a mutation changes server state, invalidate every affected query family, not just the page-local list. Follow the multi-invalidation pattern already used in admin news and doorlock screens
Reuse apps/iris/src/hooks/use-has-permission.ts and existing permission guard components instead of duplicating permission logic in the view
New user-facing error and success messages should go through t(...) and the locale files, even when surfaced through toasts

Files:

  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs.tsx
  • apps/iris/src/components/subs-view.tsx
apps/iris/src/components/**/*dialog.tsx

📄 CodeRabbit inference engine (.github/instructions/iris-dialog-form.instructions.md)

apps/iris/src/components/**/*dialog.tsx: Follow the dialog structure used in files like card-dialog.tsx and user-dialog.tsx: create the form near the top of the component, derive reactive slices with useStore(form.store, selector), and render fields with <form.Field>{(field) => ...}</form.Field>
Reuse validation schemas from apps/iris/src/utils/form-schemas.ts when available. If a schema becomes shared by multiple dialogs, move it there instead of copying validation logic
form.reset takes raw values, not { values: ... }. Because form.reset and form.setFieldValue are not stable dependencies, do not add them to useEffect arrays when synchronizing dialog state
Reuse or extend shared dialog prop types such as admin.types.ts and doorlock.types.ts instead of defining near-duplicate props in each dialog
Keep submit side effects together: mutation success should close the dialog, invalidate the relevant query keys, and surface translated success or failure feedback
New labels, button text, placeholders, and empty states belong in t(...) and the locale files, even if older dialogs still have hardcoded strings

Files:

  • apps/iris/src/components/admin/substitution-dialog.tsx
apps/iris/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/iris.instructions.md)

apps/iris/src/**/*.{ts,tsx}: Keep user-facing text in t(...) and update both locale trees under apps/iris/public/locales/en and apps/iris/public/locales/hu
TanStack Form is the default form pattern; follow examples with useForm, useStore(form.store, selector), and <form.Field>{(field) => ...}</form.Field>
form.reset(values) takes raw values, not { values }. form.reset and form.setFieldValue are not stable useEffect dependencies, so omit them from dependency arrays when needed
Base UI dropdown wrappers use onClick, not Radix-style onSelect, unless the local component explicitly exposes a different API
apps/iris/src/components/ui/chart.tsx already owns ResponsiveContainer; do not wrap chart children in another one
Keep public timetable filter state in TanStack Router search params instead of duplicating it in unrelated local state

Files:

  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs.tsx
  • apps/iris/src/components/subs-view.tsx
🔇 Additional comments (3)
apps/iris/src/components/admin/substitution-dialog.tsx (1)

318-338: LGTM!

Also applies to: 366-367

apps/iris/src/components/subs.tsx (1)

16-23: LGTM!

Also applies to: 229-234, 254-265, 280-281, 289-289, 296-300, 306-306, 336-339

apps/iris/src/components/subs-view.tsx (1)

55-60: LGTM!

Also applies to: 88-172, 174-248, 251-363, 365-406, 410-419, 421-492, 518-559, 561-593, 608-630, 648-651

Comment thread apps/iris/src/components/admin/substitution-dialog.tsx
Comment thread apps/iris/src/components/subs-view.tsx
Comment thread apps/iris/src/components/subs-view.tsx
Comment thread apps/iris/src/components/subs.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/iris/src/routes/_private/admin/timetable/manage.tsx (1)

163-180: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Centralize the preview-delete query key under queryKeys.timetables.

Line 179 still uses an inline timetable-domain key; this should live in apps/iris/src/utils/query-keys.ts like the other timetable keys.

Suggested fix
--- a/apps/iris/src/utils/query-keys.ts
+++ b/apps/iris/src/utils/query-keys.ts
@@
   timetables: {
     all: () => ['timetables'] as const,
     latestValid: () => ['timetables', 'latestValid'] as const,
+    previewDelete: (id: string | undefined) =>
+      ['timetables', 'preview-delete', id] as const,
   },
--- a/apps/iris/src/routes/_private/admin/timetable/manage.tsx
+++ b/apps/iris/src/routes/_private/admin/timetable/manage.tsx
@@
-    queryKey: ['timetables', 'preview-delete', itemToDelete?.id] as const,
+    queryKey: queryKeys.timetables.previewDelete(itemToDelete?.id),
   });

As per coding guidelines, "Always use centralized keys from apps/iris/src/utils/query-keys.ts for React Query. Do not introduce inline array query keys for existing domains".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/iris/src/routes/_private/admin/timetable/manage.tsx` around lines 163 -
180, Replace the inline React Query key used in previewQuery with the
centralized key from queryKeys.timetables: import queryKeys and change the
queryKey from ['timetables','preview-delete', itemToDelete?.id] to the
corresponding helper on queryKeys.timetables (e.g.,
queryKeys.timetables.previewDelete(itemToDelete?.id) or whatever preview-delete
helper exists); keep the rest of the previewQuery (queryFn, enabled) unchanged
and ensure the import of queryKeys is added at the top of the file.
apps/iris/src/components/timetable/index.tsx (1)

131-150: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the centralized latestValid query key helper in this block.

Line 149 still inlines the key, so this migration is only partial and can drift from queryKeys.

Suggested fix
   const latestValidTimetableQuery = useQuery({
     ...QUERY_OPTIONS,
@@
-    queryKey: ['timetables', 'latestValid'] as const,
+    queryKey: queryKeys.timetables.latestValid(),
   });

As per coding guidelines, "Always use centralized keys from apps/iris/src/utils/query-keys.ts for React Query. Do not introduce inline array query keys for existing domains".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/iris/src/components/timetable/index.tsx` around lines 131 - 150, Replace
the inline queryKey array used in latestValidTimetableQuery with the centralized
helper from query-keys; specifically, change the queryKey in the useQuery that
creates latestValidTimetableQuery to use queryKeys.timetables.latestValid() (or
the appropriate latestValid helper) instead of ['timetables', 'latestValid'] so
the key is consistent with the rest of the codebase.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/iris/public/locales/hu/translation.json`:
- Line 175: The Hungarian translation for the "clearFilter" key contains a typo
("FIlterek törlése"); update the value for clearFilter in translation.json to
use correct casing ("Filterek törlése") by editing the "clearFilter" entry so
the UI/ARIA strings display the corrected word.

---

Outside diff comments:
In `@apps/iris/src/components/timetable/index.tsx`:
- Around line 131-150: Replace the inline queryKey array used in
latestValidTimetableQuery with the centralized helper from query-keys;
specifically, change the queryKey in the useQuery that creates
latestValidTimetableQuery to use queryKeys.timetables.latestValid() (or the
appropriate latestValid helper) instead of ['timetables', 'latestValid'] so the
key is consistent with the rest of the codebase.

In `@apps/iris/src/routes/_private/admin/timetable/manage.tsx`:
- Around line 163-180: Replace the inline React Query key used in previewQuery
with the centralized key from queryKeys.timetables: import queryKeys and change
the queryKey from ['timetables','preview-delete', itemToDelete?.id] to the
corresponding helper on queryKeys.timetables (e.g.,
queryKeys.timetables.previewDelete(itemToDelete?.id) or whatever preview-delete
helper exists); keep the rest of the previewQuery (queryFn, enabled) unchanged
and ensure the import of queryKeys is added at the top of the file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 773af6a2-680f-4b6d-be36-201ce49643e2

📥 Commits

Reviewing files that changed from the base of the PR and between 7355c2a and 5138de3.

📒 Files selected for processing (9)
  • apps/iris/public/locales/en/translation.json
  • apps/iris/public/locales/hu/translation.json
  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/admin/timetable-import-dialog.tsx
  • apps/iris/src/components/subs-view.tsx
  • apps/iris/src/components/subs.tsx
  • apps/iris/src/components/timetable/index.tsx
  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
  • apps/iris/src/utils/query-keys.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
apps/{chronos,iris}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/filc-reuse.instructions.md)

apps/{chronos,iris}/src/**/*.{ts,tsx}: Reuse existing helpers, types, schemas, and hooks before adding new ones. Check nearby feature folders first, then shared files such as apps/chronos/src/database/helpers.ts, apps/iris/src/utils/query-keys.ts, apps/iris/src/hooks/use-has-permission.ts, apps/iris/src/components/admin/admin.types.ts, and apps/iris/src/components/doorlock/doorlock.types.ts
When a second call site needs the same logic, prefer extracting or extending the existing abstraction instead of creating a parallel helper with a slightly different name
Keep abstractions local to the narrowest shared boundary that already exists. Do not create cross-app utilities for one feature-specific use
Extend existing dialog props, response shapes, and query key families instead of re-declaring near-identical types in each file
Prefer the smallest root-cause fix that matches neighboring code over broad rewrites or speculative cleanup
Keep imports on the app alias boundary: #... for Chronos and @/... for Iris

Files:

  • apps/iris/src/components/admin/timetable-import-dialog.tsx
  • apps/iris/src/utils/query-keys.ts
  • apps/iris/src/components/timetable/index.tsx
  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs-view.tsx
  • apps/iris/src/components/subs.tsx
apps/iris/src/{routes,components}/**/*.tsx

📄 CodeRabbit inference engine (.github/instructions/iris-data-flow.instructions.md)

apps/iris/src/{routes,components}/**/*.tsx: Always use centralized keys from apps/iris/src/utils/query-keys.ts for React Query. Do not introduce inline array query keys for existing domains
Use parseResponse(...) and the generated Hono client from apps/iris/src/utils/hc.ts for API requests when that is the local pattern
When a mutation changes server state, invalidate every affected query family, not just the page-local list. Follow the multi-invalidation pattern already used in admin news and doorlock screens
Reuse apps/iris/src/hooks/use-has-permission.ts and existing permission guard components instead of duplicating permission logic in the view
New user-facing error and success messages should go through t(...) and the locale files, even when surfaced through toasts

Files:

  • apps/iris/src/components/admin/timetable-import-dialog.tsx
  • apps/iris/src/components/timetable/index.tsx
  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs-view.tsx
  • apps/iris/src/components/subs.tsx
apps/iris/src/components/**/*dialog.tsx

📄 CodeRabbit inference engine (.github/instructions/iris-dialog-form.instructions.md)

apps/iris/src/components/**/*dialog.tsx: Follow the dialog structure used in files like card-dialog.tsx and user-dialog.tsx: create the form near the top of the component, derive reactive slices with useStore(form.store, selector), and render fields with <form.Field>{(field) => ...}</form.Field>
Reuse validation schemas from apps/iris/src/utils/form-schemas.ts when available. If a schema becomes shared by multiple dialogs, move it there instead of copying validation logic
form.reset takes raw values, not { values: ... }. Because form.reset and form.setFieldValue are not stable dependencies, do not add them to useEffect arrays when synchronizing dialog state
Reuse or extend shared dialog prop types such as admin.types.ts and doorlock.types.ts instead of defining near-duplicate props in each dialog
Keep submit side effects together: mutation success should close the dialog, invalidate the relevant query keys, and surface translated success or failure feedback
New labels, button text, placeholders, and empty states belong in t(...) and the locale files, even if older dialogs still have hardcoded strings

Files:

  • apps/iris/src/components/admin/timetable-import-dialog.tsx
  • apps/iris/src/components/admin/substitution-dialog.tsx
apps/iris/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/iris.instructions.md)

apps/iris/src/**/*.{ts,tsx}: Keep user-facing text in t(...) and update both locale trees under apps/iris/public/locales/en and apps/iris/public/locales/hu
TanStack Form is the default form pattern; follow examples with useForm, useStore(form.store, selector), and <form.Field>{(field) => ...}</form.Field>
form.reset(values) takes raw values, not { values }. form.reset and form.setFieldValue are not stable useEffect dependencies, so omit them from dependency arrays when needed
Base UI dropdown wrappers use onClick, not Radix-style onSelect, unless the local component explicitly exposes a different API
apps/iris/src/components/ui/chart.tsx already owns ResponsiveContainer; do not wrap chart children in another one
Keep public timetable filter state in TanStack Router search params instead of duplicating it in unrelated local state

Files:

  • apps/iris/src/components/admin/timetable-import-dialog.tsx
  • apps/iris/src/utils/query-keys.ts
  • apps/iris/src/components/timetable/index.tsx
  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
  • apps/iris/src/components/admin/substitution-dialog.tsx
  • apps/iris/src/components/subs-view.tsx
  • apps/iris/src/components/subs.tsx
apps/iris/src/routes/**/*.tsx

📄 CodeRabbit inference engine (.github/instructions/iris-data-flow.instructions.md)

apps/iris/src/routes/**/*.tsx: Follow route composition patterns from apps/iris/src/routes/_private/admin/news/system-messages.tsx: use createFileRoute(...) at the top, then permission gating, then queries and mutations grouped near the component that owns them
Keep search-param-driven page state in TanStack Router when the page already uses it for filters or selection. Do not fork that state into unrelated local state

Files:

  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
apps/iris/src/routes/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/iris.instructions.md)

Treat apps/iris/src/route-tree.gen.ts as generated; change source files under apps/iris/src/routes instead

Files:

  • apps/iris/src/routes/_private/admin/timetable/manage.tsx
🔇 Additional comments (7)
apps/iris/src/components/admin/substitution-dialog.tsx (1)

200-207: LGTM!

Also applies to: 210-220

apps/iris/public/locales/en/translation.json (1)

185-186: LGTM!

apps/iris/src/components/subs-view.tsx (1)

393-395: LGTM!

Also applies to: 421-445

apps/iris/src/components/subs.tsx (1)

267-274: LGTM!

apps/iris/src/utils/query-keys.ts (1)

96-99: LGTM!

apps/iris/src/routes/_private/admin/timetable/manage.tsx (1)

160-161: LGTM!

Also applies to: 208-230

apps/iris/src/components/admin/timetable-import-dialog.tsx (1)

87-90: LGTM!

Comment thread apps/iris/public/locales/hu/translation.json Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 27, 2026
@KoZsombat KoZsombat dismissed coderabbitai[bot]’s stale review May 28, 2026 00:41

The merge-base changed after approval.

Copy link
Copy Markdown
Member

@nemvince nemvince left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

billions must merge

@nemvince nemvince merged commit eaf9de3 into main May 28, 2026
7 checks passed
@nemvince nemvince deleted the substitution-page-filter-and-ui-fixes branch May 28, 2026 00:43
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Filc Issue Tracker May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Refactor public substitution view Substitution view should be filterable by class

2 participants