import { deleteAccount, getAllAccounts, updateAccountInfo, type LocalAccount, } from "@/repository/account"; import type { UserProfile } from "@/types"; import { create } from "zustand"; import { useDbStore } from "./db"; import { fetchProfileApi } from "@/api/profile"; export interface IAuthState { profile: UserProfile | null; authenticating: boolean; activeAccount: LocalAccount | null; loadingAccounts: boolean; accounts: LocalAccount[]; signInRequired: boolean; hasAuthenticated: boolean; hasLoadedAccounts: boolean; loadAccounts: () => Promise; updateActiveAccount: (account: LocalAccount) => Promise; deleteActiveAccount: () => Promise; authenticate: () => Promise; requireSignIn: () => void; signOut: () => void; } const getActiveAccountId = (): string | null => { const accountId = localStorage.getItem("guard-selected"); return accountId; }; const saveActiveAccountId = (accountId: string): void => { localStorage.setItem("guard-selected", accountId); }; const resetActiveAccount = (): void => { localStorage.removeItem("guard-selected"); }; // TODO: maybe add deleteActiveAccount export const useAuth = create((set, get) => ({ profile: null, authenticating: false, activeAccount: null, accounts: [], loadingAccounts: false, signInRequired: false, hasAuthenticated: false, hasLoadedAccounts: false, updateActiveAccount: async (account) => { set({ activeAccount: account }); saveActiveAccountId(account.accountId); set({ signInRequired: false }); }, loadAccounts: async () => { set({ loadingAccounts: true }); const db = useDbStore.getState().db; if (!db) return; const accounts = await getAllAccounts(db); console.log("loaded accounts:", accounts); if (!accounts || accounts.length === 0) { set({ signInRequired: true }); } const active = getActiveAccountId(); if (!active) { set({ signInRequired: true }); } else { const account = accounts.find((acc) => acc.accountId === active); if (!account) { resetActiveAccount(); set({ signInRequired: true }); } else { set({ activeAccount: account }); } } set({ accounts, loadingAccounts: false, hasLoadedAccounts: true, }); }, deleteActiveAccount: async () => { resetActiveAccount(); set({ activeAccount: null }); get().loadAccounts(); }, authenticate: async () => { const { authenticating } = get(); if (authenticating) return; set({ authenticating: true }); try { const response = await fetchProfileApi(); console.log("authenticate response:", response); try { // update local account information const db = useDbStore.getState().db; if (db) { await updateAccountInfo(db, { accountId: response.id, label: response.full_name, ...(response.profile_picture ? { profilePicture: response.profile_picture } : {}), }); } } finally { set({ profile: response }); } } catch (err) { // TODO: set error console.log(err); } finally { set({ authenticating: false, hasAuthenticated: true }); } }, requireSignIn: () => set({ signInRequired: true }), signOut: async () => { resetActiveAccount(); const db = useDbStore.getState().db; const activeAccount = get().activeAccount; if (db && activeAccount) { await deleteAccount(db, activeAccount.accountId); } await get().loadAccounts(); set({ activeAccount: null, signInRequired: true }); }, }));