177 lines
4.5 KiB
TypeScript
177 lines
4.5 KiB
TypeScript
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<User>) {
|
|
if (profileData.language) {
|
|
await setLocale(profileData.language);
|
|
}
|
|
|
|
await itPost("/api/core/me/", profileData, { method: "PUT" });
|
|
Object.assign(this.$state, profileData);
|
|
},
|
|
},
|
|
});
|