diff --git a/my-library/src/context/ReviewContext.js b/my-library/src/context/ReviewContext.js
new file mode 100644
index 0000000..dbdb13e
--- /dev/null
+++ b/my-library/src/context/ReviewContext.js
@@ -0,0 +1,40 @@
+import { createContext, useContext, useState } from 'react';
+
+const ReviewContext = createContext(null);
+
+export function ReviewProvider({ children }) {
+ const [reviews, setReviews] = useState(() => {
+ const saved = localStorage.getItem('reviews');
+ return saved ? JSON.parse(saved) : [];
+ });
+
+ function addReview(bookId, bookTitle, username, rating, comment) {
+ const review = {
+ reviewId: crypto.randomUUID(),
+ bookId,
+ bookTitle,
+ username,
+ rating,
+ comment,
+ createdAt: new Date().toISOString(),
+ };
+ const updated = [...reviews, review];
+ setReviews(updated);
+ localStorage.setItem('reviews', JSON.stringify(updated));
+ return review;
+ }
+
+ function getReviewsByBook(bookId) {
+ return reviews.filter(r => String(r.bookId) === String(bookId));
+ }
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useReviews() {
+ return useContext(ReviewContext);
+}
diff --git a/my-library/src/index.js b/my-library/src/index.js
index 451e262..c851583 100644
--- a/my-library/src/index.js
+++ b/my-library/src/index.js
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { AuthProvider } from './context/AuthContext';
import { ReservationProvider } from './context/ReservationContext';
+import { ReviewProvider } from './context/ReviewContext';
import App from './App';
import './styles/global.css';
@@ -12,7 +13,9 @@ root.render(
-
+
+
+
diff --git a/my-library/src/pages/BookDetail.jsx b/my-library/src/pages/BookDetail.jsx
index ca937e9..e4b3f47 100644
--- a/my-library/src/pages/BookDetail.jsx
+++ b/my-library/src/pages/BookDetail.jsx
@@ -3,10 +3,15 @@ import { useParams, Link } from 'react-router-dom';
import { getBookById } from '../api/books';
import { useAuth } from '../context/AuthContext';
import { useReservations } from '../context/ReservationContext';
+import { useReviews } from '../context/ReviewContext';
export default function BookDetail() {
const { user } = useAuth();
const { addReservation } = useReservations();
+ const { addReview, getReviewsByBook } = useReviews();
+ const [rating, setRating] = useState(5);
+ const [comment, setComment] = useState('');
+ const [reviewStatus, setReviewStatus] = useState(null);
const { bookId } = useParams();
const [book, setBook] = useState(null);
const [loading, setLoading] = useState(true);
@@ -23,6 +28,14 @@ export default function BookDetail() {
setPhoneNumber('');
}
+ function handleReview(e) {
+ e.preventDefault();
+ addReview(book.isbn, book.title, user.username, Number(rating), comment);
+ setReviewStatus({ success: true, message: 'Avis publié avec succès !' });
+ setComment('');
+ setRating(5);
+ }
+
if (loading) return Chargement…
;
if (error) return {error}
← Retour au catalogue;
@@ -40,6 +53,50 @@ export default function BookDetail() {
Catégories : {book.categories?.join(', ')}
{book.description && {book.description}
}
+
+ Avis des lecteurs
+ {getReviewsByBook(book.isbn).length === 0 ? (
+ Aucun avis pour le moment.
+ ) : (
+
+ {getReviewsByBook(book.isbn).map(r => (
+ -
+ {r.username} — {'*'.repeat(r.rating)}
+
+ {r.comment}
+
+ {new Date(r.createdAt).toLocaleDateString('fr-FR')}
+
+ ))}
+
+ )}
+ {user?.role === 'user' && (
+
+ )}
+ {reviewStatus && (
+
+ {reviewStatus.message}
+
+ )}
+
+
{user?.role === 'user' &&