import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers"; import { setI18nLanguage } from "@/i18nextWrapper"; import type { Country } from "@/services/entities"; import { directUpload } from "@/services/files"; import dayjs from "dayjs"; import { defineStore } from "pinia"; let logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT || "/"; if (import.meta.env.VITE_OAUTH_API_BASE_URL) { logoutRedirectUrl = `${ import.meta.env.VITE_OAUTH_API_BASE_URL }logout/?post_logout_redirect_uri=${window.location.origin}`; } const AVAILABLE_LANGUAGES = ["de", "fr", "it"]; export type AvailableLanguages = "de" | "fr" | "it"; export type InvoiceAddress = "prv" | "org"; export interface User { id: string; username: string; first_name: string; last_name: string; email: string; avatar_url: string; organisation: number | null; is_superuser: boolean; loggedIn: boolean; language: AvailableLanguages; course_session_experts: string[]; invoice_address: InvoiceAddress | null; street: string | null; street_number: string | null; postal_code: string | null; city: string | null; country: Country | null; organisation_detail_name: string | null; organisation_street: string | null; organisation_street_number: string | null; organisation_postal_code: string | null; organisation_city: string | null; organisation_country: Country | null; } let defaultLanguage: AvailableLanguages = "de"; const isAvailableLanguage = (language: string): language is AvailableLanguages => { return AVAILABLE_LANGUAGES.includes(language); }; const languagesWithoutCountryCode = navigator.languages.map( (lang) => lang.split("-")[0] ); for (const language of languagesWithoutCountryCode) { if (isAvailableLanguage(language)) { defaultLanguage = language; break; } } const initialUserState: User = { id: "", email: "", first_name: "", last_name: "", username: "", avatar_url: "", is_superuser: false, organisation: 0, course_session_experts: [], loggedIn: false, language: defaultLanguage, invoice_address: "prv", street: null, street_number: null, postal_code: null, city: null, country: null, organisation_detail_name: null, organisation_street: null, organisation_street_number: null, organisation_postal_code: null, organisation_city: null, organisation_country: null, }; async function setLocale(language: AvailableLanguages) { switch (language) { case "de": await import("dayjs/locale/de"); break; case "fr": await import("dayjs/locale/fr"); break; case "it": await import("dayjs/locale/it"); } dayjs.locale(language); setI18nLanguage(language); } export const useUserStore = defineStore({ id: "user", state: () => initialUserState as User, getters: { getFullName(): string { return `${this.first_name} ${this.last_name}`.trim(); }, languageName(): string { if (this.language === "de") { return "Deutsch"; } if (this.language === "fr") { return "Français"; } if (this.language === "it") { return "Italiano"; } return this.language; }, }, actions: { async handleLogin(username: string, password: string, next = "/") { if (username && password) { try { this.$state = await itPost("/api/core/login/", { username, password, }); this.loggedIn = true; bustItGetCache(); window.location.href = next; } catch (e) { this.loggedIn = false; alert("Login failed"); } } }, handleLogout() { Object.assign(this, initialUserState); itPost("/api/core/logout/", {}).then(() => { let redirectUrl; if (logoutRedirectUrl !== "") { redirectUrl = logoutRedirectUrl; } else { redirectUrl = "/"; } window.location.href = redirectUrl; }); }, async fetchUser() { const data = await itGetCached("/api/core/me/"); this.$state = data; this.loggedIn = true; await setLocale(data.language); }, async setUserAvatar(file: File) { const r = await directUpload("/api/core/avatar/", file); this.$state.avatar_url = r.url; }, async updateUserProfile(profileData: Partial) { if (profileData.language) { await setLocale(profileData.language); } await itPost("/api/core/me/", profileData, { method: "PUT" }); Object.assign(this.$state, profileData); }, }, });