ui and bug fixers 29/09
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
// client-only `roleId` cached by lib/auth-session.ts for anything access-related
|
||||
// (that cache remains display-only, e.g. for the header's user name).
|
||||
import { createContext, useContext, useEffect, useState } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
import { authApi } from "@/lib/api/auth"
|
||||
import { MeResponse } from "@/types/rbac"
|
||||
@@ -32,6 +33,10 @@ function readStoredActiveBranch(): ActiveBranch | null {
|
||||
}
|
||||
|
||||
interface AuthContextValue {
|
||||
/** Re-fetches `/auth/me` — call after changing settings it reflects (e.g. Branch Configuration). */
|
||||
refresh: () => void
|
||||
/** The caller's local user id — compare against a document's `createdBy`. */
|
||||
userId: number | null
|
||||
roleCode: string | null
|
||||
roleName: string | null
|
||||
navCodes: string[]
|
||||
@@ -62,11 +67,19 @@ interface AuthContextValue {
|
||||
* everything else. Always false when `branchingEnabled` itself is false.
|
||||
*/
|
||||
warehouseBranchingEnabled: boolean
|
||||
/**
|
||||
* Independent sub-toggle for Purchase Orders (Settings → Branch Configuration). False means
|
||||
* POs are one shared pool: no branch picker/column on PO screens. Always false when
|
||||
* `branchingEnabled` is false.
|
||||
*/
|
||||
purchaseOrderBranchingEnabled: boolean
|
||||
/** True until the first `/auth/me` response lands. */
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextValue>({
|
||||
refresh: () => {},
|
||||
userId: null,
|
||||
roleCode: null,
|
||||
roleName: null,
|
||||
navCodes: [],
|
||||
@@ -78,12 +91,17 @@ const AuthContext = createContext<AuthContextValue>({
|
||||
setActiveBranch: () => {},
|
||||
branchingEnabled: true,
|
||||
warehouseBranchingEnabled: true,
|
||||
purchaseOrderBranchingEnabled: true,
|
||||
loading: true,
|
||||
})
|
||||
|
||||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
const [me, setMe] = useState<MeResponse | null>(null)
|
||||
const [activeBranch, setActiveBranchState] = useState<ActiveBranch | null>(null)
|
||||
// Bumped by refresh() to re-fetch /auth/me — e.g. right after Branch Configuration changes,
|
||||
// so the header and every branch-aware screen update without a full page reload.
|
||||
const [reloadKey, setReloadKey] = useState(0)
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
@@ -95,12 +113,17 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
.catch(() => {
|
||||
// Unauthenticated/unreachable — fall back to "no permissions" rather than
|
||||
// crash the shell; proxy.ts already redirects unauthenticated users to /login.
|
||||
if (!cancelled) setMe({ roleCode: null, roleName: null, navCodes: [], isAdmin: false, branchId: null, branchName: null, branchingEnabled: true, warehouseBranchingEnabled: true })
|
||||
if (!cancelled) setMe({ roleCode: null, roleName: null, navCodes: [], isAdmin: false, branchId: null, branchName: null, branchingEnabled: true, warehouseBranchingEnabled: true, mustChangePassword: false, purchaseOrderBranchingEnabled: true, userId: null })
|
||||
})
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
}, [reloadKey])
|
||||
|
||||
useEffect(() => {
|
||||
// Admin-created accounts must replace their issued password before using the app.
|
||||
if (me?.mustChangePassword) router.replace("/change-password")
|
||||
}, [me, router])
|
||||
|
||||
useEffect(() => {
|
||||
if (me === null) return
|
||||
@@ -115,21 +138,29 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
if (typeof window !== "undefined") window.localStorage.setItem(ACTIVE_BRANCH_KEY, JSON.stringify(next))
|
||||
}
|
||||
|
||||
// With branching switched off there is no "current branch" at all — ignore any stale
|
||||
// header pick (or own-branch pin) so no screen keeps silently filtering by it.
|
||||
const branchingEnabled = me?.branchingEnabled ?? true
|
||||
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
refresh: () => setReloadKey((k) => k + 1),
|
||||
userId: me?.userId ?? null,
|
||||
roleCode: me?.roleCode ?? null,
|
||||
roleName: me?.roleName ?? null,
|
||||
navCodes: me?.navCodes ?? [],
|
||||
isAdmin: me?.isAdmin ?? false,
|
||||
branchId: me?.branchId ?? null,
|
||||
branchName: me?.branchName ?? null,
|
||||
activeBranchId: activeBranch?.id ?? null,
|
||||
activeBranchName: activeBranch?.name ?? null,
|
||||
activeBranchId: branchingEnabled ? (activeBranch?.id ?? null) : null,
|
||||
activeBranchName: branchingEnabled ? (activeBranch?.name ?? null) : null,
|
||||
setActiveBranch,
|
||||
branchingEnabled: me?.branchingEnabled ?? true,
|
||||
branchingEnabled,
|
||||
warehouseBranchingEnabled: me?.warehouseBranchingEnabled ?? true,
|
||||
loading: me === null,
|
||||
purchaseOrderBranchingEnabled: me?.purchaseOrderBranchingEnabled ?? true,
|
||||
// Stays "loading" while a forced password change redirects away, so the shell never flashes.
|
||||
loading: me === null || me.mustChangePassword,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user