Merge remote-tracking branch 'origin/main' into Css&HomePage
This commit is contained in:
6
.vscode/extensions.json
vendored
6
.vscode/extensions.json
vendored
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
"recommendations": [
|
||||||
|
"Vue.volar",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"vuetifyjs.vuetify-vscode"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit"
|
"source.fixAll": "always",
|
||||||
|
"source.organizeImports": "always"
|
||||||
},
|
},
|
||||||
"eslint.validate": [
|
"eslint.validate": [
|
||||||
"javascript"
|
"javascript"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Hutopia
|
# Hutopia
|
||||||
|
|
||||||
This template should help get you started developing with Vue 3 in Vite.
|
Hutopia frontEnd. Using vue3 and vuetify3.
|
||||||
|
|
||||||
## Recommended IDE Setup
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
defineProps({
|
|
||||||
msg: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="greetings">
|
|
||||||
<h1 class="green">{{ msg }}</h1>
|
|
||||||
<h3>
|
|
||||||
You’ve successfully created a project with
|
|
||||||
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
|
|
||||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
h1 {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 2.6rem;
|
|
||||||
position: relative;
|
|
||||||
top: -10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.greetings h1,
|
|
||||||
.greetings h3 {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.greetings h1,
|
|
||||||
.greetings h3 {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import WelcomeItem from './WelcomeItem.vue'
|
|
||||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
|
||||||
import ToolingIcon from './icons/IconTooling.vue'
|
|
||||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
|
||||||
import CommunityIcon from './icons/IconCommunity.vue'
|
|
||||||
import SupportIcon from './icons/IconSupport.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<DocumentationIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Documentation</template>
|
|
||||||
|
|
||||||
Vue’s
|
|
||||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
|
||||||
provides you with all information you need to get started.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<ToolingIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Tooling</template>
|
|
||||||
|
|
||||||
This project is served and bundled with
|
|
||||||
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
|
||||||
recommended IDE setup is
|
|
||||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
|
|
||||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
|
|
||||||
you need to test your components and web pages, check out
|
|
||||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
|
|
||||||
<a href="https://on.cypress.io/component" target="_blank" rel="noopener"
|
|
||||||
>Cypress Component Testing</a
|
|
||||||
>.
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
More instructions are available in <code>README.md</code>.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<EcosystemIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Ecosystem</template>
|
|
||||||
|
|
||||||
Get official tools and libraries for your project:
|
|
||||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
|
||||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
|
||||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
|
||||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
|
||||||
you need more resources, we suggest paying
|
|
||||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
|
||||||
a visit.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<CommunityIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Community</template>
|
|
||||||
|
|
||||||
Got stuck? Ask your question on
|
|
||||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
|
|
||||||
Discord server, or
|
|
||||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
|
||||||
>StackOverflow</a
|
|
||||||
>. You should also subscribe to
|
|
||||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
|
|
||||||
the official
|
|
||||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
|
||||||
twitter account for latest news in the Vue world.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<SupportIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Support Vue</template>
|
|
||||||
|
|
||||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
|
||||||
us by
|
|
||||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
|
||||||
</WelcomeItem>
|
|
||||||
</template>
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="item">
|
|
||||||
<i>
|
|
||||||
<slot name="icon"></slot>
|
|
||||||
</i>
|
|
||||||
<div class="details">
|
|
||||||
<h3>
|
|
||||||
<slot name="heading"></slot>
|
|
||||||
</h3>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.item {
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
|
||||||
flex: 1;
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
place-content: center;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 0.4rem;
|
|
||||||
color: var(--color-heading);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.item {
|
|
||||||
margin-top: 0;
|
|
||||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
top: calc(50% - 25px);
|
|
||||||
left: -26px;
|
|
||||||
position: absolute;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
background: var(--color-background);
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:before {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:after {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:first-of-type:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:last-of-type:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -91,6 +91,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div v-if="user">
|
||||||
|
Hello, {{ user.email }}
|
||||||
|
</div>
|
||||||
|
<v-btn color="red" variant="text" @click="logout()">Logout</v-btn>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -113,13 +117,20 @@
|
|||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useAuthStore } from '@/plugins/store/authStore';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
authStore.logout();
|
||||||
|
router.push('/login');
|
||||||
|
}
|
||||||
|
|
||||||
<script>
|
const user = authStore.user;
|
||||||
export default {
|
|
||||||
name: 'App',
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style src="../cssstyle/index.css"></style>
|
<style src="../cssstyle/index.css"></style>
|
||||||
@@ -3,24 +3,25 @@ import { createApp } from 'vue'
|
|||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import axios from 'axios'
|
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
import '@mdi/font/css/materialdesignicons.css'
|
||||||
import 'vuetify/styles'
|
import 'vuetify/styles'
|
||||||
import { createVuetify } from 'vuetify'
|
import { createVuetify } from 'vuetify'
|
||||||
import * as components from 'vuetify/components'
|
import * as components from 'vuetify/components'
|
||||||
import * as directives from 'vuetify/directives'
|
import * as directives from 'vuetify/directives'
|
||||||
|
import clientPlugin from './plugins/clientPlugin'
|
||||||
|
|
||||||
const vuetify = createVuetify({
|
const vuetify = createVuetify({
|
||||||
components,
|
components,
|
||||||
directives
|
directives
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.defaults.baseURL = 'http://127.0.0.1:8000';
|
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
// Create an axios client preconfigured to the Hutopy API.
|
||||||
|
app.use(clientPlugin);
|
||||||
|
|
||||||
app.use(createPinia());
|
app.use(createPinia());
|
||||||
app.use(vuetify);
|
app.use(vuetify);
|
||||||
app.use(router, axios);
|
app.use(router);
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
34
src/plugins/clientPlugin.js
Normal file
34
src/plugins/clientPlugin.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
const clientKey = Symbol('client');
|
||||||
|
|
||||||
|
export default {
|
||||||
|
//todo: Need to have the baseURL in the config for later ( dev and prod env. )
|
||||||
|
install: (app) => {
|
||||||
|
const axiosInstance = axios.create({
|
||||||
|
baseURL: 'https://localhost:5001/',
|
||||||
|
timeout: 2000,
|
||||||
|
});
|
||||||
|
|
||||||
|
axiosInstance.interceptors.request.use((config) => {
|
||||||
|
const token = localStorage.getItem('jwt');
|
||||||
|
if (token) {
|
||||||
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}, (error) => {
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.provide(clientKey, axiosInstance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useClient() {
|
||||||
|
const client = inject(clientKey);
|
||||||
|
if (!client) {
|
||||||
|
throw new Error('Axios instance is not provided');
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
55
src/plugins/store/authStore.js
Normal file
55
src/plugins/store/authStore.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
const baseUrl = '/api/Users';
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore({
|
||||||
|
id: 'auth',
|
||||||
|
state: () => ({
|
||||||
|
user: null,
|
||||||
|
refreshTokenTimeout: null
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async login(client, email, password) {
|
||||||
|
const requestBody = {
|
||||||
|
email: email,
|
||||||
|
password: password
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const response = await client.post(`${baseUrl}/login`, requestBody)
|
||||||
|
this.user = {
|
||||||
|
accessToken: response.data.accessToken,
|
||||||
|
refreshToken: response.data.refreshToken,
|
||||||
|
email: email
|
||||||
|
}
|
||||||
|
localStorage.setItem('jwt', this.user.accessToken);
|
||||||
|
this.startRefreshTokenTimer();
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('Login failed.')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
localStorage.setItem('jwt', '');
|
||||||
|
this.stopRefreshTokenTimer();
|
||||||
|
this.user = null;
|
||||||
|
|
||||||
|
},
|
||||||
|
async refreshToken(client) {
|
||||||
|
const response = await client.post(`${baseUrl}/refresh`, {});
|
||||||
|
this.user.accessToken = response.accessToken;
|
||||||
|
localStorage.setItem('jwt', this.user.accessToken);
|
||||||
|
|
||||||
|
|
||||||
|
this.startRefreshTokenTimer();
|
||||||
|
},
|
||||||
|
startRefreshTokenTimer() {
|
||||||
|
const timeout = 50 * 1000;
|
||||||
|
this.refreshTokenTimeout = setTimeout(this.refreshToken, timeout);
|
||||||
|
},
|
||||||
|
stopRefreshTokenTimer() {
|
||||||
|
clearTimeout(this.refreshTokenTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,47 +1,66 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="max-w-7x1 max-auto grid grid-cols-2 gap-4">
|
<v-row align="center" justify="center">
|
||||||
<div class="main-left">
|
<v-col cols="4">
|
||||||
<div class="p-12 bg-white border border-gray-200 rounded-lg">
|
<v-container>
|
||||||
<h1 class="mb-6 text-2xl font-bold">Log in</h1>
|
<v-card>
|
||||||
|
<v-toolbar color="primary" :dark="true">
|
||||||
|
<v-toolbar-title>Login</v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-card-text>
|
||||||
|
<v-form>
|
||||||
|
<v-text-field prepend-icon="person" type="text" v-model="user.email" label="E-mail"></v-text-field>
|
||||||
|
<v-text-field
|
||||||
|
prepend-icon="lock"
|
||||||
|
type="password"
|
||||||
|
v-model="user.password"
|
||||||
|
label="password"
|
||||||
|
></v-text-field>
|
||||||
|
</v-form>
|
||||||
|
<v-snackbar v-model="errorSnackBar">
|
||||||
|
Email ou mot de passe invalide.
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn color="red" variant="text" @click="errorSnackBar = false">
|
||||||
|
Fermer
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<div class="flex-grow-1"></div>
|
||||||
|
<v-btn color="primary" @click="login">Login</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
<v-btn color="red" @click="goHome()">Continuer sans se connecter</v-btn>
|
||||||
|
|
||||||
<p class="mb-6 texte-gray-500"> Lorem Ipsum is simply dummy text of the printing and typesetting industry.
|
</v-container>
|
||||||
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer
|
</v-col>
|
||||||
took a galley of type and scrambled it to make a type specimen book. It has survived not only five
|
</v-row>
|
||||||
centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was
|
|
||||||
popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more
|
|
||||||
recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. </p>
|
|
||||||
|
|
||||||
<p class="font-bold"> Don't have an account ? <RouterLink :to="{ 'name': 'signup' }" class="underline">Click
|
|
||||||
here</RouterLink> to create one! </p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="main-right">
|
|
||||||
<div class="p-12 bg-white border border-gray-200 rounded-lg">
|
|
||||||
<form class="space-y-6">
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label>E-mail</label> <br>
|
|
||||||
<input type="email" placeholder="Your e-mail adress"
|
|
||||||
class="w-full mt-2 py-4 px-6 border border-gray-200 rounded-lg">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label>Password</label> <br>
|
|
||||||
<input type="password" placeholder="Your password"
|
|
||||||
class="w-full mt-2 py-4 px-6 border border-gray-200 rounded-lg">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button class="py-4 px-6 bg-purple-600 text-white rounded-lg"> Log in</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useClient } from '@/plugins/clientPlugin';
|
||||||
|
import { useAuthStore } from '@/plugins/store/authStore';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const client = useClient();
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
let user = ref({});
|
||||||
|
let errorSnackBar = ref(false);
|
||||||
|
|
||||||
|
const goHome = () => {
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(){
|
||||||
|
try {
|
||||||
|
await authStore.login(client, user.value.email, user.value.password)
|
||||||
|
router.push('/');
|
||||||
|
} catch (error) {
|
||||||
|
errorSnackBar.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -340,35 +340,74 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<v-btn variant="outlined" @click="callBackend()">
|
||||||
|
Get items
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</v-app>
|
<v-snackbar v-model="errorNoAccessSnackBar">
|
||||||
|
Vous n'etes pas connecter !
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn color="red" variant="text" @click="errorNoAccessSnackBar = false">
|
||||||
|
Fermer
|
||||||
|
</v-btn>
|
||||||
|
<v-btn color="green" variant="text" @click="goToLoginPage()">
|
||||||
|
Se connecter
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
|
||||||
|
<v-list lines="one">
|
||||||
|
<v-list-item
|
||||||
|
v-for="item in itemList"
|
||||||
|
:key="item"
|
||||||
|
:title="item.id"
|
||||||
|
:subtitle="item.title"
|
||||||
|
></v-list-item>
|
||||||
|
</v-list>
|
||||||
<FooterLayout></FooterLayout>
|
<FooterLayout></FooterLayout>
|
||||||
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script async setup>
|
||||||
import DefaultLayout from '@/layouts/DefaultLayout.vue';
|
import DefaultLayout from '@/layouts/DefaultLayout.vue';
|
||||||
|
import { useClient } from '@/plugins/clientPlugin';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
import FooterLayout from '@/layouts/FooterLayout.vue';
|
import FooterLayout from '@/layouts/FooterLayout.vue';
|
||||||
|
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const client = useClient();
|
||||||
|
|
||||||
</script>
|
let itemList = ref([]);
|
||||||
|
let errorNoAccessSnackBar = ref(false);
|
||||||
|
|
||||||
<script>
|
const showOverlay(index) {
|
||||||
export default {
|
|
||||||
data: () => ({
|
|
||||||
overlays: [false, false, false],
|
|
||||||
}),
|
|
||||||
methods: {
|
|
||||||
showOverlay(index) {
|
|
||||||
this.overlays[index] = true;
|
this.overlays[index] = true;
|
||||||
},
|
},
|
||||||
hideOverlay(index) {
|
hideOverlay(index) {
|
||||||
this.overlays[index] = false;
|
this.overlays[index] = false;
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
async function callBackend() {
|
||||||
|
try {
|
||||||
|
const response = await client.get('/api/TodoItems?ListId=1&PageNumber=1&PageSize=10');
|
||||||
|
const responseItems = response.data.items;
|
||||||
|
const orderedResponseItems = responseItems.sort((a, b) => a.id - b.id);
|
||||||
|
itemList.value = orderedResponseItems
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
errorNoAccessSnackBar.value = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goToLoginPage = () => {
|
||||||
|
router.push('/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style src="../../cssstyle/index.css"></style>
|
<style src="../../cssstyle/index.css"></style>
|
||||||
|
|||||||
Reference in New Issue
Block a user