feat: Revert homepage changes, fix Persian slug 404, and make various article and about us adjustments
- Removed the newly added city-focused section from the homepage. - Fixed 404 error for Persian slugs in specialties and blog pages by implementing a decode helper. - Removed the "مخصوص شهر" label from article headers. - Linked article tags to their respective filter pages. - Adjusted related content images to prevent distortion. - Added a section in the "About Us" page for physician registration guidance. - Updated the logo in the "About Us" header to the correct version. - Added tests for the new functionality and ensured existing tests are updated accordingly.
This commit is contained in:
@@ -0,0 +1,469 @@
|
||||
# بازگرداندن صفحهٔ اصلی، رفع ۴۰۴ اسلاگ فارسی، سه اصلاح صفحهٔ مقاله، و دو اصلاح «درباره ما»
|
||||
|
||||
## پروژه
|
||||
|
||||
`nobat724_front` — سایت عمومی. بدون تغییر بکاند.
|
||||
|
||||
## زمینه
|
||||
|
||||
پنج مورد جدا که کاربر روی محیط محلی دید. یکی بازگرداندن تغییری است که در تسک قبلی
|
||||
اضافه شد، یکی باگ ۴۰۴ با ریشهٔ اثباتشده، و سه اصلاح کوچک روی صفحهٔ مقاله.
|
||||
|
||||
## مشکل / هدف
|
||||
|
||||
### ۱. بخش تازهٔ صفحهٔ اصلی برداشته شود
|
||||
|
||||
در تسک قبلی برای رفع `Duplicate, Google chose different canonical` یک بخش شهرمحور
|
||||
به صفحهٔ اصلی اضافه شد: متن مقدمه، «تخصصهای پرمراجعه در …» و «پزشکان …».
|
||||
کاربر آن را نمیخواهد. صفحهٔ اصلی به حالت قبل برگردد.
|
||||
|
||||
### ۲. اسلاگ فارسی ۴۰۴ میدهد
|
||||
|
||||
```
|
||||
/specialties/%D8%AC%D8%B1%D8%A7%D8%AD-%DA%AF%D9%88%D8%A7%D8%B1%D8%B4 → 404
|
||||
/specialties/gastroenterology → 200
|
||||
```
|
||||
|
||||
**ریشه با ابزارگذاری روی build واقعی اثبات شد** — `generateMetadata` و بدنهٔ صفحه دو
|
||||
مقدار متفاوت میگیرند:
|
||||
|
||||
```
|
||||
generateMetadata → slug = "جراح-گوارش" found: true
|
||||
بدنهٔ صفحه → slug = "%D8%AC%D8%B1%D8%A7%D8%AD-%DA%AF%D9%88%D8%A7%D8%B1%D8%B4" found: false → notFound()
|
||||
```
|
||||
|
||||
یعنی Next در بدنهٔ صفحه segment را decode نمیکند. رشتهها بایتبهبایت یکیاند
|
||||
(هر دو NFC، بدون تفاوت codepoint)، پس مشکل نرمالسازی نیست.
|
||||
|
||||
**این باگ فقط مخصوص صفحهٔ تخصص نیست.** slug مقالهها هم فارسی است
|
||||
(`آلرژی-دارویی-…-58d2e880`)، پس `app/blog/[slug]/page.js` هم همین را دارد و امروز
|
||||
با uuid تست میشود که ASCII است و مشکل را پنهان میکند.
|
||||
|
||||
### ۳. برچسب «مخصوص شهر» از صفحهٔ مقاله حذف شود
|
||||
|
||||
فقط همین جمله. منطق scope شهریِ مقالهها دستنخورده میماند.
|
||||
|
||||
### ۴. تگهای مقاله لینک شوند
|
||||
|
||||
الان چیپهای بدون لینکاند. کامنت کد میگوید «صفحهٔ فیلتر تگ وجود ندارد» — این کامنت
|
||||
کهنه است؛ `components/blogs/index.js` از قبل `?tag=` را میخواند و اعمال میکند.
|
||||
|
||||
### ۵. عکس «مطالب مرتبط» دفرمه است
|
||||
|
||||
عکس داخل `<li className="flex">` است و ظرفش `shrink-0` ندارد. با تیتر بلند، عرض عکس
|
||||
فشرده میشود و ارتفاعش ثابت میماند.
|
||||
|
||||
### ۶. صفحهٔ «درباره ما» راه عضویت پزشک را نمیگوید
|
||||
|
||||
مسیر صفحه:
|
||||
|
||||
```
|
||||
/about-us
|
||||
```
|
||||
|
||||
متن فعلی فقط از دید بیمار نوشته شده. پزشکی که بخواهد به سامانه اضافه شود هیچ
|
||||
راهنماییای نمیبیند. باید بند تازهای اضافه شود که او را به این سایت بفرستد:
|
||||
|
||||
```
|
||||
https://clinic-pro.ir/
|
||||
```
|
||||
|
||||
### ۷. لوگوی هدر «درباره ما» غلط است
|
||||
|
||||
هدر بنفش صفحهٔ «درباره ما» فایل قدیمی را نشان میدهد:
|
||||
|
||||
```
|
||||
/assets/images/logo-2.png
|
||||
```
|
||||
|
||||
هیچجای دیگر سایت این فایل را مصرف نمیکند. لوگوی واقعی سایت این است:
|
||||
|
||||
```
|
||||
/nobat724.svg
|
||||
```
|
||||
|
||||
که هدر اصلی سایت در `app/component/Logo.js` از آن استفاده میکند.
|
||||
|
||||
**دو نکته که سادهترین راهحل را میشکنند:**
|
||||
|
||||
اول، رنگ stroke لوگو `#5559CE` است و پسزمینهٔ هدر `#5559C2`. اگر همان svg را
|
||||
مستقیم بگذارید، لوگو تقریباً نامرئی میشود. باید نسخهٔ روشن رندر شود.
|
||||
|
||||
دوم، `SiteLogo` از قبل همین کار را میکند: هم `city.logo_url` را در نظر میگیرد و
|
||||
هم `stroke` را پارامتری گرفته. مسیرش:
|
||||
|
||||
```
|
||||
components/doctor/poster/SiteLogo.js
|
||||
```
|
||||
|
||||
## معیار پذیرش
|
||||
|
||||
- ✅ موفق: `/specialties/%D8%AC%D8%B1%D8%A7%D8%AD-%DA%AF%D9%88%D8%A7%D8%B1%D8%B4`
|
||||
کد `200` بدهد و تیتر «متخصص جراح گوارش در …» را نشان دهد.
|
||||
- ✅ موفق: `/specialties/gastroenterology` همچنان `200` — اسلاگ لاتین نشکند.
|
||||
- ✅ موفق: صفحهٔ مقاله دیگر «مخصوص شهر:» ندارد، ولی نویسنده و تاریخ سر جایشاناند.
|
||||
- ✅ موفق: هر تگ مقاله لینک به `/blogs?tag=<نام تگ>` است و آن صفحه همان فیلتر را اعمال میکند.
|
||||
- ✅ موفق: HTML صفحهٔ اصلی هیچکدام از «تخصصهای پرمراجعه در»، «پزشکان <شهر>» را ندارد.
|
||||
- ❌ خطا: اسلاگ ناموجود — چه فارسی چه لاتین — همچنان `404` بدهد، نه `200` یا `500`.
|
||||
- ❌ خطا: مقالهای بدون تگ، بلوک تگ را اصلاً رندر نکند.
|
||||
- ⚠️ مرزی: اسلاگ فارسی که با `%` شروع نمیشود ولی حرف فارسی خام دارد هم کار کند.
|
||||
- ⚠️ مرزی: تگ حاوی فاصله یا `&` باید در URL درست encode شود.
|
||||
- ⚠️ مرزی: عکس مطالب مرتبط با تیتر بسیار بلند نباید باریک شود؛ نسبت ابعاد ثابت بماند.
|
||||
- ✅ موفق: صفحهٔ `/about-us` بندی دارد که پزشک را به `https://clinic-pro.ir/` میفرستد،
|
||||
و آن آدرس لینک واقعی است نه متن ساده.
|
||||
- ✅ موفق: لینک عضویت پزشک `target="_blank"` و `rel="noopener noreferrer"` دارد.
|
||||
- ✅ موفق: هیچ ارجاعی به `logo-2.png` در کد نماند و لوگوی هدر «درباره ما» روی
|
||||
پسزمینهٔ بنفش دیده شود.
|
||||
- ❌ خطا: نام سایت در بند تازه هاردکد نشود؛ همان `siteName` که بقیهٔ صفحه استفاده میکند.
|
||||
- ⚠️ مرزی: شهری که `logo_url` دارد باید لوگوی خودش را در هدر ببیند، نه لوگوی پیشفرض.
|
||||
|
||||
## فایلهای مرتبط
|
||||
|
||||
| فایل | نقش |
|
||||
|------|-----|
|
||||
| `components/home/index.js` | چیدمان صفحهٔ اصلی — `CityHighlights` از اینجا حذف شود |
|
||||
| `components/home/CityHighlights.js` | کامپوننتی که باید برداشته شود |
|
||||
| `components/home/CityHighlights.test.js` | تستش هم با آن میرود |
|
||||
| `lib/listingIntro.js` | `buildCityIntro` و `CITY_INTROS` — فقط مصرفکنندهشان صفحهٔ اصلی بود |
|
||||
| `lib/cityIntro.test.js` | تستهای `buildCityIntro` |
|
||||
| `app/specialties/[slug]/page.js` | ۴۰۴ اسلاگ فارسی |
|
||||
| `app/blog/[slug]/page.js` | همان باگ، پنهان چون با uuid تست میشود |
|
||||
| `components/blog/head/index.js` | برچسب «مخصوص شهر» و چیپهای تگ |
|
||||
| `components/blogs/index.js` | خوانندهٔ `?tag=` — تأیید میکند لینک تگ کار میکند |
|
||||
| `components/blog/relatedContent/Item.js` | عکس دفرمه |
|
||||
| `components/aboutUs/index.js` | متن «درباره ما» — بند تازهٔ پزشک اینجا اضافه شود |
|
||||
| `components/aboutUs/Head.js` | هدر بنفش با لوگوی غلط |
|
||||
| `components/doctor/poster/SiteLogo.js` | لوگوی درست، `stroke` پارامتری، پشتیبانی `logo_url` |
|
||||
| `app/component/Logo.js` | لوگوی هدر اصلی — مرجع اینکه لوگوی واقعی کدام است |
|
||||
| `public/assets/images/logo-2.png` | فایل یتیم — بعد از اصلاح هیچ مصرفکنندهای ندارد |
|
||||
|
||||
## وضعیت فعلی
|
||||
|
||||
### صفحهٔ اصلی
|
||||
|
||||
```jsx
|
||||
// components/home/index.js
|
||||
<div className="padding-responsive z-20 min-h-screen py-[120px] flex items-center justify-center flex-col gap-[40px]">
|
||||
<TextHeader />
|
||||
<SearchBar />
|
||||
<FrequentSearches />
|
||||
<CityHighlights />
|
||||
</div>
|
||||
```
|
||||
|
||||
### صفحهٔ تخصص — دو مصرف متفاوت از یک param
|
||||
|
||||
```jsx
|
||||
// app/specialties/[slug]/page.js:18
|
||||
const findSpecialty = (slug) =>
|
||||
specialtiesData.find((item) => item.slug === slug && item.status === 1) ?? null;
|
||||
|
||||
// :45 generateMetadata — اینجا decode شده میرسد
|
||||
const { slug } = await params;
|
||||
const specialty = findSpecialty(slug);
|
||||
if (!specialty) notFound();
|
||||
|
||||
// :78 بدنهٔ صفحه — اینجا encode شده میرسد
|
||||
const { slug } = await params;
|
||||
const specialty = findSpecialty(slug);
|
||||
if (!specialty) notFound();
|
||||
```
|
||||
|
||||
### برچسب شهر
|
||||
|
||||
```jsx
|
||||
// components/blog/head/index.js:49
|
||||
{cityName && (
|
||||
<div className="flex items-center justify-start gap-1">
|
||||
<p className="text-[#9B9B9B] text-[11px] md:text-[13px] lg:text-[14px] font-normal">
|
||||
مخصوص شهر:
|
||||
</p>
|
||||
<p className="text-[#9B9B9B] text-[11px] md:text-[14px] lg:text-[16px] font-medium">
|
||||
{cityName}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
### تگهای بدون لینک
|
||||
|
||||
```jsx
|
||||
// components/blog/head/index.js:90
|
||||
{/* فهرست کامل تگها — تا این تغییر فقط تگ اول در بردکرامب دیده میشد.
|
||||
صفحهٔ فیلتر تگ وجود ندارد، پس چیپها بدون لینک رندر میشوند. */}
|
||||
{tags.length > 0 && (
|
||||
<ul className="flex flex-wrap items-center justify-start gap-2 mt-[12px] md:mt-[16px]">
|
||||
{tags.map((tag, idx) => (
|
||||
<li
|
||||
key={`${tag}-${idx}`}
|
||||
className="bg-[#F5F5F5] text-[#525252] rounded-full px-[12px] py-[4px] text-[11px] md:text-[13px] font-medium"
|
||||
>
|
||||
{tag}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
```
|
||||
|
||||
ولی فیلتر تگ از قبل هست:
|
||||
|
||||
```js
|
||||
// components/blogs/index.js:16
|
||||
const selectedTag = searchParams.get("tag") || null;
|
||||
// :32
|
||||
params.tag = selectedTag;
|
||||
```
|
||||
|
||||
### عکس مطالب مرتبط
|
||||
|
||||
```jsx
|
||||
// components/blog/relatedContent/Item.js
|
||||
<li className="flex w-full relative items-start justify-start gap-[8px] py-[12px]">
|
||||
<CustomLoading width={80} height={72} loading={loading}>
|
||||
<Link href={`/blog/${data.uuid}`}>
|
||||
<img
|
||||
className=" w-[64px] sm:w-[73px] md:w-[85px] lg:w-[97px] h-[56px] sm:h-[64px] md:h-[75px] lg:h-[88px] rounded-[8px] overflow-hidden object-cover "
|
||||
src={cover}
|
||||
alt={data.title || "article"}
|
||||
/>
|
||||
</Link>
|
||||
</CustomLoading>
|
||||
```
|
||||
|
||||
### هدر «درباره ما»
|
||||
|
||||
```jsx
|
||||
// components/aboutUs/Head.js
|
||||
<div className="bg-[#5559C2] rounded-none md:rounded-lg w-full py-[24px] flex flex-col items-center justify-center gap-[13px] md:gap-[16px]">
|
||||
<Image
|
||||
src="/assets/images/logo-2.png"
|
||||
height={46}
|
||||
width={46}
|
||||
alt="logo"
|
||||
/>
|
||||
<h1 className="...">درباره {siteName}</h1>
|
||||
{slogan && <p className="...">{slogan}</p>}
|
||||
</div>
|
||||
```
|
||||
|
||||
`Head` الان فقط `siteName` و `slogan` میگیرد؛ `matchedCity` به آن پاس نمیشود.
|
||||
|
||||
### متن «درباره ما»
|
||||
|
||||
```jsx
|
||||
// components/aboutUs/index.js — دو بند، هر دو از دید بیمار
|
||||
<p>{siteName} یک سامانهی آنلاین نوبتدهی پزشکی است که …</p>
|
||||
<p>در {siteName} میتوانید بر اساس تخصص، نام پزشک یا مرکز درمانی جستجو کنید …</p>
|
||||
```
|
||||
|
||||
## وظایف
|
||||
|
||||
### ۱. برداشتن بخش شهرمحور صفحهٔ اصلی
|
||||
|
||||
- `<CityHighlights />` و importش از `components/home/index.js` حذف شود.
|
||||
- فایل `components/home/CityHighlights.js` و تستش پاک شوند.
|
||||
- `buildCityIntro` و `CITY_INTROS` در `lib/listingIntro.js` تنها مصرفکنندهشان همین
|
||||
کامپوننت بود؛ با آن پاک شوند. تستهای مربوطه در `lib/cityIntro.test.js` هم بروند.
|
||||
**کد مرده نگه ندارید** — همین اشتباه قبلاً با `buildDoctorsIntro` تکرار شد.
|
||||
- `buildClinicsIntro` و `CLINIC_INTROS` بمانند؛ `/clinics` هنوز مصرفشان میکند.
|
||||
|
||||
**نحوه تست:**
|
||||
```bash
|
||||
grep -rn "CityHighlights\|buildCityIntro" app components lib # باید خالی باشد
|
||||
npm run test && npm run lint
|
||||
NODE_TLS_REJECT_UNAUTHORIZED=0 npm run build && npm run start &
|
||||
curl -s -H "Host: yasuj-nobat.ir" http://localhost:3000/ | grep -cE "تخصصهای پرمراجعه|پزشکان یاسوج" # باید 0
|
||||
```
|
||||
|
||||
### ۲. رفع ۴۰۴ اسلاگ فارسی
|
||||
|
||||
یک helper مشترک بسازید — این باگ در دو صفحه هست و فردا در صفحهٔ سوم هم میآید:
|
||||
|
||||
```js
|
||||
// lib/routeParams.js
|
||||
/**
|
||||
* segment مسیر را به شکل decodeشده برمیگرداند.
|
||||
*
|
||||
* Next در `generateMetadata` مقدار decodeشده میدهد ولی در بدنهٔ همان صفحه مقدار
|
||||
* خام؛ روی اسلاگهای فارسی این یعنی متادیتا درست ساخته میشود و بلافاصله بعدش
|
||||
* صفحه ۴۰۴ میدهد. اثباتشده روی build واقعی، نه فرض.
|
||||
*
|
||||
* decode شکستخورده (درصدِ ناقص در ورودی) نباید صفحه را بشکند؛ همان مقدار خام
|
||||
* برمیگردد تا نتیجهاش ۴۰۴ طبیعی باشد نه ۵۰۰.
|
||||
*/
|
||||
export function decodeRouteParam(value) {
|
||||
if (typeof value !== "string" || !value.includes("%")) return value;
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
سپس در هر دو صفحه، بلافاصله بعد از `await params`:
|
||||
|
||||
```js
|
||||
const { slug: rawSlug } = await params;
|
||||
const slug = decodeRouteParam(rawSlug);
|
||||
```
|
||||
|
||||
در `app/specialties/[slug]/page.js` هر دو جا (`generateMetadata` و بدنه) و در
|
||||
`app/blog/[slug]/page.js` هم هر دو جا.
|
||||
|
||||
**مواظب `slug` که به کامپوننت پاس میشود باشید:** در صفحهٔ تخصص، `slug` به
|
||||
`SpecialtyDetailPage` میرود و آنجا در breadcrumb به `/specialties/${slug}` تبدیل
|
||||
میشود. مقدار decodeشده آنجا درست است چون `next/link` خودش encode میکند.
|
||||
|
||||
**نحوه تست:**
|
||||
```bash
|
||||
NODE_TLS_REJECT_UNAUTHORIZED=0 npm run build && npm run start &
|
||||
for u in "/specialties/%D8%AC%D8%B1%D8%A7%D8%AD-%DA%AF%D9%88%D8%A7%D8%B1%D8%B4" \
|
||||
"/specialties/gastroenterology" "/specialties/does-not-exist"; do
|
||||
echo -n "$u → "; curl -s -o /dev/null -w "%{http_code}\n" -H "Host: yasuj-nobat.ir" "http://localhost:3000$u"
|
||||
done
|
||||
# انتظار: 200، 200، 404
|
||||
```
|
||||
بهعلاوه unit test برای `decodeRouteParam` در `lib/routeParams.test.js`: مقدار
|
||||
encodeشده، مقدار خام فارسی، مقدار لاتین، رشتهٔ با `%` ناقص (نباید throw کند)،
|
||||
ورودی `undefined`.
|
||||
|
||||
### ۳. حذف برچسب «مخصوص شهر»
|
||||
|
||||
کل بلوک `{cityName && (...)}` در `components/blog/head/index.js` برداشته شود.
|
||||
اگر `cityName` بعد از آن هیچ مصرفی ندارد، محاسبهاش هم پاک شود تا متغیر بلااستفاده نماند.
|
||||
|
||||
منطق scope شهریِ مقالهها (`domainScopeCityId` و `city_id` در fetch) **دست نخورد** —
|
||||
کاربر فقط همین جمله را خواست.
|
||||
|
||||
**نحوه تست:** `curl` صفحهٔ مقاله و `grep -c "مخصوص شهر"` که باید صفر باشد، در حالی که
|
||||
`grep -c "نویسنده:"` همچنان یک است.
|
||||
|
||||
### ۴. لینککردن تگها
|
||||
|
||||
هر چیپ به `/blogs?tag=<نام>` لینک شود. `next/link` خودش encode میکند، ولی چون تگ
|
||||
ممکن است فاصله یا `&` داشته باشد، از شکل شیئی استفاده کنید تا مطمئن شوید:
|
||||
|
||||
```jsx
|
||||
<Link href={{ pathname: "/blogs", query: { tag } }} className="...">
|
||||
{tag}
|
||||
</Link>
|
||||
```
|
||||
|
||||
کامنت کهنهٔ بالای بلوک («صفحهٔ فیلتر تگ وجود ندارد») حذف یا اصلاح شود؛ همان کامنت
|
||||
باعث شد این قابلیت جا بماند.
|
||||
|
||||
استایل چیپ عوض نشود، فقط `hover` مناسب اضافه شود چون حالا کلیکشدنی است.
|
||||
|
||||
**نحوه تست:** تست کامپوننتی روی `components/blog/head` — مقاله با دو تگ، دو
|
||||
`role="link"` با `href` شامل `/blogs?tag=`؛ مقاله بدون تگ، هیچ لیستی رندر نشود.
|
||||
سپس دستی: کلیک روی تگ باید به `/blogs?tag=…` برود و همان فیلتر اعمال شود.
|
||||
|
||||
### ۵. رفع دفرمگی عکس مطالب مرتبط
|
||||
|
||||
به ظرف عکس `shrink-0` اضافه شود تا در flex فشرده نشود:
|
||||
|
||||
```jsx
|
||||
<CustomLoading width={80} height={72} loading={loading}>
|
||||
<Link href={`/blog/${data.uuid}`} className="block shrink-0">
|
||||
<img className="... shrink-0 ..." ... />
|
||||
</Link>
|
||||
</CustomLoading>
|
||||
```
|
||||
|
||||
اگر `CustomLoading` خودش ظرف flex میسازد، `shrink-0` باید روی همان بیرونیترین
|
||||
عنصرِ داخل `<li>` بنشیند — اول ساختار رندرشده را ببینید، بعد کلاس را جای درست بگذارید.
|
||||
|
||||
**نحوه تست:** تست کامپوننتی که کلاس `shrink-0` روی ظرف عکس هست. بهعلاوه بررسی
|
||||
چشمی در مرورگر با یک تیتر بسیار بلند — jsdom چیدمان را اندازه نمیگیرد، پس این مورد
|
||||
را **صادقانه بهعنوان «بررسی چشمی» گزارش کنید**، نه بهعنوان تست خودکار.
|
||||
|
||||
### ۶. بند عضویت پزشک در «درباره ما»
|
||||
|
||||
یک بند سوم بعد از دو بند فعلی در `components/aboutUs/index.js` اضافه شود. متن
|
||||
پیشنهادی:
|
||||
|
||||
```jsx
|
||||
<p>
|
||||
اگر پزشک هستید و میخواهید در {siteName} نوبتدهی آنلاین داشته باشید، ثبتنام
|
||||
از طریق سامانهی کلینیکپرو انجام میشود. کافی است به{" "}
|
||||
<a
|
||||
href="https://clinic-pro.ir/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[#5559C2] font-medium underline underline-offset-4"
|
||||
>
|
||||
clinic-pro.ir
|
||||
</a>{" "}
|
||||
مراجعه کنید و حساب مطب خود را بسازید. پس از تأیید، پروفایل و برنامهی
|
||||
نوبتدهی شما روی {siteName} نمایش داده میشود.
|
||||
</p>
|
||||
```
|
||||
|
||||
قواعد:
|
||||
|
||||
- نام سایت هاردکد نشود؛ همان `siteName` بالای فایل استفاده شود.
|
||||
- لینک خارجی است، پس `next/link` لازم نیست؛ `<a>` با `target="_blank"` و
|
||||
`rel="noopener noreferrer"` درست است.
|
||||
- استایل بند از بقیه جدا نشود؛ همان ظرف `flex flex-col gap-[16px]` را میگیرد.
|
||||
|
||||
**نحوه تست:**
|
||||
```bash
|
||||
NODE_TLS_REJECT_UNAUTHORIZED=0 npm run build && npm run start &
|
||||
curl -s -H "Host: yasuj-nobat.ir" http://localhost:3000/about-us | grep -c "clinic-pro.ir" # باید ≥ 1
|
||||
```
|
||||
بهعلاوه تست کامپوننتی: لینکی با `href="https://clinic-pro.ir/"` رندر شود و
|
||||
`rel` شامل `noopener` باشد.
|
||||
|
||||
### ۷. اصلاح لوگوی هدر «درباره ما»
|
||||
|
||||
`<Image src="/assets/images/logo-2.png" />` با `SiteLogo` جایگزین شود:
|
||||
|
||||
```jsx
|
||||
<SiteLogo city={matchedCity} stroke="#FAFAFA" className="w-[46px] h-[46px]" />
|
||||
```
|
||||
|
||||
- `matchedCity` باید از `components/aboutUs/index.js` به `Head` پاس شود؛ الان
|
||||
فقط `siteName` و `slogan` میرود.
|
||||
- `stroke="#FAFAFA"` لازم است چون رنگ پیشفرض روی پسزمینهٔ بنفش گم میشود.
|
||||
- `crossOrigin="anonymous"` داخل `SiteLogo` برای حالت poster گذاشته شده و اینجا
|
||||
ضرری ندارد؛ دست نزنید.
|
||||
- اگر `SiteLogo` جای بهتری لازم دارد چون دیگر فقط مال poster نیست، جابهجاییاش
|
||||
به `components/common/` قابل قبول است — ولی آنوقت هر دو مصرفکننده باید
|
||||
بهروز شوند و تستها سبز بمانند.
|
||||
- بعد از اصلاح، `public/assets/images/logo-2.png` هیچ مصرفکنندهای ندارد و پاک
|
||||
میشود. **اول با grep ثابت کنید یتیم است، بعد پاک کنید.**
|
||||
|
||||
**نحوه تست:**
|
||||
```bash
|
||||
grep -rn "logo-2" app components public --include="*.js" --include="*.json" # باید خالی باشد
|
||||
```
|
||||
بهعلاوه تست کامپوننتی روی `components/aboutUs/Head`: شهر بدون `logo_url` باید
|
||||
svg درونخطی بدهد، شهر با `logo_url` باید `<img>` با همان آدرس بدهد.
|
||||
بررسی چشمی هم لازم است — دیدهشدن لوگو روی بنفش را jsdom نمیسنجد. آن را
|
||||
**صادقانه بهعنوان «بررسی چشمی» گزارش کنید**.
|
||||
|
||||
## نکات مهم
|
||||
|
||||
- **۴۰۴ اسلاگ فارسی، مهمترین بخش این تسک است.** اگر فقط صفحهٔ تخصص درست شود و
|
||||
صفحهٔ مقاله جا بماند، همان باگ با اولین مقالهٔ فارسیاسلاگ برمیگردد. هر دو صفحه
|
||||
در همین تسک اصلاح شوند.
|
||||
- **دلیل helper مشترک بهجای دو تکه کد:** دو مصرفکنندهٔ فعلی و یک الگوی تکرارشونده.
|
||||
این abstraction «برای آینده» نیست؛ همین حالا دو جا لازم است.
|
||||
- **حذف کد مرده جزو کار است.** `buildCityIntro` بعد از برداشتن `CityHighlights`
|
||||
بلااستفاده میشود. نگهداشتنش همان وضعیتی را میسازد که `buildDoctorsIntro` ساخته
|
||||
بود: تابعی که تست دارد ولی هیچجا رندر نمیشود.
|
||||
- **سنجهٔ شباهت صفحهٔ اصلی برمیگردد به حدود ۹۰٪.** تسک قبلی آن را به ۷۱٫۵٪ رسانده
|
||||
بود. این عقبگرد خواستهٔ کاربر است و باید در گزارش پایانی صریح ذکر شود، نه بیصدا.
|
||||
مشکل `Duplicate, Google chose different canonical` روی صفحهٔ اصلی برمیگردد.
|
||||
- **دو مورد «درباره ما» مستقل از پنج مورد قبلیاند.** اگر یکی از آنها گیر کرد،
|
||||
بقیه را کامل کنید و همان یکی را صریح گزارش دهید.
|
||||
- **لوگو مسئلهٔ کنتراست است، نه فقط عوضکردن فایل.** stroke لوگو `#5559CE` و
|
||||
پسزمینه `#5559C2` است. اگر بدون `stroke` روشن جایگزین کنید، تستها سبز
|
||||
میشوند ولی کاربر لوگو را نمیبیند.
|
||||
- خط پایهٔ ریپو پیش از این تسک: `npm run test` چهار شکستِ ازقبلموجود در
|
||||
`lib/lib.test.js` و `lib/getStateInfo.test.js`؛ `npm run lint` سه خطا در فایلهای
|
||||
بیربط. اینها رگرسیون نیستند.
|
||||
- `npm run start` هشدار `"next start" does not work with "output: standalone"`
|
||||
میدهد. صفحات رندر میشوند و برای این تستها کافی است، ولی اگر رفتار عجیبی دیدید
|
||||
اول همین را در نظر بگیرید.
|
||||
Reference in New Issue
Block a user