From 68d3b8681652f6083389eb18804e474f0007dc1a Mon Sep 17 00:00:00 2001 From: Guamss Date: Tue, 16 Dec 2025 11:17:07 +0100 Subject: [PATCH] added delete form --- src/components/BookCard.vue | 75 ++++++++++++++--- src/components/DeleteBookForm.vue | 112 +++++++++++++++++++++++++ src/main.ts | 2 + src/services/authentication.service.ts | 10 +-- src/services/book.service.ts | 8 +- src/views/Home.vue | 35 +++++++- 6 files changed, 224 insertions(+), 18 deletions(-) create mode 100644 src/components/DeleteBookForm.vue diff --git a/src/components/BookCard.vue b/src/components/BookCard.vue index fdb9fed..a50b63a 100644 --- a/src/components/BookCard.vue +++ b/src/components/BookCard.vue @@ -2,7 +2,9 @@ import { useAuth } from '@/composables/useAuth'; import type { Book } from '@/models/book'; import { convertState } from '@/utils'; -import { ref } from 'vue'; +import { ref, Transition } from 'vue'; + +const emit = defineEmits(["openDeleteModal", "concernedBook"]); const API_URL = import.meta.env.VITE_MBL_API_URL const props = defineProps<{ book: Book }>() @@ -42,10 +44,17 @@ function unshowButtonOnLeave() {
-

-
- - +
+

+ +

+ +
+ + +
+
@@ -67,11 +76,51 @@ function unshowButtonOnLeave() { background-color: #832f30; } +.v-enter-active, +.v-leave-active { + transition: opacity 0.5s ease; +} + +.v-enter-from, +.v-leave-to { + opacity: 0; +} + +.delete-button { + border: none; + border-radius: 4px; + min-width: 13%; + background-color: #ef4444; +} + +.update-button { + border: none; + border-radius: 4px; + background-color: #1e90ff; + min-width: 85%; +} + +.delete-button:hover { + transition: 0.3s; + background-color: #c53838; +} + +.update-button:hover { + transition: 0.3s; + background-color: #176cc0; +} + +.delete-button, .update-button { + font-weight: bold; + cursor: pointer; + padding: 0.5em; +} + .buttons { + margin: 1em; display: flex; align-items: stretch; - gap: 1em; - justify-content: center; + justify-content: space-between; } .state-div { @@ -105,16 +154,22 @@ function unshowButtonOnLeave() { border: 1px solid transparent; } -.chevron { +.chevron-div { margin-top: 0; + min-width: 100%; align-self: center; - transition: background-color 0.5s ease, transform 0.5s ease; } -.chevron:hover { +.chevron-go-up { + transition: background-color 0.5s ease, transform 0.5s ease; transform: rotate(180deg); } +.chevron-go-down { + transition: background-color 0.5s ease, transform 0.5s ease; + transform: rotate(0); +} + .card a { text-decoration: none } diff --git a/src/components/DeleteBookForm.vue b/src/components/DeleteBookForm.vue new file mode 100644 index 0000000..65f077e --- /dev/null +++ b/src/components/DeleteBookForm.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/src/main.ts b/src/main.ts index 0dedfbc..f8248a3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,11 +7,13 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faArrowRightFromBracket } from "@fortawesome/free-solid-svg-icons"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; +import { faTrashCan } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; library.add(faArrowRightFromBracket); library.add(faPlus); library.add(faChevronDown); +library.add(faTrashCan); createApp(App) .use(router) diff --git a/src/services/authentication.service.ts b/src/services/authentication.service.ts index 089dbd9..812524b 100644 --- a/src/services/authentication.service.ts +++ b/src/services/authentication.service.ts @@ -6,7 +6,7 @@ export class AuthenticationService { constructor() { const apiURL = import.meta.env.VITE_MBL_API_URL; - + this.client = axios.create({ baseURL: `${apiURL}/api/`, headers: { @@ -38,7 +38,7 @@ export class AuthenticationService { originalRequest._retry = true; try { - const newData = await this.refreshToken(); + const newData = await this.refreshToken(); sessionStorage.setItem("access", newData.access); originalRequest.headers.Authorization = `Bearer ${newData.access}`; @@ -57,7 +57,6 @@ export class AuthenticationService { ); } - async findUsers() { return await this.client.get("users").then((res) => { return res.data as User; @@ -65,7 +64,6 @@ export class AuthenticationService { } async findMe() { - return await this.client .get("profile") .then((res) => { @@ -79,7 +77,7 @@ export class AuthenticationService { async refreshToken() { const refreshToken = localStorage.getItem("refresh"); const apiURL = import.meta.env.VITE_MBL_API_URL; - + return await axios .post(`${apiURL}/api/token/refresh/`, { refresh: refreshToken, @@ -105,4 +103,4 @@ export class AuthenticationService { throw error; }); } -} \ No newline at end of file +} diff --git a/src/services/book.service.ts b/src/services/book.service.ts index 20b9841..7437d1b 100644 --- a/src/services/book.service.ts +++ b/src/services/book.service.ts @@ -55,7 +55,7 @@ export class BookService { ); } -async findBooks() { + async findBooks() { return await this.client .get("") .then((res) => { @@ -66,6 +66,12 @@ async findBooks() { }); } + async deleteBookById(id: number) { + return await this.client.delete(`/${id}/`).catch((error) => { + throw error; + }); + } + async createBook(formData: FormData) { return await this.client .post("", formData) diff --git a/src/views/Home.vue b/src/views/Home.vue index 3da2ff7..9d7a847 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -6,10 +6,13 @@ import BookCard from "@/components/BookCard.vue"; import CreateBookForm from "@/components/CreateBookForm.vue"; import { useAuth } from "@/composables/useAuth"; import { useToast } from "vue-toast-notification"; +import DeleteBookForm from "@/components/DeleteBookForm.vue"; const books = ref([]); const bookService = new BookService(); const isCreatingBookFormOpened = ref(false); +const isDeletingBookFormOpened = ref(false); +const deletingBook = ref(undefined); const { isAuthenticated } = useAuth(); const toastService = useToast(); @@ -38,6 +41,22 @@ function closeBookFormModal() { isCreatingBookFormOpened.value = false; } +function closeDeleteBookFormModal() { + isDeletingBookFormOpened.value = false; +} + +function deleteBookFromList(bool: boolean) { + if (deletingBook.value && bool) { + books.value = books.value.filter((book) => book.id !== deletingBook.value?.id); + deletingBook.value = undefined; + toastService.success(`Livre supprimé avec succès"`, { + position: "bottom-right", + pauseOnHover: true, + dismissible: true, + }); + } +} + onMounted(async () => { books.value = await bookService.findBooks(); @@ -57,8 +76,22 @@ onMounted(async () => { @new-book="(book) => pushNewBook(book)" @close-book-form-modal="closeBookFormModal" /> +
- +