frontend: sign up, logout, basic preferencies

This commit is contained in:
L-Nafaryus 2024-03-29 00:13:26 +05:00
parent e868c87a7e
commit 76e6d5183f
Signed by: L-Nafaryus
GPG Key ID: 582F8B0866B294A1
25 changed files with 571 additions and 109 deletions

View File

@ -10,6 +10,7 @@
"dependencies": {
"autoprefixer": "^10.4.18",
"axios": "^1.6.8",
"pinia": "^2.1.7",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"vue": "^3.3.11",
@ -2468,6 +2469,56 @@
"node": ">=0.10.0"
}
},
"node_modules/pinia": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
"integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
"dependencies": {
"@vue/devtools-api": "^6.5.0",
"vue-demi": ">=0.14.5"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",

View File

@ -13,6 +13,7 @@
"dependencies": {
"autoprefixer": "^10.4.18",
"axios": "^1.6.8",
"pinia": "^2.1.7",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"vue": "^3.3.11",

View File

@ -0,0 +1,22 @@
<script setup lang="ts">
import { ref } from "vue";
const active = ref<bool>(false);
function activate() {
active.value = !active.value;
}
function deactivate() {
active.value = false;
}
</script>
<template>
<div @click="activate" v-click-outside="deactivate">
<slot name="button"></slot>
<div v-if="active">
<slot name="content"></slot>
</div>
</div>
</template>

View File

@ -1,5 +0,0 @@
<template>
<h1>
<slot></slot>
</h1>
</template>

View File

@ -0,0 +1,5 @@
<template>
<h1 class="text-center pt-3 pb-3 bg-orange-900 rounded border border-orange-700">
<slot></slot>
</h1>
</template>

View File

@ -0,0 +1,14 @@
export const click_outside = {
beforeMount: function(element: any, binding: any) {
element.clickOutsideEvent = function(event: any) {
if (!(element == event.target || element.contains(event.target))) {
binding.value(event);
}
};
document.body.addEventListener("click", element.clickOutsideEvent);
},
unmounted: function(element: any) {
document.body.removeEventListener("click", element.clickOutsideEvent);
}
}

View File

@ -1,10 +1,15 @@
import { createApp } from 'vue';
import App from '@/App.vue';
import router from '@/router';
import App from "@/App.vue";
import '@/assets/style.css';
import { createApp } from "vue";
import { createPinia } from "pinia";
import router from "@/router";
import { click_outside } from "@/directives/click-outside";
import "@/assets/style.css";
createApp(App)
.use(createPinia())
.use(router)
.directive("click-outside", click_outside)
.mount('#app');

View File

@ -3,10 +3,22 @@ import { createRouter, createWebHistory } from "vue-router";
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", component: () => import("@/views/Home.vue") },
{ path: "/user/login", component: () => import("@/views/SignIn.vue") },
{ path: "/:user", name: "User", component: () => import("@/views/User.vue") },
{ path: "/:pathMatch(.*)*", component: () => import("@/views/Error.vue") }
{ path: "/", name: "Home", component: () => import("@/views/Home.vue") },
{ path: "/user/login", name: "SignIn", component: () => import("@/views/user/SignIn.vue") },
{ path: "/user/register", name: "SignUp", component: () => import("@/views/user/SignUp.vue") },
{
path: "/user/preferencies", name: "Preferencies", redirect: { name: "Preferencies-Profile" }, component: () => import("@/views/user/Preferencies.vue"), children: [
{ path: "profile", name: "Preferencies-Profile", component: () => import("@/views/user/preferencies/Profile.vue") },
{ path: "account", name: "Preferencies-Account", component: () => import("@/views/user/preferencies/Account.vue") },
]
},
{ path: "/:user", name: "Profile", component: () => import("@/views/user/Profile.vue") },
{ path: "/admin/settings", name: "Settings", component: () => import("@/views/admin/Settings.vue") },
{ path: "/:pathMatch(.*)*", name: "NotFound", component: () => import("@/views/error/NotFound.vue") }
]
});

View File

