42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { useSession } from 'next-auth/react';
|
||
|
|
import useSWR from 'swr';
|
||
|
|
import { apiClient } from '@/services/api-client';
|
||
|
|
import type { UserResponse } from '@meshitrack/shared';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Provides authentication state and user profile (including householdIds).
|
||
|
|
*
|
||
|
|
* The access token comes from the NextAuth session (Keycloak JWT).
|
||
|
|
* Household membership is fetched from the API (`GET /users/me`) via SWR
|
||
|
|
* so it is always fresh -- no stale JWT claims.
|
||
|
|
*/
|
||
|
|
export function useApi() {
|
||
|
|
const { data: session, status } = useSession();
|
||
|
|
|
||
|
|
// Set API client token synchronously so SWR fetches have credentials.
|
||
|
|
if (session?.accessToken) {
|
||
|
|
apiClient.accessToken = session.accessToken;
|
||
|
|
}
|
||
|
|
|
||
|
|
const shouldFetch = status === 'authenticated' && apiClient.hasToken;
|
||
|
|
|
||
|
|
const {
|
||
|
|
data: profile,
|
||
|
|
mutate: refreshProfile,
|
||
|
|
isLoading: profileLoading,
|
||
|
|
} = useSWR<UserResponse>(shouldFetch ? 'user-profile' : null, () =>
|
||
|
|
apiClient.get<UserResponse>('/users/me'),
|
||
|
|
);
|
||
|
|
|
||
|
|
return {
|
||
|
|
householdId: profile?.householdIds?.[0] ?? null,
|
||
|
|
householdIds: profile?.householdIds ?? [],
|
||
|
|
isLoading: status === 'loading' || (shouldFetch && profileLoading),
|
||
|
|
isAuthenticated: status === 'authenticated',
|
||
|
|
profile: profile ?? null,
|
||
|
|
refreshProfile,
|
||
|
|
};
|
||
|
|
}
|