1. Review page with React JS

Powerpuff Girls Review Page With React Jsسلام دوستان تو این پست می خوایم یادبگیریم چطوری با ری‌اکت یک صفحه Review بسازیم.یک صفحه Review صفحه‌ای که در اون درمورد افراد، مشاغل،محصولات و یا مکان های توریستی یک سری اطلاعات میده؛ مثلا یک شخصی رو با اسم، سن،شغل و یک متن کوتاه درمورد اون شخص یا درمورد کارش معرفی میکنه. ماهم در اینجا می خوایم یک Personal Review Page رو با ری‌اکت پیاده‌سازی کنیم.توجه: خب موضوعی که من برای این صفحه انتخاب کردم Personal Review Page هستش؛ یعنی دیتاها و داده‌ها، باید درمورد اشخاص باشن؛ اگه بخواهیم درمورد یک محصول یا یک مکان Review page بسازیم، باید نوع داده‌ها رو عوض کنیم نه کل برنامه نویسی صفحه رو !!برای ساخت این صفحه Review چهار مرحله داریم:ساخت دیتا (data.js)ساخت صفحه مرور (Review.js)ساخت صفحه اصلی (App.js)استایل دهی به صفحات (index.js)در ادامه به ترتیب با نحوه ساخت این صفحات و کدنویسیشون آشنا میشیم.اول از همه باید یه برنامه react رو بسازیم به اینصورت که تو آدرس مورد‌نظر در ترمینال مینویسیم:npm create-react-app appname و یا میتونی از این استفاده کنی npx create-react-app appname مسیردهی کامل پروژه ساخت دیتا (data.js) خب دیتای صفحه Review رو به‌صورت آرایه‌ای از آبجکت‌ها تعریف میکنیم؛ به اینصورت که هر عضو آرایه یک آبجکت هست و هر آبجکت ویژگی هایی چون name, age, job, power, image, birthday و متنی (text) در‌مورد اون آبجکت به ما میده.دیتای من درمورد سه شخصیت اصلی کارتون PowerPuffGirls هستش که به صورت زیر آوردم:data.js const reviews = [{ id:1, name: 'Blossom' ,birthday:'2002/07/03', job: 'tactician and self proclaimed leader of the Powerpuff Girls', power: 'Freezing objects with her breath', image:"./assets/Blossom1.jpg",text: 'Her personality ingredient is "everything nice", her signature color is bright pink, and she has long red-orange waist length hair with bangs in a triangular part with a red bow and a pink hair clip with a red heart. She was named for having spoken freely and honestly to the Professor shortly after her creation as shown in The Powerpuff Girls Movie. She is often seen as the most level headed, intelligent, and composed member of the group and also strong and determined. She is also a master strategist and apt planner.' },{ id:2, name: 'Bubles' ,birthday:'2002/07/03', job: 'Member of PowerPuffGirls', power: 'Projecting powerful sonic screams, and creating a shockwave of thunder with a single clap from her hands', image:"./assets/Bubbles1.jpg", text: 'Her signature color is blue, her personality ingredient is "sugar", and she has blonde hair in pigtails. Bubbles is seen as kind and very sweet but she is also capable of extreme rage and can fight monsters just as well as her sisters can. Her best friend is a stuffed octopus doll she calls "Octi", and she also loves animals. She exhibits the ability to both understand multiple languages and communicate with various animals.',},{id:3, name: 'Buttercup' ,birthday:'2002/07/03',job: 'Member of PowerPuffGirls', power:'Url her tongue, and creating fireballs by rubbing her hands together untill smoke comes out which forms a flaming ball that she throws at an opponent', image:"./assets/Buttercup1.jpg", text: 'Her personality ingredient is "spice", her signature color is green, and she has short black hair in a flip. She loves to get dirty, fights hard and plays rough; she does not plan and is all action. Her unique powers are to curl her tongue, and creating fireballs by rubbing her hands together untill smoke comes out which forms a flaming ball that she throws at an opponent. McCracken originally wanted to name the character "Bud" until a friend suggested the name Buttercup. According to The Powerpuff Girls Movie, Buttercup really dislikes the name she was given.', },];export default reviews;آدرس عکس ها رو در فولدری بنام public که در خارج از src برنامه هست، و در فولدری بنام assets ذخیره کردم. در پایین عکس‌هایی که استفاده کردم رو آوردم؛ شما خودتون میتونیدهرچقدر که خواستین دیتا و اطلاعات به data.js اضافه کنین../assets/Blossom1.jpg./assets/Buble1.jpg./assets/Buttercup1.jpg2. ساخت صفحه مرور (َReview.js)خب از این قسمت وارد برنامه نویسی خود صفحه میشیم. قبل اینکه برنامه نویسی رو شروع کنیم، باید react-icons رو از طریق ترمینال نصب کنیم که برای نصب کافیه که در مسیر src پروژه در ترمینال بنویسیم:npm install react-icons حال فایل‌های زیر رو به قسمت اول برنامه اضافه میکنیم:import React , {useState} from &quotreact&quot import data from './data'; import { FaChevronLeft , FaChevronRight , FaQuoteLeft, FaQuoteRight} from 'react-icons/fa';یک arrow function داخل متغیر Review تعریف میکنیم و این متغیر رو اکسپورت میکنیم:const Review = () => { } export default Review;ادامه کدها رو داخل این متغیر مینویسیم. چون data.js یک آرایه هست پس برای جستجو در آرایه باید از اندیس صفر آرایه شروع کرده و تا اندازه طول آرایه جستجو را ادامه دهد. برای همین با استفاده از هوک useState یک index تعریف می کنیم و مقدار اولیه صفر را به آن می دهیم ( یادتون باشه useState رو import کنین "import React , {useState} from "react) :const [index , setIndex] = useState(0);حال اطلاعات موجود در data[index] رو در متغیرهای زیر ذخیره میکنیم:const {name, image, job, power, text} = data[index]در برنامه Review سه کلید <> و surprise me تعریف شده که وظایف زیر رو دارن:با کلیک روی کلید < ایندکس دیتا یدونه به جلو میره data(index+1) و با کلیک روی کلید > ایندکس دیتا یدونه به عقب data(index-1) بر میگرده و با کلیک روی کلید surprise me به صورت رندوم یکی از افراد data.js رو نشون میده data(random). البته index+1 تا وقتیکه دیتا هست جلو میره و وقتی به انتهای آرایه ی دیتا میرسه باید دوباره به اول آرایه برگرده یعنی بشه index=0 ؛ همچنین وقتی index-1 میشه تا اندیس 0 باید کاهش پیدا کنه و بعد اندیس صفر باید بشه index=data.length-1 . بنابراین باید یه تابع برای کنترل index افزایشی یا کاهشی بنام checkNumber بنویسیم. توابع زیر رو برای 4 حالت مذکور پیاده سازی میکنیم:تابع checkNumber const checkNumber = (number) => { if(number < 0){ return data.length -1; } if(number > data.length-1){ return 0; } return number; }تابع prevData : کلید >const prevData = () => { setIndex((index) => { let newIndex = index -1; return checkNumber(newIndex); }) }تابع nextData : کلید <const nextData = () => { setIndex((index) => { let newIndex = index+1; return checkNumber(newIndex); }) } تابع randomData: کلید surprise meconst randomData = () => { let randomNumber = Math.floor(Math.random() * 10) if (randomNumber === index ) { randomNumber = index + 1 }خب حالا رسیدیم به قسمت return تابع اصلی (Review) و برگردوندن صفحه‌ی اون؛ فقط کافیه تو ادامه کدهای بالا این کدها رو بهش اضافه کنیم:return <article className=&quotreview&quot> <div > <img src={image} alt={name} className=&quotperson-image&quot /> </div> <h4 className=&quotauthor&quot> <strong><em>Name: </strong></em> {name}</h4> <p className=&quotjob&quot> <strong><em> Job: </strong></em> {job}</p> <p className=&quotpower&quot> <strong><em> Power: </strong></em> {power}</p> <p className=&quotinfo&quot>{text}</p> <div className=&quotbutton-container&quot> <button className=&quotprev-btn&quot ={prevData}> <FaChevronLeft /> </button> <button className=&quotnext-btn&quot ={nextData}> <FaChevronRight /> </button> <button className=&quotrandom-btn&quot ={randomData}> Suprise Me! </button> </div> </article>قسمت Review.js تموم شد.3. ساخت صفحه اصلی (App.js)تو App.js فقط کافیه صفحه Review.js که در مرحله 2 ساختیم رو با استفاده از تابع App برگردونیم:import React from &quotreact&quot import Review from './Review'; function App() { return ( <main> <section className='container'> <div className=&quottitle&quot> <h2>Power Puff Girls Review *_*</h2> <div className=&quotunderline&quot></div> </div> <Review /> </section> </main> ); } export default App;4. استایل دهی به صفحات (index.css)تو این قسمت استایل های صفحه رو مینویسیم::root { --clr-primary-1: hsl(205, 86%, 17%); --clr-primary-2: hsl(205, 77%, 27%); --clr-primary-3: hsl(205, 72%, 37%); --clr-primary-4: hsl(205, 63%, 48%); /* primary/main color */ --clr-primary-5: hsl(205, 78%, 60%); /* lighter shades of primary color */ --clr-primary-6: hsl(205, 89%, 70%); --clr-primary-7: hsl(205, 90%, 76%); --clr-primary-8: hsl(205, 86%, 81%); --clr-primary-9: hsl(205, 90%, 88%); --clr-primary-10: hsl(205, 100%, 96%); /* darkest grey - used for headings */ --clr-grey-1: hsl(209, 61%, 16%); --clr-grey-2: hsl(211, 39%, 23%); --clr-grey-3: hsl(209, 34%, 30%); --clr-grey-4: hsl(209, 28%, 39%); /* grey used for paragraphs */ --clr-grey-5: hsl(210, 22%, 49%); --clr-grey-6: hsl(209, 23%, 60%); --clr-grey-7: hsl(211, 27%, 70%); --clr-grey-8: hsl(210, 31%, 80%); --clr-grey-9: hsl(212, 33%, 89%); --clr-grey-10: hsl(210, 36%, 96%); --clr-white: #fff; --clr-red-dark: hsl(360, 67%, 44%); --clr-red-light: hsl(360, 71%, 66%); --clr-green-dark: hsl(125, 67%, 44%); --clr-green-light: hsl(125, 71%, 66%); --clr-black: #222; --transition: all 0.3s linear; --spacing: 0.1rem; --radius: 0.25rem; --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); --max-width: 1170px; --fixed-width: 620px; }, ::after, ::before { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; background: var(--clr-grey-10); color: var(--clr-grey-1); line-height: 1.5; font-size: 0.875rem; } ul { list-style-type: none; } a { text-decoration: none; } h1, h2, h3, h4 { letter-spacing: var(--spacing); text-transform: capitalize; line-height: 1.25; margin-bottom: 0.75rem; } h1 { font-size: 3rem; } h2 { font-size: 2rem; } h3 { font-size: 1.25rem; } h4 { font-size: 0.875rem; } p { margin-bottom: 1.25rem; color: var(--clr-grey-5); } @media screen and (min-width: 800px) { h1 { font-size: 4rem; } h2 { font-size: 2.5rem; } h3 { font-size: 1.75rem; } h4 { font-size: 1rem; } body { font-size: 1rem; } h1, h2, h3, h4 { line-height: 1; } } .section { width: 90vw; margin: 0 auto; max-width: var(--max-width); } @media screen and (min-width: 992px) { .section { width: 95vw; } } main { min-height: 100vh; display: grid; place-items: center; } .title { text-align: center; margin-bottom: 4rem; } .underline { height: 0.25rem; width: 5rem; background: var(--clr-primary-5); margin-left: auto; margin-right: auto; } .container { width: 80vw; max-width: var(--fixed-width); } .review { background: var(--clr-white); padding: 1.5rem 2rem; border-radius: var(--radius); box-shadow: var(--light-shadow); transition: var(--transition); text-align: center; } .review:hover { box-shadow: var(--dark-shadow); } .img-container { position:relative; width: 150px; height: 150px; border-radius: 50%; margin: 0 auto; margin-bottom: 1.5rem; } .person-img { width: 100%; display:block; height: 100%; object-fit:cover; border-radius: 50%; position: relative; } .quote-icon { position: absolute; top: 0; left: 0; width: 2.5rem; height: 2.5rem; display: grid; place-items: center; border-radius: 50%; transform: translateY(25%); background: var(--clr-primary-5); color: var(--clr-white); } .img-container::before { content: ''; width: 100%; height: 100%; background: var(--clr-primary-5); position: absolute; top: -0.25rem; right: -0.5rem; border-radius: 50%; } .author { margin-bottom: 0.25rem; } .job { margin-bottom: 0.5rem; text-transform: uppercase; color: var(--clr-primary-5); font-size: 0.85rem; } .info { margin-bottom: 0.75rem; } .prev-btn, .next-btn { color: var(--clr-primary-7); font-size: 1.25rem; background: transparent; border-color: transparent; margin: 0 0.5rem; transition: var(--transition); cursor: pointer; } .prev-btn:hover, .next-btn:hover { color: var(--clr-primary-5); } .random-btn { margin-top: 0.5rem; background: var(--clr-primary-10); color: var(--clr-primary-5); padding: 0.25rem 0.5rem; text-transform: capitalize; border-radius: var(--radius); transition: var(--transition); border-color: transparent; cursor: pointer; } .random-btn:hover { background: var(--clr-primary-5); color: var(--clr-primary-1); }حالا کافیه تو ترمینال در مسیر src برنامه بنویسیم npm start و تامام 8)Be happy and enjoy the Life 8)