Exercices

LocalStorage Weather Api ToDo et LocalStorage

React+ionic

Ionic Create project 4.React Outils utiles 5.Lifecycle Methods 6.JSX

Gestion Ventes

Produit CRUD

6.Form :Ajouter un produit 8.Liste produits 9.Pagination 10.Liste produits +Pagination 11.Liste produits +Datatable 11.Liste produits +load more 12.Supprimer un produit 14.Details d'un produit 15.Recherche et Autocomplete

Reacts:Utils

Gestion des erreurs Variables d'environment Cookies Internationalization proptypes Form validation React Animation Fragment Google Maps

Utilisateur CRUD

18.Inscription upload file 19.Connexion et Les sessions 19.Connexion: JWT Token

Ventes CRUD

17.Vendre un produit 18.Facture Generate PDF 19.Statisques Charts

Redux





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>
        }