From 54c97314f8fb9b6d81ba4a54aeca3ff2a104e3d6 Mon Sep 17 00:00:00 2001 From: L-Nafaryus Date: Tue, 16 Apr 2024 22:33:34 +0500 Subject: [PATCH] frontend: new api client, router guards, better structure --- .../{frontend => elnafo-frontend}/.gitignore | 0 .../{frontend => elnafo-frontend}/Cargo.toml | 3 +- .../{frontend => elnafo-frontend}/askama.toml | 0 crates/{frontend => elnafo-frontend}/build.rs | 0 .../{frontend => elnafo-frontend}/index.html | 4 +- .../package-lock.json | 0 .../package.json | 0 .../postcss.config.js | 0 .../{frontend => elnafo-frontend}/src/App.vue | 0 crates/elnafo-frontend/src/api-client.ts | 19 ++++ crates/elnafo-frontend/src/api/client.ts | 47 +++++++++ crates/elnafo-frontend/src/api/index.ts | 1 + crates/elnafo-frontend/src/api/user.ts | 91 ++++++++++++++++++ .../elnafo-frontend/src/assets/background.svg | 51 ++++++++++ crates/elnafo-frontend/src/assets/logo.svg | 83 ++++++++++++++++ crates/elnafo-frontend/src/assets/style.css | 50 ++++++++++ .../src/components/DropdownItem.vue | 0 .../src/components/DropdownMenu.vue | 0 .../src/components/NavBar.vue | 0 .../src/components/error/Error.vue | 0 .../src/components/icons/IconCommunity.vue | 0 .../components/icons/IconDocumentation.vue | 0 .../src/components/icons/IconEcosystem.vue | 0 .../src/components/icons/IconSupport.vue | 0 .../src/components/icons/IconTooling.vue | 0 .../src/components/icons/Meerkat.vue | 0 .../src/directives/click-outside.ts | 0 .../{frontend => elnafo-frontend}/src/lib.rs | 4 +- .../{frontend => elnafo-frontend}/src/main.ts | 0 crates/elnafo-frontend/src/router.ts | 86 +++++++++++++++++ crates/elnafo-frontend/src/stores/index.ts | 23 +++++ .../src/views/Base.vue | 74 ++++++-------- .../src/views/Home.vue | 0 .../src/views/admin/Settings.vue | 0 .../src/views/error/NotFound.vue | 0 .../src/views/user/Preferencies.vue | 10 +- .../src/views/user/Profile.vue | 47 +++++++++ .../src/views/user/SignIn.vue | 53 ++++++---- .../src/views/user/SignUp.vue | 23 ++--- .../src/views/user/preferencies/Account.vue | 28 ++---- .../src/views/user/preferencies/Profile.vue | 96 +++++++++++++++++++ .../tailwind.config.js | 2 +- .../templates/base.html | 6 +- .../tsconfig.app.json | 0 .../tsconfig.json | 0 crates/elnafo-frontend/tsconfig.vite.json | 20 ++++ crates/elnafo-frontend/vite.config.ts | 25 +++++ crates/frontend/src/api-client.ts | 11 --- crates/frontend/src/assets/style.css | 31 ------ crates/frontend/src/router.ts | 25 ----- crates/frontend/src/services/user.ts | 25 ----- crates/frontend/src/stores/preferencies.ts | 5 - crates/frontend/src/stores/user.ts | 5 - crates/frontend/src/views/user/Profile.vue | 53 ---------- .../src/views/user/preferencies/Profile.vue | 67 ------------- crates/frontend/tsconfig.vite.json | 17 ---- crates/frontend/vite.config.ts | 25 ----- 57 files changed, 724 insertions(+), 386 deletions(-) rename crates/{frontend => elnafo-frontend}/.gitignore (100%) rename crates/{frontend => elnafo-frontend}/Cargo.toml (75%) rename crates/{frontend => elnafo-frontend}/askama.toml (100%) rename crates/{frontend => elnafo-frontend}/build.rs (100%) rename crates/{frontend => elnafo-frontend}/index.html (73%) rename crates/{frontend => elnafo-frontend}/package-lock.json (100%) rename crates/{frontend => elnafo-frontend}/package.json (100%) rename crates/{frontend => elnafo-frontend}/postcss.config.js (100%) rename crates/{frontend => elnafo-frontend}/src/App.vue (100%) create mode 100644 crates/elnafo-frontend/src/api-client.ts create mode 100644 crates/elnafo-frontend/src/api/client.ts create mode 100644 crates/elnafo-frontend/src/api/index.ts create mode 100644 crates/elnafo-frontend/src/api/user.ts create mode 100644 crates/elnafo-frontend/src/assets/background.svg create mode 100644 crates/elnafo-frontend/src/assets/logo.svg create mode 100644 crates/elnafo-frontend/src/assets/style.css rename crates/{frontend => elnafo-frontend}/src/components/DropdownItem.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/DropdownMenu.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/NavBar.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/error/Error.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/IconCommunity.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/IconDocumentation.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/IconEcosystem.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/IconSupport.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/IconTooling.vue (100%) rename crates/{frontend => elnafo-frontend}/src/components/icons/Meerkat.vue (100%) rename crates/{frontend => elnafo-frontend}/src/directives/click-outside.ts (100%) rename crates/{frontend => elnafo-frontend}/src/lib.rs (79%) rename crates/{frontend => elnafo-frontend}/src/main.ts (100%) create mode 100644 crates/elnafo-frontend/src/router.ts create mode 100644 crates/elnafo-frontend/src/stores/index.ts rename crates/{frontend => elnafo-frontend}/src/views/Base.vue (52%) rename crates/{frontend => elnafo-frontend}/src/views/Home.vue (100%) rename crates/{frontend => elnafo-frontend}/src/views/admin/Settings.vue (100%) rename crates/{frontend => elnafo-frontend}/src/views/error/NotFound.vue (100%) rename crates/{frontend => elnafo-frontend}/src/views/user/Preferencies.vue (69%) create mode 100644 crates/elnafo-frontend/src/views/user/Profile.vue rename crates/{frontend => elnafo-frontend}/src/views/user/SignIn.vue (58%) rename crates/{frontend => elnafo-frontend}/src/views/user/SignUp.vue (74%) rename crates/{frontend => elnafo-frontend}/src/views/user/preferencies/Account.vue (85%) create mode 100644 crates/elnafo-frontend/src/views/user/preferencies/Profile.vue rename crates/{frontend => elnafo-frontend}/tailwind.config.js (92%) rename crates/{frontend => elnafo-frontend}/templates/base.html (61%) rename crates/{frontend => elnafo-frontend}/tsconfig.app.json (100%) rename crates/{frontend => elnafo-frontend}/tsconfig.json (100%) create mode 100644 crates/elnafo-frontend/tsconfig.vite.json create mode 100644 crates/elnafo-frontend/vite.config.ts delete mode 100644 crates/frontend/src/api-client.ts delete mode 100644 crates/frontend/src/assets/style.css delete mode 100644 crates/frontend/src/router.ts delete mode 100644 crates/frontend/src/services/user.ts delete mode 100644 crates/frontend/src/stores/preferencies.ts delete mode 100644 crates/frontend/src/stores/user.ts delete mode 100644 crates/frontend/src/views/user/Profile.vue delete mode 100644 crates/frontend/src/views/user/preferencies/Profile.vue delete mode 100644 crates/frontend/tsconfig.vite.json delete mode 100644 crates/frontend/vite.config.ts diff --git a/crates/frontend/.gitignore b/crates/elnafo-frontend/.gitignore similarity index 100% rename from crates/frontend/.gitignore rename to crates/elnafo-frontend/.gitignore diff --git a/crates/frontend/Cargo.toml b/crates/elnafo-frontend/Cargo.toml similarity index 75% rename from crates/frontend/Cargo.toml rename to crates/elnafo-frontend/Cargo.toml index 54adfd7..63e27e7 100644 --- a/crates/frontend/Cargo.toml +++ b/crates/elnafo-frontend/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "frontend" +name = "elnafo-frontend" version = "0.1.0" edition = "2021" +authors = ["L-Nafaryus "] [build-dependencies] ignore = "0.4.22" diff --git a/crates/frontend/askama.toml b/crates/elnafo-frontend/askama.toml similarity index 100% rename from crates/frontend/askama.toml rename to crates/elnafo-frontend/askama.toml diff --git a/crates/frontend/build.rs b/crates/elnafo-frontend/build.rs similarity index 100% rename from crates/frontend/build.rs rename to crates/elnafo-frontend/build.rs diff --git a/crates/frontend/index.html b/crates/elnafo-frontend/index.html similarity index 73% rename from crates/frontend/index.html rename to crates/elnafo-frontend/index.html index 3c765bb..41b4046 100644 --- a/crates/frontend/index.html +++ b/crates/elnafo-frontend/index.html @@ -2,11 +2,11 @@ - + Elnafo Dev - +
diff --git a/crates/frontend/package-lock.json b/crates/elnafo-frontend/package-lock.json similarity index 100% rename from crates/frontend/package-lock.json rename to crates/elnafo-frontend/package-lock.json diff --git a/crates/frontend/package.json b/crates/elnafo-frontend/package.json similarity index 100% rename from crates/frontend/package.json rename to crates/elnafo-frontend/package.json diff --git a/crates/frontend/postcss.config.js b/crates/elnafo-frontend/postcss.config.js similarity index 100% rename from crates/frontend/postcss.config.js rename to crates/elnafo-frontend/postcss.config.js diff --git a/crates/frontend/src/App.vue b/crates/elnafo-frontend/src/App.vue similarity index 100% rename from crates/frontend/src/App.vue rename to crates/elnafo-frontend/src/App.vue diff --git a/crates/elnafo-frontend/src/api-client.ts b/crates/elnafo-frontend/src/api-client.ts new file mode 100644 index 0000000..f15bffc --- /dev/null +++ b/crates/elnafo-frontend/src/api-client.ts @@ -0,0 +1,19 @@ +import axios, { type AxiosInstance } from "axios"; + +const api_client: AxiosInstance = axios.create({ + baseURL: import.meta.hot ? "http://localhost:54600/api" : "/api", + headers: { + "Content-Type": "application/json" + }, + withCredentials: true, +}); + +export const api_client_upload: AxiosInstance = axios.create({ + baseURL: import.meta.hot ? "http://localhost:54600/api" : "/api", + headers: { + "Content-Type": "multipart/form-data" + }, + withCredentials: true, +}); + +export default api_client; diff --git a/crates/elnafo-frontend/src/api/client.ts b/crates/elnafo-frontend/src/api/client.ts new file mode 100644 index 0000000..e6b3600 --- /dev/null +++ b/crates/elnafo-frontend/src/api/client.ts @@ -0,0 +1,47 @@ +import axios, { type AxiosInstance, AxiosError } from "axios"; + +export class HttpError extends Error { + status_code: number; + + constructor(status_code: number, message: string) { + super(JSON.stringify({ status_code: status_code, message: message })); + Object.setPrototypeOf(this, new.target.prototype); + + this.name = Error.name; + this.status_code = status_code; + } +} + +export interface ResponseError { + status_code: number, + message: string +} + +export function handle_error(error: AxiosError): Promise { + return Promise.reject({ status_code: error.response?.status, message: error.response?.data }); +} + +const debug = import.meta.hot; + +export const client: AxiosInstance = axios.create({ + baseURL: debug ? "http://localhost:54600/api" : "/api", + headers: { + "Content-Type": "application/json" + }, + withCredentials: true, +}); + +export const upload_client: AxiosInstance = axios.create({ + baseURL: debug ? "http://localhost:54600/api" : "/api", + headers: { + "Content-Type": "multipart/form-data" + }, + withCredentials: true, +}); + +export const resources_client: AxiosInstance = axios.create({ + baseURL: debug ? "http://localhost:54600/resources" : "/resources", + responseType: "blob" +}); + +export default client; diff --git a/crates/elnafo-frontend/src/api/index.ts b/crates/elnafo-frontend/src/api/index.ts new file mode 100644 index 0000000..a3c42e9 --- /dev/null +++ b/crates/elnafo-frontend/src/api/index.ts @@ -0,0 +1 @@ +export * as user from "@/api/user"; diff --git a/crates/elnafo-frontend/src/api/user.ts b/crates/elnafo-frontend/src/api/user.ts new file mode 100644 index 0000000..5b95738 --- /dev/null +++ b/crates/elnafo-frontend/src/api/user.ts @@ -0,0 +1,91 @@ +import { client, upload_client, resources_client, type ResponseError, handle_error } from "@/api/client"; + +export interface NewUser { + login: string, + password: string, + email: string +} + +export interface User { + id: string, + login: string, + name: string, + email: string, + is_admin: boolean, + avatar: string +} + +export interface RemoveUser { + id: string, +} + +export interface LoginUser { + email: string | null, + login: string | null, + password: string, +} + +export type Image = string | ArrayBuffer; + +export async function register(body: NewUser): Promise { + return await client.post("/user/register", JSON.stringify(body)) + .then(async response => { return Promise.resolve(response.data); }) + .catch(handle_error); +} + +export async function login(body: LoginUser): Promise { + return await client.post("/user/login", JSON.stringify(body)) + .then(async response => { return Promise.resolve(response.data); }) + .catch(handle_error); +} + +export async function remove(body: RemoveUser): Promise { + return await client.post("/user/remove", JSON.stringify(body)) + .then(async () => { return Promise.resolve(null); }) + .catch(handle_error); +} + +export async function logout(): Promise { + return await client.get("/user/logout") + .then(async () => { return Promise.resolve(null); }) + .catch(handle_error); +} + +export async function current(): Promise { + return await client.get("/user/current") + .then(async response => { return Promise.resolve(response.data); }) + .catch(handle_error); +} + +export async function avatar(file: FormData, progress?: any): Promise { + return await upload_client.post("/user/avatar", file, { + onUploadProgress: progress ?? null, + //headers: { "Accept-Encoding": "gzip" } + }) + .then(async () => { return Promise.resolve(null); }) + .catch(handle_error); +} + +export async function get_avatar(avatar: string): Promise { + return await resources_client.get("/avatars/".concat(avatar)) + .then(async response => { + return new Promise((resolve, reject) => { + let reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result); + }; + reader.onerror = (e) => { + reject(e); + }; + reader.readAsDataURL(response.data); + }) + }) + .catch(handle_error); +} + +export async function profile(login: string): Promise { + return await client.get("/user/".concat(login)) + .then(async response => { return Promise.resolve(response.data); }) + .catch(handle_error); +} diff --git a/crates/elnafo-frontend/src/assets/background.svg b/crates/elnafo-frontend/src/assets/background.svg new file mode 100644 index 0000000..f0de024 --- /dev/null +++ b/crates/elnafo-frontend/src/assets/background.svg @@ -0,0 +1,51 @@ + + + + diff --git a/crates/elnafo-frontend/src/assets/logo.svg b/crates/elnafo-frontend/src/assets/logo.svg new file mode 100644 index 0000000..57191c6 --- /dev/null +++ b/crates/elnafo-frontend/src/assets/logo.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/elnafo-frontend/src/assets/style.css b/crates/elnafo-frontend/src/assets/style.css new file mode 100644 index 0000000..c096abe --- /dev/null +++ b/crates/elnafo-frontend/src/assets/style.css @@ -0,0 +1,50 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + background-color: rgba(36, 14, 84, 1); /*linear-gradient(rgba(36, 14, 84, 1) 80%, rgba(55, 22, 130, 1)); */ + background-image: url("./background.svg"); + background-position: left top; + background-repeat: repeat-x; + } + + a { + @apply text-green-500 hover:text-green-400; + } + + h1 { + font-family: BioRhyme,serif; + font-weight: 700; + } + + label { + font-family: Space Mono,monospace; + font-weight: 500; + } +} + +@layer utilities { + .bg-roll::before { + background: linear-gradient(90deg, #fb0094, #0000ff, #fb0093); + background-size: 200%; + + @apply absolute w-[100%] h-[100%] content-[''] animate-border-roll; + } + + .bg-grid { + + background: + linear-gradient(180deg, rgba(0, 0, 0, 0) 0px, rgba(187, 65, 143, 1) 10%, + rgba(187, 65, 143, 1) 2px, rgba(0, 0, 0, 0) 0px), + linear-gradient(90deg, rgba(0, 0, 0, 0) 0px, rgba(187, 65, 143, 1) 10%, + rgba(187, 65, 143, 1) 2px, rgba(0, 0, 0, 0) 0px); + background-size: 2em 4em, 6em 2em; + transform: perspective(500px) rotateX(60deg) scale(0.5); + transform-origin: 50% 0%; + z-index: -1; + + @apply absolute w-[250%] -left-[75%] h-[200%]; + } +} diff --git a/crates/frontend/src/components/DropdownItem.vue b/crates/elnafo-frontend/src/components/DropdownItem.vue similarity index 100% rename from crates/frontend/src/components/DropdownItem.vue rename to crates/elnafo-frontend/src/components/DropdownItem.vue diff --git a/crates/frontend/src/components/DropdownMenu.vue b/crates/elnafo-frontend/src/components/DropdownMenu.vue similarity index 100% rename from crates/frontend/src/components/DropdownMenu.vue rename to crates/elnafo-frontend/src/components/DropdownMenu.vue diff --git a/crates/frontend/src/components/NavBar.vue b/crates/elnafo-frontend/src/components/NavBar.vue similarity index 100% rename from crates/frontend/src/components/NavBar.vue rename to crates/elnafo-frontend/src/components/NavBar.vue diff --git a/crates/frontend/src/components/error/Error.vue b/crates/elnafo-frontend/src/components/error/Error.vue similarity index 100% rename from crates/frontend/src/components/error/Error.vue rename to crates/elnafo-frontend/src/components/error/Error.vue diff --git a/crates/frontend/src/components/icons/IconCommunity.vue b/crates/elnafo-frontend/src/components/icons/IconCommunity.vue similarity index 100% rename from crates/frontend/src/components/icons/IconCommunity.vue rename to crates/elnafo-frontend/src/components/icons/IconCommunity.vue diff --git a/crates/frontend/src/components/icons/IconDocumentation.vue b/crates/elnafo-frontend/src/components/icons/IconDocumentation.vue similarity index 100% rename from crates/frontend/src/components/icons/IconDocumentation.vue rename to crates/elnafo-frontend/src/components/icons/IconDocumentation.vue diff --git a/crates/frontend/src/components/icons/IconEcosystem.vue b/crates/elnafo-frontend/src/components/icons/IconEcosystem.vue similarity index 100% rename from crates/frontend/src/components/icons/IconEcosystem.vue rename to crates/elnafo-frontend/src/components/icons/IconEcosystem.vue diff --git a/crates/frontend/src/components/icons/IconSupport.vue b/crates/elnafo-frontend/src/components/icons/IconSupport.vue similarity index 100% rename from crates/frontend/src/components/icons/IconSupport.vue rename to crates/elnafo-frontend/src/components/icons/IconSupport.vue diff --git a/crates/frontend/src/components/icons/IconTooling.vue b/crates/elnafo-frontend/src/components/icons/IconTooling.vue similarity index 100% rename from crates/frontend/src/components/icons/IconTooling.vue rename to crates/elnafo-frontend/src/components/icons/IconTooling.vue diff --git a/crates/frontend/src/components/icons/Meerkat.vue b/crates/elnafo-frontend/src/components/icons/Meerkat.vue similarity index 100% rename from crates/frontend/src/components/icons/Meerkat.vue rename to crates/elnafo-frontend/src/components/icons/Meerkat.vue diff --git a/crates/frontend/src/directives/click-outside.ts b/crates/elnafo-frontend/src/directives/click-outside.ts similarity index 100% rename from crates/frontend/src/directives/click-outside.ts rename to crates/elnafo-frontend/src/directives/click-outside.ts diff --git a/crates/frontend/src/lib.rs b/crates/elnafo-frontend/src/lib.rs similarity index 79% rename from crates/frontend/src/lib.rs rename to crates/elnafo-frontend/src/lib.rs index d15bb29..2ad44e3 100644 --- a/crates/frontend/src/lib.rs +++ b/crates/elnafo-frontend/src/lib.rs @@ -2,11 +2,9 @@ use askama_axum::Template; use rust_embed::RustEmbed; #[derive(RustEmbed)] -#[folder = "dist/assets/"] +#[folder = "dist/resources/assets/"] pub struct Assets; -// TODO: parse assets and add paths to templates - #[derive(Template)] #[template(path = "base.html")] pub struct BaseTemplate<'a> { diff --git a/crates/frontend/src/main.ts b/crates/elnafo-frontend/src/main.ts similarity index 100% rename from crates/frontend/src/main.ts rename to crates/elnafo-frontend/src/main.ts diff --git a/crates/elnafo-frontend/src/router.ts b/crates/elnafo-frontend/src/router.ts new file mode 100644 index 0000000..3fb497a --- /dev/null +++ b/crates/elnafo-frontend/src/router.ts @@ -0,0 +1,86 @@ +import { createRouter, createWebHistory } from "vue-router"; + +import { user } from "@/api"; +import { useUserStore } from "@/stores"; + + +async function check_authorized(): Promise { + const userStore = useUserStore(); + + // TODO: add timer + return await user.current() + .then(async user => { userStore.current = user; }) + .then(async () => { + if (userStore.current.avatar?.length) { + await user.get_avatar(userStore.current.avatar) + .then(async avatar => { userStore.avatar = avatar; }) + } + }) + .then(async () => { return true; }) + .catch(() => { + return false; + }); +} + +async function bypass_auth(to: any, from: any) { + if (await check_authorized() && (to.name === "signin" || to.name === "signup")) { + return from; + } +} + +async function required_auth(to: any, from: any) { + if (!await check_authorized()) { + return { name: "signin" }; + } +} + +async function required_admin(to: any, from: any) { + const userStore = useUserStore(); + return userStore.current.is_admin; +} + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { + path: "/", name: "home", beforeEnter: [bypass_auth], + component: () => import("@/views/Home.vue"), + }, + { + path: "/user/login", name: "signin", beforeEnter: [bypass_auth], + component: () => import("@/views/user/SignIn.vue") + }, + { + path: "/user/register", name: "signup", //beforeEnter: [bypass_auth], + component: () => import("@/views/user/SignUp.vue") + }, + { + path: "/user/preferencies", name: "prefs", redirect: { name: "prefs-profile" }, beforeEnter: [required_auth], + component: () => import("@/views/user/Preferencies.vue"), + children: [ + { + path: "profile", name: "prefs-profile", beforeEnter: [required_auth], + component: () => import("@/views/user/preferencies/Profile.vue") + }, + { + path: "account", name: "prefs-account", beforeEnter: [required_auth], + component: () => import("@/views/user/preferencies/Account.vue") + }, + ] + }, + { + path: "/:user", name: "profile", beforeEnter: [bypass_auth], + component: () => import("@/views/user/Profile.vue") + }, + { + path: "/admin/settings", name: "settings", beforeEnter: [required_auth, required_admin], + component: () => import("@/views/admin/Settings.vue") + }, + { + path: "/:pathMatch(.*)*", name: "not-found", beforeEnter: [bypass_auth], + component: () => import("@/views/error/NotFound.vue") + } + ] +}); + +export default router; diff --git a/crates/elnafo-frontend/src/stores/index.ts b/crates/elnafo-frontend/src/stores/index.ts new file mode 100644 index 0000000..9a87b24 --- /dev/null +++ b/crates/elnafo-frontend/src/stores/index.ts @@ -0,0 +1,23 @@ +import { defineStore } from "pinia"; +import { ref, type Ref } from "vue"; + +import { user } from "@/api"; + +export const useUserStore = defineStore("user", () => { + const current: Ref = ref(null); + const avatar: Ref = ref(null); + + function clear() { + current.value = null; + avatar.value = null; + } + + return { current, avatar, clear }; +}); + +export const useMiscStore = defineStore("misc", () => { + // preferencies current tab + const p_current_tab: Ref = ref(0); + + return { p_current_tab }; +}); diff --git a/crates/frontend/src/views/Base.vue b/crates/elnafo-frontend/src/views/Base.vue similarity index 52% rename from crates/frontend/src/views/Base.vue rename to crates/elnafo-frontend/src/views/Base.vue index 3ea3e5a..5805fc4 100644 --- a/crates/frontend/src/views/Base.vue +++ b/crates/elnafo-frontend/src/views/Base.vue @@ -6,43 +6,19 @@ import DropdownMenu from "@/components/DropdownMenu.vue"; import { ref, onMounted } from "vue"; import router from "@/router"; -import User from "@/services/user"; -import { useUserStore } from "@/stores/user"; +import { user } from "@/api"; +import { useUserStore } from "@/stores"; -const user = ref(null); const userStore = useUserStore(); -const error = ref(null); +const error = ref(null); -onMounted(async () => { - await User.current() - .then(async response => { - if (response.status != 200) { - return Promise.reject(response.data && response.data.message || response.status); - }; - if (response.data.hasOwnProperty("user")) { - userStore.login = response.data.user.login; - }; - }) - .catch(e => { - console.log(`${e.name}[${e.code}]: ${e.message}`); - }); -}); - -async function user_logout() { - await User.logout() - .then(async response => { - error.value = null; - - if (response.status != 200) { - return Promise.reject(response.data && response.data.message || response.status); - }; - - userStore.login = null; +async function signout() { + await user.logout() + .then(async () => { + userStore.clear(); router.push({ path: "/" }); }) - .catch(e => { - console.error("Error occured:", e); - }); + .catch(error => { error.value = error; }); } @@ -54,50 +30,54 @@ async function user_logout() { -
-
-
-
+
+
+ +
+
- + + diff --git a/crates/frontend/src/views/Home.vue b/crates/elnafo-frontend/src/views/Home.vue similarity index 100% rename from crates/frontend/src/views/Home.vue rename to crates/elnafo-frontend/src/views/Home.vue diff --git a/crates/frontend/src/views/admin/Settings.vue b/crates/elnafo-frontend/src/views/admin/Settings.vue similarity index 100% rename from crates/frontend/src/views/admin/Settings.vue rename to crates/elnafo-frontend/src/views/admin/Settings.vue diff --git a/crates/frontend/src/views/error/NotFound.vue b/crates/elnafo-frontend/src/views/error/NotFound.vue similarity index 100% rename from crates/frontend/src/views/error/NotFound.vue rename to crates/elnafo-frontend/src/views/error/NotFound.vue diff --git a/crates/frontend/src/views/user/Preferencies.vue b/crates/elnafo-frontend/src/views/user/Preferencies.vue similarity index 69% rename from crates/frontend/src/views/user/Preferencies.vue rename to crates/elnafo-frontend/src/views/user/Preferencies.vue index 5f1415e..047f653 100644 --- a/crates/frontend/src/views/user/Preferencies.vue +++ b/crates/elnafo-frontend/src/views/user/Preferencies.vue @@ -3,9 +3,9 @@ import Base from "@/views/Base.vue"; import { ref, onMounted, watch, getCurrentInstance } from "vue"; -import { usePreferenciesStore } from "@/stores/preferencies.ts"; +import { useMiscStore } from "@/stores"; -const preferenciesStore = usePreferenciesStore(); +const miscStore = useMiscStore(); @@ -16,12 +16,10 @@ const preferenciesStore = usePreferenciesStore();

User Preferencies

- Profile - Account
diff --git a/crates/elnafo-frontend/src/views/user/Profile.vue b/crates/elnafo-frontend/src/views/user/Profile.vue new file mode 100644 index 0000000..1536a13 --- /dev/null +++ b/crates/elnafo-frontend/src/views/user/Profile.vue @@ -0,0 +1,47 @@ + + + diff --git a/crates/frontend/src/views/user/SignIn.vue b/crates/elnafo-frontend/src/views/user/SignIn.vue similarity index 58% rename from crates/frontend/src/views/user/SignIn.vue rename to crates/elnafo-frontend/src/views/user/SignIn.vue index a45b819..ee08f30 100644 --- a/crates/frontend/src/views/user/SignIn.vue +++ b/crates/elnafo-frontend/src/views/user/SignIn.vue @@ -2,43 +2,54 @@ import Base from "@/views/Base.vue"; import Error from "@/components/error/Error.vue"; -import { ref } from "vue"; +import { ref, onMounted } from "vue"; import router from "@/router"; -import User from "@/services/user"; -import { useUserStore } from "@/stores/user"; +import { user } from "@/api"; +import { useUserStore } from "@/stores"; -const email = defineModel("email"); +const email_or_login = defineModel("email_or_login"); const password = defineModel("password"); -const error = ref(null); const userStore = useUserStore(); +const error = ref(null); -async function login() { - await User.login(email.value, password.value) - .then(async response => { - if (response.status != 200) { - return Promise.reject(response.data && response.data.message || response.status); - } +onMounted(async () => { + if (userStore.current) { + router.replace({ path: "/" }); + } +}); - userStore.login = response.data.user.login; - router.push({ path: `/${userStore.login}` }); +async function signin() { + const body: user.LoginUser = { + email: null, + login: null, + password: password.value + }; + + if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email_or_login.value)) { + body.email = email_or_login.value; + } else { + body.login = email_or_login.value; + } + + await user.login(body) + .then(async user => { + userStore.current = user; + router.push({ path: "/" }); }) - .catch(e => { - error.value = e; - console.log(`${e.name}[${e.code}]: ${e.message}`); - }); + .catch(error => { error.value = error; }); }; diff --git a/crates/frontend/src/views/user/preferencies/Account.vue b/crates/elnafo-frontend/src/views/user/preferencies/Account.vue similarity index 85% rename from crates/frontend/src/views/user/preferencies/Account.vue rename to crates/elnafo-frontend/src/views/user/preferencies/Account.vue index fec525a..384d2ca 100644 --- a/crates/frontend/src/views/user/preferencies/Account.vue +++ b/crates/elnafo-frontend/src/views/user/preferencies/Account.vue @@ -4,9 +4,7 @@ import Base from "@/views/Base.vue"; import { ref, onMounted, watch, getCurrentInstance } from "vue"; import router from "@/router"; -import User from "@/services/user"; -import { useUserStore } from "@/stores/user"; -import { usePreferenciesStore } from "@/stores/preferencies.ts"; +import { useUserStore, useMiscStore } from "@/stores"; const password = defineModel("password"); const new_password = defineModel("new-password"); @@ -19,31 +17,17 @@ const confirm_password = defineModel("confirm-password"); const error = ref(null); const userStore = useUserStore(); -const preferenciesStore = usePreferenciesStore(); +const miscStore = useMiscStore(); onMounted(async () => { - preferenciesStore.current_tab = 1; + miscStore.p_current_tab = 1; - !userStore.login ? router.push({ name: "SignIn" }) : await User.current() - .then(async response => { - error.value = null; - - if (response.status != 200) { - return Promise.reject(response.data && response.data.message || response.status); - }; - - email.value = response.data.user.email; - }) - .catch(e => { - error.value = e; - console.log(`${e.name}[${e.code}]: ${e.message}`); - }); });