چند وقت پیش عرفان پروژهای را قبول کرد؛ پروژهای که در آن باید صفحهی یک مقاله را با ریاکت طراحی میکرد؛ صفحهای که از چهار قسمت اصلی تشکیل شده که به شرح زیر است:
- عنوان و توضیحات مقاله
 - سیستم امتیازدهی به مقاله
 - سیستم ثبت نظر
 - قسمت نمایش نظرات بهصورت تودرتو
 
متأسفانه در اواسط پروژه بود که عرفان درگیر ویروس کرونا شد و پروژه ناقص ماند، اما از آنجایی که عرفان روی قولی که میدهد بسیار حساس است، از شما خواسته تا قسمتهایی از پروژه را که باقی مانده کامل کنید تا مبادا بد قول شود و بتواند پروژه را سر وقت تحویل دهد.
جزئیات پروژه
پروژهی اولیه را از این لینک دانلود کنید.
ساختار فایلهای پروژه
comments
├── package.json
├── package-lock.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── README.md
├── server
│   ├── app.js
│   ├── posts.json
│   └── techs.json
└── src
    ├── App.css
    ├── App.jsx
    ├── assets
    │   └── avatar.png
    ├── components
    │   ├── AddComment.jsx
    │   ├── Comment.jsx
    │   ├── Post.jsx
    │   ├── Rate.jsx
    │   └── SelectBox.jsx
    ├── container
    │   └── Comments.jsx
    ├── data
    │   └── data.js
    ├── index.js
    └── __tests__
        └── sample.test.js
راهاندازی پروژه
- 
پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
 - 
اجرای دستور
npm iپکیج های مورد نیاز را نصب کنید. - 
با اجرای دستور
npm run serverسرور را اجرا کنید. - 
با اجرای دستور
npm startپروژه را اجرا کنید. 
قسمتهای باقیمانده از پروژه که باید پیادهسازی شوند
پاسخ به نظر دیگران
در کامپوننت Comment دکمهای تحت عنوان reply وجود دارد که با کلیک کردن روی آن به وضعیت پاسخ میرویم. در وضعیت پاسخ، اتفاقاتی رخ می دهد که به شرح زیر است:
- کاربر باید به المانی با کلاس 
ac-wrapperاسکرول شود. این المان در فایلAddCommentوجود دارد. - در فایل 
AddCommentیک تگh2وجود دارد که محتوای آن در وضعیت پاسخ باید برابر باشد با: 
Write your comment in response to {name}:
که {name} برابر است با نام فردی که قرار است به او پاسخ داده شود.
و در وضعیت ثبت نظر باید برابر باشد با:
Write your comment:
- 
در وضعیت پاسخ باید بعد از دکمهی
Sendدر فایلAddCommentدکمهای تحت عنوانCancelاضافه شود که در صورت کلیک کردن روی این دکمه، باید از وضعیت پاسخ به وضعیت ثبت نظر برگردیم. - 
اگر در وضعیت ثبت نظر باشیم، در فایل
AddCommentبعد ازinputبا نوعemailباید کامپوننتSelectBoxفراخوانی شود، اما اگر در وضعیت پاسخ باشیم، این کامپوننت نباید در صفحه وجود داشته باشد. 
انتخاب topic
مقالات موضوعات مختلفی را شامل میشوند. کاربر هنگام ثبت نظر باید topic یا موضوعی را مشخص کند. برای این کار، عرفان سروری آماده کرده است که یک رشته دریافت میکند و بین topic های موجود جستوجو میکند و لیست topic هایی که رشتهی ارسالشده در آنها وجود دارد را بر میگرداند. برای مثال اگر topic ها در سرور بهصورت زیر باشند:
php , python , java , c++ , Go
اگر حرف p برای سرور ارسال شود، سرور لیست زیر را برمیگرداند:
{
    "data": {
        "matchedTechs": [
            { "id": 1, "name": "php" },
            { "id": 2, "name": "python" }
        ]
    },
    "status": "success"
}
در فایل components/SelectBox یک input با کلاس tpc وجود دارد. در صورت تغییر value این input، باید یک درخواست GET به آدرس http://127.0.0.1:8000/ ارسال شود و مقدار input در query string با کلید search ارسال کنید تا لیست topic ها دریافت شوند.
عرفان برای نمایش topic ها یک المان div با کلاس c-selectbox ساخته است. این المان به نحوی طراحی و استایلدهی شده است که شبیه به یک dropdown باشد. اگر استایل های زیر را داشته باشد:
padding: 0;
height: 0;
overflow: "hidden";
لیست topic ها نمایش داده نمیشود و dropdown در وضعیت بسته است و اگر این استایل ها را نداشته باشد، dropdown در وضعیت باز است و لیست topic ها در صفحه نمایش داده می شود.
در صورتی که لیست topic ها خالی باشد، dropdown باید بسته باشد.
در صورتی که لیست topic ها خالی نباشد، باید لیست را در المان div با کلاسc-selectbox بهصورت زیر رندر کنید:
<div className="item">
    <label htmlFor={آیدی تاپیک}>{نام تاپیک}</label>
    <input type="radio" name="" id={آیدی تاپیک} />
