Initial commit: Negin Dental Clinic website

Next.js (App Router) clone of negindentalclinic.ir, wired to the
Meshkee Website API (blog, contact form, favicon), with on-page SEO
and a scroll-reveal animation sequence on the homepage.

See context.md for full project context.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 18:28:54 +03:30
co-authored by Claude Sonnet 5
commit f16b47966b
70 changed files with 4810 additions and 0 deletions
+301
View File
@@ -0,0 +1,301 @@
import Image from "next/image";
import Link from "next/link";
import { getBlogs, blogTitle, blogExcerpt, blogCover, blogDate, faDate, slugifyFa } from "@/lib/meshkee";
import Reveal from "@/components/Reveal";
import styles from "./page.module.css";
export const revalidate = 120;
const FEATURES = [
{
en: "Appointment",
fa: "نوبت‌دهی",
text: "برای گرفتن نوبت از متخصصین کلینیک با ما تماس بگیرید.",
cta: { label: "درخواست نوبت", href: "/contact-us" },
icon: "/assets/img/icons/1.png",
},
{
en: "Emergency Case",
fa: "موارد اورژانسی",
text: "در صورت بروز موارد اورژانسی با کلینیک نگین تماس بگیرید.",
cta: { label: "۰۲۵ - ۳۲۹۴۵۰۷۷", href: "tel:+982532945077" },
icon: "/assets/img/icons/2.png",
},
{
en: "Our Doctors",
fa: "پزشکان ما",
text: "ارائه خدمات توسط دندانپزشکان مجرب و متخصصان عضو هیئت علمی دانشکده دندانپزشکی.",
cta: { label: "معرفی پزشکان", href: "/about-us" },
icon: "/assets/img/icons/3.png",
},
];
const SCHEDULE = [
{ day: "شنبه", doctors: ["دکتر شجری", "دکتر صانعی‌پور", "دکتر دیناروند"] },
{ day: "یکشنبه", doctors: ["دکتر صانعی‌پور", "دکتر دیناروند", "دکتر شجری"] },
{ day: "دوشنبه", doctors: ["دکتر کریمی", "دکتر حسینی مطلق", "دکتر صانعی‌پور"] },
{ day: "سه‌شنبه", doctors: ["دکتر شجری", "دکتر دیناروند", "دکتر رسولی"] },
{ day: "چهارشنبه", doctors: ["دکتر صبری", "دکتر صانعی‌پور", "دکتر دیناروند"] },
{ day: "پنجشنبه", doctors: ["دکتر صبری", "دکتر رسولی", "دکتر حسینی مطلق"] },
];
const SERVICES = [
{ en: "Prosthesis", fa: "پروتز", text: "روکش ثابت و متحرک، روکش ایمپلنت.", icon: "/assets/img/icons/4.png" },
{ en: "Specialized", fa: "خدمات تخصصی", text: "خدمات تخصصی کودکان: کشیدن، ترمیم، عصب‌کشی، روکش استیل و فضانگهدارنده.", icon: "/assets/img/icons/5.png" },
{ en: "Public", fa: "خدمات عمومی", text: "کشیدن، ترمیم (پر کردن)، جرم‌گیری، درمان ریشه و ساخت پروتز.", icon: "/assets/img/icons/6.png" },
{ en: "Root Canal", fa: "درمان ریشه", text: "عصب‌کشی تخصصی شامل ریشه‌های عفونی، ریشه‌های سخت و کانال‌های تنگ و باریک.", icon: "/assets/img/icons/7.png" },
{ en: "Orthodontic", fa: "ارتودنسی", text: "ردیف کردن دندان‌ها و ساخت پلاک مخصوص کودکان مبتلا به شکاف کام.", icon: "/assets/img/icons/8.png" },
{ en: "Prio", fa: "پریو", text: "جراحی‌های لثه، جراحی‌های نرم و سخت، جراحی ایمپلنت و درمان بیماری‌های لثه.", icon: "/assets/img/icons/9.png" },
];
export default async function HomePage() {
const { items: latestBlogs } = await getBlogs({ page: 1, pageSize: 3 });
return (
<>
{/* ---------- hero ---------- */}
<section className={styles.hero}>
<div className={`container ${styles.heroInner}`}>
<div className={styles.heroCopy}>
<Reveal as="span" from="up" delay={0} className={`en-title ${styles.heroEn}`}>
Negin Dental Clinic
</Reveal>
<Reveal as="h1" from="up" delay={110} className={styles.heroTitle}>
کلینیک دندانپزشکی نگین
</Reveal>
<Reveal as="p" from="up" delay={220} className={styles.heroLead}>
ارائه‌دهنده کلیات خدمات دندانپزشکی از جمله ایمپلنت، ارتودنسی شفاف
(الاینر) و خدمات زیبایی، در محیطی آرام و مناسب برای بانوان و کودکان.
</Reveal>
<Reveal as="div" from="up" delay={330} className={styles.heroActions}>
<Link href="/contact-us" className="btn">
لیست نوبت‌دهی
</Link>
<Link href="/virtual-tour" className="btn btn--ghost">
سفر به کلینیک
</Link>
</Reveal>
</div>
<Reveal as="div" from="scale" delay={200} className={styles.heroArt}>
<Image
src="/assets/img/slider-1.png"
alt="خدمات دندانپزشکی کلینیک نگین"
width={754}
height={810}
priority
/>
</Reveal>
</div>
</section>
{/* ---------- feature cards ---------- */}
<section className={styles.features}>
<h2 className="visually-hidden">دسترسی سریع</h2>
<div className={`container grid grid--3`}>
{FEATURES.map((f, i) => (
<Reveal as="article" from="up" delay={i * 110} key={f.en} className="card">
<div className="card__icon">
<Image src={f.icon} alt="" width={60} height={60} />
</div>
<span className="card__en">{f.en}</span>
<h3 className="card__title">{f.fa}</h3>
<p className="card__text">{f.text}</p>
<Link
href={f.cta.href}
className={styles.cardLink}
dir={f.cta.href.startsWith("tel:") ? "ltr" : undefined}
>
{f.cta.label}
</Link>
</Reveal>
))}
</div>
</section>
{/* ---------- weekly schedule ---------- */}
<section className="section section--tint">
<div className="container">
<Reveal as="div" from="up" className="sec-head">
<span className="sec-head__en">Weekly Schedule</span>
<h2 className="sec-head__fa">خدمات ما در کلینیک</h2>
<p className="sec-head__lead">
برای درمان‌های خاص، به جدول زمان‌بندی حضور متخصصین در کلینیک توجه کنید.
</p>
</Reveal>
<Reveal as="div" from="up" delay={120} className={styles.tableWrap}>
<table className={styles.schedule}>
<thead>
<tr>
{SCHEDULE.map((s) => (
<th key={s.day}>{s.day}</th>
))}
</tr>
</thead>
<tbody>
<tr>
{SCHEDULE.map((s) => (
<td key={s.day}>
{s.doctors.map((d) => (
<span key={d}>{d}</span>
))}
</td>
))}
</tr>
</tbody>
</table>
</Reveal>
</div>
</section>
{/* ---------- info: Negin Dental Clinic ---------- */}
<section className="section">
<div className={`container ${styles.split}`}>
<Reveal as="div" from="right" className={styles.splitArt}>
<Image src="/assets/img/info3-2.jpg" alt="کلینیک دندانپزشکی نگین" width={720} height={540} />
</Reveal>
<Reveal as="div" from="left" delay={120} className={styles.splitCopy}>
<span className="sec-head__en">Negin Dental Clinic</span>
<h2>دندانپزشکی نگین</h2>
<p>
این مرکز در تمام ایام هفته با همراهی پزشکان متعهد و مجرب، در زمینه
تشخیص و درمان مشکلات و دردهای ناگهانی دندان در خدمت مادران و فرزندان
می‌باشد. لذا برای درمان‌های خاص به جدول زمان‌بندی حضور متخصصین در
کلینیک توجه کنید.
</p>
<Link href="/services" className="btn btn--cyan">
مشاهده خدمات
</Link>
</Reveal>
</div>
</section>
{/* ---------- info: About Negin Dental ---------- */}
<section className="section section--grey">
<div className={`container ${styles.split} ${styles.splitReverse}`}>
<Reveal as="div" from="left" className={styles.splitArt}>
<Image src="/assets/img/info3-3.jpg" alt="درباره کلینیک نگین" width={720} height={540} />
</Reveal>
<Reveal as="div" from="right" delay={120} className={styles.splitCopy}>
<span className="sec-head__en">About Negin Dental</span>
<h2>درباره کلینیک نگین</h2>
<p>
با شماره‌های کلینیک نگین تماس بگیرید و بدون حضور در کلینیک، نوبت خود
را با دکتر مورد نظر هماهنگ کنید. کادر مجرب دندانپزشکی و استفاده از
مواد با کیفیت، از مزیت‌های بارز کلینیک نگین است.
</p>
<Link href="/about-us" className="btn btn--ghost">
درباره ما
</Link>
</Reveal>
</div>
</section>
{/* ---------- services ---------- */}
<section className="section">
<div className="container">
<Reveal as="div" from="up" className="sec-head">
<span className="sec-head__en">Services</span>
<h2 className="sec-head__fa">خدمات ما در کلینیک</h2>
<p className="sec-head__lead">
ارائه کلیه خدمات دندانپزشکی توسط دندانپزشکان مجرب و متخصصان عضو هیئت
علمی دانشکده دندانپزشکی، با بهره‌گیری از تجهیزات پیشرفته و به‌روز دنیا.
</p>
</Reveal>
<div className="grid grid--3">
{SERVICES.map((s, i) => (
<Reveal as="article" from="up" delay={(i % 3) * 110} key={s.en} className="card">
<div className="card__icon">
<Image src={s.icon} alt="" width={60} height={60} />
</div>
<span className="card__en">{s.en}</span>
<h3 className="card__title">{s.fa}</h3>
<p className="card__text">{s.text}</p>
</Reveal>
))}
</div>
<div className="text-center" style={{ marginTop: 44 }}>
<Link href="/services" className="btn">
لیست کامل خدمات
</Link>
</div>
</div>
</section>
{/* ---------- latest blog posts ---------- */}
{latestBlogs.length > 0 ? (
<section className="section section--tint">
<div className="container">
<Reveal as="div" from="up" className="sec-head">
<span className="sec-head__en">Blog</span>
<h2 className="sec-head__fa">آخرین مقالات</h2>
</Reveal>
<div className="grid grid--3">
{latestBlogs.map((blog, i) => {
const title = blogTitle(blog);
const cover = blogCover(blog);
const href = `/blog/${blog.id}/${slugifyFa(title)}`;
return (
<Reveal as="article" from="up" delay={i * 110} key={blog.id} className={styles.blogCard}>
<Link href={href} className={styles.blogCardArt}>
{cover ? (
<Image src={cover} alt={title} width={420} height={260} />
) : (
<span className={styles.blogCardArtFallback} aria-hidden="true" />
)}
</Link>
<div className={styles.blogCardBody}>
{blogDate(blog) ? (
<span className={styles.blogCardDate}>{faDate(blogDate(blog))}</span>
) : null}
<h3>
<Link href={href}>{title}</Link>
</h3>
{blogExcerpt(blog) ? <p>{blogExcerpt(blog)}</p> : null}
</div>
</Reveal>
);
})}
</div>
<div className="text-center" style={{ marginTop: 44 }}>
<Link href="/blog" className="btn btn--ghost">
همه مقالات
</Link>
</div>
</div>
</section>
) : null}
{/* ---------- call CTA ---------- */}
<section className={styles.cta}>
<div className={`container ${styles.ctaInner}`}>
<Reveal as="div" from="right">
<span className="en-title" style={{ color: "var(--cyan-soft)" }}>
Call Us
</span>
<h2 className={styles.ctaTitle}>با ما در ارتباط باشید</h2>
<p className={styles.ctaText}>
در صورت موارد اورژانسی و نوبت‌دهی با ما تماس بگیرید. همکاران مستقر در
کلینیک، پرونده‌ای شامل اطلاعات شناسایی اولیه برای شما تشکیل می‌دهند و
سپس شما را به بخش تشخیص بیماری‌های دهان و دندان هدایت می‌کنند.
</p>
</Reveal>
<Reveal
as="a"
from="left"
delay={150}
dir="ltr"
href="tel:+982532945077"
className={styles.ctaPhone}
>
۰۲۵ - ۳۲۹۴۵۰۷۷
</Reveal>
</div>
</section>
</>
);
}