Add DOW-aligned LY toggle to directors forecast worksheet and report

Checkbox in the header switches between 364-day same-weekday comparison
and same calendar-date last year. Default remains DOW-aligned.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-21 18:29:02 +00:00
parent 2e8a908f05
commit 9530125509
4 changed files with 33 additions and 20 deletions

View file

@ -42,7 +42,7 @@ type DayOverride = {
// ── Worksheet tab ─────────────────────────────────────────────────────────────
function WorksheetTab({ year, month }: { year: number; month: number }) {
function WorksheetTab({ year, month, dowAlign }: { year: number; month: number; dowAlign: boolean }) {
const { user } = useAuth()
const canEdit = can(user, 'edit')
@ -57,7 +57,7 @@ function WorksheetTab({ year, month }: { year: number; month: number }) {
const load = useCallback(async () => {
setLoading(true); setError(null)
try {
const d: WorksheetData = await dfGetWorksheet(year, month)
const d: WorksheetData = await dfGetWorksheet(year, month, dowAlign)
setData(d)
setRate(String(d.session.pickup_avg_rate ?? 135))
const ovrs: Record<string, DayOverride> = {}
@ -73,7 +73,7 @@ function WorksheetTab({ year, month }: { year: number; month: number }) {
setDirty(false)
} catch { setError('Failed to load worksheet data.') }
finally { setLoading(false) }
}, [year, month])
}, [year, month, dowAlign])
useEffect(() => { load() }, [load])
@ -287,7 +287,7 @@ function VarCell({ a, b }: { a: number; b: number }) {
return <td className={v >= 0 ? 'df-pos' : 'df-neg'}>{v >= 0 ? '+' : ''}{fmtCcy(v)}</td>
}
function ReportTab({ year, month }: { year: number; month: number }) {
function ReportTab({ year, month, dowAlign }: { year: number; month: number; dowAlign: boolean }) {
const { user } = useAuth()
const canEdit = can(user, 'edit')
@ -299,10 +299,10 @@ function ReportTab({ year, month }: { year: number; month: number }) {
const load = useCallback(async () => {
setLoading(true); setError(null)
try { setData(await dfGetReport(year, month)) }
try { setData(await dfGetReport(year, month, dowAlign)) }
catch { setError('Failed to load report data.') }
finally { setLoading(false) }
}, [year, month])
}, [year, month, dowAlign])
useEffect(() => { load() }, [load])
@ -494,14 +494,19 @@ type Tab = 'worksheet' | 'report'
export default function DirectorsForecast() {
useFrameViewport('desktop')
const now = new Date()
const [year, setYear] = useState(now.getFullYear())
const [month, setMonth] = useState(now.getMonth() + 1)
const [tab, setTab] = useState<Tab>('worksheet')
const [year, setYear] = useState(now.getFullYear())
const [month, setMonth] = useState(now.getMonth() + 1)
const [tab, setTab] = useState<Tab>('worksheet')
const [dowAlign, setDowAlign] = useState(true)
return (
<div className="df-root">
<div className="df-header">
<MonthNav year={year} month={month} onChange={(y, m) => { setYear(y); setMonth(m) }} />
<label className="df-dow-toggle">
<input type="checkbox" checked={dowAlign} onChange={e => setDowAlign(e.target.checked)} />
DOW-aligned LY
</label>
<div className="df-tabs">
<button className={`df-tab${tab === 'worksheet' ? ' active' : ''}`} onClick={() => setTab('worksheet')}>
Worksheet
@ -513,8 +518,8 @@ export default function DirectorsForecast() {
</div>
{tab === 'worksheet'
? <WorksheetTab key={`ws-${year}-${month}`} year={year} month={month} />
: <ReportTab key={`rp-${year}-${month}`} year={year} month={month} />}
? <WorksheetTab key={`ws-${year}-${month}-${dowAlign}`} year={year} month={month} dowAlign={dowAlign} />
: <ReportTab key={`rp-${year}-${month}-${dowAlign}`} year={year} month={month} dowAlign={dowAlign} />}
</div>
)
}