[#824] Fix Writer tab badge to use time-based deadline expiry#834
[#824] Fix Writer tab badge to use time-based deadline expiry#834realproject7 merged 5 commits intomainfrom
Conversation
… sunset Badge showed "active" on expired storylines because it only checked the sunset flag. Now uses DEADLINE_MS (168h) time-based check matching DeadlineCountdown logic: expired when has_deadline && last_plot_time + 168h < now, complete when sunset, otherwise active. Fixes #824 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
project7-interns
left a comment
There was a problem hiding this comment.
LGTM. Badge priority order is correct: sunset→complete, then time-based deadline check→expired, else→active. Reuses the shared DEADLINE_MS constant from DeadlineCountdown.tsx (168h) and matches the same pattern already used in create/page.tsx. The has_deadline guard correctly keeps non-deadline storylines as 'active'.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
The Writer tab badge now uses the intended time-based deadline expiry check instead of relying only on sunset, which resolves the contradictory expired-vs-active display from issue #824.
Findings
- None. The change is narrowly scoped to
src/app/profile/[address]/page.tsx, reusesDEADLINE_MSfromDeadlineCountdown.tsx, and preserves the existingsunset->completepath.
Decision
Approving because the PR matches the acceptance criteria: deadline-based stories can now show expired, sunset still maps to complete, and non-deadline stories remain active.
Compute isExpired flag before return to avoid calling Date.now() during render. Same logic, just hoisted to a variable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Re-approved after 6df20e7. Date.now() correctly hoisted to isExpired variable before return, resolving the react-hooks/purity lint. Logic unchanged — same priority order and guards.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The follow-up commit does not actually resolve the lint blocker on PR #834. Date.now() was moved out of JSX, but it is still being called during StoryRow render.
Findings
- [medium]
isExpiredstill callsDate.now()inside the component body, which is still render-time impurity and still failsreact-hooks/purity. The current GitHub Actions run already showslint-and-typecheckfailing on this change.- File:
src/app/profile/[address]/page.tsx:871 - Suggestion: Avoid calling
Date.now()during render at all. Derive the reference time outside render (for example via state/effect or another existing time source) and then compare that value againstlast_plot_time + DEADLINE_MS.
- File:
Decision
Requesting changes because the PR remains unmergeable: the intended badge logic is fine, but the latest implementation still violates the purity lint rule.
Date.now() in component body is still render-time impurity. Use useState(() => Date.now()) to capture timestamp once on mount, making the component pure for React Compiler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The new useState(() => Date.now()) fix avoids render-time impurity, but it freezes the reference time at mount and makes the Writer-tab badge drift out of sync with the live deadline countdown.
Findings
- [medium]
nowis captured once withuseState(() => Date.now())and never updates, so a storyline that is still active when the page mounts will keep its greenactivebadge even after the deadline passes. At that pointDeadlineCountdownwill flip toexpiredwhile the badge staysactive, recreating the contradictory state this issue is supposed to fix.- File:
src/app/profile/[address]/page.tsx:871 - Suggestion: Use a time source that updates after mount instead of a frozen timestamp, so the badge can transition from
activetoexpiredwhile the page is open without violating the purity lint rule.
- File:
Decision
Requesting changes because the current implementation fixes the lint symptom but reintroduces the underlying expired-vs-active mismatch once the deadline passes during an open session.
Replace frozen useState with useCallback+useEffect+setInterval pattern (same as DeadlineCountdown) so badge updates when deadline passes. Ticks every 60s. Lint-disable matches existing codebase pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Re-approved after 02a8f93. Live-updating useCallback + useState + useEffect/setInterval (60s) pattern matches DeadlineCountdown.tsx. Badge will correctly transition from active→expired in real time. The eslint-disable for the initial-sync setIsExpired follows the existing codebase convention.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The new interval-based fix removes the frozen timestamp problem, but it still leaves a visible contradiction window because the badge updates much less frequently than DeadlineCountdown.
Findings
- [medium] The Writer-tab badge only recomputes expiry once every
60_000ms, whileDeadlineCountdownupdates every second. For up to 59 seconds after the deadline passes, the row can still showDeadline: expired · active, which is the exact contradiction issue #824 is meant to eliminate.- File:
src/app/profile/[address]/page.tsx:880 - Suggestion: Keep the badge on the same cadence as
DeadlineCountdownor derive both from a shared time source so they flip toexpiredtogether.
- File:
Decision
Requesting changes because the current implementation fixes the stale mount-time timestamp but still allows the expired-vs-active mismatch during an open session.
60s interval left a contradiction window where DeadlineCountdown showed expired but badge still showed active. Now both tick every 1s. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Re-approved after 5d06c59. Interval now 1s matching DeadlineCountdown cadence — badge and countdown flip together with no contradiction window.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
The latest commit aligns the Writer-tab badge update cadence with DeadlineCountdown, so the badge can transition from active to expired in sync without reintroducing the render-purity lint failure.
Findings
- None. The
useCallback+useState+useEffectinterval approach now ticks every1_000ms, matchingDeadlineCountdownand removing the contradiction window from the prior version.
Decision
Approving because the PR now meets the acceptance criteria: expired deadlines show expired, sunset still maps to complete, non-deadline stories stay active, and the badge/countdown stay in sync during an open session.
Summary
has_deadline && last_plot_time + 168h < nowinstead of onlysunsetDEADLINE_MSfromDeadlineCountdown.tsxfor consistent deadline logicTest plan
sunset=trueshows "complete" badgehas_deadlineshows "active" badgeFixes #824
🤖 Generated with Claude Code