Kovak Yazılım kurumsal site — Next.js 16 + Appwrite

- Anasayfa, Hizmetler, Projeler, Hakkımızda, İletişim sayfaları
- Header/Footer, Hero, ServicesGrid, ProjectsGrid, ContactForm bileşenleri
- Appwrite TablesDB entegrasyonu (services, projects, contact_messages)
- Server Action ile iletişim formu (submitContact)
- Brand palette: navy #0F2C5C + sky #4DA3C7
- kovakyazilim.com'dan alınan logo public/logo.png
This commit is contained in:
Ege Can Komur
2026-05-20 01:52:27 +03:00
parent 8a3a466087
commit 3b3efafcc8
26 changed files with 1192 additions and 75 deletions
+42
View File
@@ -0,0 +1,42 @@
import { Icon } from "@/components/icon";
import { siteConfig } from "@/lib/site-config";
import type { ServiceRow } from "@/lib/types";
type ServiceLike = {
slug: string;
title: string;
description: string;
icon?: string | null;
};
export function ServicesGrid({ services }: { services: ServiceRow[] }) {
const items: ServiceLike[] =
services.length > 0
? services
: (siteConfig.fallbackServices as readonly ServiceLike[]).slice();
return (
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{items.map((s) => (
<article
key={s.slug}
id={s.slug}
className="group relative overflow-hidden rounded-2xl border border-[var(--border)] bg-white p-6 transition hover:border-[var(--sky)]/40 hover:shadow-lg hover:shadow-[var(--sky)]/10"
>
<div className="absolute -right-12 -top-12 size-32 rounded-full bg-[var(--sky-50)] opacity-0 transition group-hover:opacity-100" aria-hidden />
<div className="relative">
<div className="flex size-12 items-center justify-center rounded-xl bg-[var(--navy-50)] text-[var(--navy)]">
<Icon name={s.icon} className="size-6" />
</div>
<h3 className="mt-5 text-lg font-semibold text-[var(--navy)]">
{s.title}
</h3>
<p className="mt-2 text-sm leading-relaxed text-[var(--muted)]">
{s.description}
</p>
</div>
</article>
))}
</div>
);
}