1+ /**
2+ * React Query hooks for authentication state management.
3+ *
4+ * **Architecture:**
5+ * Wraps auth API functions with React Query for:
6+ * - Caching (reduce redundant API calls)
7+ * - Loading states (isLoading, isPending)
8+ * - Error handling (error object)
9+ * - Optimistic updates (immediate UI feedback)
10+ * - Query invalidation (refresh data after mutations)
11+ *
12+ * **Authentication Flow:**
13+ * 1. useRegister/useLogin: Mutate to create session
14+ * 2. onSuccess: Invalidate ['me'] query to trigger refetch
15+ * 3. useMe: Query fetches current user data
16+ * 4. useLogout: Mutate to clear session, clear ['me'] cache
17+ *
18+ * **Cache Keys:**
19+ * - ['me']: Current user data (5-minute stale time)
20+ *
21+ * **Usage Pattern:**
22+ * ```typescript
23+ * const { mutate: login, isPending } = useLogin();
24+ * const { data: user, isLoading } = useMe();
25+ * const { mutate: logout } = useLogout();
26+ *
27+ * // Login
28+ * login({ email, password }, {
29+ * onSuccess: () => navigate('/dashboard'),
30+ * onError: (error) => showToast(error.message),
31+ * });
32+ *
33+ * // Check auth
34+ * if (user) {
35+ * // User logged in
36+ * }
37+ *
38+ * // Logout
39+ * logout();
40+ * ```
41+ */
142'use client' ;
243
344import { useMutation , useQuery , useQueryClient } from '@tanstack/react-query' ;
445import { login , register , logout , fetchMe } from '@/lib/api/auth' ;
546import type { LoginPayload , RegisterPayload } from '@/lib/api/types' ;
647
48+ /**
49+ * Login mutation hook.
50+ *
51+ * **Mutation:**
52+ * Calls POST /api/auth/login with credentials.
53+ * Sets HttpOnly session cookie on success.
54+ *
55+ * **Side Effects:**
56+ * - onSuccess: Invalidates ['me'] query to refetch user data
57+ * - Cookie automatically sent on future requests
58+ *
59+ * **Usage:**
60+ * ```typescript
61+ * const { mutate: login, isPending, error } = useLogin();
62+ *
63+ * login({ email: 'user@example .com', password: 'secret' }, {
64+ * onSuccess: () => {
65+ * showToast('Login successful');
66+ * navigate('/dashboard');
67+ * },
68+ * onError: (error) => {
69+ * showToast(error.message);
70+ * },
71+ * });
72+ * ```
73+ *
74+ * **Return Values:**
75+ * - mutate: Function to trigger login
76+ * - isPending: True while request in flight
77+ * - error: Error object if request fails
78+ * - data: Response data if successful
79+ *
80+ * @returns React Query mutation result
81+ */
782export function useLogin ( ) {
883 const queryClient = useQueryClient ( ) ;
984
@@ -16,6 +91,50 @@ export function useLogin() {
1691 } ) ;
1792}
1893
94+ /**
95+ * Registration mutation hook.
96+ *
97+ * **Mutation:**
98+ * Calls POST /api/auth/register with user data.
99+ * Creates account and sets HttpOnly session cookie.
100+ *
101+ * **Side Effects:**
102+ * - onSuccess: Invalidates ['me'] query to refetch user data
103+ * - User immediately authenticated after registration
104+ *
105+ * **Validation:**
106+ * - email: Must be valid and unique
107+ * - password: Minimum 8 characters
108+ * - firstName, lastName: Required
109+ *
110+ * **Usage:**
111+ * ```typescript
112+ * const { mutate: register, isPending, error } = useRegister();
113+ *
114+ * register({
115+ * email: 'user@example .com',
116+ * password: 'SecurePass123',
117+ * firstName: 'John',
118+ * lastName: 'Doe',
119+ * }, {
120+ * onSuccess: () => {
121+ * showToast('Account created!');
122+ * navigate('/dashboard');
123+ * },
124+ * onError: (error) => {
125+ * showToast(error.message); // e.g., "Email already registered"
126+ * },
127+ * });
128+ * ```
129+ *
130+ * **Return Values:**
131+ * - mutate: Function to trigger registration
132+ * - isPending: True while request in flight
133+ * - error: Error object if request fails
134+ * - data: Response data if successful
135+ *
136+ * @returns React Query mutation result
137+ */
19138export function useRegister ( ) {
20139 const queryClient = useQueryClient ( ) ;
21140
@@ -28,6 +147,40 @@ export function useRegister() {
28147 } ) ;
29148}
30149
150+ /**
151+ * Logout mutation hook.
152+ *
153+ * **Mutation:**
154+ * Calls POST /api/auth/logout to clear session.
155+ * Clears HttpOnly cookie on server.
156+ *
157+ * **Side Effects:**
158+ * - onSuccess: Sets ['me'] query data to null (immediate UI update)
159+ * - onSuccess: Invalidates ['me'] query (trigger refetch if component still mounted)
160+ *
161+ * **Security Note:**
162+ * JWT token remains valid until expiration (stateless).
163+ * Attacker with stolen token can still use it.
164+ * Logout only clears cookie and client cache.
165+ *
166+ * **Usage:**
167+ * ```typescript
168+ * const { mutate: logout, isPending } = useLogout();
169+ *
170+ * logout(undefined, {
171+ * onSuccess: () => {
172+ * showToast('Logged out');
173+ * navigate('/login');
174+ * },
175+ * });
176+ * ```
177+ *
178+ * **Return Values:**
179+ * - mutate: Function to trigger logout
180+ * - isPending: True while request in flight
181+ *
182+ * @returns React Query mutation result
183+ */
31184export function useLogout ( ) {
32185 const queryClient = useQueryClient ( ) ;
33186
@@ -41,6 +194,49 @@ export function useLogout() {
41194 } ) ;
42195}
43196
197+ /**
198+ * Current user query hook.
199+ *
200+ * **Query:**
201+ * Fetches GET /api/auth/me to get authenticated user.
202+ * Requires valid session cookie.
203+ *
204+ * **Caching:**
205+ * - staleTime: 5 minutes (avoid refetch on every navigation)
206+ * - retry: false (don't retry on 401, user just not logged in)
207+ *
208+ * **Usage:**
209+ * ```typescript
210+ * const { data, isLoading, error } = useMe();
211+ *
212+ * if (isLoading) return <Spinner />;
213+ * if (error) return <LoginPrompt />;
214+ * if (data?.user) {
215+ * return <Dashboard user={data.user} />;
216+ * }
217+ * ```
218+ *
219+ * **Conditional Fetching:**
220+ * ```typescript
221+ * // Only fetch if needed
222+ * const { data } = useMe(false); // Don't fetch
223+ * const { data } = useMe(shouldFetch); // Conditional
224+ * ```
225+ *
226+ * **Return Values:**
227+ * - data: { user: User } or undefined
228+ * - isLoading: True on initial fetch
229+ * - error: Error object if request fails (e.g., 401)
230+ *
231+ * **Authentication Check:**
232+ * ```typescript
233+ * const { data: currentUser } = useMe();
234+ * const isAuthenticated = Boolean(currentUser?.user);
235+ * ```
236+ *
237+ * @param enabled - Whether to fetch (default: true)
238+ * @returns React Query query result
239+ */
44240export function useMe ( enabled = true ) {
45241 return useQuery ( {
46242 queryKey : [ 'me' ] ,
0 commit comments