2import { createContext, useContext, useState, useEffect, ReactNode } from "react";
3import { apiClient } from "@/lib/client/apiClient";
4import { defaultConfig } from "@/lib/config";
9 role: 'staff' | 'employee' | 'admin';
12export interface Store {
16 type?: 'management' | 'store';
19export interface Session {
22 authenticated: boolean;
25interface StoreContextType {
26 // Legacy store name support
28 setStoreName: (name: string) => void;
29 refreshStoreName: () => Promise<void>;
31 // New session support
32 session: Session | null;
33 isAuthenticated: boolean;
36 checkSession: () => Promise<void>;
37 logout: () => Promise<void>;
40const StoreContext = createContext<StoreContextType | undefined>(undefined);
42export function StoreProvider({ children }: { children: ReactNode }) {
43 // Always start with server-safe default to prevent hydration mismatch
44 const [storeName, setStoreName] = useState(() => {
45 // Fallback order: Config UI name, then app name, then default
46 return defaultConfig.values?.UserInterfaceFriendlyName ||
47 process.env.NEXT_PUBLIC_APP_NAME ||
51 const [session, setSession] = useState<Session | null>(null);
52 const [isLoading, setIsLoading] = useState(true);
53 const [error, setError] = useState<string | null>(null);
55 // Load from sessionStorage after hydration to avoid mismatch
57 if (typeof window !== 'undefined') {
58 const cached = sessionStorage.getItem('store_name');
65 // Check for existing session on mount
70 async function checkSession() {
73 const response = await fetch('/api/auth/session');
75 const data = await response.json();
76 if (data.isAuthenticated && data.session) {
77 setSession(data.session);
79 // Update store name if available
80 if (data.session.store?.name) {
81 setStoreName(data.session.store.name);
82 if (typeof window !== 'undefined') {
83 sessionStorage.setItem('store_name', data.session.store.name);
93 console.error('Session check failed:', err);
100 async function logout() {
102 await fetch('/api/auth/logout', { method: 'POST' });
104 if (typeof window !== 'undefined') {
105 window.location.href = '/login';
108 console.error('Logout failed:', err);
113 // Legacy: Fetch store name from locations API if not authenticated
114 if (session || typeof window === 'undefined') return;
116 const cached = sessionStorage.getItem('store_name');
119 const fetchStoreName = async () => {
121 const result = await apiClient.getLocations();
122 if (result.success) {
123 const apiData: any = result.data || result;
124 const locationData = (!Array.isArray(apiData) && apiData?.DATS) || (!Array.isArray(apiData) && apiData?.data?.Location) || (Array.isArray(apiData) ? apiData : null);
125 const locations = Array.isArray(locationData) ? locationData : [];
127 if (locations.length > 0) {
128 const firstLocation = locations[0];
129 const locationName = firstLocation.f500 || firstLocation.Name;
131 setStoreName(locationName);
132 sessionStorage.setItem('store_name', locationName);
137 console.warn('Failed to fetch store name from API:', error);
144 const updateStoreName = (name: string) => {
146 if (typeof window !== 'undefined') {
147 sessionStorage.setItem('store_name', name);
151 const refreshStoreName = async () => {
153 const result = await apiClient.getLocations();
154 if (result.success) {
155 const apiData: any = result.data || result;
156 const locationData = (!Array.isArray(apiData) && apiData?.DATS) || (!Array.isArray(apiData) && apiData?.data?.Location) || (Array.isArray(apiData) ? apiData : null);
157 const locations = Array.isArray(locationData) ? locationData : [];
159 if (locations.length > 0) {
160 const firstLocation = locations[0];
161 const locationName = firstLocation.f500 || firstLocation.Name;
163 updateStoreName(locationName);
168 console.warn('Failed to refresh store name from API:', error);
173 <StoreContext.Provider value={{
175 setStoreName: updateStoreName,
178 isAuthenticated: session !== null && session.authenticated,
185 </StoreContext.Provider>
189export function useStore() {
190 const context = useContext(StoreContext);
191 if (context === undefined) {
192 throw new Error("useStore must be used within a StoreProvider");