feat(admin): ویرایشپذیری هیروی صفحهها و پروژهها
- page-heroes به فهرست موجودیتهای پنل اضافه شد و PageHero یک دکمهٔ واضح «عنوان، سرآغاز و تصویر هیروی این صفحه» گرفت (پیشتر فقط ویرایش درجای نامرئی روی خود متن بود). - صفحهٔ پروژهها و صفحهٔ جزئیات پروژه حالا از دیتابیس خوانده میشوند (فایل استاتیک projectsData فقط جانشین دیتابیس خالی/اسلاگهای قدیمی است) — پیشتر ویرایش پنل روی این دو صفحه اصلاً نمایش داده نمیشد. - روی لیست پروژهها دکمهٔ ویرایش/جابهجایی/حذف و «افزودن پروژه» اضافه شد و روی صفحهٔ جزئیات هر پروژه دکمهٔ ویرایش همان پروژه.
This commit is contained in:
@@ -12,21 +12,35 @@ import { useSite, useStatusLabel } from '../api';
|
||||
import { useLang } from '../i18n/lang';
|
||||
import { applySeo } from '../seo';
|
||||
import { projectsData } from '../data/projectsData';
|
||||
import { SingletonPill } from '../admin/Editable';
|
||||
|
||||
export function ProjectDetail() {
|
||||
const { slug } = useParams<{ slug: string }>()
|
||||
const { projects, brand } = useSite()
|
||||
const { t, href, lang } = useLang()
|
||||
|
||||
const currentProject = projectsData.find((p) => p.slug === slug)
|
||||
|
||||
// اولویت با رکورد دیتابیس است تا ویرایش پنل روی صفحهٔ جزئیات هم دیده شود؛
|
||||
// فایل استاتیک فقط برای اسلاگهای قدیمی که در دیتابیس نیستند به کار میرود.
|
||||
const dbProject = projects.find((p) => p.slug === slug)
|
||||
const staticProject = projectsData.find((p) => p.slug === slug)
|
||||
const currentProject = dbProject
|
||||
? {
|
||||
id: String(dbProject.id),
|
||||
slug: dbProject.slug,
|
||||
name: { en: dbProject.title_en || dbProject.title, fa: dbProject.title },
|
||||
location: { en: dbProject.location_en || dbProject.location, fa: dbProject.location },
|
||||
area: { en: dbProject.area_en || dbProject.area, fa: dbProject.area },
|
||||
status: (dbProject.status === 'progress' ? 'progress' : 'done') as 'done' | 'progress',
|
||||
}
|
||||
: staticProject
|
||||
|
||||
const [lightbox, setLightbox] = useState<number | null>(null)
|
||||
|
||||
if (!currentProject) {
|
||||
return <div className="text-center py-20 text-ivory">Project not found</div>
|
||||
}
|
||||
|
||||
const backendProject = projects.find((p) => p.slug === slug)
|
||||
const backendProject = dbProject
|
||||
|
||||
// Dynamic bilingual text from projectsData
|
||||
const displayTitle = currentProject.name[lang as 'en' | 'fa'] || currentProject.name.en;
|
||||
@@ -76,7 +90,10 @@ export function ProjectDetail() {
|
||||
});
|
||||
}, [currentProject.slug, lang, href, displayTitle, summary, image, brand.name]);
|
||||
|
||||
const related = projectsData.filter((p) => p.slug !== currentProject.slug).slice(0, 3)
|
||||
// پروژههای مرتبط — از دیتابیس، و اگر خالی بود از فهرست استاتیک قدیمی
|
||||
const related = (projects.length > 0 ? projects : projectsData)
|
||||
.filter((p) => p.slug !== currentProject.slug)
|
||||
.slice(0, 3)
|
||||
|
||||
const facts = [
|
||||
{ label: t('specLocation'), value: displayLocation },
|
||||
@@ -104,8 +121,15 @@ export function ProjectDetail() {
|
||||
<span className="text-copper">{displayTitle}</span>
|
||||
</nav>
|
||||
|
||||
<div className="mb-8">
|
||||
<div className="mb-8 flex flex-col items-start gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<h1 className="text-4xl lg:text-5xl font-bold text-ivory">{displayTitle}</h1>
|
||||
{dbProject && (
|
||||
<SingletonPill
|
||||
resource="projects"
|
||||
label="ویرایش این پروژه (عنوان، مشخصات، گالری، متن)"
|
||||
select={(d) => d.projects.find((p) => p.slug === slug)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Gallery Desktop: Grid. Mobile: Grid */}
|
||||
|
||||
Reference in New Issue
Block a user