@ -1,10 +1,18 @@
import api_client from "@/api-client";
class User {
async register(login: string, email: string, password: string): Promise<JSON> {
return await api_client.post("/user/register", JSON.stringify({ login: login, email: email, password: password }));
}
async login(email: string, password: string): Promise<JSON> {
return await api_client.post("/user/login", JSON.stringify({ email: email, password: password }));
}
async logout(): Promise<JSON> {
return await api_client.get("/user/logout");
}
async get(login: any): Promise<JSON> {
return await api_client.get(`/user/${login}`);
}

View File

@ -0,0 +1,5 @@
import { defineStore } from "pinia";
export const usePreferenciesStore = defineStore("preferencies", {
state: () => ({ current_tab: null }),
});

View File

@ -0,0 +1,5 @@
import { defineStore } from "pinia";
export const useUserStore = defineStore("user", {
state: () => ({ login: null }),
});

View File

@ -1,10 +1,17 @@
<script setup lang="ts">
import Meerkat from '@/components/icons/Meerkat.vue';
import NavBar from '@/components/NavBar.vue';
import Meerkat from "@/components/icons/Meerkat.vue";
import NavBar from "@/components/NavBar.vue";
import DropdownMenu from "@/components/DropdownMenu.vue";
import { ref, onMounted } from "vue";
import router from "@/router";
import User from "@/services/user";
import { ref, onMounted } from 'vue';
import { useUserStore } from "@/stores/user";
const user = ref(null);
const userStore = useUserStore();
const error = ref<string>(null);
onMounted(async () => {
await User.current()
@ -13,13 +20,31 @@ onMounted(async () => {
return Promise.reject(response.data && response.data.message || response.status);
};
if (response.data.hasOwnProperty("user")) {
user.value = response.data.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;
router.push({ path: "/" });
})
.catch(e => {
console.error("Error occured:", e);
});
});
}
</script>
<template>
@ -29,10 +54,35 @@ onMounted(async () => {
<Meerkat />
</template>
<template #right>
<RouterLink v-if="user" class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600"
:to="{ name: 'User', params: { user: user.login } }">{{ user.name }}</RouterLink>
<RouterLink v-if="!user" class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600"
to="/user/login">
<DropdownMenu v-if="userStore.login">
<template #button>
<span
class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600 cursor-pointer">{{
userStore.login }}</span>
</template>
<template #content>
<div
class="absolute flex flex-col left-auto right-0 mt-4 bg-zinc-700 border rounded border-zinc-500 mr-3">
<RouterLink :to="{ name: 'Profile', params: { user: userStore.login } }"
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
Profile</RouterLink>
<RouterLink :to="{ name: 'Preferencies' }"
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
Preferencies</RouterLink>
<div class="border-t border-zinc-500 ml-0 mr-0"></div>
<RouterLink :to="{ name: 'Settings' }"
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
Settings</RouterLink>
<div class="border-t border-zinc-500 ml-0 mr-0"></div>
<div @click="user_logout"
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600 cursor-pointer">
Sign Out</div>
</div>
</template>
</DropdownMenu>
<RouterLink v-if="!userStore.login"
class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600" to="/user/login">
Sign In</RouterLink>
</template>
</NavBar>

View File

@ -1,10 +0,0 @@
<script setup lang="ts">
import Base from '@/views/Base.vue';
import Login from '@/components/Login.vue';
</script>
<template>
<Base>
<Login />
</Base>
</template>

View File

@ -1,54 +0,0 @@
<script setup lang="ts">
import Base from '@/views/Base.vue';
import Error from "@/components/Error.vue";
import { ref, onMounted, watch } from 'vue';
import { onBeforeRouteUpdate, useRoute } from 'vue-router'
import User from "@/services/user";
const route = useRoute();
const name = ref(null);
const error = ref(null);
onMounted(async () => {
await User.get(route.params.user)
.then(async response => {
if (response.status != 200) {
return Promise.reject(response.data && response.data.message || response.status);
};
if (response.data.hasOwnProperty("user")) {
name.value = response.data.user.name;
} else {
error.value = "404 Not Found";
};
})
.catch(e => {
console.error("Error occured:", e);
});
});
watch(() => route.params.user, async (to, from) => {
await User.get(route.params.user)
.then(async response => {
if (response.status != 200) {
return Promise.reject(response.data && response.data.message || response.status);
};
if (response.data.hasOwnProperty("user")) {
name.value = response.data.user.name;
} else {
error.value = "404 Not Found";
};
})
.catch(e => {
console.error("Error occured:", e);
});
});
</script>
<template>
<Base>
<div v-if="error">
<Error>{{ error }}</Error>
</div>
<p v-else>{{ name }}</p>
</Base>
</template>

