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, ArticleCreate, Image, ImageDownload, VideoUploaded, YTViewsUserData } from '@/interfaces'; import i18n from '@/plugins/i18n' import { wsUrl } from "@/env"; const defaultState: MainState = { isLoggedIn: null, token: '', logInError: false, userProfile: null, dashboardMiniDrawer: false, dashboardShowDrawer: true, notifications: [], videos: [], images: [], videosWebSocket: new WebSocket(`${wsUrl}/api/v1/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(); await this.routeLoggedIn(); this.addNotification({ content: i18n.global.t("loggedIn"), color: "success" }); } else { await this.logOut(); } } catch (err) { this.addNotification({ content: i18n.global.t("loggedError"), color: "error" }); this.setLogInError(true); await this.logOut(); } }, async qrLogIn(username: string, password: string, ser_no: string) { try { const response = await api.qrLogInGetToken(username, password, ser_no); return response; } catch (error) { console.log('error', error); } }, async googleLogin(username: string) { try { const response = await api.googleLogin(username); 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(); } }, async qrGoogleLogin(username: string, ser_no: string) { try { const response = await api.qrGoogleLogin(username, ser_no); return response; } catch (error) { console.log('error', error); } }, async qrAddTime(code: string) { try { const response = await api.qrAddTime(this.token, code); return response; } catch (error) { console.log('error', error); return error; } }, 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 cancelCheckLoggedIn() { 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) { this.addNotification({ content: i18n.global.t("registerError"), color: "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([ await api.uploadPlot(mainStore.token, video_data, file), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); mainStore.removeNotification(loadingNotification); if (response[0].data.accepted !== false) { mainStore.addNotification({ content: i18n.global.t("fileReceived"), color: "success", }) } else { mainStore.addNotification({ content: i18n.global.t("uploadFailed"), color: "error", }) } // mainStore.removeNotification(loadingNotification); // mainStore.addNotification({ // content: i18n.global.t("fileReceived"), // color: "success", // }) this.actionGetVideos(); return response[0].data; } catch (error) { await mainStore.checkApiError(error); } const ret: VideoUploaded = { accepted: false, error_message: "api error", video_info: null } return ret }, 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", link: "" }; 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); }, async finishImage(payload: ImageDownload) { const WS = new WebSocket(`${wsUrl}/api/v1/images/sr`); let image = this.images.filter(e => { return payload.stored_file_name.includes(e.stored_file_name) }); const mainStore = useMainStore(); try { const response = await api.downloadImage(mainStore.token, payload); if (image) { image.map(e => { e.state = "completed"; e.link = response.data; }) } } catch (error) { await mainStore.checkApiError(error); } // 全部完成後回傳 WebSocket let processing = this.images.find(e => e.state !== "completed"); if (!processing) { setTimeout(() => { // WS.close(); WS.send("unsubscribe"); }, 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 ecpayPaymentHTML(amount: number) { const mainStore = useMainStore(); try { const response = await api.ecpayPaymentHTML(mainStore.token, amount) if (response) { return response.data; } } catch (error) { await mainStore.checkApiError(error); } }, async YTViewsTestPayment(user_data: YTViewsUserData) { const mainStore = useMainStore(); try { const response = ( await Promise.all([ api.YTViewsTestPayment(user_data), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); if (response[0]) { return response[0].data; } } catch (error) { await mainStore.checkApiError(error); } }, async YTViewsPayment(user_data: YTViewsUserData, lang: string) { const mainStore = useMainStore(); try { const response = ( await Promise.all([ api.YTViewsPayment(user_data, lang), await new Promise((resolve, _) => setTimeout(() => resolve(), 0)), ]) ); if (response[0]) { return response[0].data; } } catch (error) { await mainStore.checkApiError(error); } }, async getYTViewsList() { const mainStore = useMainStore(); try { const response = await api.getYTViewsList(); if (response) { return response.data; } } catch (error) { await mainStore.checkApiError(error); } }, } });