82 lines
3.5 KiB
TypeScript
82 lines
3.5 KiB
TypeScript
import React from 'react'
|
|
|
|
import { AnimatePresence, motion } from 'framer-motion'
|
|
import { Reveal } from '../Reveal'
|
|
import { PremiumButton } from '../PremiumButton'
|
|
import { ProjectCard } from '../ProjectCard'
|
|
import { SectionHeading } from '../SectionHeading'
|
|
import { useSectionHeading, useSite } from '../../api'
|
|
import { useFieldSaver } from '../../admin/AdminContext'
|
|
import { useLang } from '../../i18n/lang'
|
|
import { InlineEdit } from '../admin/InlineEdit'
|
|
|
|
export function FeaturedProjects() {
|
|
const { projects } = useSite()
|
|
const { href } = useLang()
|
|
const heading = useSectionHeading('featured_projects')
|
|
const save = useFieldSaver()
|
|
|
|
// سه پروژهٔ ثابت صفحهٔ اصلی — بدون تب وضعیت؛ ویرایش پنل همانجا اعمال میشود
|
|
const FEATURED_TITLES = ['آرامش زنیث', 'آرامش الیسیان', 'آرامش آوالون']
|
|
const list = projects.filter((p) => FEATURED_TITLES.includes(p.title))
|
|
.sort((a, b) => FEATURED_TITLES.indexOf(a.title) - FEATURED_TITLES.indexOf(b.title))
|
|
|
|
return (
|
|
<section className="w-full max-w-full overflow-x-clip bg-char py-16 md:py-24 lg:py-32" aria-labelledby="projects-title">
|
|
<div className="mx-auto max-w-site px-4 md:px-6 lg:px-10">
|
|
<SectionHeading title={heading.title} lead={heading.lead} headingKey="featured_projects" />
|
|
|
|
<div className="mt-8 min-h-[420px] md:mt-10">
|
|
<AnimatePresence mode="wait">
|
|
<motion.div
|
|
key="featured"
|
|
initial={{ opacity: 0, y: 15 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, ease: [0.23, 1, 0.32, 1] }}
|
|
className="flex gap-4 overflow-x-auto pb-4 snap-x snap-mandatory [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none] md:grid md:grid-cols-3 md:gap-6 md:overflow-visible md:pb-0"
|
|
>
|
|
{list.map((project, i) => {
|
|
const imageUrl = project.image || undefined;
|
|
|
|
return (
|
|
<motion.div
|
|
key={project.id}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.5, delay: i * 0.1, ease: [0.23, 1, 0.32, 1] }}
|
|
className="h-full w-[82vw] max-w-[320px] shrink-0 snap-center md:w-auto md:max-w-none md:shrink"
|
|
>
|
|
<ProjectCard
|
|
project={project}
|
|
imageUrl={imageUrl}
|
|
detailHref={`/projects/${project.slug}`}
|
|
/>
|
|
</motion.div>
|
|
)
|
|
})}
|
|
</motion.div>
|
|
</AnimatePresence>
|
|
</div>
|
|
|
|
{/* دکمه مشاهده همه پروژهها */}
|
|
{heading.cta_label && heading.cta_href && (
|
|
<Reveal delay={0.1}>
|
|
<div className="mt-10 flex justify-center md:mt-12">
|
|
<PremiumButton to={href(heading.cta_href)}>
|
|
<InlineEdit
|
|
value={heading.cta_label}
|
|
onSave={(v) =>
|
|
save('section-headings', heading.id, { cta_label: v }, (d) => {
|
|
const h = d.section_headings.find((s) => s.id === heading.id)
|
|
if (h) (h as unknown as Record<string, unknown>)["cta_label"] = v
|
|
})
|
|
}
|
|
/>
|
|
</PremiumButton>
|
|
</div>
|
|
</Reveal>
|
|
)}
|
|
</div>
|
|
</section>
|
|
)
|
|
} |