158 lines
3.6 KiB
TypeScript
158 lines
3.6 KiB
TypeScript
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<void>;
|
|
updateActiveAccount: (account: LocalAccount) => Promise<void>;
|
|
deleteActiveAccount: () => Promise<void>;
|
|
|
|
authenticate: () => Promise<void>;
|
|
|
|
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<IAuthState>((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 });
|
|
},
|
|
}));
|