BillTracker/client/components/FormatSync.tsx

38 lines
1.5 KiB
TypeScript

import { useLayoutEffect, useState, type ReactNode } from 'react';
import { useSettings } from '@/hooks/useQueries';
import { setMoneyFormat, getActiveCurrency } from '@/lib/money';
import { setDateFormat, getActiveDateFormat } from '@/lib/utils';
/**
* Reconciles the server's currency / date_format preferences into the
* module-level formatters (money.ts / utils.ts). Those are read synchronously
* from localStorage at load, so same-device use is already correct with no
* flash; this only does work when the server value differs from what's cached —
* i.e. a first login on a new device, or a change made on another device. In
* that case it bumps a `key` so the routed subtree re-renders once with the
* right formatting (cheap; these settings change rarely). Normal on-device
* changes write through immediately, so this never forces a disruptive remount
* mid-session.
*/
export function FormatSync({ children }: { children: ReactNode }) {
const { data } = useSettings();
const [version, setVersion] = useState(0);
useLayoutEffect(() => {
if (!data) return;
const s = data as Record<string, unknown>;
let changed = false;
if (typeof s.currency === 'string' && s.currency !== getActiveCurrency()) {
setMoneyFormat(s.currency);
changed = true;
}
if (typeof s.date_format === 'string' && s.date_format !== getActiveDateFormat()) {
setDateFormat(s.date_format);
changed = true;
}
if (changed) setVersion((v) => v + 1);
}, [data]);
return <div key={version} className="contents">{children}</div>;
}