// /composables/useAuth.ts interface User { id: string; email: string; nickname: string; avatar: string | null; coins: number; exp: number; dailyStreak: number; soundOn: boolean; confettiOn: boolean; createdAt: string; updatedAt: string; } export function useAuth() { // All Nuxt composables that require instance access MUST be called inside the setup function. // useState is how we create shared, SSR-safe state in Nuxt. const user = useState('user', () => null); const initialized = useState('auth_initialized', () => false); const loading = ref(false); // This is a local, non-shared loading ref for fetchMe's internal use const api = useApi(); const isAuthenticated = computed(() => !!user.value); const fetchMe = async () => { // This function can be called multiple times, but the logic inside // will only run once thanks to the initialized flag. if (initialized.value) return; loading.value = true; try { // The backend returns the user object nested under a 'user' key. const response = await api<{ user: User }>('/auth/me', { method: 'GET' }); user.value = response.user; // Correctly assign the nested user object } catch (error) { user.value = null; // Silently set user to null on 401 } finally { loading.value = false; initialized.value = true; // Mark as initialized after the first attempt } }; const login = async (email, password) => { // The calling component is responsible for its own loading state. // This function just performs the action. await api('/auth/login', { method: 'POST', body: { email, password }, }); // After a successful login, allow a re-fetch of the user state. initialized.value = false; await fetchMe(); }; const logout = async () => { try { await api('/auth/logout', { method: 'POST' }); } finally { // Always clear state and redirect, regardless of API call success. user.value = null; initialized.value = false; await navigateTo('/login'); } }; const updateUser = (partialUser: Partial) => { if (user.value) { user.value = { ...user.value, ...partialUser }; } }; // Expose the state and methods. return { user, isAuthenticated, initialized, fetchMe, login, logout, updateUser, }; }