FAC-WEB feat: show academic year alongside semester labels#154
Merged
Conversation
Compose "Semester 2 • 2025-2026" via a shared formatSemesterDisplay util at lib/format-semester.ts, wired into two composition points: mapSemesterOptionsToViewModel (propagates to the three semester dropdowns and every downstream selectedSemesterLabel consumer) and useFacultyReportDetailViewModel (the faculty-report sticky header, which reads report?.semester.label directly and bypasses the ViewModel chain). Drops the now-redundant academicYear field from ScopedSemesterOption and widens the dashboard-header semester trigger to md:w-64 so the longer composed label doesn't truncate at md+ viewports. The API already ships academicYear on every semester DTO — this is presentation-only. Fallback to "(year unknown)" when academicYear is absent, surfacing data gaps instead of silently dropping the year. Closes #153
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
4 tasks
y4nder
added a commit
that referenced
this pull request
Apr 23, 2026
Compose "Semester 2 • 2025-2026" via a shared formatSemesterDisplay util at lib/format-semester.ts, wired into two composition points: mapSemesterOptionsToViewModel (propagates to the three semester dropdowns and every downstream selectedSemesterLabel consumer) and useFacultyReportDetailViewModel (the faculty-report sticky header, which reads report?.semester.label directly and bypasses the ViewModel chain). Drops the now-redundant academicYear field from ScopedSemesterOption and widens the dashboard-header semester trigger to md:w-64 so the longer composed label doesn't truncate at md+ viewports. The API already ships academicYear on every semester DTO — this is presentation-only. Fallback to "(year unknown)" when academicYear is absent, surfacing data gaps instead of silently dropping the year. Closes #153
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #153.
Summary
formatSemesterDisplayutil atlib/format-semester.tscomposinglabel+academicYearinto"Semester 2 • 2025-2026"(bullet•matches the existing separator convention).mapSemesterOptionsToViewModel— propagates the composed label to all three semester dropdowns (dashboard header, scoped faculty list, faculty-evaluation toolbar) and every downstreamselectedSemesterLabelconsumer (tab empty states, export dialogs, attention cards, section headers, faculty cards, evaluate action menus).useFacultyReportDetailViewModel— the faculty-report sticky header readsreport?.semester.labeloff the report response and bypasses the ViewModel chain.academicYearfield fromScopedSemesterOptionto prevent consumers from accidentally rendering both sides of the composed string.md:w-48tomd:w-64so the longer composed label fits without truncation.No API / backend changes — the backend already ships
academicYearon every semester DTO; this is purely presentation.Why
Current UI shows bare
Semester 2in dropdowns and headers — ambiguous when data spans multiple academic years (Semester 2 of 2024-2025vsSemester 2 of 2025-2026).Fallback behavior
label+academicYearpresent →"Semester 2 • 2025-2026"labelpresent,academicYearabsent →"Semester 2 (year unknown)"labelabsent,code+academicYearpresent →"S22526 • 2025-2026"(preserves the pre-existing fallback)"Unknown Semester (year unknown)"Whitespace-only values are treated as missing.
Quality gates
bun run typecheck✅bun run lint✅ (includingno-nested-ternary— the report-detail fallback chain was refactored to named consts)bun run build✅ (28/28 pages)Test plan
/faculty/analytics— sticky header on the faculty report screen shows composed labelselectedSemesterLabelconsumer per grouping (tab empty state, export dialog, attention card, section header, faculty card, evaluate action menu) — each inherits the composed label from the ViewModel/faculty/analyticswith nosemesterId, confirm the URL bar has?semesterId=<uuid>&semesterLabel=Semester+2+%E2%80%A2+2025-2026; copy-paste into a new tab and verify the sticky header decodes correctlymd:w-64tomd:w-56(224px still fits the composed label at text-sm)academic_year IS NULL, verify they render as"Semester 2 (year unknown)"(or inject via DevTools React Query cache)Tech-spec
api.faculytics/_bmad-output/implementation-artifacts/tech-spec-semester-label-with-academic-year.mdFollow-ups (not this PR)
admin.faculyticscopy of the util (separate ticket)SemesterFilterResponseDtorequired vsSemesterShortResponseDto/SemesterItemResponseDtooptional) — API-side audit