Crud:Exemple
Soit le tableau d'object Repas suivant:
listeRepas = [ { id: 1, nom: 'Repas 1', prix: 15.99, details: { listeIngredients: ['Ingrédient 1', 'Ingrédient 2', 'Ingrédient 3'], calories: 500, allergenes: ['Noix', 'Gluten'], tempsPreparation: 30, // en minutes typeCuisine: 'Italienne', }, commentaires: [ { auteur: 'John Doe', texte: 'Très délicieux !', note: 4.5, }, // Ajoutez d'autres commentaires au besoin ], promotions: [ { libelle: 'Réduction de 10%', description: 'Valable jusqu\'au 31 décembre.', value:-30 }, // Ajoutez d'autres promotions au besoin ], }, ... ]
Créer le compsant ListeRepas
Ajouter la fonction supprimerRepas
listeRepas.js
import { useDispatch, useSelector } from "react-redux";
import { supprimerRepas } from "./actions";
import { useNavigate } from "react-router-dom";
export default function ListeRepas() {
const listeRepas = useSelector((state)=>state.listeRepas)
const dispatch = useDispatch()
const supprimer = (id) => {
dispatch(supprimerRepas(id))
}
const navigate = useNavigate()
const Commentaire = (id) => {
navigate('/listeCommentaire/'+id)
}
const ajouterPromotion = (id) => {
navigate('/ajouterPromo/'+id)
}
const ajouterI = (id) => {
navigate('/ajouterIngredient/'+id)
}
return <div className="m-5">
<h1>Liste Repas : </h1>
{listeRepas.map((r)=>{
return <div className="border border-5 p-3 w-50 m-2">
<b>ID : </b>{r.id}
<b> - Nom : </b>{r.nom}
<b> - Prix : </b>{r.prix} <br />
<b> - Details : </b><ul>
<li>liste Ingredients: <ul>
{r.details.listeIngredients.map((i)=>{
return <li>{i} </li>
})}
<li><input type="button" onClick={()=>ajouterI(r.id)} value="Ajouter Ingredient" className="btn btn-outline-warning btn-sm"/></li>
</ul>
</li>
<li>Calories: {r.details.calories}</li>
<li>Allergenes: <ul>
{r.details.allergenes.map((a)=>{
return <li>{a}</li>
})}
</ul>
</li>
<li>Temps Preparation: {r.details.tempsPreparation}</li>
<li>Type Cuisine: {r.details.typeCuisine}</li>
</ul><hr />
<input type="button" value="List Commentaires" onClick={()=>{Commentaire(r.id)}} className="btn btn-warning" /> <hr />
<div className="bg-info p-3">
<h4>Promotions : </h4>
{r.promotions.map(p=>{
return <div>
<h6>Libelle : {p.libelle}</h6>
<p>{p.description}</p>
<b>Value : {p.value}</b> <hr />
</div>
})}
<input type="button" onClick={()=>{ajouterPromotion(r.id)}} value="Ajouter Promotion" className="btn btn-info btn-sm m-2" />
</div> <hr />
<input type="button" value="Supprimer" className="btn btn-danger" onClick={()=>{supprimer(r.id)}}/>
</div>
})}
</div>
}
Actions.js
export const supprimerRepas = (id) => ({
type: 'deleteRepas',
payload : id
});
export const supprimerComment = (auteur,idR) => ({
type: 'deleteComment',
payload : {auteur,idR}
});
export const incrementNote = (auteur,idR) => ({
type: 'PlusNote',
payload : {auteur,idR}
});
export const ajouterRepas = (repas) => ({
type: 'addRepas',
payload : repas
});
export const ajouterPromo = (id,promo) => ({
type: 'addPromo',
payload : {id,promo}
});
export const ajouterIngredient = (id,i) => ({
type: 'addIngred',
payload : {id,i}
});
export const ajouterComment = (id,comment) => ({
type : 'addComment',
payload : {id,comment}
})
Reducer.js
const initialState = {
listeRepas : [
{
id: 1,
nom: 'Repas 1',
prix: 15.99,
details: {
listeIngredients: ['Ingrédient 1', 'Ingrédient 2', 'Ingrédient 3'],
calories: 500,
allergenes: ['Noix', 'Gluten'],
tempsPreparation: 30,
typeCuisine: 'Italienne',
},
commentaires: [
{
auteur: 'John Doe',
texte: 'Très délicieux !',
note: 4.5,
},
],
promotions: [
{
libelle: 'Réduction de 10%',
description: 'Valable jusqu\'au 31 décembre.',
value:-30
},
],
}
]}
const RepasReducer = (state=initialState,action) => {
switch(action.type) {
case 'deleteRepas' :
return {...state,
listeRepas:state.listeRepas.filter((r)=>r.id!=action.payload)};
case 'deleteComment' :
return {...state,
listeRepas:state.listeRepas.map((r)=>{
if(r.id==action.payload.idR) {
r.commentaires=r.commentaires.filter(c=>c.auteur!=action.payload.auteur)
} return r
})};
case 'PlusNote' :
return {...state,
listeRepas:state.listeRepas.map((r)=>{
if(r.id==action.payload.idR) {
r.commentaires.map((c)=>{
if(c.auteur==action.payload.auteur) {
c.note=c.note+0.5
}
})
} return r
})};
case 'addRepas' :
return {...state,
listeRepas:[...state.listeRepas,action.payload]};
case 'addPromo' :
return {...state,
listeRepas:state.listeRepas.map((r)=>{
if(r.id==action.payload.id) {
r.promotions.push(action.payload.promo)
} return r
})};
case 'addIngred' :
return {...state,
listeRepas:state.listeRepas.map((r)=>{
if(r.id==action.payload.id) {
r.details.listeIngredients.push(action.payload.i)
} return r
})};
case 'addComment' :
return {...state,
listeRepas:state.listeRepas.map((r)=>{
if(r.id==action.payload.id) {
r.commentaires.push(action.payload.comment)
} return r
})};
default : return state
}
}
export default RepasReducer
App.js
import { Link, Route, BrowserRouter as Router, Routes } from "react-router-dom";
import ListeRepas from "./listeRepas";
import ListeCommentaire from "./listeCommentaire";
import AjouterRepas from "./ajouterPepas";
import AjouterPromotion from "./ajouterPromo";
import AjouterIngred from "./ajouterIngred";
import FiltreRepas from "./FiltreRepas";
import AjouterComment from "./ajouterComment";
import PrixRepas from "./NotesRepas";
export default function App () {
return <Router>
<nav>
<ul className="nav">
<li className="nav-item"><Link to='/listeRepas' className="nav-link">Liste Repas</Link></li>
<li className="nav-item"><Link to='/ajouterRepas' className="nav-link">Ajouter Repas</Link></li>
<li className="nav-item"><Link to='/filtre' className="nav-link">Filtrer Par Temps</Link></li>
<li className="nav-item"><Link to='/noteRepas' className="nav-link">Prix Repas</Link></li>
</ul>
</nav>
<Routes>
<Route path='/listeRepas' element={<ListeRepas/>}/>
<Route path='/ajouterRepas' element={<AjouterRepas/>}/>
<Route path='/listeCommentaire/:id' element={<ListeCommentaire/>}/>
<Route path='/ajouterPromo/:id' element={<AjouterPromotion/>}/>
<Route path='/ajouterIngredient/:id' element={<AjouterIngred/>}/>
<Route path='/filtre' element={<FiltreRepas/>}/>
<Route path='/noteRepas' element={<PrixRepas/>}/>
<Route path='/ajouterComment/:id' element={<AjouterComment/>}/>
</Routes>
</Router>
}
Créer le compsant ListeCommentaires d'un repas sélectionnée
Ajouter la fonction incrémenterNoteCommentaire
Ajouter la fonction supprimerCommentaire
ListeCommentaires.js
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { incrementNote, supprimerComment } from "./actions";
export default function ListeCommentaire() {
const {id} = useParams()
const listeRepas = useSelector((state)=>state.listeRepas)
const listeCommentaire = listeRepas.find((r)=>r.id==id).commentaires
const dispatch = useDispatch()
const sup = (auteur) => {
dispatch(supprimerComment(auteur,id))
}
const plusNote = (auteur) => {
dispatch(incrementNote(auteur,id))
}
const navigate = useNavigate()
const ajouter = () => {
navigate('/ajouterComment/'+id)
}
return <div className="m-5">
<h1>Commentaires :</h1>
{listeCommentaire.map(c=>{
return <div className="border p-3">
<h6>Auteur : {c.auteur}</h6>
<p>{c.texte}</p>
<b>Note : {c.note}</b>
<input type="button" value="+" onClick={()=>{plusNote(c.auteur)}} className="btn btn-outline-warning btn-sm m-2" /><br />
<input type="button" value="delete" onClick={()=>{sup(c.auteur)}} className="btn btn-danger" />
</div>
})} <br/>
<input type="button" value="Ajouter Commentaire" onClick={ajouter} className="btn btn-primary"/>
</div>
}
Créer le compsant AjouterCommentaire d'un repas sélectionnées
AjouterCommentaire.js
import { useState } from "react"
import { useDispatch } from "react-redux"
import { useNavigate, useParams } from "react-router-dom"
import { ajouterComment } from "./actions"
export default function AjouterComment() {
const {id} = useParams()
const [comment,setComment] = useState({auteur:'',texte:'',note:0})
const getValue = (event) => {
setComment({...comment,[event.target.name]:event.target.value})
}
const dispatch = useDispatch()
const navigate = useNavigate()
const ajouter = () => {
dispatch(ajouterComment(id,comment))
navigate('/listeCommentaire/'+id)
}
return <div className="m-5">
<h1>Ajouter comment : </h1>
<b>Auteur : </b>
<input type="text" onChange={getValue} name="auteur"/> <br />
<hr /><b>Text</b> <br />
<textarea name="texte" onChange={getValue} cols="30" rows="10"></textarea><br />
<input type="button" value="Ajouter" onClick={ajouter} className="btn btn-success" />
</div>
}
Créer le compsant AjouterRepas
ajouterRepas.js
import { useState } from "react"
import { useDispatch, useSelector } from "react-redux"
import { ajouterRepas } from "./actions"
import { useNavigate } from "react-router-dom"
export default function AjouterRepas () {
const listeRepas = useSelector(state=>state.listeRepas)
const [nom,setNom]=useState()
const [prix,setPrix]=useState()
const [ingred,setIngred]=useState()
const [caloreis,setCalories]=useState()
const [allergenes,setAllergenes]=useState()
const [temps,setTemps]=useState()
const [type,setType]=useState()
const dispatch = useDispatch()
const navigate = useNavigate()
const ajouter = () => {
dispatch(ajouterRepas({
id: listeRepas[listeRepas.length-1].id+1,
nom: nom,
prix: prix,
details: {
listeIngredients: [ingred],
calories: caloreis,
allergenes: [allergenes],
tempsPreparation: temps,
typeCuisine: type,
},
commentaires: [],
promotions: [],
}))
navigate('/listeRepas')
}
return <div className="m-5">
<h1>Ajouter Repas :</h1>
<table>
<tr>
<th>Nom :</th>
<td><input type="text" onChange={(event)=>{setNom(event.target.value)}}/></td>
</tr>
<tr>
<th>Prix :</th>
<td><input type="number" onChange={(event)=>{setPrix(event.target.value)}}/></td>
</tr>
<tr>
<th>Ingredients :</th>
<td><input type="text" onChange={(event)=>{setIngred(event.target.value)}}/></td>
</tr>
<tr>
<th>Calories :</th>
<td><input type="number" onChange={(event)=>{setCalories(event.target.value)}}/></td>
</tr>
<tr>
<th>allergenes: </th>
<td><input type="text" onChange={(event)=>{setAllergenes(event.target.value)}}/></td>
</tr>
<tr>
<th>Temps Preparation: </th>
<td><input type="number" onChange={(event)=>{setTemps(event.target.value)}}/> <i>- minutes</i></td>
</tr>
<tr>
<th>Type Cuisine : </th>
<td><input type="text" onChange={(event)=>{setType(event.target.value)}}/></td>
</tr>
<tr>
<td></td>
<td><input type="button" value="Ajouter" onClick={ajouter} className="btn btn-success"/></td>
</tr>
</table>
</div>
}
Créer le compsant AjouterPromotion d'un repas sélectionnées
AjouterPromotion.js
import { useState } from "react"
import { useDispatch } from "react-redux"
import { ajouterPromo } from "./actions"
import { useNavigate, useParams } from "react-router-dom"
export default function AjouterPromotion() {
const {id} = useParams()
const [promo,setPromo] = useState({libelle:'',description:'',value:0})
const getValue = (event) => {
setPromo({...promo,[event.target.name]:event.target.value})
}
const navigate = useNavigate()
const dispatch = useDispatch()
const ajouter = () => {
dispatch(ajouterPromo(id,promo))
navigate('/listeRepas')
}
return <div className="m-5">
<h1>Ajouter Promotion :</h1>
<b>Libelle : </b>
<input type="text" onChange={getValue} name="libelle"/><br /><br />
<b>Description : </b>
<input type="text" onChange={getValue} name="description"/><br /><br />
<b>Value : </b>
<input type="number" onChange={getValue} name="value"/><br /><br />
<input type="button" value="Ajouter" onClick={ajouter} className="btn btn-primary"/>
</div>
}
Créer le compsant AjouterIngredient permet d'ajouter un ingrédient à un repas sélectionnée
AjouterIngredient.js
import { useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { ajouterIngredient } from "./actions";
export default function AjouterIngred() {
const [ingredient,setIngredient] = useState()
const {id} = useParams()
const dispatch = useDispatch()
const navigate = useNavigate()
const ajouter = () => {
dispatch(ajouterIngredient(id,ingredient))
navigate('/listeRepas')
}
return <div className="m-4">
<h1>Ajouter Ingredinet</h1>
<input type="text" onChange={(event)=>setIngredient(event.target.value)} />
<input type="button" onClick={ajouter} value="Ajouter" className="btn btn-success" />
</div>
}
Créer le compsant FiltreRepas par tempsPreparation
FiltreRepas.js
import { useDispatch, useSelector } from "react-redux";
import { supprimerRepas } from "./actions";
import { useEffect, useState } from "react";
export default function FiltreRepas() {
const listeRepas = useSelector((state)=>state.listeRepas)
const [liste,setListe] = useState([])
const [temps,setTemps] = useState(0)
const dispatch = useDispatch()
const supprimer = (id) => {
dispatch(supprimerRepas(id))
}
useEffect(()=>{
if(temps!=0) {
setListe(listeRepas.filter(r=>r.details.tempsPreparation==temps))
} else setListe(listeRepas)
})
return <div className="m-5">
<h1>Filtrer Par Temps de preparation : </h1>
<input type="number" onChange={(event)=>setTemps(event.target.value)}/>
{liste.map((r)=>{
return <div className="border p-3 w-50 m-2">
<b>ID : </b>{r.id}
<b> - Nom : </b>{r.nom}
<b> - Prix : </b>{r.prix} <br />
<b> - Temps Preparation : </b>{r.details.tempsPreparation} <br />
<input type="button" value="Supprimer" className="btn btn-danger" onClick={()=>{supprimer(r.id)}}/>
</div>
})}
</div>
}
Créer le compsant prixRepas permet trier le repas par leur prix en order croissant
prixRepas.js
import { useDispatch, useSelector } from "react-redux";
import { supprimerRepas } from "./actions";
export default function PrixRepas () {
const listeRepas = useSelector((state)=>state.listeRepas).sort((a,b)=>b.prix - a.prix)
const dispatch = useDispatch()
const supprimer = (id) => {
dispatch(supprimerRepas(id))
}
return <div className="m-5">
<h1>Trier les repas par prix : </h1>
{listeRepas.map((r)=>{
return <div className="border p-3 w-50 m-2">
<b>ID : </b>{r.id}
<b> - Nom : </b>{r.nom}
<b> - Prix : </b>{r.prix} <br />
<input type="button" value="Supprimer" className="btn btn-danger" onClick={()=>{supprimer(r.id)}}/>
</div>
})}
</div>
}