store user login

This commit is contained in:
2026-08-25 18:00:16 +05:30
parent 1dc582ba07
commit 517a99d577
62 changed files with 8059 additions and 650 deletions

View File

@@ -26,6 +26,8 @@ export interface BranchScopeValue {
scoped: TenantLocation[];
/** The selected branch, or undefined under All. */
current: TenantLocation | undefined;
/** True in the Store user workspace: one branch, fixed, `select` inert. */
isPinned: boolean;
}
const BranchScopeContext = createContext<BranchScopeValue | null>(null);
@@ -46,26 +48,50 @@ const PARAM = 'branch';
* alone — putting the tenant id in an editable address bar would turn the one
* boundary we control into a text field.
*/
export function BranchScopeProvider({ children }: { children: ReactNode }) {
export function BranchScopeProvider({
children,
pin,
}: {
children: ReactNode;
/**
* Fix the scope to one branch — the Store user workspace.
*
* When set, `selected` is always this id, `branches` and `scoped` hold only
* that outlet, and `select` does nothing. The URL param is ignored rather
* than merely defaulted: Fiesta authorises a POS or catalogue read on
* `locationid` alone, so an address bar that can change it is not a filter,
* it is the authorisation boundary in a text field.
*/
pin?: number;
}) {
const { user } = useAuth();
const [params, setParams] = useSearchParams();
const tenantid = user?.tenantid ?? 0;
const { data, isLoading } = useTenantLocations(tenantid || undefined);
const branches = useMemo(
const all = useMemo(
() => [...(data ?? [])].sort((a, b) => a.locationid - b.locationid),
[data],
);
// Pinned: the one outlet, and nothing else is ever in the list. Unpinned: all
// of them, with All-branches available.
const branches = useMemo(
() => (pin === undefined ? all : all.filter((branch) => branch.locationid === pin)),
[all, pin],
);
const raw = params.get(PARAM);
const parsed = raw === null || raw === 'all' ? null : Number(raw);
// An id in the URL that this tenant does not own falls back to All rather
// than showing an empty page — the id is user-editable, so it is untrusted.
const selected =
parsed !== null && Number.isFinite(parsed) && branches.some((b) => b.locationid === parsed)
? parsed
: null;
pin !== undefined
? pin
: parsed !== null && Number.isFinite(parsed) && branches.some((b) => b.locationid === parsed)
? parsed
: null;
const value = useMemo<BranchScopeValue>(() => {
const current = selected === null ? undefined : branches.find((b) => b.locationid === selected);
@@ -75,15 +101,17 @@ export function BranchScopeProvider({ children }: { children: ReactNode }) {
tenantid,
selected,
current,
isPinned: pin !== undefined,
scoped: current ? [current] : branches,
select: (next) => {
if (pin !== undefined) return;
const nextParams = new URLSearchParams(params);
if (next === null) nextParams.delete(PARAM);
else nextParams.set(PARAM, String(next));
setParams(nextParams, { replace: true });
},
};
}, [branches, isLoading, tenantid, selected, params, setParams]);
}, [branches, isLoading, tenantid, selected, params, setParams, pin]);
return <BranchScopeContext.Provider value={value}>{children}</BranchScopeContext.Provider>;
}