import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers"; import { loadI18nextLocaleMessages, setI18nLanguage } from "@/i18nextWrapper"; import type { Country, CourseProfile } from "@/services/entities"; import { directUpload } from "@/services/files"; import dayjs from "dayjs"; import { defineStore } from "pinia"; 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; street_number: string; postal_code: string; city: string; country: Country | null; birth_date: string; phone_number: string; organisation_detail_name: string; organisation_street: string; organisation_street_number: string; organisation_postal_code: string; organisation_city: string; organisation_country: Country | null; chosen_profile?: CourseProfile; } 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: "", street_number: "", postal_code: "", city: "", country: null, birth_date: "", phone_number: "", organisation_detail_name: "", organisation_street: "", organisation_street_number: "", organisation_postal_code: "", organisation_city: "", organisation_country: null, chosen_profile: undefined, }; 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); loadI18nextLocaleMessages(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); window.location.href = `${window.location.origin}/sso/logout`; }, async fetchUser() { const data: any = 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); }, updateChosenCourseProfile(courseProfile: CourseProfile) { Object.assign(this.$state, { chosen_profile: courseProfile }); }, }, });