</div>
با کلیک بر روی المان div با کلاس item که رندر کردهاید، اتفاقات زیر باید رخ دهد:
ابتدا باید dropdown بسته شود و سپس باید نام کامل آن topic به عنوان مقدار input با کلاس tpc قرار بگیرد
دقت کنید در زمانی که لیست تاپیک ها خالی نیست و ما در حال نمایش topic ها هستیم در صورتی که کاربر  بهصورت کلی روی body کلیک کند، باید dropdown بسته شود و مقدار input با کلاس tpc تغییر نکند.
امتیازدهی
در این بخش از سؤال، شما باید سیستم امتیازدهی به مقاله را پیادهسازی کنید. در فایل Rate.jsx یک استیت به نام star وجود دارد که مقدار اولیهی آن به صورت زیر است:
[
    { id: 1, hover: false, clicked: false },
    { id: 2, hover: false, clicked: false },
    { id: 3, hover: false, clicked: false },
    { id: 4, hover: false, clicked: false },
    { id: 5, hover: false, clicked: false }
]
در صورتی که مقدار hover و clicked برابر با true باشد، ستارههای تو پر و در غیر اینصورت، ستارههای تو خالی نمایش داده میشوند. در این بخش چهار تابع داریم که دو تا از آنها بهصورت کامل نوشته شده و دو تابع را باید شما پیادهسازی کنید. عملکرد دو تابعی که به صورت کامل از قبل نوشته شده بهشرح زیر است:
تابع hoverHandler
این تابع رویداد onMouseEnter روی ستارهها را هندل میکند، بهطوری که یک شناسه دریافت میکند و مقدار hover هر آبجکتی که شناسهی آنها از نظر عددی کوچکتر از شناسهی دریافتی است را برابر با true میکند. برای مثال، فرض کنید کاربر ستارهی چهارم را hover کرده است. ما باید ستارههایی با شناسهی 1 تا 4 را آپدیت کنیم و مقدار hover آنها را true کنیم.
تابع blurHandler
این تابع رویداد onMouseLeave را روی ستارهها هندل میکند، بهطوری که مقدار hover هر آبجکت را آپدیت کرده و آن را برابر با false قرار میدهد.
و اما دو تابعی که شما باید آنها را کامل کنید:
تابع submitRateHandler
این تابع در قدم اول مانند تابع hoverHandler کار می کند، با این تفاوت که به جای true کردن مقدار hover هر آبجکت، باید مقدار clicked هر آبجکت را true کند. در ادامه، باید یک درخواست از نوع PATCH به آدرس http://127.0.0.1:8000/posts/ ارسال کند و در بدنهی درخواست، شناسهی آخرین آبجکتی که ویژگی clicked آن برابر با true شده را به عنوان rate به صورت JSON به سرور ارسال کند.
متأسفانه در حال حاضر سرور خراب است و عرفان از دوستش سینا خواسته تا سرور را درست کند، اما سینا در سفر به سر میبرد و شما باید با همین سرور خراب کار کنید! اشکال سرور این است که با احتمال ۵۰ درصد، rate کاربران را ثبت میکند و با احتمال ۵۰ درصد، درخواست شما با خطا مواجه میشود. علاوه بر این، سرور یک تأخیر یک ثانیه ای نیز دارد. اگر درخواست شما با موفقیت ثبت شود پیام سرور به شما به صورت زیر خواهد بود:
{
    "message": "Your rate for this post has been registered.",
    "status": "success"
}
پس از دریافت پیام بالا، باید مقدار message را بهصورت یک toast نمایش دهید. برای این کار، عرفان به پیشنهاد مهیار از پکیج react-toastify استفاده کرده است. البته کدهای این قسمت را نیز در اختیار شما قرار داده است. کافی است در صورت دریافت پاسخ موفقیتآمیز، از تکهکد زیر استفاده کنید:
toast.success(پیامی که از سرور دریافت کرده اید, {
    position: "top-left",
});
در صورت fail شدن درخواست، پاسخ سرور بهصورت زیر خواهد بود:
{
    "message": "Rating registering failed, try again.",
    "rate": آخرین امتیازی که در سرور ثبت شده است,
    "status": "error"
}
مقدار rate برابر با آخرین امتیاز ثبتشدهی کاربر است. شما باید این مقدار را به تابع stepBackward ارسال کنید.
به دلیل این که سرور تأخیر دارد، ما در زمان تآخیر باید امتیازی که کاربر ثبت کرده است را آپدیت و رندر کنیم، اما به محض این که پاسخ از سرور دریافت شود، در صورتی که درخواست fail شده باشد، باید سیستم rating را مجدد آپدیت کنیم و به rate قبلی برگردیم (منظور آخرین امتیازی است که کاربر وارد کرده و در سرور ثبت شده). به این تکنیک، optimistic rendering گفته میشود. تابع stepBackward در واقع قرار است این کار را برای ما هندل کند. پس از فراخوانی تابع stepBackward باید مجدداً یک toast به کاربر نمایش دهید. برای این کار، از تکهکد زیر استفاده کنید:
toast.error(پیامی که از سرور دریافت کرده اید, {
    position: "top-left",
});
تابع stepBackward
این تابع یک rate دریافت میکند و باید استیت مربوط به ستارهها را آپدیت کند، به طوری که مقدار clicked مربوط به المانهای دارای شناسههای کوچکتر یا مساوی rate را true کند و مقدار hover آنها را false کند. برای مثال، استیت ستارهها در هر وضعیتی که باشد، در صورت fail شدن درخواست اگر سرور مقدار rate را 3 برگرداند، باید آبجکتهایی با شناسههای 1 تا 3 طوری آپدیت شوند که مقدار clickedشان true و مقدار hoverشان false شود.
توجه: شما تنها مجاز به اعمال تغییرات در فایلهای زیر هستید:
src/App.jsx
src/components/AddComment.jsx
src/components/Comment.jsx
src/components/Rate.jsx
src/components/SelectBox.jsx
آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، پوشهی src را زیپ کرده و آپلود کنید.
ارسال پاسخ برای این سؤال