# پروژه اولیه
پروژهی اولیه را از
[این لینک](/contest/assignments/33751/download_problem_initial_project/118646/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار پروژه
</summary>
```
product-slider
├── assets
│ ├── css
│ │ ├── index.css
│ │ ├── productCard.css
│ │ └── productSlider.css
│ ├── font
│ │ └── Vazir.ttf
│ └── images
│ ├── 01.jpg
│ ├── 02.jpg
│ ├── 03.jpg
│ ├── 04.jpg
│ ├── 05.jpg
│ ├── 06.jpg
│ ├── favicon.ico
│ ├── next.png
│ └── previous.png
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── plugins
│ │ └── index.js
│ └── support
│ ├── commands.js
│ └── index.js
├── data
│ └── index.js
├── utils
│ └── number.js
├── cypress.json
├── index.html
├── package.json
└── script.js
```
</details>
# جزئیات
ظاهر کلی برنامه بهاین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/yxIZggzHTl/product-slider.gif)
فرض کنید که میخواهیم برای صفحهی اصلی وبسایت یک اسلایدر یا نمایشدهندهی محصول ایجاد کنیم. این اسلایدر باید در لحظه از بین محصولات یک محصول را به صورت تصادفی به کاربر نمایش دهد.
#### مواردی که باید در این سوال رعایت کنید:
- مدت زمان نمایش هر اسلاید ۴ ثانیه است.
- بعد از گذشتن ۴ ثانیه محصول تصادفی بعدی نمایش داده میشود.
- کاربر باید بتواند توسط دکمه های مربوطه، اسلاید قبل و بعد را مشاهده کند.
- انتخاب و نمایش محصول جدید باید به صورت تصادفی باشد و نباید شامل دو محصول آخر که نمایش داده شده است، باشد.
#### تغییرات لازم برای هر فایل:
- فایل `script.js`: موارد خواسته شده باید در این فایل قرار داده شوند.
- در فایل فوق سه تابع برای شما در نظر گرفته شده است که باید آنها را تکمیل کنید.
# نکات
- فرض کنید حداقل تعداد محصولات ۴ عدد خواهد بود.
- شما تنها مجاز به اعمال تغییرات در فایل `script.js` هستید.
- برای ارسال پاسخ فقط فایل `script.js` ارسال کنید.
اسلایدر محصولات
# پروژه اولیه
پروژهی اولیه را از
[این لینک](/contest/assignments/33751/download_problem_initial_project/118648/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار پروژه
</summary>
```
khalabane-zebel
├── assets
│ └── images
│ └── favicon.ico
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── plugins
│ │ └── index.js
│ └── support
│ ├── commands.js
│ └── index.js
├── styles
│ └── app.css
├── cypress.json
├── index.html
├── package.json
└── script.js
```
</details>
# جزئیات
ظاهر کلی برنامه بهاین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/ExBVYAz7v3/draganddrop.gif)
در این سوال میخواهیم یک بازی طراحی کنیم تا خلبان بتواند با کمک آن، توانایی بینایی خود را به چالش بکشد.
طراحی این بازی اینگونه است که یک رنگ به عنوان صورت سوال و چهار رنگ هم به عنوان گزینهها قرار میگیرند. حال خلبان باید با استفاده از کشیدن رنگها و رهاسازی آنها در بخشهای `darker` و `lighter`، مشخص کند که کدام رنگها تیرهتر و کدام رنگها روشنتر از رنگ اصلی یا همان رنگ سوال میباشند.
#### مواردی که باید در این سوال رعایت کنید:
- خلبان باید بتواند از بخش `.optionsBox` دایرههای رنگی را بکشد (*drag*) و در بخش `.lighterBox` یا `.darkerBox` رها کند (*drop*).
- خلبان ممکن است اشتباه کند و دایرهها در قسمت نادرست قرار دهد. بههمین دلیل خلبان میتواند در هر شرایطی دایرهها را بین قسمتهای `.lighterBox` و `.darkerBox` جابهجا کند. (عمل *drag and drop*)
- امکان برگشتن دایرههای قرار داده شده در قسمتهای `.lighterBox` و `.darkerBox` به قسمت `.optionsBox` وجود ندارد.
- هنگامی که خلبان تمام دایرهها را در `.lighterBox` و `.darkerBox` قرار داد، دکمه ثبت باید فعال شود.
- شما باید تابع `handleDragAndDrop` را تکمیل کنید.
- دایرههای رنگی در متغیر `answerBoxes` قرار داده شده است.
#### تغییرات لازم برای هر فایل:
- فایل `script.js`: موارد خواستهشده باید در این فایل قرار داده شوند.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `script.js` هستید.
- برای ارسال پاسخ فقط فایل `script.js` ارسال کنید.
- قسمتی از کد مورد نیاز برای عمل *drag and drop* در پروژه اولیه آمده است.
برای اطلاعات بیشتر میتوانید به [این لینک](https://www.javascripttutorial.net/web-apis/javascript-drag-and-drop/) مراجعه کنید.
خلبان زبل
# پروژه اولیه
پروژهی اولیه را از
[این لینک](/contest/assignments/33751/download_problem_initial_project/118645/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار پروژه
</summary>
```
use-page-data
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── hooks
│ │ └── usePageData.js
│ ├── App.js
│ ├── index.css
│ └── index.js
└── package.json
```
</details>
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `use-page-data` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
ظاهر کلی برنامه بهاین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/SuztAPWIlP/usePageData.gif)
از آنجایی که تعداد محصولات دیجیکالا در حال زیاد شدن است، ساخت *Custom Hook*
به یک بخش جدانشدنی از پروژهها تبدیل شده است.
ساختار *api* ها در دیجیکالا در تمام پروژهها رعایت شده است.
این موضوع باعث میشود ساخت یک *Custom Hook* برای ارسال درخواستها به سرور
بسیار مفید باشد.
در این سوال از شما میخواهیم یک *Custom Hook* به این منظور پیادهسازی کنید.
این هوک باید ورودیهای زیر را دریافت کند:
```json
{
"url": string,
"fireOnLoad": boolean,
"successCallback": (data) => void,
"failedCallback": () => void,
}
```
- `url`: این پارامتر آدرس *api* را مشخص میکند. بهعبارتی دیگر شما باید به این آدرس درخواست را ارسال کنید.
- `fireOnLoad`: این پارامتر مشخص میکند که آیا درخواست در هنگام ایجاد کامپوننت (*mount*) ارسال شود یا خیر.
- `successCallback`: این پارامتر یک *callback function* ،است و درصورتی که درخواست با موفقیت تمام شد باید صدا زده شود. پارامتر ورودی این تابع، پاسخ سرور است.
- `failedCallback`: این پارامتر یک *callback function* است و درصورتی که درخواست ناموفق بود، باید صدا زده شود.
خروجی هوک باید به شکل زیر باشد:
```json
{
"pending": boolean,
"hasError": boolean,
"data": any,
"request": () => Promise<any>,
}
```
- `pending`: نشاندهندهی آن است که درخواست به سرور فرستاده شده است ولی هنوز پاسخی از سرور دریافت نشده است.
- `hasError`: نشاندهندهی ناموفق بودن درخواست ارسالی است.
- `request`: یک تابع *async* برای ارسال درخواست است.
این تابع بخش اصلی هوک است.
در صورت موفقبودن درخواست این تابع باید پاسخ را برگرداند (*resolve*).
این تابع را میتوان به صورت جداگانه نیز صدا کرد.
- `data` : پاسخ سرور در این فیلد قرار داده میشود.
همچنین این هوک باید قابلیت کشکردن درخواستها را درصورت موفقیتآمیز بودن ریکوئست داشته باشد؛ بهاینصورت که برای هر *url* وضعیت درخواست را ذخیره کند و در درخواستهای بعدی به آن *url* از کش بخواند و درخواست جدیدی ارسال نکند.
بهعنوان مثال اگر هوک در چند جای مختلف استفاده شود یا اگر متد *request* چند بار برای یک *url* فراخوانی شود تنها یک ریکوئست به *url* داده شده زده میشود و پاسخ سرور برای بقیه ریکوئستها با *url* یکسان استفاده میگردد.
ساختار کش را میتوانید هرطور که خواستید پیاده سازی کنید به طور مثال این ساختار میتواند برای هر *url* به شکل زیر باشد:
```json
{
"hasError": boolean,
"result": any,
}
```
#### مواردی که باید در این سوال رعایت کنید:
- در صورتی که مقدار `fireOnLoad` برابر `true` باشد، باید تابع *request* در هنگام *mount* شدن کامپوننت صدا زده شود.
- درصورت وجود یک *url* در کش، درخواست جدیدی به آن *url* نباید ارسال شود.
- شرایط گفته شده باید برای هنگامی که *url* در کش موجود است نیز برقرار باشد.
- باید بتوان توسط تابع *request* به پاسخ سرور پس از *resolve* شدن دسترسی داشت.
#### تغییرات لازم برای هر فایل:
- فایل `usePageData.js`: موارد خواسته شده باید در این فایل قرار داده شوند.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `usePageData.js` هستید.
- فرض کنید تمام درخواستهای *GET* میباشند.
- برای ارسال پاسخ فقط فایل `usePageData.js` ارسال کنید.
هوک درخواستدهنده
# پروژه اولیه
پروژهی اولیه را از
[این لینک](/contest/assignments/33751/download_problem_initial_project/118647/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار پروژه
</summary>
```
pindo
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ └── logo512.png
├── src
│ ├── assets
│ │ └── font
│ │ └── Vazir.ttf
│ ├── components
│ │ ├── Button
│ │ │ ├── Button.css
│ │ │ └── index.jsx
│ │ ├── Checkbox
│ │ │ └── index.jsx
│ │ ├── CitySelector
│ │ │ ├── CitySelectorItem.jsx
│ │ │ └── index.jsx
│ │ ├── Dropdown
│ │ │ └── index.jsx
│ │ ├── Error
│ │ │ └── index.jsx
│ │ ├── TextInput
│ │ │ └── index.jsx
│ │ ├── Textarea
│ │ │ └── index.jsx
│ │ └── FormItem.jsx
│ ├── constants
│ │ ├── Errors.js
│ │ └── FormType.js
│ ├── data
│ │ ├── cities.js
│ │ └── formData.js
│ ├── App.css
│ ├── App.jsx
│ ├── index.css
│ └── index.js
└── package.json
```
</details>
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `pindo` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
ظاهر کلی برنامه بهاین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/d0jAsU8SZt/pindo.gif)
یکی از قسمتهای اصلی پروژه پیندو ایجاد آگهی است. کاربران در دستهبندیهای مختلفی میتوانند برای کالای خود آگهی ایجاد کنند.
برای مثال فرم ایجاد آگهی برای گوشی موبایل با ظروف آشپزخانه متفاوت است.
به همین جهت فرم ایجاد آگهی باید به صورت داینامیک باشد.
در این سوال از شما میخواهیم این فرمهای داینامیک را بسازید.
اِلِمانهای فرم در یک آرایه قرار دارد.
ساختار این آرایه به شکل زیر است:
```json
{
"type": string,
"required": boolean | undefined,
"name": string,
"label": string,
"options": { "title": string, "value": number }[],
"dependency": {
"show": { "name": string, "value": string | boolean | number },
"required": { "name": string, "value": string | boolean | number },
} | undefined,
}
```
#### فیلد *type*
این فیلد نشاندهندهی نوع اِلمان است.
هر المان فرم میتواند یکی از مقادیر *type* زیر را داشته باشد:
```js
const FormType = {
TEXT: "text",
DROPDOWN: "dropdown",
TEXTAREA: "textarea",
CHECKBOX: "checkbox",
CITY: "city",
};
```
#### فیلد *required*
این فیلد نشان میدهد که آیا تکمیل این المان اجباری خواهد بود یا خیر.
درصورتی که این فیلد `true` باشد، کاربر باید حتما برای این فیلد مقداری را وارد کند.
این فیلد میتواند خالی باشد و این به معنای غیراجباری بودن این فیلد است.
#### فیلد *name*
این فیلد نشاندهندهی کلید اصلی آن المان است. در هنگام ساخت دادههای ورودی کاربر، مقدار کلید برابر این فیلد است.
#### فیلد *label*
این فیلد مشخصکنندهی برچسب (لیبل) المان است.
#### فیلد *options*
در صورتی که *type* یک المان برابر *FormType.DROPDOWN* باشد، مقادیری قابل انتخاب در فرم *select* در این
فیلد قرار میگیرد.
#### فیلد *dependency*
هر المان میتواند به المان دیگری وابستگی داشته باشد. این موضوع در این فیلد مشخص میشود.
در صورتی که این فیلد وجود نداشت، به این معنا است که این فیلد به فیلد دیگری وابستگی ندارد.
وابستگی به دو شکل وجود دارد:
- وابستگی *show*: به این معنا است که نمایش این فیلد به مقدار یک فیلد دیگر وابسته است.
- وابستگی *required*: به این معنا است که اجباری بودن این فیلد به مقدار یک فیلد دیگر وابسته است.
هر کدام از این وابستگیها به شکل زیر مشخص میشوند:
```json
{ "name": string, "value": string | boolean | number }
```
که *name* نشاندهندهی فیلدی است که به آن وابسته است و *value* نشاندهندهی شرط وابستگی است.
در صورتی که مقدار فیلد *name* برابر *value* بود، شرط وابستگی برقرار است.
برای مثال در دادهی زیر فیلد *productIssues* به فیلد *productStatus* وابسته است.
در صورتی که مقدار انتخابی در *productStatus* برابر **4** باشد (یعنی مقدار انتخابی **خراب** باشد)،
این فیلد باید (*productIssues*) نمایش داده شود.
همچنین اجباریبودن فیلد *city* به مقدار فیلد *delivery* بستگی دارد و مقدار این فیلد باید `true` باشد.
دقت کنید این فیلد باید نمایش داده شود ولی اجباریبودن آن به فیلد دیگری بستگی دارد.
```json
[
{
"type": "dropdown",
"name": "productStatus",
"label": "وضعیت کالا",
"options": [
{ "title": "نو", "value": 1 },
{ "title": "در حد نو", "value": 2 },
{ "title": "دست دوم", "value": 3 },
{ "title": "خراب", "value": 4 },
],
},
{
"type": "textarea",
"name": "productIssues",
"label": "مشکلات کالا",
"dependency": {
"show": { "name": "productStatus", "value": 4 },
},
},
{
"type": "checkbox",
"name": "delivery",
"label": "از سیستم دلیوری استفاده خواهم کرد",
},
{
"type": "city",
"name": "cityId",
"label": "محل آگهی",
"dependency": {
"required": { "name": "delivery", "value": true },
},
},
];
```
#### مواردی که باید در این سوال رعایت کنید:
- شما باید برنامهای بنویسید که لیست فیلدها را دریافت کند و به این شکل ساختاری نمایش دهد.
- فرم نهایی در صورتی باید *submit* شود که تمام شرایط لازم در آن رعایت شده باشد (تمام فیلدهای اجباری وارد شده باشند).
- مقادیر وارد شده باید به تابع `onSubmit` پاس داده شود. (این تابع به شکل *prop* به کامپوننت داده میشود)
- در صورتی که یک فیلد اجباری پر نشده بود، باید برای آن فیلد خطا نمایش داده شود (کاپوننت آن آورده شده است و فقط لازم است برحسب شرایط از آن استفاده کنید).
- در صورتی که یک فیلد غیراجباری پر نشده بود، باید برای آن فیلد مقدار `undefiend` به تابع `onSubmit`
فرستاده شود.
#### تغییرات لازم برای هر فایل:
- فایل `App.jsx`: منطق اصلی کد شما در این فایل قرار میگیرد.
در این فایل شما *props* را بهعنوان ورودی میگیرید.
- *onSubmit*: زمانی که فرم بدون خطا بود، به این تابع مقادیر وارد شده را بهعنوان پارامتر ورودی بفرستید.
- *fields*: فیلدهای فرم در این *prop* قرار میگیرد.
- فایل `FormItem.jsx`: در این کامپوننت شما براساس *type* هر المان باید از یکی کامپوننتهای آورده شده،
استفاده کنید.
شما لازم است براساس هر آیتم در *fields* از این کامپوننت استفاده کنید.
# نکات
- حتما از کامپوننتهای داخل پروژه استفاده شود، در غیر این صورت نمره سوال را نخواهید گرفت.
- شما تنها مجاز به اعمال تغییرات در فایلهای `App.jsx` و `FormItem.jsx` و `package.json` هستید.
- به کامنتهای داخل فایلها دقت کنید.
- استفاده از کتابخانههای خارجی مجاز است. (در پروژه اولیه کتابخانهی
[react-hook-form](https://react-hook-form.com/get-started#IntegratingwithUIlibraries)
قرار داده شده است)
- برای ارسال پاسخ کل پروژه را *zip* کرده و ارسال کنید. دقت کنید که پوشهی *node_modules* در فایل ارسالی نباشد.
پیندو
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/33751/download_problem_initial_project/118644/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار پروژه
</summary>
```
nested-comments
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── components
│ │ ├── CommentBox
│ │ │ ├── _styles.scss
│ │ │ └── index.jsx
│ │ └── CommentList
│ │ ├── _styles.scss
│ │ └── index.jsx
│ ├── data
│ │ └── data.json
│ ├── App.jsx
│ ├── index.css
│ └── index.jsx
└── package.json
```
</details>
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `nested-comments` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/kwZHYJFRJj/recursive-component-screenshot.png)
در این سوال میخواهیم لیست کامنتها را بهصورت درختی نمایش دهیم.
لیست کامنتها در پوشه `data` وجود دارد. ساختار هر کامنت به شکل زیر است:
```json
{
"id": string,
"info": {
"title": string,
"description": string
},
"parentId": string | null,
"user": {
"firstName": string,
"lastName": string
}
}
```
در این ساختار هر کامنت دارای یک _parentId_ است. اگر مقدار این فیلد `null` باشد به این معنا است که این کامنت دارای والد نیست.
در غیر این صورت به ایدی والد این کامنت اشاره میکند.
برای مثال لیست کامنتها به شکل زیر است:
```json
[
{
"id": "id-1",
"info": {
"title": "title-1",
"description": "description-1"
},
"parentId": null,
"user": {
"firstName": "firstName-1",
"lastName": "lastName-1"
}
},
{
"id": "id-2",
"info": {
"title": "title-2",
"description": "description-2"
},
"parentId": "id-1",
"user": {
"firstName": "firstName-2",
"lastName": "lastName-2"
}
},
{
"id": "id-3",
"info": {
"title": "title-3",
"description": "description-3"
},
"parentId": "id-2",
"user": {
"firstName": "firstName-3",
"lastName": "lastName-3"
}
},
{
"id": "id-4",
"info": {
"title": "title-4",
"description": "description-4"
},
"parentId": null,
"user": {
"firstName": "firstName-4",
"lastName": "lastName-4"
}
},
{
"id": "id-5",
"info": {
"title": "title-5",
"description": "description-5"
},
"parentId": "id-1",
"user": {
"firstName": "firstName-5",
"lastName": "lastName-5"
}
},
]
```
این لیست باید به شکل زیر نشان داده شود:
```
├── id-1
│ ├── id-2
│ │ └── id-3
│ └── id-5
└── id-4
```
در شکل بالا کامنتهای *id-1* و *id-4* سطح صفر، *id-2* و *id-5* سطح یک و کامنت *id-3* سطح دو هستند.
#### مواردی که باید در این سوال رعایت کنید:
- شما باید برنامهای بنویسید که لیست کامنتها را دریافت کند و به این شکل ساختاری نمایش دهد.
- هر کامنت باید براساس سطحش در درخت دارای استایل `margin-left` باشد.
برای مثال اگر کامنت در سطح صفر بود (یعنی والد است و والدی ندارد) باید دارای استایل `margin-left: 0px` باشد.
اگر کامنت در سطح یک بود (دارای والد است) باید دارای استایل `margin-left: 16px` باشد.
اگر کامنت در سطح دو بود (دارای والد است و والد آن خود والد دارد) باید دارای استایل `margin-left: 32px` باشد.
- هر کامنت سطح صفری باید دارای کلاس `root-comment` باشد.
- در صورتی که لیست کامنتها خالی باشد، باید فقط کامپوننت `EmptyList` نمایش داده شود.
#### تغییرات لازم برای هر فایل:
- فایل `App.jsx`: شما لیست کامنتها را در کامپوننت دریافت میکنید. قبل از فرستادن `comments` به کامپوننت `CommentList` باید ساختار مورد نظر را ایجاد کنید.
- فایل `CommentList.jsx`: در این کامپوننت شما باید لیست کامنتها را نمایش دهید. کلاس `root-comment` را برساس شرایط گفته شده در قسمت گفته شده قرار دهید.
شما باید کامنت سطح صفر بههمراه فرزندانش را در اینجا نشان دهید. در صورتی که فرزندی نداشت چیزی نباید نشان دهید.
- فایل `CommentBox.jsx`: برای نمایش هر کامنت از این کامپوننت استفاده کنید. استایل `margin-left` و شرایط گفته شده باید در اینجا پیادهسازی شود.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایلهای `App.jsx` و `CommentList.jsx` و `CommentBox.jsx` هستید.
- به کامنتهای داخل فایلها دقت کنید.
- مقدارهای `data-testid` پروژه اولیه نباید تغییر کنند.
- برای قسمت استایل از *inline-style* استفاده کنید.
- این استایل به اِلِمان با کلاس `comment-box` داخل فایل `CommentBox.jsx` داده شود.
- برای ارسال پاسخ کل پروژه را *zip* کرده و ارسال کنید. دقت کنید که پوشهی *node_modules* در فایل ارسالی نباشد.