frontend: api client, dynamic routes
This commit is contained in:
parent
04dcf039c3
commit
e868c87a7e
11
crates/frontend/src/api-client.ts
Normal file
11
crates/frontend/src/api-client.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import axios, { type AxiosInstance } from "axios";
|
||||
|
||||
const api_client: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.hot ? "http://localhost:54600/api/v1" : "/api/v1",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
export default api_client;
|
5
crates/frontend/src/components/Error.vue
Normal file
5
crates/frontend/src/components/Error.vue
Normal file
@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<h1>
|
||||
<slot></slot>
|
||||
</h1>
|
||||
</template>
|
@ -1,30 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import router from '@/router';
|
||||
import { ref } from "vue";
|
||||
import router from "@/router";
|
||||
import User from "@/services/user";
|
||||
|
||||
const email = defineModel("email");
|
||||
const password = defineModel("password");
|
||||
const errorMessage = ref(null);
|
||||
|
||||
async function login() {
|
||||
await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/login" : "/api/v1/user/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify({ email: email.value, password: password.value })
|
||||
})
|
||||
await User.login(email.value, password.value)
|
||||
.then(async response => {
|
||||
//const isJson = response.headers.get('content-type')?.includes('application/json');
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
const error = (data && data.message) || response.status;
|
||||
return Promise.reject(error);
|
||||
if (response.status != 200) {
|
||||
return Promise.reject(response.data && response.data.message || response.status);
|
||||
}
|
||||
|
||||
router.push({ path: '/me' });
|
||||
const login = response.data.user.login;
|
||||
router.push({ path: `/${login}` });
|
||||
})
|
||||
.catch(error => {
|
||||
errorMessage.value = error;
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
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: '/me', component: () => import('./views/Me.vue') }
|
||||
{ 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") }
|
||||
]
|
||||
});
|
||||
|
||||
|
17
crates/frontend/src/services/user.ts
Normal file
17
crates/frontend/src/services/user.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import api_client from "@/api-client";
|
||||
|
||||
class User {
|
||||
async login(email: string, password: string): Promise<JSON> {
|
||||
return await api_client.post("/user/login", JSON.stringify({ email: email, password: password }));
|
||||
}
|
||||
|
||||
async get(login: any): Promise<JSON> {
|
||||
return await api_client.get(`/user/${login}`);
|
||||
}
|
||||
|
||||
async current(): Promise<JSON> {
|
||||
return await api_client.get("/user/current");
|
||||
}
|
||||
}
|
||||
|
||||
export default new User();
|
@ -1,10 +1,25 @@
|
||||
<script setup lang="ts">
|
||||
import Meerkat from '@/components/icons/Meerkat.vue';
|
||||
import NavBar from '@/components/NavBar.vue';
|
||||
import User from "@/services/user";
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
function next() {
|
||||
window.location.pathname = "/me";
|
||||
const user = 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")) {
|
||||
user.value = response.data.user;
|
||||
};
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("Error occured:", e);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -14,10 +29,11 @@ function next() {
|
||||
<Meerkat />
|
||||
</template>
|
||||
<template #right>
|
||||
<RouterLink class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600" to="/user/login">
|
||||
<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">
|
||||
Sign In</RouterLink>
|
||||
<a class="flex min-w-9 min-h-9 pt-1 pb-1 pl-3 pr-3 rounded hover:bg-zinc-600" href="/user/register">Sign
|
||||
up</a>
|
||||
</template>
|
||||
</NavBar>
|
||||
|
||||
|
10
crates/frontend/src/views/Error.vue
Normal file
10
crates/frontend/src/views/Error.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import Base from "@/views/Base.vue";
|
||||
import Error from "@/components/Error.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Base>
|
||||
<Error>Not Found</Error>
|
||||
</Base>
|
||||
</template>
|
@ -1,47 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import Base from '@/views/Base.vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
const email = ref(null);
|
||||
const name = ref(null);
|
||||
const is_admin = ref(null);
|
||||
const errorMessage = ref(null);
|
||||
|
||||
onMounted(async () => {
|
||||
const asd = await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/profile" : "/api/v1/user/profile", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then(async response => {
|
||||
const isJson = response.headers.get('content-type')?.includes('application/json');
|
||||
const data = isJson && await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
const error = (data && data.message) || response.status;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
name.value = data.user.name;
|
||||
email.value = data.user.email;
|
||||
is_admin.value = data.user.is_admin;
|
||||
})
|
||||
.catch(error => {
|
||||
errorMessage.value = error;
|
||||
console.error("Error occured:", error);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Base>
|
||||
<p v-if="errorMessage" class="text-center pt-3 pb-3 bg-orange-900 rounded border border-orange-700">{{
|
||||
errorMessage }}</p>
|
||||
<p>{{ name }}</p>
|
||||
<p>{{ email }}</p>
|
||||
<p>{{ is_admin }}</p>
|
||||
</Base>
|
||||
</template>
|
54
crates/frontend/src/views/User.vue
Normal file
54
crates/frontend/src/views/User.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<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>
|
Loading…
Reference in New Issue
Block a user