CampgroundTickets/app/lib/auth.tsx
Hank 1ca2c38fbf
Some checks failed
Build Android APK / build-apk (push) Failing after 57m31s
Fix login hang after PIN + enrich Banquet mode
- Auth: introduce a shared AuthProvider/useAuth so entering the PIN updates
  reactive state and the layout's gate navigates immediately (previously it
  cached the token check at startup, so login appeared to hang until a manual
  refresh). login/scanner now use signIn/signOut.
- Banquet: donor lookup now returns lifetime giving, last-12-months giving
  (computed from dated transactions), member/donor status, bear name, and tags.
  The banquet result screen shows status badge + lifetime and last-year figures.
  Tickets are irrelevant in banquet mode.
- Admin: fix "‹ Scanner" back link wrapping (remove fixed width).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 16:01:41 +00:00

43 lines
1.2 KiB
TypeScript

import { createContext, useContext, useEffect, useState, type ReactNode } from "react";
import { login as apiLogin, logout as apiLogout, getToken, onAuthCleared } from "./api";
interface AuthState {
ready: boolean; // finished the initial token load
signedIn: boolean;
signIn: (pin: string) => Promise<void>;
signOut: () => Promise<void>;
}
const Ctx = createContext<AuthState | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [ready, setReady] = useState(false);
const [signedIn, setSignedIn] = useState(false);
useEffect(() => {
getToken().then((t) => {
setSignedIn(!!t);
setReady(true);
});
// Keep state in sync when the token is cleared elsewhere (401 handling).
onAuthCleared(() => setSignedIn(false));
return () => onAuthCleared(null);
}, []);
const signIn = async (pin: string) => {
await apiLogin(pin);
setSignedIn(true);
};
const signOut = async () => {
await apiLogout();
setSignedIn(false);
};
return <Ctx.Provider value={{ ready, signedIn, signIn, signOut }}>{children}</Ctx.Provider>;
}
export function useAuth(): AuthState {
const c = useContext(Ctx);
if (!c) throw new Error("useAuth must be used within AuthProvider");
return c;
}