diff --git a/my-library/src/App.jsx b/my-library/src/App.jsx index e0083bb..9bf7291 100644 --- a/my-library/src/App.jsx +++ b/my-library/src/App.jsx @@ -12,6 +12,7 @@ import Login from './pages/Login'; import Reservations from './pages/Reservations'; import Returns from './pages/Returns'; import Subscription from './pages/Subscription'; +import Loans from './pages/Loans'; import { useAuth } from './context/AuthContext'; function RequireAuth({ children }) { @@ -41,6 +42,7 @@ export default function App() { } /> } /> } /> + } /> } /> diff --git a/my-library/src/components/Navbar.jsx b/my-library/src/components/Navbar.jsx index 9872ec9..d28da7d 100644 --- a/my-library/src/components/Navbar.jsx +++ b/my-library/src/components/Navbar.jsx @@ -21,6 +21,7 @@ export default function Navbar() { {user &&
  • Commandes
  • } {user?.role === 'user' &&
  • Mes réservations
  • } {user?.role === 'user' &&
  • Mon abonnement
  • } + {user?.role === 'user' &&
  • Mes prêts
  • } {user &&
  • Mon compte
  • } {user?.role === 'admin' &&
  • Clients
  • } {user?.role === 'admin' &&
  • Retours
  • } diff --git a/my-library/src/context/LoanContext.js b/my-library/src/context/LoanContext.js new file mode 100644 index 0000000..08b8bb2 --- /dev/null +++ b/my-library/src/context/LoanContext.js @@ -0,0 +1,45 @@ +import { createContext, useContext, useState } from 'react'; + +const LoanContext = createContext(null); + +export function LoanProvider({ children }) { + const [loans, setLoans] = useState(() => { + const saved = localStorage.getItem('loans'); + return saved ? JSON.parse(saved) : []; + }); + + function addLoan(book, borrowerPhone, dueDate) { + const loan = { + loanId: crypto.randomUUID(), + bookId: book.isbn, + bookTitle: book.title, + bookAuthor: book.author, + borrowerPhone, + dueDate, + status: 'ACTIVE', + loanedAt: new Date().toISOString(), + }; + const updated = [...loans, loan]; + setLoans(updated); + localStorage.setItem('loans', JSON.stringify(updated)); + return loan; + } + + function returnLoan(loanId) { + const updated = loans.map(l => + l.loanId === loanId ? { ...l, status: 'RETURNED' } : l + ); + setLoans(updated); + localStorage.setItem('loans', JSON.stringify(updated)); + } + + return ( + + {children} + + ); +} + +export function useLoans() { + return useContext(LoanContext); +} diff --git a/my-library/src/index.js b/my-library/src/index.js index 50db091..c330510 100644 --- a/my-library/src/index.js +++ b/my-library/src/index.js @@ -6,6 +6,7 @@ import { ReservationProvider } from './context/ReservationContext'; import { ReviewProvider } from './context/ReviewContext'; import { ReturnProvider } from './context/ReturnContext'; import { SubscriptionProvider } from './context/SubscriptionContext'; +import { LoanProvider } from './context/LoanContext'; import App from './App'; import './styles/global.css'; @@ -18,7 +19,9 @@ root.render( - + + + diff --git a/my-library/src/pages/Loans.jsx b/my-library/src/pages/Loans.jsx new file mode 100644 index 0000000..473d048 --- /dev/null +++ b/my-library/src/pages/Loans.jsx @@ -0,0 +1,54 @@ +import { useLoans } from '../context/LoanContext'; + +export default function Loans() { + const { loans, returnLoan } = useLoans(); + + const activeLoans = loans.filter(l => l.status === 'ACTIVE'); + const returnedLoans = loans.filter(l => l.status === 'RETURNED'); + + return ( +
    +

    Mes prêts

    + +
    +

    Prêts en cours ({activeLoans.length})

    + {activeLoans.length === 0 ? ( +

    Aucun prêt en cours.

    + ) : ( +
      + {activeLoans.map(l => ( +
    • + {l.bookTitle} — {l.bookAuthor} +
      + Prêté à : {l.borrowerPhone} +
      + À rendre avant le : {new Date(l.dueDate).toLocaleDateString('fr-FR')} +
      + Prêté le : {new Date(l.loanedAt).toLocaleDateString('fr-FR')} +
      + +
    • + ))} +
    + )} +
    + + {returnedLoans.length > 0 && ( +
    +

    Prêts terminés ({returnedLoans.length})

    +
      + {returnedLoans.map(l => ( +
    • + {l.bookTitle} — {l.bookAuthor} +
      + Prêté à : {l.borrowerPhone} +
      + Rendu ✓ +
    • + ))} +
    +
    + )} +
    + ); +} diff --git a/my-library/src/pages/Reservations.jsx b/my-library/src/pages/Reservations.jsx index 3bf535a..b66f0f0 100644 --- a/my-library/src/pages/Reservations.jsx +++ b/my-library/src/pages/Reservations.jsx @@ -1,8 +1,32 @@ +import { useState } from 'react'; import { useReservations } from '../context/ReservationContext'; +import { useLoans } from '../context/LoanContext'; import { Link } from 'react-router-dom'; export default function Reservations() { const { reservations, cancelReservation } = useReservations(); + const { addLoan } = useLoans(); + const [loanForms, setLoanForms] = useState({}); + const [loanStatuses, setLoanStatuses] = useState({}); + + function handleLoanChange(reservationId, field, value) { + setLoanForms(prev => ({ + ...prev, + [reservationId]: { ...prev[reservationId], [field]: value } + })); + } + + function handleLoan(e, reservation) { + e.preventDefault(); + const form = loanForms[reservation.reservationId] || {}; + addLoan( + { isbn: reservation.bookId, title: reservation.bookTitle, author: reservation.bookAuthor }, + form.borrowerPhone, + form.dueDate + ); + setLoanStatuses(prev => ({ ...prev, [reservation.reservationId]: 'Prêt enregistré avec succès !' })); + setLoanForms(prev => ({ ...prev, [reservation.reservationId]: {} })); + } if (reservations.length === 0) { return ( @@ -29,6 +53,36 @@ export default function Reservations() { Statut : {r.status}
    + +
    + Prêter ce livre à un autre lecteur +
    handleLoan(e, r)}> + + + +
    + {loanStatuses[r.reservationId] && ( +

    {loanStatuses[r.reservationId]}

    + )} +
    ))}