React js Darija Review App الجزء الثاني
فهاد الجزء الثاني من React js Darija Review App غادي نكملوا ل projet ديالنا ونزيدو ل components لي بقاو باش نعرضوا reviews نديروا عليهم التعديلات والحذف ديالهم.
نظرة سريعة بالفيديو
1- إضافة ل ListItem Component
من بعد فنفس dossier components زيد fichier ListItem.js لي فيه غادي يتعرض كل تقييم تزاد و لي فيه غادي يكون الكود التالي :
//
import React,{useContext, useState, useEffect} from 'react';
import {ReviewContext} from './context/ReviewContext'
import { motion, AnimatePresence } from "framer-motion";
import {showRating} from './Helpers';
export default function ListItem({review}) {
const {editReview, reviewToEdit, removeReview} = useContext(ReviewContext);
const [disabled, setDisabled] = useState(false);
useEffect(() => {
if(reviewToEdit.review && reviewToEdit.review.id === review.id){
setDisabled(true);
}else{
setDisabled(false);
}
},[reviewToEdit]);
const removeRating = (id) => {
removeReview(id);
}
return (
<AnimatePresence>
<motion.div
key={review.id}
initial={{ opacity: 0}}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ delay: .5 }}
>
<li className="list-group-item d-flex justify-content-between align-items-start">
<div className="ms-2 me-auto">
<div className="fw-bold">{review.name}</div>
<p>{review.message}</p>
<p>
{showRating(review.rating)}
</p>
</div>
<div className="d-flex flex-column align-items-center">
<button className="btn btn-sm btn-warning mb-2">
<i className="bi bi-pencil" onClick={() => editReview(review)}></i>
</button>
<button className="btn btn-sm btn-danger"
disabled={disabled}>
<i className="bi bi-trash"
onClick={() => removeRating(review.id)}></i>
</button>
</div>
</li>
</motion.div>
</AnimatePresence>
)
}
2- إضافة ل AverageRating Component
من بعد فنفس dossier components زيد fichier AverageRating.js لي فيه غادي يتعرض المعدل ديال التقييم و لي فيه غادي يكون الكود التالي :
//
import React, { useContext } from 'react'
import { ReviewContext } from './context/ReviewContext';
export default function AverageRating() {
const {reviews} = useContext(ReviewContext);
const calculateReviewsAverage = () => {
let average = reviews.reduce((acc,review) => {
return acc + review.rating / reviews.length;
},0);
return average > 0 ? average.toFixed(1) : 0;
}
return (
<div className="container my-4">
<div className="d-flex justify-content-between align-items-center">
<h5>Reviews: <span className="badge bg-dark rounded-pill ">{reviews.length}</span></h5>
<h5>
Average:{" "}
<span className="badge bg-warning text-dark rounded-pill">
{calculateReviewsAverage()}
</span>
</h5>
</div>
</div>
)
}
3- إضافة ل ReviewContext
من بعد فنفس dossier components زيد dossier context فيه زيد fichier ReviewContext.js لي فيه هاد الكود :
//
import {createContext} from 'react';
export const ReviewContext = createContext();
4- إضافة ل fichier Helpers.js
من بعد فنفس dossier components زيد fichier Helpers.js لي فيه غادي يكون الكود التالي :
//
export const showRating = (rating) => {
switch(rating){
case 1 :
return <i className="bi bi-star-fill text-warning"></i>;
case 2 :
return (
<>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
</>
);
case 3 :
return (
<>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
</>
);
case 4 :
return (
<>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
</>
);
case 5 :
return (
<>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
<i className="bi bi-star-fill text-warning"></i>
</>
);
default:
return 'something went wrong!'
}
}
5- تعديل App.js
من بعد دير تعديلات على ل App.js باش ل App ديالنا تخدم كما ينبغي ودير ل commande :
npm start
باش ت tester ل app .
الكود ديال الملف هو :
//
import {useState} from 'react';
import Form from "./components/Form";
import Header from "./components/Header";
import ReviewList from "./components/ReviewList";
import {ReviewContext} from "./components/context/ReviewContext";
function App() {
const [reviews,setReviews] = useState([]);
const [reviewToEdit,setReviewToEdit] = useState({
review : null,
updating: false
});
const addReview = (review) => {
setReviews([review, ...reviews]);
}
const editReview = (review) => {
setReviewToEdit({
review,
updating: true
});
}
const updateReview = (review) => {
setReviews(reviews.map(item => item.id === review.id ?
{...item,...review} : item));
setReviewToEdit({
review : null,
updating: false
});
}
const removeReview = (id) => {
setReviews(reviews.filter(review => review.id !== id));
}
return (
<ReviewContext.Provider value={
{
reviews, addReview, editReview,
updateReview, reviewToEdit, removeReview
}
}>
<div className="container">
<div className="row my-5">
<div className="col-md-8 mx-auto">
<div className="card">
<div className="card-header bg-white">
<Header/>
</div>
<div className="card-body">
<Form/>
<ReviewList/>
</div>
</div>
</div>
</div>
</div>
</ReviewContext.Provider>
);
}
export default App;