- New useReportsPeriod hook reads/writes period via ?from=&to=&period= URL params, default civil year, pure resolver exported for tests - New per-domain hooks: useHighlights, useTrends, useCompare, useCategoryZoom (stubs wired to useReportsPeriod, to be fleshed out in #71-#74) - Rewire legacy useReports to consume useReportsPeriod; keep backward-compat state shape (period/customDateFrom/customDateTo) so /reports tabs keep working - Mark useReports @deprecated pending removal in #76 - Tests: 7 new cases covering resolveReportsPeriod defaults, bookmarks, invalid inputs, preset resolution Fixes #70 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
import { useReducer, useCallback } from "react";
|
|
import { useReportsPeriod } from "./useReportsPeriod";
|
|
|
|
interface State {
|
|
zoomedCategoryId: number | null;
|
|
rollupChildren: boolean;
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
type Action =
|
|
| { type: "SET_CATEGORY"; payload: number | null }
|
|
| { type: "TOGGLE_ROLLUP"; payload: boolean }
|
|
| { type: "SET_LOADING"; payload: boolean }
|
|
| { type: "SET_ERROR"; payload: string };
|
|
|
|
const initialState: State = {
|
|
zoomedCategoryId: null,
|
|
rollupChildren: true,
|
|
isLoading: false,
|
|
error: null,
|
|
};
|
|
|
|
function reducer(state: State, action: Action): State {
|
|
switch (action.type) {
|
|
case "SET_CATEGORY":
|
|
return { ...state, zoomedCategoryId: action.payload };
|
|
case "TOGGLE_ROLLUP":
|
|
return { ...state, rollupChildren: action.payload };
|
|
case "SET_LOADING":
|
|
return { ...state, isLoading: action.payload };
|
|
case "SET_ERROR":
|
|
return { ...state, error: action.payload, isLoading: false };
|
|
default:
|
|
return state;
|
|
}
|
|
}
|
|
|
|
export function useCategoryZoom() {
|
|
const { from, to } = useReportsPeriod();
|
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
|
|
const setCategory = useCallback((id: number | null) => {
|
|
dispatch({ type: "SET_CATEGORY", payload: id });
|
|
}, []);
|
|
|
|
const setRollupChildren = useCallback((flag: boolean) => {
|
|
dispatch({ type: "TOGGLE_ROLLUP", payload: flag });
|
|
}, []);
|
|
|
|
// Real fetch lives in Issue #74 (getCategoryZoom with recursive CTE).
|
|
return { ...state, setCategory, setRollupChildren, from, to };
|
|
}
|