refacto !!!

This commit is contained in:
Guamss 2025-12-14 12:24:38 +01:00
parent d2b8c5ade4
commit cbc02ce5cc
8 changed files with 199 additions and 174 deletions

48
package-lock.json generated
View File

@ -1115,9 +1115,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.39.1", "version": "9.39.2",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
"integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1365,9 +1365,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@rolldown/pluginutils": { "node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.50", "version": "1.0.0-beta.53",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
"integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@ -1757,9 +1757,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.19.2", "version": "22.19.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
"integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==", "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2010,19 +2010,19 @@
} }
}, },
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "6.0.2", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz",
"integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", "integrity": "sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@rolldown/pluginutils": "1.0.0-beta.50" "@rolldown/pluginutils": "1.0.0-beta.53"
}, },
"engines": { "engines": {
"node": "^20.19.0 || >=22.12.0" "node": "^20.19.0 || >=22.12.0"
}, },
"peerDependencies": { "peerDependencies": {
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0",
"vue": "^3.2.25" "vue": "^3.2.25"
} }
}, },
@ -2453,9 +2453,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.9.6", "version": "2.9.7",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.7.tgz",
"integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", "integrity": "sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@ -2947,9 +2947,9 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.39.1", "version": "9.39.2",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2959,7 +2959,7 @@
"@eslint/config-helpers": "^0.4.2", "@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0", "@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.39.1", "@eslint/js": "9.39.2",
"@eslint/plugin-kit": "^0.4.1", "@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@ -5257,9 +5257,9 @@
} }
}, },
"node_modules/vue-router": { "node_modules/vue-router": {
"version": "4.6.3", "version": "4.6.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
"integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vue/devtools-api": "^6.6.4" "@vue/devtools-api": "^6.6.4"

View File

@ -0,0 +1,97 @@
<script setup lang="ts">
import type { Book } from '@/models/book';
import { convertState } from '@/utils';
const API_URL = import.meta.env.VITE_MBL_API_URL
const props = defineProps<{ book: Book }>()
</script>
<template>
<div class="card">
<img :src="`${API_URL}${props.book.illustration}`" class="image"></img>
<div class="content">
<a href="#">
<span class="title">{{ props.book.title }}</span>
</a>
<p class="desc">
Livre écrit par <strong>{{ props.book.author }}</strong>
</p>
<p v-if="book.state === 'COMPLETED' || props.book.state === 'DROPPED'">Note
{{ props.book.note }}/5</p>
<div class="state-div">
<p>{{ convertState(props.book.state) }}</p>
<div :class="props.book.state" class="state-indicator"></div>
</div>
</div>
</div>
</template>
<style>
.COMPLETED {
background-color: #2d4276;
}
.PLAN {
background-color: #747474;
}
.READING {
background-color: #338543;
}
.DROPPED {
background-color: #832f30;
}
.state-div {
display: flex;
align-items: center;
flex-direction: column;
}
.state-indicator {
width: 100%;
height: 10px;
border-radius: 25px;
}
.image {
border-radius: 0.5rem;
object-fit: cover;
width: 100%;
height: 150px;
}
.card {
max-width: 300px;
min-width: 300px;;
border-radius: 0.5rem;
background-color: light-dark(#efedea, #282828);
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
border: 1px solid transparent;
}
.card a {
text-decoration: none
}
.content {
padding: 1.1rem;
}
.title {
color: light-dark(#121212, #efefec);
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 600;
}
.desc {
margin-top: 0.5rem;
color: light-dark(#6B7280, #b4b4b1);
font-size: 0.875rem;
line-height: 1.25rem;
}
</style>

View File

@ -0,0 +1,8 @@
<script lang="ts">
</script>
<template>
</template>
<style>
</style>

View File

@ -1,146 +0,0 @@
<script setup lang="ts">
import type { Book } from "@/models/book";
import { BookService } from "@/services/book.service";
import { convertState } from "@/utils";
import { onMounted, ref } from "vue";
const API_URL = import.meta.env.VITE_MBL_API_URL
const books = ref<Book[]>([]);
const bookService = new BookService();
onMounted(async () => {
books.value = await bookService.findBooks();
books.value.map((book) => {
book.added_at = new Date(book.added_at);
});
books.value.sort((a, b) => {
if (a.updated_at > b.updated_at) {
return -1;
} else if (a.updated_at < b.updated_at) {
return 1;
}
return 0;
})
});
</script>
<template>
<main class="cards">
<div v-for="book in books" class="card">
<img :src="API_URL + book.illustration" class="image"></img>
<div class="content">
<a href="#">
<span class="title">{{ book.title }}</span>
</a>
<p class="desc">
Livre écrit par <strong>{{ book.author }}</strong>
</p>
<p v-if="book.state === 'COMPLETED' || book.state === 'DROPPED'">Note {{ book.note }}/5</p>
<div class="state-div">
<p>{{ convertState(book.state) }}</p>
<div :class="book.state" class="state-indicator"></div>
</div>
</div>
</div>
</main>
</template>
<style scoped>
.COMPLETED {
background-color: #2d4276;
}
.PLAN {
background-color: #747474;
}
.READING {
background-color: #338543;
}
.DROPPED {
background-color: #832f30;
}
.state-div {
display: flex;
align-items: center;
flex-direction: column;
}
.state-indicator {
width: 100%;
height: 10px;
border-radius: 25px;
}
.cards {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 2em;
}
.card {
max-width: 300px;
min-width: 300px;;
border-radius: 0.5rem;
background-color: light-dark(#efedea, #282828);
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
border: 1px solid transparent;
}
.card a {
text-decoration: none
}
.content {
padding: 1.1rem;
}
.image {
border-radius: 0.5rem;
object-fit: cover;
width: 100%;
height: 150px;
}
.title {
color: light-dark(#121212, #efefec);
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 600;
}
.desc {
margin-top: 0.5rem;
color: light-dark(#6B7280, #b4b4b1);
font-size: 0.875rem;
line-height: 1.25rem;
}
.action {
display: inline-flex;
margin-top: 1rem;
color: #ffffff;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
align-items: center;
gap: 0.25rem;
background-color: #2563EB;
padding: 4px 8px;
border-radius: 4px;
}
.action span {
transition: .3s ease;
}
.action:hover span {
transform: translateX(4px);
}
</style>

View File

@ -1,7 +1,7 @@
import { createWebHistory, createRouter } from "vue-router"; import { createWebHistory, createRouter } from "vue-router";
import Authenticate from "./components/Authenticate.vue"; import Authenticate from "@/views/Authenticate.vue";
import Home from "./components/Home.vue"; import Home from "@/views/Home.vue";
import NotFound from "./components/NotFound.vue"; import NotFound from "@/views/NotFound.vue";
const routes = [ const routes = [
{ {
@ -31,7 +31,7 @@ router.beforeEach((to, from) => {
const authenticated = sessionStorage.getItem("access"); const authenticated = sessionStorage.getItem("access");
if (to.path === "/login" && authenticated) { if (to.path === "/login" && authenticated) {
return { name: "Home " }; return { name: "Home" };
} }
if (to.path === "/logout" && !authenticated) { if (to.path === "/logout" && !authenticated) {

66
src/views/Home.vue Normal file
View File

@ -0,0 +1,66 @@
<script setup lang="ts">
import type { Book } from "@/models/book";
import { BookService } from "@/services/book.service";
import { onMounted, ref } from "vue";
import BookCard from "@/components/BookCard.vue";
const books = ref<Book[]>([]);
const bookService = new BookService();
onMounted(async () => {
books.value = await bookService.findBooks();
books.value.map((book) => {
book.added_at = new Date(book.added_at);
});
books.value.sort((a, b) => {
if (a.updated_at > b.updated_at) {
return -1;
} else if (a.updated_at < b.updated_at) {
return 1;
}
return 0;
})
});
</script>
<template>
<main class="cards">
<BookCard v-for="book in books"
:book="book"
:key="book.id"
class="card"/>
</main>
</template>
<style scoped>
.cards {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 2em;
}
.action {
display: inline-flex;
margin-top: 1rem;
color: #ffffff;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
align-items: center;
gap: 0.25rem;
background-color: #2563EB;
padding: 4px 8px;
border-radius: 4px;
}
.action span {
transition: .3s ease;
}
.action:hover span {
transform: translateX(4px);
}
</style>