import axios from "axios" import { defineStore } from "pinia"; import { api } from "@/api" import router from "@/router" import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils"; import type { AppNotification } from '@/interfaces'; import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState } from '@/interfaces'; const defaultState: MainState = { isLoggedIn: null, token: '', logInError: false, userProfile: null, dashboardMiniDrawer: false, dashboardShowDrawer: true, notifications: [], }; export const useMainStore = defineStore("MainStoreId", { state: () => defaultState, getters: { readhasAdminAccess: (state) => state.userProfile && state.userProfile.is_superuser && state.userProfile.is_active, readLoginError: (state) => state.logInError, readDashboardShowDrawer: (state) => state.dashboardShowDrawer, readDashboardMiniDrawer: (state) => state.dashboardMiniDrawer, readUserProfile: (state) => state.userProfile, readToken: (state) => state.token, readIsLoggedIn: (state) => state.isLoggedIn, readFirstNotification: (state) => state.notifications.length > 0 && state.notifications[0], }, actions:{ // setters setToken(payload: string) { this.token = payload; }, setLoggedIn(payload: boolean) { this.isLoggedIn = payload; }, setLogInError(payload: boolean) { this.logInError = payload; }, setUserProfile(payload: IUserProfile) { this.userProfile = payload }, setDashboardMiniDrawer(payload: boolean) { this.dashboardMiniDrawer = payload; }, setDashboardShowDrawer(payload: boolean) { this.dashboardShowDrawer = payload; }, addNotification(payload: AppNotification) { this.notifications.push(payload); }, removeNotification(payload: AppNotification) { if (payload) { this.notifications = this.notifications.filter( (notification) => notification !== payload, ); } }, // actions async logIn(username:string, password:string) { try { const response = await api.logInGetToken(username, password); const token: string = response.data.access_token; if (token) { saveLocalToken(token); this.setToken(token); this.setLoggedIn(true); this.setLogInError(false); await this.getUserProfile(); await this.routeLoggedIn(); this.addNotification({content: "Logged in", color: "success" }); } else { await this.logOut(); } } catch (err) { this.setLogInError(true); await this.logOut(); } }, async getUserProfile() { try { const response = await api.getMe(this.token); if (response.data) { this.setUserProfile(response.data) } } catch (error) { await this.checkApiError(error); } }, async updateUserProfile(payload: IUserProfileUpdate) { try { const loadingNotification = { content: "saving", showProgress: true }; await this.addNotification(loadingNotification); const response = ( await Promise.all([ api.updateMe(this.token, payload), await new Promise((resolve, _) => setTimeout(() => resolve(), 500)), ]) )[0]; this.setUserProfile(response.data); this.removeNotification(loadingNotification); this.addNotification({ content: "Profile successfully updated", color: "success", }); } catch (error) { await this.checkApiError(error); } }, async checkLoggedIn() { if (!this.isLoggedIn) { let token = this.token; if (!token) { const localToken = getLocalToken(); if (localToken) { this.setToken(localToken); token = localToken; } } if (token) { try { const response = await api.getMe(token); this.setLoggedIn(true); this.setUserProfile(response.data); } catch (error) { await this.removeLogIn(); } } else { await this.removeLogIn(); } } }, async removeLogIn() { removeLocalToken(); this.setToken(""); this.setLoggedIn(false); }, async logOut() { await this.removeLogIn(); this.routeLogOut(); }, async userLogOut() { await this.logOut(); this.addNotification({ content: "Logged out", color: "success" }); }, routeLogOut() { if (router.currentRoute.value.path !== "/login") { router.push("/login"); } }, async checkApiError(payload: unknown) { if (axios.isAxiosError(payload)) { if (payload.response?.status === 401) { await this.logOut(); } } }, routeLoggedIn() { if (router.currentRoute.value.path === "/login" || router.currentRoute.value.path === "/") { router.push("/main/dashboard"); } }, async dispatchRemoveNotification(payload: {notification: AppNotification; timeout: number },) { return new Promise((resolve, _) => { setTimeout(() => { this.removeNotification(payload.notification); resolve(true); }, payload.timeout); }); }, async register(payload: IUserProfileRegister) { const loadingNotification = { content: "Sgining up...", showProgress: true, }; try { this.addNotification(loadingNotification); const response = ( await Promise.all([ api.registerUser(payload), await new Promise((resolve, _) => setTimeout(() => resolve(), 500)), ]) )[0]; this.removeNotification(loadingNotification); this.addNotification({ content: "successfully registered", color: "success", }); } catch (error) { await this.checkApiError(error); } }, async passwordRecovery(payload: {username: string }) { const loadingNotification = { content: "Sending password recovery email", showProgress: true, }; try { this.addNotification(loadingNotification); await Promise.all([ api.passwordRecovery(payload.username), await new Promise((resolve, _) => setTimeout(() => resolve(), 500)), ]); this.removeNotification(loadingNotification); this.addNotification({ content: "Password recovery email sent", color: "success", }); await this.logOut(); } catch (error) { this.removeNotification(loadingNotification); this.addNotification({ color: "error", content: "Incorrect username" }); } }, async resetPassword(payload: {password: string; token: string }) { const loadingNotification = { content: "Resetting password", showProgress: true }; try { this.addNotification(loadingNotification); await Promise.all([ api.resetPassword(payload.password, payload.token), await new Promise((resolve, _) => setTimeout(() => resolve(), 500)), ]); this.removeNotification(loadingNotification); this.addNotification( { content: "Password successfully reset", color: "success", }); await this.logOut(); } catch (error) { this.removeNotification(loadingNotification); this.addNotification({ color: "error", content: "Error resetting password", }); } }, } });