2026-07-05 15:54:19 -05:00
|
|
|
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]);
|
|
|
|
|
|
2026-07-06 14:23:53 -05:00
|
|
|
return (
|
|
|
|
|
<div key={version} className="contents">
|
|
|
|
|
{children}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-07-05 15:54:19 -05:00
|
|
|
}
|