Merge pull request '✨ Enregistrer un livre' (#2) from EnregistrerLivre into main
Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
@@ -5,6 +5,7 @@ import Books from './pages/Books';
|
||||
import Orders from './pages/Orders';
|
||||
import Profile from './pages/Profile';
|
||||
import NotFound from './pages/NotFound';
|
||||
import AddBook from './pages/AddBook';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -15,6 +16,7 @@ export default function App() {
|
||||
<Route path="orders" element={<Orders />} />
|
||||
<Route path="profile" element={<Profile />} />
|
||||
<Route path="*" element={<NotFound />} />
|
||||
<Route path="books/new" element={<AddBook />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
|
||||
@@ -2,4 +2,8 @@ import client from './client';
|
||||
|
||||
export function getBooks(page = 0, size = 20) {
|
||||
return client.get('/api/books', { params: { page, size } });
|
||||
}
|
||||
|
||||
export function registerBook(book) {
|
||||
return client.post('/api/books', book);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import { useState } from 'react';
|
||||
import { registerBook } from '../api/books';
|
||||
|
||||
const CATEGORIES = ['FICTION', 'NON_FICTION', 'SCIENCE_FICTION', 'FANTASY', 'MYSTERY', 'THRILLER', 'ROMANCE', 'BIOGRAPHY', 'HISTORY', 'POETRY', 'CHILDRENS', 'YOUNG_ADULT', 'SCIENCE', 'PHILOSOPHY', 'SELF_HELP', 'TRAVEL', 'COOKING', 'ART', 'RELIGION', 'REFERENCE'];
|
||||
|
||||
const initialForm = {
|
||||
isbn: '', title: '', author: '', publisher: '', publicationDate: '', price: '', quantity: '', categories: [], description: '', language: '',
|
||||
};
|
||||
|
||||
export default function AddBook() {
|
||||
const [form, setForm] = useState(initialForm);
|
||||
const [message, setMessage] = useState(null);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
function handleChange(e) {
|
||||
const { name, value } = e.target;
|
||||
setForm((prev) => ({ ...prev, [name]: value }));
|
||||
}
|
||||
|
||||
function handleCategoryChange(e) {
|
||||
setForm((prev) => ({ ...prev, categories: e.target.value ? [e.target.value] : [] }));
|
||||
}
|
||||
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
setSubmitting(true);
|
||||
setMessage(null);
|
||||
|
||||
const payload = {
|
||||
...form,
|
||||
isbn: Number(form.isbn),
|
||||
price: Number(form.price),
|
||||
quantity: Number(form.quantity),
|
||||
};
|
||||
|
||||
registerBook(payload)
|
||||
.then((response) => {
|
||||
setMessage({ type: 'success', text: `Livre créé (id : ${response.data}) ✅` });
|
||||
setForm(initialForm);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
const status = error.response?.status;
|
||||
if (status === 406) setMessage({ type: 'error', text: 'Ce livre existe déjà.' });
|
||||
else if (status === 400) setMessage({ type: 'error', text: 'Données invalides, vérifie les champs.' });
|
||||
else setMessage({ type: 'error', text: 'Erreur lors de la création.' });
|
||||
})
|
||||
.finally(() => setSubmitting(false));
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1>Ajouter un livre</h1>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<table>
|
||||
<tr>
|
||||
<td>ISBN</td>
|
||||
<td><input name="isbn" type="number" value={form.isbn} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Titre</td>
|
||||
<td><input name="title" value={form.title} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Auteur</td>
|
||||
<td><input name="author" value={form.author} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Éditeur</td>
|
||||
<td><input name="publisher" value={form.publisher} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date de publication</td>
|
||||
<td><input name="publicationDate" type="date" value={form.publicationDate} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prix</td>
|
||||
<td><input name="price" type="number" step="0.01" value={form.price} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Quantité</td>
|
||||
<td><input name="quantity" type="number" value={form.quantity} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Langue</td>
|
||||
<td><input name="language" value={form.language} onChange={handleChange} required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Catégorie</td>
|
||||
<td><select value={form.categories[0] || ''} onChange={handleCategoryChange} required><option value=""> choisir </option>{CATEGORIES.map((c) => <option key={c} value={c}>{c}</option>)}</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td><textarea name="description" value={form.description} onChange={handleChange} /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="submit" disabled={submitting}>
|
||||
{submitting ? 'Envoi…' : 'Ajouter le livre'}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{message && <p>{message.text}</p>}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { getBooks } from '../api/books';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function Books() {
|
||||
const [books, setBooks] = useState([]);
|
||||
@@ -27,6 +28,7 @@ export default function Books() {
|
||||
return (
|
||||
<main>
|
||||
<h1>Catalogue</h1>
|
||||
<Link to="/books/new">+ Ajouter un livre</Link>
|
||||
<ul>
|
||||
{books.map((book) => (
|
||||
<li key={book.isbn}>
|
||||
|
||||
Reference in New Issue
Block a user