Problem Registration Calendar Follow-up — Deadline Edit Entry Point + Calendar UX Improvements
Context
After completing the calendar single widget + react-day-picker v9 mapping + ko locale application in Sprint 139, the user directly used the feature in production and 5 follow-up items of feedback were generated:
- "It would be nice to have a deadline edit feature" — no path to change deadline after registration
- "The calendar view is not intuitive and it's inconvenient because the selected date doesn't appear" — unable to confirm user input immediately
- "The weekday display looks wrong" — regression even after Sprint 139 PR #183 grid mapping
- "The month switch button position looks wrong" — nav button position misaligned
- "Can't change month on the edit page" — nav button not clickable
Additionally found a separate issue during diagnosis:
- "Feedback page (
/admin/feedbacks) inaccessible" — user email not included in ADMIN_EMAILS plaintext in production gateway-secrets
Decisions
Wave Split + Integrated PR Strategy
- Waves A~C integrated into a single PR (#185) — maintaining consistency across 3 entry points + bulk i18n key additions
- Follow-up as separate PR (#186) — regression found after receiving additional user feedback, single root cause (calendar.tsx)
- ADMIN_EMAILS is outside the scope of this code repo (aether-gitops + production cluster cert work) → delegated to user for direct handling
Impact Scope Decision
- Frontend single layer → suitable for single sprint (matches sprint scoping memory)
- No DB schema changes, no backend service changes
Changes
Wave A — Deadline Edit Entry Point (PR #185)
frontend/src/app/[locale]/problems/[id]/page.tsx:
- Added
Pencilicon import - Added Pencil button to isAdmin conditional area in header (placed to the left of Trash2)
- Click triggers
router.push('/problems/${problemId}/edit') - i18n: Added
detail.editProblemko/en
Existing /problems/[id]/edit/page.tsx is already a Sprint 139 output with ADMIN guard + Calendar deadline handling complete → 0 new pages written.
Wave B — Selected Date Text (3 Entry Points Unified)
AddProblemModal.tsxConfirmStep/problems/create/page.tsx/problems/[id]/edit/page.tsx
Each entry point adds DAY_KEYS = ['sun','mon','tue','wed','thu','fri','sat'] module constant + selectedDateText computed variable. Display "Month Day (Weekday)" text below calendar in primary color + font-medium. Displayed together with existing calculatedWeek text.
New i18n keys:
form.selectedDate: "{month}/{day} ({dayName})"addModal.confirm.selectedDate: Same pattern
Reuses detail.deadlineFormat + detail.dayNames (Sprint 139 output) pattern.
Wave C — calendar.tsx Highlight Enhancement (PR #185)
weekday:'h-8 text-[11px] font-normal text-text-3 flex items-center justify-center'→'h-8 text-[11px] font-normal text-text-3 text-center leading-8'- Reason: Applying
flex items-center justify-centerto a grid item when parent isgrid grid-cols-7can cause unintended alignment.text-center+leading-8achieves the same visual effect while the grid cell works correctly.
- Reason: Applying
day_button: Addeddata-[selected-single=true]:font-semibold→ visual emphasis of selected datetoday:'font-semibold text-primary'→'font-semibold text-primary underline underline-offset-4 decoration-primary/40'→ enhanced visual distinction of today's date
Follow-up — calendar.tsx Nav Button Position Regression (PR #186)
Additional user visual verification discovered after Wave C changes:
- "Month switch button position looks wrong"
- "Can't change month on edit page" (not clickable)
Root cause: Missing relative on calendar.tsx root className. react-day-picker v9's nav uses absolute positioning, and without relative on the root, position is calculated based on the nearest positioned ancestor. Depending on each entry point's parent container:
- AddProblemModal: nav position follows wrapping div positioning
- create/edit: nav pushed to page outer container, not clickable
Fix (calendar.tsx, +2 -2):
- root:
'p-3 mx-auto w-fit'→'relative p-3 mx-auto w-fit' - nav:
'inset-x-1 top-1'→'inset-x-3 top-3'(aligned with rootp-3padding) - nav: Added
pointer-events-none [&>button]:pointer-events-auto— prevents nav container floating above caption from blocking caption clicks
Verification
- jest 1348 tests passed (0 regressions)
- tsc clean / lint 0 new warnings
- CI 28 pass / 8 skipping / 0 fail / mergeStateStatus CLEAN
- Critic invoked ✅ (PR #185 base origin/main, Codex
gpt-5):- Command:
codex review --base origin/main - Session:
019dd7c6-ee11-7d43-87ab-68b8644b24bf - Result: "Changes internally consistent, edit entry button uses locale-aware router, i18n keys exist for both ko/en, selected date UI reuses existing deadline value, no additional regressions found"
- Overall verdict: ✅ Mergeable
- Command:
- Follow-up PR #186 — 4 character UI className change, 0 permission/input flow/time processing changes → Critic not invoked (same policy as Sprint 139 PR #183)
Branch Discipline ✅
feat/sprint-140-calendar-followup(PR #185)fix/sprint-140-calendar-nav-position(PR #186)- 0 direct commits to main (6 consecutive sprints compliant since Sprint 134 violation)
Findings / Separate Seeds
react-day-picker v9 wrapper authoring: relative is mandatory
v9's nav uses absolute positioning based on root. Without relative on the wrapper component's root, the nearest positioned ancestor is used as reference → position misalignment varies by entry point environment. Needs to be added to PR pre-flight checklist (Sprint 139 follow-up dependency major upgrade check + this item).
Production sealed-secret SSoT Conflict
- AlgoSu repo
infra/sealed-secrets/generated/sealed-gateway-secrets.yaml: ADMIN_EMAILS key missing (outdated) - aether-gitops repo
algosu/base/sealed-secrets/sealed-gateway-secrets.yaml: ADMIN_EMAILS sealed value present (actually reflected in production) - ArgoCD only watches the aether-gitops repo → sealed-secrets in the AlgoSu repo are historical artifacts
- Sprint 141 seed: Clean up sealed-secrets in AlgoSu repo (remove or automate sync) + write ADMIN_EMAILS update procedure runbook
Value of User Visual Verification Reconfirmed
- After Sprint 139 PR #181 merge, user verification → 3 Calendar v9 compat regressions found (PR #183)
- After Sprint 140 PR #185 merge, user verification → 2 nav position regressions found (PR #186)
- This sprint also revealed admin permission issue due to unaddressed production sealed-secret
- Lesson: UI/UX work requires visual verification as a core step before merge. Regressions that cannot be caught by automated verification (jest/tsc/lint) are found every time.
Critic Invocation Policy Application (Continued)
- Sprint 140 main PR (#185): Wave A permission entry point + routing → invoked → no regressions found, passed
- Sprint 140 follow-up (#186): 4 character UI className change → not invoked (policy compliance)
- Policy guide consistency maintained: invoke when "user input flow changes" / "time processing changes" / "new permission entry points"
Oracle Dispatch Infrastructure P1 Unresolved (Continued)
oracle-spawn.sh architect PATH issue discovered in Sprint 139 was not addressed in this sprint either. Proceeded with Oracle working directly. Carried over to Sprint 141.
Operational Work (Completed Directly by User)
User directly performed the following on the production cluster:
- Updated
ADMIN_EMAILSsealed value in aether-gitops repoalgosu/base/sealed-secrets/sealed-gateway-secrets.yaml - Generated sealed value including
[email protected]with production cluster cert - Confirmed
/admin/feedbacksaccess activated after ArgoCD sync + Gateway pod rolling restart
This work requires production cluster access + sealed-secrets-controller cert and cannot be performed in Oracle's local environment (local k3d) → delegated to user. Not having the AI collaboration environment (Claude Code) directly access production security zones is a security best practice.