feat: Hakkımızda sayfası yönetilebilir (site_settings + /admin/site)

Önce hard-coded olan tüm metinler artık /admin/site > 'Hakkımızda sayfası'
bölümünden düzenlenebilir.

site_settings'e 9 yeni alan eklendi:
- about_eyebrow, about_title, about_description (üst hero)
- about_values (string array JSON {title, description}) — 4 değer kartı
- about_hero_image (opsiyonel, boşsa logo gösterilir)
- about_team_eyebrow, about_team_title, about_team_description
- about_stats (string array JSON {value, label}) — alt navy bant

Mevcut WP değerleri default olarak seed edildi.

Hakkımızda sayfası (app/(site)/hakkimizda/page.tsx) artık:
- Tüm metinler settings'ten okunuyor (fallback default'lar var)
- Hero image varsa logo yerine onu gösteriyor
- Stats sıfırdan farklı sayıda olabilir (3 yerine 2/4)

Admin form (/admin/site):
- Yeni 'Hakkımızda sayfası' section
- 4 alt-bölüm: Üst hero / Değerler / Ekip / Stats
- MediaPicker ile hero image
- Markdown benzeri textarea'lar (--- ayırıcı, | seperator)
This commit is contained in:
Ege Can Komur
2026-05-20 20:50:30 +03:00
parent f3604d96b8
commit f49df9cbeb
4 changed files with 255 additions and 52 deletions
+106
View File
@@ -12,6 +12,7 @@ import { getSiteSettings } from "@/lib/data";
import { saveSiteSettings } from "@/lib/admin-actions";
import { MediaPicker } from "@/components/admin/media-picker";
import type {
AboutValue,
FaqItem,
ProcessStep,
StatItem,
@@ -104,6 +105,21 @@ function faqToText(items?: string[] | null): string {
return parsed.map((it) => `${it.q}\n${it.a}`).join("\n---\n");
}
function aboutValuesToText(items?: string[] | null): string {
if (!items) return "";
const parsed: AboutValue[] = [];
for (const raw of items) {
try {
const obj = JSON.parse(raw) as Partial<AboutValue>;
if (obj.title && obj.description)
parsed.push({ title: obj.title, description: obj.description });
} catch {
/* ignore */
}
}
return parsed.map((v) => `${v.title}\n${v.description}`).join("\n---\n");
}
function Section({
title,
description,
@@ -371,6 +387,96 @@ export default async function SiteSettingsPage() {
/>
</Section>
<Section
title="Hakkımızda sayfası"
description="/hakkimizda sayfasındaki metinler ve görsel."
>
<div className="grid gap-5 md:grid-cols-2">
<Field
label="Eyebrow"
name="about_eyebrow"
defaultValue={s?.about_eyebrow}
placeholder="Hakkımızda"
/>
<Field
label="Başlık"
name="about_title"
defaultValue={s?.about_title}
placeholder="Kocaeli'den dünyaya dijital ürünler"
/>
</div>
<Textarea
label="Açıklama paragrafı"
name="about_description"
rows={3}
defaultValue={s?.about_description}
/>
<Textarea
label="Değerler (4 madde önerilir)"
name="about_values"
rows={10}
defaultValue={aboutValuesToText(s?.about_values)}
placeholder={
"Uçtan uca üretim\nFikir aşamasından lansmana, tek bir ekip.\n---\nÖlçülebilir sonuç\nHer projeyi metriklerle değerlendiriyoruz."
}
help='Her blok "---" ile ayrılır. İlk satır başlık, sonrası açıklama.'
/>
<MediaPicker
label="Hero görsel (opsiyonel)"
name="about_hero_image"
defaultValue={s?.about_hero_image}
help="Boşsa logo gösterilir. Görsel eklersen logo yerine geçer."
/>
<div className="border-t border-[var(--border)] pt-5">
<p className="text-xs font-semibold uppercase tracking-wider text-[var(--muted)]">
Ekip bölümü
</p>
<div className="mt-3 grid gap-5 md:grid-cols-3">
<Field
label="Ekip eyebrow"
name="about_team_eyebrow"
defaultValue={s?.about_team_eyebrow}
placeholder="Ekibimiz"
/>
<Field
label="Ekip başlığı"
name="about_team_title"
defaultValue={s?.about_team_title}
placeholder="Projenizde Kimlerle Çalışırsınız?"
/>
<Field
label="Ekip açıklaması"
name="about_team_description"
defaultValue={s?.about_team_description}
/>
</div>
<p className="mt-2 text-xs text-[var(--muted)]">
Ekip üyeleri /admin/ekip üzerinden yönetilir.
</p>
</div>
<div className="border-t border-[var(--border)] pt-5">
<p className="text-xs font-semibold uppercase tracking-wider text-[var(--muted)]">
İstatistikler (en altta navy bant)
</p>
<div className="mt-3">
<Textarea
label="Stats"
name="about_stats"
rows={4}
defaultValue={statsToText(s?.about_stats)}
placeholder={
"50+ | Tamamlanan proje\n30+ | Mutlu müşteri\n10+ | Yıllık deneyim"
}
help='Her satır "değer | etiket" formatında.'
/>
</div>
</div>
</Section>
<Section
title="Conversion / reklam optimizasyonu"
description="Trust bandı, mini lead form ve WhatsApp metni."