update modal
This commit is contained in:
parent
68d3b86816
commit
173b4636bc
@ -4,7 +4,7 @@ import type { Book } from '@/models/book';
|
|||||||
import { convertState } from '@/utils';
|
import { convertState } from '@/utils';
|
||||||
import { ref, Transition } from 'vue';
|
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 API_URL = import.meta.env.VITE_MBL_API_URL
|
||||||
const props = defineProps<{ book: Book }>()
|
const props = defineProps<{ book: Book }>()
|
||||||
@ -13,7 +13,6 @@ const { isAuthenticated } = useAuth();
|
|||||||
|
|
||||||
function showButtonsOnHover() {
|
function showButtonsOnHover() {
|
||||||
showButtons.value = true
|
showButtons.value = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unshowButtonOnLeave() {
|
function unshowButtonOnLeave() {
|
||||||
@ -51,8 +50,8 @@ function unshowButtonOnLeave() {
|
|||||||
</p>
|
</p>
|
||||||
<Transition>
|
<Transition>
|
||||||
<div class="buttons" v-show="showButtons">
|
<div class="buttons" v-show="showButtons">
|
||||||
<button class="update-button">Modifier</button>
|
<button @click="$emit('openUpdateModal'); $emit('concernedBookToUpdate', props.book)" class="update-button">Modifier</button>
|
||||||
<button @click="$emit('openDeleteModal'); $emit('concernedBook', props.book)" class="delete-button"><font-awesome-icon icon="fa-trash-can" /></button>
|
<button @click="$emit('openDeleteModal'); $emit('concernedBookToDelete', props.book)" class="delete-button"><font-awesome-icon icon="fa-trash-can" /></button>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,10 +4,15 @@ import type { Book } from "@/models/book";
|
|||||||
import { User } from "@/models/user";
|
import { User } from "@/models/user";
|
||||||
import { AuthenticationService } from "@/services/authentication.service";
|
import { AuthenticationService } from "@/services/authentication.service";
|
||||||
import { BookService } from "@/services/book.service";
|
import { BookService } from "@/services/book.service";
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
|
|
||||||
const props = defineProps<{ isActive: boolean }>();
|
const props = defineProps<{
|
||||||
const emit = defineEmits(["closeBookFormModal", "newBook"]);
|
isActive: boolean;
|
||||||
|
isUpdating: boolean;
|
||||||
|
updatingBook: Book | undefined
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(["closeBookFormModal", "newBook", "updateBook"]);
|
||||||
|
|
||||||
const title = ref("");
|
const title = ref("");
|
||||||
const author = ref("");
|
const author = ref("");
|
||||||
@ -21,15 +26,28 @@ const bookService = new BookService();
|
|||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
{
|
|
||||||
if (isAuthenticated.value) {
|
if (isAuthenticated.value) {
|
||||||
try {
|
try {
|
||||||
concernedUser.value = await authenticationService.findMe();
|
concernedUser.value = await authenticationService.findMe();
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error);
|
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 {
|
} 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("author", author.value);
|
||||||
form.append("note", `${note.value}`);
|
form.append("note", `${note.value}`);
|
||||||
form.append("state", state.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) {
|
if (concernedUser.value?.id) {
|
||||||
form.append("user", concernedUser.value.id.toString());
|
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");
|
emit("closeBookFormModal");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -65,7 +93,7 @@ async function sendBookData() {
|
|||||||
<div class="modale card">
|
<div class="modale card">
|
||||||
<button class="btn-close" @click="$emit('closeBookFormModal')">X</button>
|
<button class="btn-close" @click="$emit('closeBookFormModal')">X</button>
|
||||||
|
|
||||||
<h2>Ajouter un livre</h2>
|
<h2>{{ props.isUpdating ? 'Modifier le livre' : 'Ajouter un livre' }}</h2>
|
||||||
|
|
||||||
<form @submit.prevent="sendBookData">
|
<form @submit.prevent="sendBookData">
|
||||||
<label for="title">Titre</label>
|
<label for="title">Titre</label>
|
||||||
@ -95,7 +123,9 @@ async function sendBookData() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="send" type="submit">Créer</button>
|
<button class="send" type="submit">
|
||||||
|
{{ props.isUpdating ? 'Modifier' : 'Créer' }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -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) {
|
async deleteBookById(id: number) {
|
||||||
return await this.client.delete(`/${id}/`).catch((error) => {
|
return await this.client.delete(`/${id}/`).catch((error) => {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@ -3,34 +3,62 @@ import type { Book } from "@/models/book";
|
|||||||
import { BookService } from "@/services/book.service";
|
import { BookService } from "@/services/book.service";
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import BookCard from "@/components/BookCard.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 { useAuth } from "@/composables/useAuth";
|
||||||
import { useToast } from "vue-toast-notification";
|
import { useToast } from "vue-toast-notification";
|
||||||
import DeleteBookForm from "@/components/DeleteBookForm.vue";
|
import DeleteBookModal from "@/components/DeleteBookModal.vue";
|
||||||
|
|
||||||
const books = ref<Book[]>([]);
|
const books = ref<Book[]>([]);
|
||||||
const bookService = new BookService();
|
const bookService = new BookService();
|
||||||
const isCreatingBookFormOpened = ref<boolean>(false);
|
|
||||||
const isDeletingBookFormOpened = ref<boolean>(false);
|
|
||||||
const deletingBook = ref<Book | undefined>(undefined);
|
|
||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
const toastService = useToast();
|
const toastService = useToast();
|
||||||
|
|
||||||
|
const isCreatingBookFormOpened = ref<boolean>(false);
|
||||||
|
const isDeletingBookFormOpened = ref<boolean>(false);
|
||||||
|
|
||||||
|
const deletingBook = ref<Book | undefined>(undefined);
|
||||||
|
const updatingBook = ref<Book | undefined>(undefined);
|
||||||
|
|
||||||
function sortBooks(a: Book, b: Book) {
|
function sortBooks(a: Book, b: Book) {
|
||||||
if (a.updated_at > b.updated_at) {
|
if (a.updated_at > b.updated_at) return -1;
|
||||||
return -1;
|
if (a.updated_at < b.updated_at) return 1;
|
||||||
} else if (a.updated_at < b.updated_at) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushNewBook(book: Book) {
|
function parseBookDates(book: Book) {
|
||||||
book.added_at = new Date(book.added_at);
|
book.added_at = new Date(book.added_at);
|
||||||
book.updated_at = new Date(book.updated_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.push(book);
|
||||||
books.value.sort(sortBooks);
|
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",
|
position: "bottom-right",
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
dismissible: true,
|
dismissible: true,
|
||||||
@ -39,17 +67,20 @@ function pushNewBook(book: Book) {
|
|||||||
|
|
||||||
function closeBookFormModal() {
|
function closeBookFormModal() {
|
||||||
isCreatingBookFormOpened.value = false;
|
isCreatingBookFormOpened.value = false;
|
||||||
|
updatingBook.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDeleteBookFormModal() {
|
function closeDeleteBookFormModal() {
|
||||||
isDeletingBookFormOpened.value = false;
|
isDeletingBookFormOpened.value = false;
|
||||||
|
deletingBook.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteBookFromList(bool: boolean) {
|
function deleteBookFromList(bool: boolean) {
|
||||||
if (deletingBook.value && bool) {
|
if (deletingBook.value && bool) {
|
||||||
books.value = books.value.filter((book) => book.id !== deletingBook.value?.id);
|
books.value = books.value.filter((book) => book.id !== deletingBook.value?.id);
|
||||||
deletingBook.value = undefined;
|
closeDeleteBookFormModal();
|
||||||
toastService.success(`Livre supprimé avec succès"`, {
|
|
||||||
|
toastService.success(`Livre supprimé avec succès`, {
|
||||||
position: "bottom-right",
|
position: "bottom-right",
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
dismissible: true,
|
dismissible: true,
|
||||||
@ -58,43 +89,51 @@ function deleteBookFromList(bool: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
books.value = await bookService.findBooks();
|
try {
|
||||||
|
const fetchedBooks = await bookService.findBooks();
|
||||||
books.value.map((book) => {
|
fetchedBooks.forEach(parseBookDates);
|
||||||
book.added_at = new Date(book.added_at);
|
books.value = fetchedBooks;
|
||||||
book.updated_at = new Date(book.updated_at);
|
|
||||||
});
|
|
||||||
|
|
||||||
books.value.sort(sortBooks);
|
books.value.sort(sortBooks);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Erreur au chargement des livres", e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CreateBookForm
|
<CreateBookModal
|
||||||
v-if="isAuthenticated"
|
v-if="isAuthenticated"
|
||||||
:is-active="isCreatingBookFormOpened"
|
:is-active="isCreatingBookFormOpened"
|
||||||
|
:is-updating="updatingBook !== undefined"
|
||||||
|
:updating-book="updatingBook"
|
||||||
@new-book="(book) => pushNewBook(book)"
|
@new-book="(book) => pushNewBook(book)"
|
||||||
|
@update-book="(book) => handleBookUpdate(book)"
|
||||||
@close-book-form-modal="closeBookFormModal"
|
@close-book-form-modal="closeBookFormModal"
|
||||||
/>
|
/>
|
||||||
<DeleteBookForm
|
|
||||||
|
<DeleteBookModal
|
||||||
v-if="isAuthenticated"
|
v-if="isAuthenticated"
|
||||||
:is-active="isDeletingBookFormOpened"
|
:is-active="isDeletingBookFormOpened"
|
||||||
:concerned-book="deletingBook"
|
:concerned-book="deletingBook"
|
||||||
@is-deleted="(bool) => deleteBookFromList(bool)"
|
@is-deleted="(bool) => deleteBookFromList(bool)"
|
||||||
@close-delete-book-modal="closeDeleteBookFormModal"
|
@close-delete-book-modal="closeDeleteBookFormModal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<main class="cards">
|
<main class="cards">
|
||||||
<BookCard
|
<BookCard
|
||||||
v-for="book in books"
|
v-for="book in books"
|
||||||
:book="book"
|
:book="book"
|
||||||
:key="book.id"
|
:key="book.id"
|
||||||
@concerned-book="(book) => (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"
|
@open-delete-modal="isDeletingBookFormOpened = true"
|
||||||
class="card"
|
class="card"
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div v-if="isAuthenticated" class="add-button-container">
|
<div v-if="isAuthenticated" class="add-button-container">
|
||||||
<button @click="isCreatingBookFormOpened = true" class="add-button">
|
<button @click="openCreateModal" class="add-button">
|
||||||
<h3><font-awesome-icon icon="fa-plus" /> Ajouter un livre</h3>
|
<h3><font-awesome-icon icon="fa-plus" /> Ajouter un livre</h3>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -108,6 +147,7 @@ onMounted(async () => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
margin-left: 2em;
|
margin-left: 2em;
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-button {
|
.add-button {
|
||||||
@ -119,6 +159,7 @@ onMounted(async () => {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-button:hover {
|
.add-button:hover {
|
||||||
@ -131,28 +172,7 @@ onMounted(async () => {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 2em;
|
gap: 2em;
|
||||||
}
|
padding-bottom: 5em;
|
||||||
|
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 820px) {
|
@media (max-width: 820px) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user