View File

@ -1,10 +1,11 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import Error from "@/components/Error.vue";
</script>
<template>
<Base>
<Error>Not Found</Error>
<div>
</div>
</Base>
</template>

View File

@ -0,0 +1,10 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import Error from "@/components/error/Error.vue";
</script>
<template>
<Base>
<Error>404 Not Found</Error>
</Base>
</template>

View File

@ -0,0 +1,38 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import { ref, onMounted, watch, getCurrentInstance } from "vue";
import { usePreferenciesStore } from "@/stores/preferencies.ts";
const preferenciesStore = usePreferenciesStore();
</script>
<template>
<Base>
<div class="flex gap-4 mt-4 ml-auto mr-auto content ">
<Router-View />
<div>
<div class="border rounded border-zinc-500 flex-col w-64">
<h1 class="pl-5 pr-5 pt-2 pb-2">User Preferencies</h1>
<RouterLink :to="{ name: 'Preferencies-Profile' }"
:class="{ 'bg-zinc-600': preferenciesStore.current_tab === 0 }"
class="flex min-w-7 pl-5 pr-5 pt-2 pb-2 hover:bg-zinc-600 border-t border-zinc-500">
Profile</RouterLink>
<RouterLink :to="{ name: 'Preferencies-Account' }"
:class="{ 'bg-zinc-600': preferenciesStore.current_tab === 1 }"
class="flex min-w-7 pl-5 pr-5 pt-2 pb-2 hover:bg-zinc-600 border-t border-zinc-500">
Account</RouterLink>
</div>
</div>
</div>
</Base>
</template>
<style>
.content {
width: 1280px;
max-width: calc(100% - 64px);
}
</style>

View File

@ -0,0 +1,53 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import Error from "@/components/error/Error.vue";
import { ref, onMounted, watch, getCurrentInstance } from "vue";
import { onBeforeRouteUpdate, useRoute } from "vue-router"
import User from "@/services/user";
import { useUserStore } from "@/stores/user";
const route = useRoute();
const name = ref<string>(null);
const userStore = useUserStore();
const error = ref<string>(null);
async function user_profile(login: string) {
await User.get(login)
.then(async response => {
error.value = null;
if (response.status != 200) {
return Promise.reject(response.data && response.data.message || response.status);
};
if (response.data.hasOwnProperty("user")) {
name.value = response.data.user.name;
} else {
error.value = "404 Not Found";
};
})
.catch(e => {
console.error("Error occured:", e);
});
};
onMounted(async () => {
await user_profile(route.params.user);
});
watch(route, async (to, from) => {
await user_profile(to.params.user);
});
</script>
<template>
<Base>
<div class="ml-auto mr-auto w-1/2 pt-5 pb-5">
<Error v-if="error">{{ error }}</Error>
<p v-else>{{ name }}</p>
</div>
</Base>
</template>

View File

