fix: api client, auth workflow
This commit is contained in:
parent
aef6c2b541
commit
ec41110e0b
@ -1,4 +1,4 @@
|
|||||||
import { client, type ResponseError, handle_error } from "@/api/client";
|
import { api_client, type ResponseError, handle_error } from "@/client";
|
||||||
|
|
||||||
export interface UserCredentials {
|
export interface UserCredentials {
|
||||||
name: string,
|
name: string,
|
||||||
@ -7,17 +7,16 @@ export interface UserCredentials {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function signup(body: UserCredentials): Promise<null | ResponseError> {
|
export async function signup(body: UserCredentials): Promise<null | ResponseError> {
|
||||||
return await client.post("/auth/signup", JSON.stringify(body))
|
return await api_client.post("/auth/signup", JSON.stringify(body))
|
||||||
.catch(handle_error);
|
.catch(handle_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signin(body: UserCredentials): Promise<null | ResponseError> {
|
export async function signin(body: UserCredentials): Promise<null | ResponseError> {
|
||||||
return await client.post("/auth/signin", JSON.stringify(body))
|
return await api_client.post("/auth/signin", JSON.stringify(body))
|
||||||
.catch(handle_error);
|
.catch(handle_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function signout(): Promise<null | ResponseError> {
|
export async function signout(): Promise<null | ResponseError> {
|
||||||
return await client.post("/auth/signout")
|
return await api_client.get("/auth/signout")
|
||||||
.catch(handle_error);
|
.catch(handle_error);
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export * as auth from "@/api/auth";
|
export * as auth from "@/api/auth";
|
||||||
export * as user from "@/api/user";
|
export * as user from "@/api/user";
|
||||||
|
export * as repository from "@/api/repository";
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { api_client, type ResponseError, handle_error } from "@/client";
|
||||||
|
|
||||||
|
export interface RepositoryInfo {
|
||||||
|
id: number,
|
||||||
|
capacity: number,
|
||||||
|
used?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function info(): Promise<RepositoryInfo | ResponseError> {
|
||||||
|
return await api_client.get("/repository")
|
||||||
|
.then(async response => { return Promise.resolve<RepositoryInfo>(response.data); })
|
||||||
|
.catch(handle_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function create(): Promise<null | ResponseError> {
|
||||||
|
return await api_client.post("/repository")
|
||||||
|
.catch(handle_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function remove(): Promise<null | ResponseError> {
|
||||||
|
return await api_client.delete("/repository")
|
||||||
|
.catch(handle_error);
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { client, upload_client, resources_client, type ResponseError, handle_error } from "@/api/client";
|
import { api_client, type ResponseError, handle_error } from "@/client";
|
||||||
|
|
||||||
export interface UserCredentials {
|
export interface UserCredentials {
|
||||||
name: string,
|
name: string,
|
||||||
@ -6,77 +6,30 @@ export interface UserCredentials {
|
|||||||
email?: string
|
email?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signup(body: UserCredentials): Promise<null | ResponseError> {
|
export interface UserInfo {
|
||||||
return await client.post("/auth/signup", JSON.stringify(body))
|
id: string,
|
||||||
.catch(handle_error);
|
name: string,
|
||||||
|
lower_name: string,
|
||||||
|
full_name?: string,
|
||||||
|
email?: string,
|
||||||
|
is_email_private: boolean,
|
||||||
|
must_change_password: boolean,
|
||||||
|
login_type: string,
|
||||||
|
created: number,
|
||||||
|
updated: number,
|
||||||
|
last_login?: number,
|
||||||
|
is_active: boolean,
|
||||||
|
is_admin: boolean,
|
||||||
|
avatar?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signin(body: UserCredentials): Promise<null | ResponseError> {
|
|
||||||
return await client.post("/auth/signin", JSON.stringify(body))
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Image = string | ArrayBuffer;
|
export type Image = string | ArrayBuffer;
|
||||||
|
|
||||||
export async function register(body: NewUser): Promise<User | ResponseError> {
|
export async function info(): Promise<UserInfo | ResponseError> {
|
||||||
return await client.post("/user/register", JSON.stringify(body))
|
return await api_client.get("/user")
|
||||||
.then(async response => { return Promise.resolve<User>(response.data); })
|
.then(async response => { return Promise.resolve<UserInfo>(response.data); })
|
||||||
.catch(handle_error);
|
.catch(handle_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function login(body: LoginUser): Promise<User | ResponseError> {
|
|
||||||
return await client.post("/user/login", JSON.stringify(body))
|
|
||||||
.then(async response => { return Promise.resolve<User>(response.data); })
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function remove(body: RemoveUser): Promise<null | ResponseError> {
|
|
||||||
return await client.post("/user/remove", JSON.stringify(body))
|
|
||||||
.then(async () => { return Promise.resolve(null); })
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function logout(): Promise<null | ResponseError> {
|
|
||||||
return await client.get("/user/logout")
|
|
||||||
.then(async () => { return Promise.resolve(null); })
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function current(): Promise<User | ResponseError> {
|
|
||||||
return await client.get("/user/current")
|
|
||||||
.then(async response => { return Promise.resolve<User>(response.data); })
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function avatar(file: FormData, progress?: any): Promise<null | ResponseError> {
|
|
||||||
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<Image | null | ResponseError> {
|
|
||||||
return await resources_client.get("/avatars/".concat(avatar))
|
|
||||||
.then(async response => {
|
|
||||||
return new Promise<Image | null>((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<User | ResponseError> {
|
|
||||||
return await client.get("/user/".concat(login))
|
|
||||||
.then(async response => { return Promise.resolve<User>(response.data); })
|
|
||||||
.catch(handle_error);
|
|
||||||
}
|
|
||||||
|
@ -22,11 +22,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@apply pt-2 pb-2 pl-5 pr-5 rounded bg-ctp-mantle hover:bg-ctp-base text-ctp-blue;
|
@apply pt-2 pb-2 pl-5 pr-5 rounded bg-ctp-mantle hover:bg-ctp-base text-ctp-blue cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-button {
|
.link-button {
|
||||||
@apply button text-ctp-green;
|
@apply button text-ctp-green cursor-pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hline {
|
||||||
|
@apply border-t border-ctp-overlay0 ml-0 mr-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -30,7 +30,7 @@ export function handle_error(error: AxiosError): Promise<ResponseError> {
|
|||||||
|
|
||||||
const debug = import.meta.hot;
|
const debug = import.meta.hot;
|
||||||
|
|
||||||
export const client: AxiosInstance = axios.create({
|
export const api_client: AxiosInstance = axios.create({
|
||||||
baseURL: debug ? "http://localhost:54601/api" : "/api",
|
baseURL: debug ? "http://localhost:54601/api" : "/api",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
@ -38,17 +38,8 @@ export const client: AxiosInstance = axios.create({
|
|||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const upload_client: AxiosInstance = axios.create({
|
|
||||||
baseURL: debug ? "http://localhost:54601/api" : "/api",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data"
|
|
||||||
},
|
|
||||||
withCredentials: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const resources_client: AxiosInstance = axios.create({
|
export const resources_client: AxiosInstance = axios.create({
|
||||||
baseURL: debug ? "http://localhost:54601/resources" : "/resources",
|
baseURL: debug ? "http://localhost:54601/resources" : "/resources",
|
||||||
responseType: "blob"
|
responseType: "blob"
|
||||||
});
|
});
|
||||||
|
|
||||||
export default client;
|
|
@ -1 +1,2 @@
|
|||||||
export * as api from "@/api";
|
export * as api from "@/api";
|
||||||
|
export * as resources from "@/resources";
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { resources_client, type ResponseError, handle_error } from "@/client";
|
||||||
|
|
||||||
|
|
||||||
|
export type Image = string | ArrayBuffer;
|
||||||
|
|
||||||
|
export async function avatars(avatar_id: string, format?: string): Promise<Image | null | ResponseError> {
|
||||||
|
return await resources_client.get("/avatars/".concat(avatar_id), { params: { format: format ? format : "png" }})
|
||||||
|
.then(async response => {
|
||||||
|
return new Promise<Image | null>((resolve, reject) => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = () => {
|
||||||
|
resolve(reader.result);
|
||||||
|
};
|
||||||
|
reader.onerror = (e) => {
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(response.data);
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(handle_error);
|
||||||
|
}
|
@ -1,18 +1,16 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
|
|
||||||
import { user } from "@/api";
|
|
||||||
import { useUserStore } from "@/stores";
|
import { useUserStore } from "@/stores";
|
||||||
|
import { api, resources } from "@";
|
||||||
|
|
||||||
async function check_authorized(): Promise<boolean> {
|
async function check_authorized(): Promise<boolean> {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
// TODO: add timer
|
return await api.user.info()
|
||||||
return await user.current()
|
.then(async user_info => { userStore.info = user_info; })
|
||||||
.then(async user => { userStore.current = user; })
|
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
if (userStore.current.avatar?.length) {
|
if (!userStore.avatar && userStore.info.avatar) {
|
||||||
await user.get_avatar(userStore.current.avatar)
|
await resources.avatars(userStore.info.avatar)
|
||||||
.then(async avatar => { userStore.avatar = avatar; })
|
.then(async avatar => { userStore.avatar = avatar; })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -69,8 +67,8 @@ const router = createRouter({
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:user", name: "profile", beforeEnter: [bypass_auth],
|
path: "/:user/repository", name: "repository", beforeEnter: [required_auth],
|
||||||
component: () => import("@/views/user/Profile.vue")
|
component: () => import("@/views/Repository.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/admin/settings", name: "settings", beforeEnter: [required_auth, required_admin],
|
path: "/admin/settings", name: "settings", beforeEnter: [required_auth, required_admin],
|
||||||
|
@ -2,17 +2,18 @@ import { defineStore } from "pinia";
|
|||||||
import { ref, type Ref } from "vue";
|
import { ref, type Ref } from "vue";
|
||||||
|
|
||||||
import { user } from "@/api";
|
import { user } from "@/api";
|
||||||
|
import { resources } from "@";
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
const current: Ref<user.User | null> = ref(null);
|
const info: Ref<user.UserInfo | null> = ref(null);
|
||||||
const avatar: Ref<Blob | null> = ref(null);
|
const avatar: Ref<resources.Image | null> = ref(null);
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
current.value = null;
|
info.value = null;
|
||||||
avatar.value = null;
|
avatar.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { current, avatar, clear };
|
return { info, avatar, clear };
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useMiscStore = defineStore("misc", () => {
|
export const useMiscStore = defineStore("misc", () => {
|
||||||
|
@ -5,14 +5,15 @@ import DropdownMenu from "@/components/DropdownMenu.vue";
|
|||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { user } from "@/api";
|
import { user, auth } from "@/api";
|
||||||
|
import { resources } from "@";
|
||||||
import { useUserStore } from "@/stores";
|
import { useUserStore } from "@/stores";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const error = ref(null);
|
const error = ref(null);
|
||||||
|
|
||||||
async function signout() {
|
async function signout() {
|
||||||
await user.logout()
|
await auth.signout()
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
userStore.clear();
|
userStore.clear();
|
||||||
router.push({ path: "/" });
|
router.push({ path: "/" });
|
||||||
@ -28,36 +29,36 @@ async function signout() {
|
|||||||
<template #left>
|
<template #left>
|
||||||
<RouterLink class="link-button" to="/">Home</RouterLink>
|
<RouterLink class="link-button" to="/">Home</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right v-if="userStore.info">
|
||||||
<DropdownMenu v-if="userStore.current">
|
<RouterLink v-if="userStore.info.is_admin" :to="{ name: 'settings' }" class="link-button">Settings
|
||||||
|
</RouterLink>
|
||||||
|
<DropdownMenu>
|
||||||
<template #button>
|
<template #button>
|
||||||
<div class="pl-3 pr-3 flex gap-2 items-center rounded hover:bg-zinc-600 cursor-pointer">
|
<div class="link-button flex">
|
||||||
<div class="max-w-8" v-if="userStore.avatar"><img :src="userStore.avatar"></div>
|
<span>{{ userStore.info.name }}</span>
|
||||||
<span class="flex min-w-9 min-h-9 items-center">{{userStore.current.login }}</span>
|
<div class="max-w-6 ml-4" v-if="userStore.avatar">
|
||||||
|
<img :src="userStore.avatar">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div
|
<div
|
||||||
class="absolute z-20 flex flex-col left-auto right-0 mt-4 bg-zinc-700 border rounded border-zinc-500 mr-3">
|
class="absolute z-20 flex flex-col left-auto right-0 mt-4 mr-3 bg-ctp-mantle border rounded border-ctp-overlay0">
|
||||||
<RouterLink :to="{ name: 'profile', params: { user: userStore.current.login } }"
|
<RouterLink :to="{ name: 'repository', params: { user: userStore.info.lower_name } }"
|
||||||
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
|
class="button">
|
||||||
Profile</RouterLink>
|
Repository</RouterLink>
|
||||||
<RouterLink :to="{ name: 'prefs' }"
|
<RouterLink :to="{ name: 'prefs' }" class="button">
|
||||||
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
|
|
||||||
Preferencies</RouterLink>
|
Preferencies</RouterLink>
|
||||||
<div class="border-t border-zinc-500 ml-0 mr-0"></div>
|
|
||||||
<RouterLink v-if="userStore.current.is_admin" :to="{ name: 'settings' }"
|
<div class="hline"></div>
|
||||||
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600">
|
<div @click="signout" class="button">
|
||||||
Settings</RouterLink>
|
|
||||||
<div class="border-t border-zinc-500 ml-0 mr-0"></div>
|
|
||||||
<div @click="signout"
|
|
||||||
class="flex min-w-7 pl-5 pr-5 pt-1 pb-1 hover:bg-zinc-600 cursor-pointer">
|
|
||||||
Sign Out</div>
|
Sign Out</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
</template>
|
||||||
<RouterLink v-if="!userStore.current" class="link-button" to="/user/login">Sign In</RouterLink>
|
<template #right v-else>
|
||||||
|
<RouterLink class="link-button" to="/auth/signin">Sign In</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
</NavBar>
|
</NavBar>
|
||||||
|
|
||||||
@ -68,8 +69,7 @@ async function signout() {
|
|||||||
|
|
||||||
<div class="relative overflow-hidden h-full ">
|
<div class="relative overflow-hidden h-full ">
|
||||||
</div>
|
</div>
|
||||||
<footer
|
<footer class="flex justify-between pb-2 pt-2 pl-5 pr-5 bg-ctp-mantle">
|
||||||
class="flex justify-between pb-2 pt-2 pl-5 pr-5 bg-ctp-mantle">
|
|
||||||
<a href="/">Made with glove by Elnafo, 2024</a>
|
<a href="/">Made with glove by Elnafo, 2024</a>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
<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 { repository } from "@/api";
|
||||||
|
import { useUserStore } from "@/stores";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const error = ref<string>(null);
|
||||||
|
|
||||||
|
const repository_info = ref(null);
|
||||||
|
const is_created = ref(null);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await repository.info()
|
||||||
|
.then(async _repository_info => {
|
||||||
|
is_created.value = true;
|
||||||
|
repository_info.value = _repository_info;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
is_created.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function create_repository() {
|
||||||
|
await repository.create()
|
||||||
|
.then(async () => {
|
||||||
|
await repository.info()
|
||||||
|
.then(async _repository_info => {
|
||||||
|
repository_info.value = _repository_info;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
error.value = err;
|
||||||
|
});
|
||||||
|
|
||||||
|
is_created.value = true;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
error.value = err;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function round_size(size: number, mesure: string) {
|
||||||
|
if (mesure == "GB") {
|
||||||
|
return size / 8 / 1024 / 1024;
|
||||||
|
} else if (mesure == "MB") {
|
||||||
|
return size / 8 / 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function size_procent() {
|
||||||
|
return Math.round(repository_info.value.used / repository_info.value.capacity) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Base>
|
||||||
|
<Error v-if="error">{{ error }}</Error>
|
||||||
|
<section v-if="is_created">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-full rounded-full h-2.5 bg-ctp-surface0">
|
||||||
|
<div class="bg-ctp-lavender h-2.5 rounded-full" :style="{ width: size_procent() + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
<span class="min-w-32 text-center">{{ round_size(repository_info.used, "GB") }} / {{
|
||||||
|
round_size(repository_info.capacity, "GB") }} GB</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section v-else>
|
||||||
|
<p>It looks like you don't have a repository yet...</p>
|
||||||
|
<div class="flex justify-center mt-8">
|
||||||
|
<button @click="create_repository" class="button">+ Create repository</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Base>
|
||||||
|
</template>
|
@ -40,7 +40,7 @@ async function signin() {
|
|||||||
|
|
||||||
await api.auth.signin(body)
|
await api.auth.signin(body)
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
//userStore.current = user;
|
//userStore.info = user_info;
|
||||||
router.push({ path: "/" });
|
router.push({ path: "/" });
|
||||||
})
|
})
|
||||||
.catch(err => { error.value = err.message; });
|
.catch(err => { error.value = err.message; });
|
||||||
@ -62,7 +62,7 @@ async function signin() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-5 flex justify-between items-center">
|
<div class="mb-5 flex justify-between items-center">
|
||||||
<button @click="signin" class="button">Sign In</button>
|
<button @click="signin" class="button">Sign In</button>
|
||||||
<button @click="$router.push('/user/register')" class="button">Sign Up</button>
|
<button @click="$router.push('/auth/signup')" class="button">Sign Up</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Error v-if="error">{{ error }}</Error>
|
<Error v-if="error">{{ error }}</Error>
|
||||||
|
@ -18,7 +18,7 @@ async function signup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await api.auth.signup({ name: login.value, password: password.value, email: email.value })
|
await api.auth.signup({ name: login.value, password: password.value, email: email.value })
|
||||||
.then(async user => { router.push({ path: "/user/login" }); })
|
.then(async user => { router.push({ path: "/auth/signin" }); })
|
||||||
.catch(err => { error.value = err.message; });
|
.catch(err => { error.value = err.message; });
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user