fix(admin): SQL GROUP BY in reports, hydration in settings, mobile tabs scroll
- reports.ts: wrap window-function arg in SUM() so it operates on the per-group aggregate instead of the raw c.id column (PostgreSQL rejects window funcs over non-grouped, non-aggregated columns). - SettingsClient.tsx: read URL hash in useEffect instead of a lazy useState initializer to avoid server/client first-render mismatch on tab content (was triggering full client re-render in /admin/settings). - layout.tsx: add pt-16 lg:pt-0 to page-content for mobile header clearance. - ReportsDashboard.tsx: memoize DateRange on primitive inputs to break useEffect → setState → re-render loop caused by buildRange returning a new object every call. - AdminFilterTabs.tsx: add overflow-x-auto so wide tab rows scroll on mobile instead of overflowing. - use-media-query.ts: always start as false for hydration safety; callers handle the mobile/unknown branch first.
This commit is contained in:
@@ -135,14 +135,17 @@ export default function SettingsClient({
|
||||
paymentSettings,
|
||||
currentUser,
|
||||
}: Props) {
|
||||
// Initial tab is determined by URL hash if present, otherwise "general".
|
||||
// No useEffect needed — we read window.location.hash during the lazy
|
||||
// initializer on the client. On the server we default to "general".
|
||||
const [activeTab, setActiveTab] = useState<Tab>(() => {
|
||||
if (typeof window === "undefined") return "general";
|
||||
// Server renders the default tab; client picks up the URL hash after mount
|
||||
// so the initial server HTML matches the first client render (avoids
|
||||
// hydration mismatch). Reading window.location.hash in a lazy initializer
|
||||
// is unsafe because the server has no hash and would render a different
|
||||
// tab than the client.
|
||||
const [activeTab, setActiveTab] = useState<Tab>("general");
|
||||
useEffect(() => {
|
||||
const hash = window.location.hash.slice(1);
|
||||
return TABS.find((t) => t.hash === hash)?.id ?? "general";
|
||||
});
|
||||
const tab = TABS.find((t) => t.hash === hash)?.id;
|
||||
if (tab) setActiveTab(tab);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-[var(--admin-bg)]">
|
||||
|
||||
Reference in New Issue
Block a user