@ -1,11 +1,18 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import Error from "@/components/error/Error.vue";
import { ref } from "vue";
import router from "@/router";
import User from "@/services/user";
import { useUserStore } from "@/stores/user";
const email = defineModel("email");
const password = defineModel("password");
const errorMessage = ref(null);
const error = ref(null);
const userStore = useUserStore();
async function login() {
await User.login(email.value, password.value)
@ -14,17 +21,18 @@ async function login() {
return Promise.reject(response.data && response.data.message || response.status);
}
const login = response.data.user.login;
router.push({ path: `/${login}` });
userStore.login = response.data.user.login;
router.push({ path: `/${userStore.login}` });
})
.catch(error => {
errorMessage.value = error;
console.error(error);
.catch(e => {
error.value = e;
console.log(`${e.name}[${e.code}]: ${e.message}`);
});
};
</script>
<template>
<Base>
<div class="ml-auto mr-auto w-1/2 pt-5 pb-5">
<h4 class="text-center pt-5 pb-5 border-b border-zinc-500">Sign In</h4>
<form @submit.prevent class="m-auto pt-5 pb-5">
@ -40,11 +48,17 @@ async function login() {
</div>
<div class="mb-5 ml-auto mr-auto">
<label class="text-right w-64 inline-block mr-5"></label>
<div class="flex justify-between items-center w-1/2 m-auto">
<button @click="login" class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5">Sign
In</button>
<p>or</p>
<button @click="$router.push('/user/register')"
class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5">Sign
Up</button>
</div>
</div>
</form>
<p v-if="errorMessage" class="text-center pt-3 pb-3 bg-orange-900 rounded border border-orange-700">{{
errorMessage }}</p>
<Error v-if="error">{{ error }}</Error>
</div>
</Base>
</template>

View File

@ -0,0 +1,61 @@
<script setup lang="ts">
import Base from "@/views/Base.vue";
import Error from "@/components/error/Error.vue";
import { ref } from "vue";
import router from "@/router";
import User from "@/services/user";
const login = defineModel("login");
const email = defineModel("email");
const password = defineModel("password");
const error = ref(null);
async function register() {
await User.register(login.value, email.value, password.value)
.then(async response => {
if (response.status != 200) {
return Promise.reject(response.data && response.data.message || response.status);
}
router.push({ path: "/user/login" });
})
.catch(e => {
error.value = e;
console.log(`${e.name}[${e.code}]: ${e.message}`);
});
};
</script>
<template>
<Base>
<div class="ml-auto mr-auto w-1/2 pt-5 pb-5">
<h4 class="text-center pt-5 pb-5 border-b border-zinc-500">Sign Up</h4>
<form @submit.prevent class="m-auto pt-5 pb-5">
<div class="mb-5 ml-auto mr-auto">
<label for="login" class="text-right w-64 inline-block mr-5">Login</label>
<input v-model="login" type="" placeholder="" name="login" required
class="w-1/2 bg-zinc-800 pl-3 pr-3 pt-2 pb-2 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="mb-5 ml-auto mr-auto">
<label for="email" class="text-right w-64 inline-block mr-5">Email Address</label>
<input v-model="email" type="email" placeholder="" name="email" required
class="w-1/2 bg-zinc-800 pl-3 pr-3 pt-2 pb-2 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="mb-5 ml-auto mr-auto">
<label for="password" class="text-right w-64 inline-block mr-5">Password</label>
<input v-model="password" placeholder="" type="password" name="password" required
class="w-1/2 bg-zinc-800 pl-3 pr-3 pt-2 pb-2 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="mb-5 ml-auto mr-auto">
<label class="text-right w-64 inline-block mr-5"></label>
<button @click="register" class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5">Sign
Up</button>
</div>
</form>
<Error v-if="error">{{ error }}</Error>
</div>
</Base>
</template>

View File

@ -0,0 +1,108 @@
<script setup lang="ts">
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";
const password = defineModel("password");
const new_password = defineModel("new-password");
const confirm_new_password = defineModel("confirm-new-password");
const email = defineModel("email");
const new_email = defineModel("new-email");
const confirm_password = defineModel("confirm-password");
const error = ref(null);
const userStore = useUserStore();
const preferenciesStore = usePreferenciesStore();
onMounted(async () => {
preferenciesStore.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}`);
});
});
</script>
<template>
<div class="flex flex-col gap-4 ml-auto mr-auto w-full">
<div class="border rounded border-zinc-500 w-full flex-col">
<h1 class="pl-5 pr-5 pt-2 pb-2">Password</h1>
<div class="border-t border-zinc-500 p-5">
<form @submit.prevent class="">
<div>
<label class="block mb-2" for="password">Current password</label>
<input v-model="password" name="password" type="password"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div>
<label class="block mb-2" for="new-password">New password</label>
<input v-model="new_password" name="new-password" type="password"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div>
<label class="block mb-2" for="confirm-new-password">Confirm new password</label>
<input v-model="confirm_new_password" name="confirm-new-password" type="password"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="border-t border-zinc-500 ml-0 mr-0 mt-3 mb-3"></div>
<button class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5 ml-auto mr-0 block">Update
password</button>
</form>
</div>
</div>
<div class="border rounded border-zinc-500 w-full flex-col">
<h1 class="pl-5 pr-5 pt-2 pb-2">Email</h1>
<div class="border-t border-zinc-500 p-5">
<form @submit.prevent class="">
<div>
<label class="block mb-2" for="email">Email</label>
<strong class="block w-full mb-4">{{ email }}</strong>
</div>
<div>
<label class="block mb-2" for="new-email">New email</label>
<input v-model="new_email" name="new-email" type="email"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="border-t border-zinc-500 ml-0 mr-0 mt-3 mb-3"></div>
<button class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5 ml-auto mr-0 block">Update
email</button>
</form>
</div>
</div>
<div class="border rounded border-red-500 w-full flex-col">
<h1 class="pl-5 pr-5 pt-2 pb-2">Delete account</h1>
<div class="border-t border-red-500 p-5">
<form @submit.prevent class="">
<div>
<label class="block mb-2" for="confirm-password">Password</label>
<input v-model="confirm_password" name="confirm-password" type="password"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="border-t border-zinc-500 ml-0 mr-0 mt-3 mb-3"></div>
<button
class="rounded bg-red-500 hover:bg-red-400 pb-2 pt-2 pl-5 pr-5 ml-auto mr-0 block">Confirm</button>
</form>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,67 @@
<script setup lang="ts">
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";
const login = defineModel("login");
const name = defineModel("name");
const email = defineModel("email");
const error = ref(null);
const userStore = useUserStore();
const preferenciesStore = usePreferenciesStore();
onMounted(async () => {
preferenciesStore.current_tab = 0;
!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);
};
login.value = response.data.user.login;
name.value = response.data.user.name;
email.value = response.data.user.email;
})
.catch(e => {
error.value = e;
console.log(`${e.name}[${e.code}]: ${e.message}`);
})
});
</script>
<template>
<div class="border rounded border-zinc-500 w-full flex-col">
<h1 class="pl-5 pr-5 pt-2 pb-2">Profile Info</h1>
<div class="border-t border-zinc-500 p-5">
<form @submit.prevent class="">
<div>
<label class="block mb-2" for="login">Login</label>
<input v-model="login" name="login"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div>
<label class="block mb-2" for="name">Username</label>
<input v-model="name" name="name"
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div>
<label class="block mb-2 " for="email">Email</label>
<input v-model="email" email="email" disabled
class="w-full bg-zinc-800 pl-3 pr-3 pt-2 pb-2 mb-4 outline-none rounded border border-zinc-500 hover:border-zinc-400 focus:border-green-800">
</div>
<div class="border-t border-zinc-500 ml-0 mr-0 mt-3 mb-3"></div>
<button
class="rounded bg-zinc-500 hover:bg-zinc-400 pb-2 pt-2 pl-5 pr-5 ml-auto mr-0 block">Update</button>
</form>
</div>
</div>
</template>

View File

@ -15,7 +15,7 @@ pub enum AuthError<E> {
impl<E: std::error::Error> IntoResponse for AuthError<E> {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
Self::InternalError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
Self::InternalError(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Internal Error: {}", e.to_string())),
Self::InternalE => (StatusCode::INTERNAL_SERVER_ERROR, "Internal E".to_string()),
Self::MissingCredentials => {
(StatusCode::BAD_REQUEST, "Missing credentials".to_string())
@ -28,10 +28,13 @@ impl<E: std::error::Error> IntoResponse for AuthError<E> {
Self::MissingUser => (StatusCode::UNAUTHORIZED, "User not exists".to_string()),
};
(
status,
Json(json!({
"status": status.to_string(),
"message": message
}))
})),
)
.into_response()
}
}

View File

@ -22,9 +22,7 @@ use super::token::TokenClaims;
pub struct RegisterUser {
pub login: String,
pub password: String,
pub name: String,
pub email: String,
pub is_admin: bool,
}
#[derive(serde::Serialize)]
@ -65,11 +63,11 @@ pub async fn register(
) -> Result<impl IntoResponse, AuthError<impl std::error::Error>> {
let user = User::register(
&state.database,
body.login,
body.login.to_owned(),
body.password,
body.name,
body.login, //body.name,
body.email,
body.is_admin,
false, //body.is_admin,
)
.await
.map_err(AuthError::InternalError)?;