پارسا که با پنل ادمین دیجیکالا کار میکرد، متوجه شد بعضی از عکسهای محصولات وضعیت مناسبی ندارند و برای درست دیده شدن آنها لازم است تا تغییراتی روی آنها اعمال شود. پارسا که از قضا خیلی هم صبور نبود، برای این کار از رامین خواست که خیلی فوری در صفحهی عکس محصولات، ابزاری برای او فراهم کند که بتواند با آنها عکس کالا را بچرخاند، برگرداند (flip کند) و مقدار روشنایی آن را تنظیم کند.
از طرفی، پارسا از بچگی به عکسهای هنری هم علاقه داشت. به همین دلیل، به رامین گفت که برایش چند فیلتر هم آماده کند که بتواند عکسهای سایت را هنری کند!
رامین که خیلی قلب مهربانی داشت، درخواست پارسا را قبول کرد، اما چون باید در جلسهی تیم فرانتاند شرکت میکرد، تنها فرصت کرد ظاهر صفحهی عکس کالا را پیادهسازی کند. حال، از شما میخواهیم که تا قبل از تمام شدن جلسهی رامین، با کامل کردن عملکرد این صفحه به او کمک کنید تا بتواند موارد درخواستی پارسا را به موقع به دستش برساند.
پروژهی اولیه را از این لینک دانلود کنید.
برای پیادهسازی هر یک از ابزارهای خواسته شده، یک div
خاص در نظر گرفته شده است که بهصورت زیر هستند:
preview
: برای چرخش، تغییرات روشنایی و اعمال فیلترهاpreview-scale
: برای بزرگنمایی با موسpreview-flip
: برای flip عمودی و افقیدر این سؤال، شما باید ۷ فیلتر را پیادهسازی کنید که در جدول زیر به آنها اشاره شده است:
نوع فیلتر | شدت فیلتر |
---|---|
grayscale | 1 |
sepia | 1 |
invert | 1 |
blur | 2px |
saturate | 2 |
contrast | 2 |
hue-rotate | 90deg |
برای پیادهسازی آنها، کافی است از فیلتر معادل آنها در CSS به همراه مقدار ذکر شده برای آن استفاده کنید. برای مثال، فیلتر grayscale
به صورت grayscale(1)
خواهد بود.
none
در لیست فیلترها، اگر فیلتری روی عکس اعمال شده باشد، باید حذف شود.preview-container
) نباید خالی شود. برای این کار لازم است به همراه چرخش مقداری بزرگنمایی نیز انجام شود. این بزرگنمایی به ازای هر درجه چرخش، خواهد بود. تصویر زیر، این مورد را واضحتر بیان میکند:transform-origin
را با توجه به موقعیت نشانگر موس روی تصویر (یا به طور دقیقتر، روی preview-scale
) تغییر دهید. برای این کار باید ابتدا موقعیت موس در صفحهی نمایش را با استفاده از pageX
و pageY
(که از ایونت e
ورودی تابع handleMouseMove
قابل دسترسیاند) به دست آورید. سپس با محاسبهی فاصلهی preview-scale
از سمت چپ و بالای صفحه نمایش به کمک offsetLeft
و offsetTop
، موقعیت موس روی preview-scale
را محاسبه کنید.preview-container
) خالی شود.toFixed
جاوااسکریپت استفاده کنید.script.js
هستید.پس از پیادهسازی موارد خواستهشده، فایل script.js
را آپلود کنید.
شکرستون یک شهرِ به شدت در حال رشد است و میزان خرید شهروندانش بسیار بالا رفته، اما از آنجایی که مشکلات زیرساختی زیادی درونش وجود دارد، روی تجربهی کاربری خیلی از محصولاتش تأثیر گذاشته است. مهدی یک مهندس نرمافزار در دیجیکالای شکرستون است و قصد دارد طی یه حرکت خفن، تجربهی کاربری این سایت را بهتر کند!
یکی از مواردی که از نظر مهدی خیلی روی تجربهی کاربری سایت تأثیرگذار است، refresh شدن صفحات پس از کلیک کردن روی لینکها است. پس از کمی سرچ و مشورت، او متوجه شد که راهحل مشکلش، استفاده از کتابخانهی react-router
است اما متأسفانه دیجیکالا در شکرستون با جاوااسکریپت خام نوشته شده!
مهدی تصمیم گرفته که وارد میدان شود و با کمک شما، یک کتابخانهی client router بسازد. از آنجایی که تجربهی کاربر برای مهدی خیلی مهم است، جابهجایی بین صفحات نباید باعث refresh شدن صفحه شود تا سرعت برنامه بالاتر رود. همچنین زمانی که کاربر روی دکمههای جلو و عقب مرورگر کلیک میکند، باید صفحهی قبلی یا بعدی بدون تأخیر نمایش داده شود.
مهدی به تنهایی نمیتواند کل این کتابخانه را پیادهسازی کند. او از شما خواسته که در پیادهسازی این کتابخانه به او کمک کنید.
پروژهی اولیه را از این لینک دانلود کنید.
برای اجرای پروژه، باید Node.js و npm را از قبل نصب کرده باشید.
client-router
دستور npm install
را برای نصب نیازمندیها اجرا کنید.npm start
را برای راهاندازی پروژه اجرا کنید.یکی از جذابترین مواردی که مهدی در react-router
دیده بود، قابلیت route params است. مهدی نیز تصمیم گرفته این قابلیت را به کتابخانهاش اضافه کند. این قابلیت به اینصورت کار میکند که هنگام تعریف route ، اگر قبل از یکی از پارامترها :
گذاشته شود، آن بخش از URL هنگام render به فانکشنش پاس داده میشود. مثال:
پروژه شامل دو فایل main.js
و clientRouter.js
است.
فایل main.js
شامل صفحات برنامه است. هر صفحه یک فانکشن است که route params را بهعنوان ورودی دریافت کرده و یک رشتهی HTML را در جواب برمیگرداند.
در انتها نیز کتابخانهی clientRouter
صدا زده شده و صفحات بهعنوان یک پارامتر به آن پاس داده میشوند.
شما باید فایل clientRouter.js
را طوری پیادهسازی کنید که برنامه همانند ویدیوی موجود در ابتدای صورت سؤال کار کند.
فایل clientRouter.js
شامل توابع زیر است:
processRoutes
: این تابع پس از هر تغییر در صفحه صدا زده میشود و وظیفهی پردازش و مقایسهی route ها را برعهده دارد.handleLinks
: این تابع وظیفهی اضافه کردن event listener ها را به لینکهای موجود در صفحه برعهده دارد.handleRouteChange
: این تابع وظیفهی گوش کردن به تغییرات URL و اجرای توابع بالا بر حسب نیاز را برعهده دارد و از قبل پیادهسازی شده است.clientRouter
باید به گونهای طراحی شود که تنها با اجرای تابع initializeRouter
و پاس دادن ورودی های مناسب، برنامه بهصورت یک SPA شروع به کار کند.clientRouter
نتوانست با هیچکدام از صفحات مچ شود، باید صفحه ی 404
به کاربر نشان داده شود.href
، از اتریبیوت data-href
استفاده میکنند تا از لینک های معمولی متمایز شوند.
نمونه:event.target
، از event.currentTarget
استفاده کنید تا هنگام کلیک روی element های زیرمجموعه لینک شما، بتوانید به element والد دسترسی داشته باشید. جزئیات بیشترclientRouter.js
هستید.پس از پیادهسازی موارد خواستهشده، فایل clientRouter.js
را آپلود کنید.
امین تازه در دیجیکالا جذب شده و از آنجایی که خیلی به چالش های فنی علاقهمند است، بابک و فرزاد تصمیم گرفتهاند از او بخواهند راهحلی برای یک مشکل پیدا کند. به امین در یافتن راهحل کمک کنید.
پروژهی اولیه را از این لینک دانلود کنید.
امین باید تابعی با نام purgeClassNames
پیادهسازی کنه که تعداد آرگومانهاش متغیر است. مثال:
این تابع باید کلاسهای مشابه را بر اساس اولویت حذف کند، یعنی کلاسهایی که زودتر به تابع پاس داده شدهاند اولویت کمتری دارند. مثلاً خروجی مثال بالا باید بهصورت زیر باشد:
در مثال فوق، کلاس m-5
با کلاس m-12
جایگزین میشود، زیرا m-12
دیرتر آمده و اولویت بیشتری دارد. کلاس d-block
بدون هیچ تغییری به خروجی منتقل میشود.
margin
🔗m-n
: مارجین از همهی جهات به اندازهی ml-n
: مارجین از چپmr-n
: مارجین از راستmb-n
: مارجین از پایینmt-n
: مارجین از بالاmy-n
: مارجین از بالا و پایینmx-n
: مارجین از چپ و راستدر توضیحات بالا، میتواند هر عددی باشد. مثال:
m-10
mr-999
mx-11
margin
:🔗ورودی ۱:
خروجی ۱:
کلاس m-5
میتواند به my-5 mx-5
تجزیه شود. بنابراین my-2
جایگزین my-5
شده و خروجی برابر با my-2 mx-5
خواهد بود.
ورودی ۲:
خروجی ۲:
ورودی ۳:
خروجی ۳:
نکته: m-n
میتواند به mx-n
و my-n
تجزیه شود. کلاس mx-n
نیز میتواند به mr-n
و ml-n
تجزیه شود. به همین ترتیب، کلاس my-n
نیز شامل mt-n
و mb-n
میشود. در این مثالها، هر عددی میتواند باشد.
padding
🔗قواعد کلاس margin
برای این کلاس هم وجود دارند. مثال:
pr-6
یا p-5
یا py-3
و...
display
🔗ساختار کلاس به صورت d-OPTION
است که OPTION
میتواند یکی از مقادیر زیر باشد:
flex
inline
inline-flex
block
inline-block
مثال:
d-block
d-inline
d-flex
display
:🔗ورودی:
خروجی:
overflow
🔗ساختار کلاس overflow
بهصورت زیر است:
overflow-OPTION
در تمامی جهاتoverflow-y-OPTION
درجهت محور yoverflow-x-OPTION
در جهت محور xدر مثالهای بالا، OPTION
میتواند یکی از مقادیر زیر باشد:
hidden
visible
scroll
auto
none
overflow
:🔗ورودی ۱:
خروجی ۱:
ورودی ۲:
خروجی ۲:
ورودی ۳:
خروجی ۳:
نکته: کلاس overflow-OPTION
میتواند به کلاسهای overflow-x-OPTION
و overflow-y-OPTION
تجزیه شود.
نقطه شکستها اندازه های تعریف شدهای هستند که به ما این امکان را میدهند تا یک کلاس را فقط در یک اندازهی مشخص اعمال کنیم.
هر کلاس میتواند فقط در یک breakpoint خاص فعال باشد، برای مثال: lg:mr-2
فقط در breakpoint lg فعال است. تمامی کلاس هایی که بالا معرفی شدند باید قابلیت استفاده با breakpoints را داشته باشند.
لیست نقطه شکست های موجود:
xs
sm
md
lg
ورودی ۱:
خروجی ۱:
همانطور که مشاهده میکنید، کلاسهایی که دارای breakpoint هستند، بر روی کلاس های معمولی اثری ندارند.
ورودی ۲:
خروجی ۲:
همانطور که مشاهده میکنید، breakpoint های متفاوت نیز بر روی یکدیگر تاثیر ندارند.
purgeClassNames
اهمیتی ندارد.purgeClassNames
باید یک رشته شامل کلاسها باشد که با استفاده از فاصله (space) از هم جدا شدهاند.purgeClassNames
داده شود که در لیست کلاسهای بالا تعریف نشده بود، شما باید آن کلاس را بدون تغییر و به صورت مستقیم به خروجی ارسال کنید.script.js
هستید.پس از پیادهسازی موارد خواستهشده، فایل script.js
را آپلود کنید.
در این سؤال، از کتابخانهی react-router-dom@6
استفاده شده است.
در دیجیکالا تعداد زیادی داده وجود دارد که برخی اوقات لازم است آنها را فیلتر کنیم. حال، میخوایم راهی پیدا کنیم که این فیلتر اعمالشده را به راحتی با بقیه به اشتراک بگذاریم. برای این کار، تصمیم گرفتهایم یک هوک بنویسیم که کارش هماهنگ کردن و اتصال state فرم فیلتر با آدرس صفحه است. بنابراین شما باید در کامل کردن این هوک (که آن را useFilter
نامیدهایم) به ما کمک کنید.
پروژهی اولیه را از این لینک دانلود کنید.
برای اجرای پروژه، باید Node.js و npm را از قبل نصب کرده باشید.
useFilter
، دستور npm install
را برای نصب نیازمندیها اجرا کنید.npm start
را برای راهاندازی پروژه اجرا کنید.دادهی لازم برای ساخت فرم بهصورت یک آرایه به هوک useFilter
پاس داده میشود. هر عضو این آرایه معادل یک المان (input element) از فرم است. آبجکت زیر شامل تمامی prop ها است که به المانها داده میشود. بعضی از این prop ها مربوط به نوع خاصی از المانها هستند. برای مثال، options
فقط مربوط به dropdown
و checkbox group
است.
options
🔗همانطور که گفته شد، این فیلد مختص dropdown
و checkbox group
است.
parent
و children
🔗بعضی از المانهای فرم ممکن است دارای وابستگی به المان دیگری باشند. این وابستگی در فرزند با فیلدی به نام parent
که یک رشته شامل نام پدر است، نمایش داده میشود و در المان پدر با فیلدی به نام children
که شامل آرایهای از رشتهها شامل نام (فیلد name
) فرزندان است.
هوک خواستهشده باید یک اتصال (binding) دوطرفه بین پارامترهای جستجوی آدرس (query params) و فیلدهای فرم داشته باشد، به این معنی که با هر تغییر در المانهای فرم، بلافاصله آدرس به روزرسانی شود و برعکس. این هوک باید یک آبجکت شامل کلیدهای زیر برگرداند:
آرایهای که فرم از روی آن ساخته میشود (متغیر formData
) بهعنوان ورودی به هوک داده میشود.
filterState
و تابع setFilterState
🔗این دو مورد، عملکردی معادل متغیر و تابع از هوک معروف useState
را دارند. متغیر یک آبجکت است که هر کلید آن باید برابر با نام (فیلد name
) از المان فرم باشد و مقدار آن هم مقدار آن المان است (فیلد value
).
onChange
🔗این تابع هنگام تغییر هر المان فرم صدا زده میشود.
onClear
🔗در پایین صفحه، دکمههایی برای پاک کردن مقادیر المانهای فرم وجود دارد. با کلیک کردن بر روی این دکمهها، باید مقدار المان مورد نظر از فرم پاک شود و همزمان این مقدار از آدرس هم پاک شود. این تابع به عنوان ورودی نام (فیلد name
) المان موردنظر را دریافت میکند.
نکته: در صورتی که مقدار المان پدر پاک شود و یا تغییر کند، مقدار المان فرزند حتماً باید ریست شود، یعنی هم از آدرس پاک شود و هم مقدار input
مربوطه از فرم خالی شود.
onClearAll
🔗در صورتی که روی دکمهی پاک کردن همه کلیک شود، مسلماً باید تمامی مقادیر المانها پاک شود و آدرس به حالت /
برود.
همانطور که میدانید، در حالت کلی پارامترهای جستجوی آدرس (query parameter) بهصورت زیر ساخته میشوند:
اما به دلایلی نیاز داریم از فرمت متفاوتی برای ساخت این آدرس استفاده کنیم؛ به اینصورت که برای پشت سر هم قرار دادن پارامترها به جای کارکتر&
از کارکتر+
و برای جدا کردن key و value بهجای کارکتر=
از ~
استفاده میکنیم. همچنین در مواردی که یک آرایه از مقادیر داریم (این اتفاق فقط در المان checkbox group
رخ میدهد)، برای جدا کردن آنها از هم به جای ,
از کارکتر --
استفاده میکنیم (ترتیب مقادیر مهم نیست). برای مثال، این پارامترهای رایج آدرس:
به این صورت تبدیل میشوند:
و در صورت تجزیه (parse) این پارامترها به آبجکت زیر میرسیم:
input
متصل به آن فیلد پاک شود.children
پاک شود، در اینصورت باید تمامی فرزندانش نیز از آدرس پاک شوند.hooks/useFilter.js
هستید.پس از پیادهسازی موارد خواستهشده، فایل useFilter.js
را آپلود کنید.
با trend شدن زمینهای متاورس و خرید آنها توسط مردم، شمسالله تصمیم گرفته که به فروش زمینهای متاورسی روی بیاورد. او که جدیداً با وبسوکت آشنا شده است، میخواهد این پروژه را با وبسوکت پیادهسازی کند. برای این کار، او سرور این پروژه را ساخته و از شما میخواهد که در قسمت فرانتاند پروژه به او کمک کنید.
پروژهی اولیه را از این لینک دانلود کنید.
برای اجرای پروژه، باید Node.js و npm را از قبل نصب کرده باشید.
metaverse-lands
، دستور npm install
را برای نصب نیازمندیها اجرا کنید.npm start
را برای راهاندازی پروژه اجرا کنید.metaverse-lands
، دستور npm install
را برای نصب نیازمندیها اجرا کنید.npm run server
را برای راهاندازی سرور پروژه اجرا کنید.در این پروژه، ارتباط شما با سرور بر بستر وبسوکت است و شما تمام دادهها را از این طریق سرور دریافت میکنید و از همین طریق برای سرور میفرستید. در همان لحظه که به وبسوکت وصل شوید، شما دیتای مپ یا نقشه و همچنین دیتای دارندگان هر نقطه از نقشه را دریافت میکنید.
ساختار دادهی ارسالی سرور بهشکل زیر است:
که type
میتواند یکی از دو مقدار MAP
و OWNER
را داشته باشد.
MAP
مشخصکنندهی دادههای نقشه اصلی است.OWNER
مشخصکنندهی دادههای دارندگان هر نقطه از نقشه است.دادههای MAP
بهشکل زیر هستند:
بدین ترتیب مختصات تمام نقاط نقشه را سرور برای شما میفرستد. دقت کنید دادههای نقشه مرتب نیست و تمام مختصات در یک آرایه قرار دارد. همچنین اگر type
یک نقطه برابر LAND
بود، بدین معنا است که آن نقطه زمین است و اگر برابر WALL
بود، بدین معنا است که آن نقطه دیوار است. در صورتی که یک نقطه LAND
بود، شما باید آن نقطه را به رنگ DEFAULT_COLORS.LAND
و اگر WALL
بود، باید به رنگ DEFAULT_COLORS.WALL
در بیاورید.
دادههای OWNER
بهشکل زیر است:
در دادههای بالا، startCord
نشاندهندهی شروع مختصات نقاطی است که تحت مالکیت فردی با رنگ اتخصاصی color
است. همچنین endCord
نشاندهندهی پایان مختصات است. تمام نقاط بین startCord
و endCord
تحت مالکیت این فرد یا شرکت است و رنگ این نقط باید به رنگ color
باشد. با این فرض این نقاط همیشه به شکل مربع یا مستطیل هستند. شما باید بر اساس این دادهها، نقشه را ترسیم کنید. پس از آن، در هر لحظه ممکن است سرور دادههای دارندگان جدید را برای شما بفرستد. شما باید بر اساس دادههای جدید، نقشه را بهروزرسانی کنید.
همچنین کاربر فعلی میتواند با انتخاب هر نقطه از نقشه، آن نقطه را برای خود خریداری کند.
برای این کار، شما باید ساختار دادهای مانند ساختار دادهی زیر را برای سرور تحت سوکت بفرستید:
سرور پس دریافت این نقاط، دادههای مالک این نقطه را برای شما میفرستد و شما باید مانند قبل، نقشه را بهروزرسانی کنید.
App.jsx
توجه کنید.Block
استفاده کنید.OWNER
پیوسته است.server
را بررسی کنید."ws://localhost:3001"
)data/index.js
قرار داده شده است.App.jsx
هستید.پس از پیادهسازی موارد خواستهشده، فایل App.jsx
را آپلود کنید.