From 173b4636bcb914ce40511d917c38be9ca45a8f06 Mon Sep 17 00:00:00 2001
From: Guamss
Date: Tue, 16 Dec 2025 18:30:48 +0100
Subject: [PATCH] update modal
---
src/components/BookCard.vue | 7 +-
...CreateBookForm.vue => CreateBookModal.vue} | 64 +++++++---
...DeleteBookForm.vue => DeleteBookModal.vue} | 0
src/services/book.service.ts | 11 ++
src/views/Home.vue | 116 ++++++++++--------
5 files changed, 129 insertions(+), 69 deletions(-)
rename src/components/{CreateBookForm.vue => CreateBookModal.vue} (74%)
rename src/components/{DeleteBookForm.vue => DeleteBookModal.vue} (100%)
diff --git a/src/components/BookCard.vue b/src/components/BookCard.vue
index a50b63a..246678b 100644
--- a/src/components/BookCard.vue
+++ b/src/components/BookCard.vue
@@ -4,7 +4,7 @@ import type { Book } from '@/models/book';
import { convertState } from '@/utils';
import { ref, Transition } from 'vue';
-const emit = defineEmits(["openDeleteModal", "concernedBook"]);
+const emit = defineEmits(["openDeleteModal", "concernedBookToDelete", "concernedBookToUpdate", "openUpdateModal"]);
const API_URL = import.meta.env.VITE_MBL_API_URL
const props = defineProps<{ book: Book }>()
@@ -13,7 +13,6 @@ const { isAuthenticated } = useAuth();
function showButtonsOnHover() {
showButtons.value = true
-
}
function unshowButtonOnLeave() {
@@ -51,8 +50,8 @@ function unshowButtonOnLeave() {
-
-
+
+
diff --git a/src/components/CreateBookForm.vue b/src/components/CreateBookModal.vue
similarity index 74%
rename from src/components/CreateBookForm.vue
rename to src/components/CreateBookModal.vue
index da96c2f..2fb1901 100644
--- a/src/components/CreateBookForm.vue
+++ b/src/components/CreateBookModal.vue
@@ -4,10 +4,15 @@ import type { Book } from "@/models/book";
import { User } from "@/models/user";
import { AuthenticationService } from "@/services/authentication.service";
import { BookService } from "@/services/book.service";
-import { onMounted, ref } from "vue";
+import { onMounted, ref, watch } from "vue";
-const props = defineProps<{ isActive: boolean }>();
-const emit = defineEmits(["closeBookFormModal", "newBook"]);
+const props = defineProps<{
+ isActive: boolean;
+ isUpdating: boolean;
+ updatingBook: Book | undefined
+}>();
+
+const emit = defineEmits(["closeBookFormModal", "newBook", "updateBook"]);
const title = ref("");
const author = ref("");
@@ -21,15 +26,28 @@ const bookService = new BookService();
const { isAuthenticated } = useAuth();
onMounted(async () => {
- {
- if (isAuthenticated.value) {
- try {
- concernedUser.value = await authenticationService.findMe();
- } catch (error: any) {
- console.error(error);
- }
+ if (isAuthenticated.value) {
+ try {
+ concernedUser.value = await authenticationService.findMe();
+ } catch (error: any) {
+ console.error(error);
+ }
+ }
+});
+
+watch(() => props.isActive, (isOpen) => {
+ if (isOpen) {
+ if (props.isUpdating && props.updatingBook) {
+ title.value = props.updatingBook.title;
+ author.value = props.updatingBook.author;
+ state.value = props.updatingBook.state;
+ note.value = props.updatingBook.note;
} else {
- concernedUser.value = undefined;
+ title.value = "";
+ author.value = "";
+ state.value = "PLAN";
+ note.value = 0;
+ illustrationFile.value = null;
}
}
});
@@ -47,13 +65,23 @@ async function sendBookData() {
form.append("author", author.value);
form.append("note", `${note.value}`);
form.append("state", state.value);
- form.append("illustration", illustrationFile.value!);
- console.log(concernedUser.value)
+
+ if (illustrationFile.value) {
+ form.append("illustration", illustrationFile.value);
+ }
+
if (concernedUser.value?.id) {
form.append("user", concernedUser.value.id.toString());
}
- const newBook: Book = await bookService.createBook(form);
- emit('newBook', newBook);
+
+ if (props.isUpdating && props.updatingBook) {
+ const updatedBook = await bookService.updateBook(props.updatingBook.id, form);
+ emit("updateBook", updatedBook);
+ } else {
+ const newBook = await bookService.createBook(form);
+ emit("newBook", newBook);
+ }
+
emit("closeBookFormModal");
}
@@ -65,7 +93,7 @@ async function sendBookData() {
-
Ajouter un livre
+
{{ props.isUpdating ? 'Modifier le livre' : 'Ajouter un livre' }}
diff --git a/src/components/DeleteBookForm.vue b/src/components/DeleteBookModal.vue
similarity index 100%
rename from src/components/DeleteBookForm.vue
rename to src/components/DeleteBookModal.vue
diff --git a/src/services/book.service.ts b/src/services/book.service.ts
index 7437d1b..f018134 100644
--- a/src/services/book.service.ts
+++ b/src/services/book.service.ts
@@ -66,6 +66,17 @@ export class BookService {
});
}
+ async updateBook(id: number, formData: FormData) {
+ return await this.client
+ .put(`/${id}/`, formData)
+ .then((res) => {
+ return res.data as Book;
+ })
+ .catch((error) => {
+ throw error;
+ });
+ }
+
async deleteBookById(id: number) {
return await this.client.delete(`/${id}/`).catch((error) => {
throw error;
diff --git a/src/views/Home.vue b/src/views/Home.vue
index 9d7a847..41ccd4b 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -3,34 +3,62 @@ import type { Book } from "@/models/book";
import { BookService } from "@/services/book.service";
import { onMounted, ref } from "vue";
import BookCard from "@/components/BookCard.vue";
-import CreateBookForm from "@/components/CreateBookForm.vue";
+import CreateBookModal from "@/components/CreateBookModal.vue";
import { useAuth } from "@/composables/useAuth";
import { useToast } from "vue-toast-notification";
-import DeleteBookForm from "@/components/DeleteBookForm.vue";
+import DeleteBookModal from "@/components/DeleteBookModal.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();
+const isCreatingBookFormOpened = ref(false);
+const isDeletingBookFormOpened = ref(false);
+
+const deletingBook = ref(undefined);
+const updatingBook = ref(undefined);
+
function sortBooks(a: Book, b: Book) {
- if (a.updated_at > b.updated_at) {
- return -1;
- } else if (a.updated_at < b.updated_at) {
- return 1;
- }
+ if (a.updated_at > b.updated_at) return -1;
+ if (a.updated_at < b.updated_at) return 1;
return 0;
}
-function pushNewBook(book: Book) {
+function parseBookDates(book: Book) {
book.added_at = new Date(book.added_at);
book.updated_at = new Date(book.updated_at);
+}
+
+function openCreateModal() {
+ updatingBook.value = undefined;
+ isCreatingBookFormOpened.value = true;
+}
+
+function pushNewBook(book: Book) {
+ parseBookDates(book);
books.value.push(book);
books.value.sort(sortBooks);
- toastService.success(`Livre créé avec succès"`, {
+
+ toastService.success(`Livre créé avec succès`, {
+ position: "bottom-right",
+ pauseOnHover: true,
+ dismissible: true,
+ });
+}
+
+function handleBookUpdate(updatedBook: Book) {
+ parseBookDates(updatedBook);
+
+ const index = books.value.findIndex((b) => b.id === updatedBook.id);
+ if (index !== -1) {
+ books.value[index] = updatedBook;
+ books.value.sort(sortBooks);
+ }
+
+ updatingBook.value = undefined;
+
+ toastService.success(`Livre modifié avec succès`, {
position: "bottom-right",
pauseOnHover: true,
dismissible: true,
@@ -39,17 +67,20 @@ function pushNewBook(book: Book) {
function closeBookFormModal() {
isCreatingBookFormOpened.value = false;
+ updatingBook.value = undefined;
}
function closeDeleteBookFormModal() {
isDeletingBookFormOpened.value = false;
+ deletingBook.value = undefined;
}
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"`, {
+ closeDeleteBookFormModal();
+
+ toastService.success(`Livre supprimé avec succès`, {
position: "bottom-right",
pauseOnHover: true,
dismissible: true,
@@ -58,43 +89,51 @@ function deleteBookFromList(bool: boolean) {
}
onMounted(async () => {
- books.value = await bookService.findBooks();
-
- books.value.map((book) => {
- book.added_at = new Date(book.added_at);
- book.updated_at = new Date(book.updated_at);
- });
-
- books.value.sort(sortBooks);
+ try {
+ const fetchedBooks = await bookService.findBooks();
+ fetchedBooks.forEach(parseBookDates);
+ books.value = fetchedBooks;
+ books.value.sort(sortBooks);
+ } catch (e) {
+ console.error("Erreur au chargement des livres", e);
+ }
});
- pushNewBook(book)"
+ @update-book="(book) => handleBookUpdate(book)"
@close-book-form-modal="closeBookFormModal"
/>
- deleteBookFromList(bool)"
@close-delete-book-modal="closeDeleteBookFormModal"
/>
+
(deletingBook = book)"
+ @open-update-modal="isCreatingBookFormOpened = true"
+ @concerned-book-to-delete="(book) => (deletingBook = book)"
+ @concerned-book-to-update="(book) => (updatingBook = book)"
@open-delete-modal="isDeletingBookFormOpened = true"
class="card"
/>
+
-
@@ -108,6 +147,7 @@ onMounted(async () => {
right: 0;
margin-left: 2em;
margin-bottom: 2em;
+ z-index: 10;
}
.add-button {
@@ -119,6 +159,7 @@ onMounted(async () => {
border-radius: 5px;
cursor: pointer;
font-weight: bold;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.add-button:hover {
@@ -131,28 +172,7 @@ onMounted(async () => {
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: 0.3s ease;
-}
-
-.action:hover span {
- transform: translateX(4px);
+ padding-bottom: 5em;
}
@media (max-width: 820px) {