Overview
The application needs a global auth state store to share the current user and access token across components without prop drilling. Zustand is already installed. Without this store, there is no centralized place for the API interceptor (FE-01) to read the token from, and every protected component must independently check auth state.
Background
File to create: frontend/lib/store/auth.store.ts
Store shape:
interface AuthState {
user: UserDto | null;
accessToken: string | null;
isAuthenticated: boolean;
login: (user: UserDto, accessToken: string) => void;
logout: () => void;
setToken: (token: string) => void;
}
Use Zustand's persist middleware to hydrate from localStorage on page refresh. Persist the user object and token. The API interceptor (FE-01) should read useAuthStore.getState().accessToken to avoid hook-call-outside-component errors.
Also create a useCurrentUser() helper hook that fetches the authenticated user from GET /api/users/me on mount and updates the store.
Acceptance Criteria
Overview
The application needs a global auth state store to share the current user and access token across components without prop drilling. Zustand is already installed. Without this store, there is no centralized place for the API interceptor (FE-01) to read the token from, and every protected component must independently check auth state.
Background
File to create:
frontend/lib/store/auth.store.tsStore shape:
Use Zustand's
persistmiddleware to hydrate fromlocalStorageon page refresh. Persist the user object and token. The API interceptor (FE-01) should readuseAuthStore.getState().accessTokento avoid hook-call-outside-component errors.Also create a
useCurrentUser()helper hook that fetches the authenticated user fromGET /api/users/meon mount and updates the store.Acceptance Criteria
localStorageviapersistmiddlewarelogout()clears state and removes from localStorageuseCurrentUser()hook calls/api/users/meand populates the store on mountUserDtomatch the backend response