vbv/client/src/stores/user.ts

170 lines
4.3 KiB
TypeScript

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<User>) {
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 });
},
},
});