Merge pull request 'Gestion client' (#5) from GestionClient into main

Reviewed-on: #5
This commit was merged in pull request #5.
This commit is contained in:
2026-06-11 16:49:36 +02:00
6 changed files with 129 additions and 1 deletions
+2
View File
@@ -7,6 +7,7 @@ import Profile from './pages/Profile';
import NotFound from './pages/NotFound';
import AddBook from './pages/AddBook';
import BookDetail from './pages/BookDetail';
import Customers from './pages/Customers';
export default function App() {
return (
@@ -19,6 +20,7 @@ export default function App() {
<Route path="*" element={<NotFound />} />
<Route path="books/new" element={<AddBook />} />
<Route path="books/:bookId" element={<BookDetail />} />
<Route path="customers" element={<Customers />} />
</Route>
</Routes>
);
+17
View File
@@ -0,0 +1,17 @@
import client from './client';
export function registerCustomer(customer) {
return client.post('/api/customers', customer);
}
export function findCustomerByPhone(phoneNumber) {
return client.get(`/api/customers/phone/${encodeURIComponent(phoneNumber)}`);
}
export function addLoyaltyPoints(customerId, points) {
return client.post(`/api/customers/${customerId}/loyalty/add`, null, { params: { points } });
}
export function subtractLoyaltyPoints(customerId, points) {
return client.post(`/api/customers/${customerId}/loyalty/subtract`, null, { params: { points } });
}
+1 -1
View File
@@ -35,7 +35,7 @@ export default function AddBook() {
registerBook(payload)
.then((response) => {
setMessage({ type: 'success', text: `Livre créé (id : ${response.data})` });
setMessage({ type: 'success', text: `Livre créé (id : ${response.data})` });
setForm(initialForm);
})
.catch((error) => {
+109
View File
@@ -0,0 +1,109 @@
import { useState } from 'react';
import { registerCustomer, findCustomerByPhone, addLoyaltyPoints, subtractLoyaltyPoints } from '../api/customers';
const initialForm = { firstName: '', lastName: '', phoneNumber: '' };
export default function Customers() {
const [form, setForm] = useState(initialForm);
const [registerMsg, setRegisterMsg] = useState(null);
const [submitting, setSubmitting] = useState(false);
const [pointsInput, setPointsInput] = useState('');
function handleChange(e) {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
}
function handleRegister(e) {
e.preventDefault();
setSubmitting(true);
setRegisterMsg(null);
registerCustomer(form)
.then((response) => {
setRegisterMsg(`Client créé (id : ${response.data})`);
setForm(initialForm);
})
.catch((error) => {
console.error(error);
setRegisterMsg('Erreur lors de la création du client.');
})
.finally(() => setSubmitting(false));
}
const [phone, setPhone] = useState('');
const [customer, setCustomer] = useState(null);
const [searchError, setSearchError] = useState(null);
function handleSearch(e) {
e.preventDefault();
setSearchError(null);
setCustomer(null);
findCustomerByPhone(phone)
.then((response) => setCustomer(response.data))
.catch((error) => {
console.error(error);
setSearchError('Aucun client trouvé avec ce numéro.');
});
}
function applyLoyalty(operation) {
const points = Number(pointsInput);
const action = operation === 'add' ? addLoyaltyPoints : subtractLoyaltyPoints;
action(customer.id, points)
.then((response) => {
setCustomer((prev) => ({ ...prev, loyaltyPoints: response.data }));
setPointsInput('');
})
.catch((error) => {
console.error(error);
if (error.response?.status === 400) setSearchError('Pas assez de points pour ce retrait.');
else setSearchError('Erreur lors de la mise à jour des points.');
});
}
return (
<main>
<h1>Gestion des clients</h1>
<section>
<h2>Enregistrer un client</h2>
<form onSubmit={handleRegister}>
<label>Prénom
<input name="firstName" value={form.firstName} onChange={handleChange} required />
</label>
<label>Nom
<input name="lastName" value={form.lastName} onChange={handleChange} required />
</label>
<label>Téléphone
<input name="phoneNumber" value={form.phoneNumber} onChange={handleChange} required />
</label>
<button type="submit" disabled={submitting}>
{submitting ? 'Envoi…' : 'Créer le client'}
</button>
</form>
{registerMsg && <p>{registerMsg}</p>}
</section>
<section>
<h2>Rechercher un client</h2>
<form onSubmit={handleSearch}>
<label>Téléphone
<input value={phone} onChange={(e) => setPhone(e.target.value)} required />
</label>
<button type="submit">Rechercher</button>
</form>
{searchError && <p>{searchError}</p>}
{customer && (
<div>
<p>{customer.firstName} {customer.lastName}</p>
<p>Téléphone : {customer.phoneNumber}</p>
<p><strong>Points de fidélité : {customer.loyaltyPoints}</strong></p>
<input type="number"value={pointsInput}onChange={(e) => setPointsInput(e.target.value)}placeholder="Nombre de points"/>
<button type="button" onClick={() => applyLoyalty('add')}>Ajouter</button>
<button type="button" onClick={() => applyLoyalty('subtract')}>Retirer</button>
</div>
)}
</section>
</main>
);
}