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, Video, VideoCreate } from '@/interfaces'; import i18n from '@/plugins/i18n' import WS from "@/stores/ws"; const defaultState: MainState = { isLoggedIn: null, token: '', logInError: false, userProfile: null, dashboardMiniDrawer: false, dashboardShowDrawer: true, notifications: [], videos: [], }; 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], readVideos: (state) => state.videos, }, 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; }, setVideos(payload: Video[]) { this.videos = 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(); console.log(this.userProfile); await this.routeLoggedIn(); this.addNotification({ content: i18n.global.t("loggedIn"), 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: i18n.global.t("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: i18n.global.t("profileUpdated"), 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); router.push("/main/dashboard"); } 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: IUserProfileCreate) { const loadingNotification = { content: i18n.global.t("signingUp"), 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: i18n.global.t("registerSuccess"), color: "success", }); setTimeout(() => { router.push("/login") }, 2000) } catch (error) { await this.checkApiError(error); } }, async passwordRecovery(username: string) { const loadingNotification = { content: i18n.global.t("sendingEmail"), showProgress: true, }; try { this.addNotification(loadingNotification); await Promise.all([ api.passwordRecovery(username), await new Promise((resolve, _) => setTimeout(() => resolve(), 500)), ]); this.removeNotification(loadingNotification); this.addNotification({ content: i18n.global.t("passwordMailSent"), color: "success", }); await this.logOut(); } catch (error) { this.removeNotification(loadingNotification); this.addNotification({ color: "error", content: i18n.global.t("incorrectUsername") }); } }, async resetPassword(password: string, token: string) { const loadingNotification = { content: "Resetting password", showProgress: true }; try { this.addNotification(loadingNotification); await Promise.all([ api.resetPassword(token, password), 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", }); } }, async uploadPlot(video_data: VideoCreate, file: File) { const mainStore = useMainStore(); try { const loadingNotification = { content: i18n.global.t("sending"), showProgress: true }; mainStore.addNotification(loadingNotification); const response = ( await Promise.all([ api.uploadPlot(mainStore.token, video_data, file), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); mainStore.removeNotification(loadingNotification); mainStore.addNotification({ content: i18n.global.t("fileReceived"), color: "success", }) this.actionGetVideos(); } catch (error) { await mainStore.checkApiError(error); } }, async uploadImage(file: File[]) { const mainStore = useMainStore(); try { const loadingNotification = { content: i18n.global.t("sending"), showProgress: true }; mainStore.addNotification(loadingNotification); const response = ( await Promise.all([ api.uploadImage(mainStore.token, file), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]).then(data => { for (let i = 0; i < data[0].data.filenames.length; i++) { const element = data[0].data.filenames[i]; const tmpImage: Image = { file_name: file[i].name, stored_file_name: element, content: "sr", state: "subscribe" }; this.addImage(tmpImage); } // localStorage.setItem('imagesList', JSON.stringify(this.images)); }) ); mainStore.removeNotification(loadingNotification); mainStore.addNotification({ content: i18n.global.t("fileReceived"), color: "success", }) // this.actionGetVideos(); } catch (error) { await mainStore.checkApiError(error); } }, async getImage(data: ImageDownload) { const mainStore = useMainStore(); try { const response = ( await Promise.all([ api.getImage(mainStore.token, data), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); } catch (error) { await mainStore.checkApiError(error); } }, addImage(payload: Image) { this.images.push(payload); }, finishImage(payload: string) { let image = this.images.filter(e => { return e.stored_file_name === payload }); if (image) { image.map(e => { e.state = "completed"; }) } // 全部完成後關閉 WebSocket // let processing = this.images.find(e => e.state !== "completed") // if (!processing) { // setTimeout(() => { // WS.close(); // }, 1000) // } return !this.images.some(e => e.state === "completed") }, async uploadArticle(article_data: ArticleCreate) { const mainStore = useMainStore(); try { const loadingNotification = { content: i18n.global.t("sending"), showProgress: true }; mainStore.addNotification(loadingNotification); const response = ( await Promise.all([ api.uploadArticle(mainStore.token, article_data), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); mainStore.removeNotification(loadingNotification); mainStore.addNotification({ content: i18n.global.t("fileReceived"), color: "success", }) // this.actionGetVideos(); } catch (error) { await mainStore.checkApiError(error); } }, async actionGetVideos() { const mainStore = useMainStore(); try { const response = await api.getVideos(mainStore.token) if (response) { this.setVideos(response.data); } } catch (error) { await mainStore.checkApiError(error); } }, async googleLogin(username:string, password: string) { try { const response = await api.googleLogInGetToken(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: i18n.global.t("loggedIn"), color: "success" }); } else { await this.logOut(); } } catch (err) { this.setLogInError(true); await this.logOut(); } } } });