feat: optymalizacja SEO i dodanie 15 stron dzielnic Wrocławia

This commit is contained in:
MichalC
2026-06-28 15:50:26 +02:00
parent 59808f1243
commit e5abd82858
14 changed files with 543 additions and 15 deletions
@@ -0,0 +1,188 @@
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { MapPin, Clock, Phone, ArrowRight, ThermometerSun } from 'lucide-react';
import { getDistrictBySlug, getAllDistrictSlugs, wroclawDistricts } from '@/content/wroclaw-districts';
import { HeroSection } from '@/components/sections/HeroSection';
import { ProcessSteps } from '@/components/sections/ProcessSteps';
import { PricingTable } from '@/components/sections/PricingTable';
import { WhyUs } from '@/components/sections/WhyUs';
import { FaqAccordion } from '@/components/sections/FaqAccordion';
import { CtaBanner } from '@/components/sections/CtaBanner';
import { Testimonials } from '@/components/sections/Testimonials';
import { acProcessSteps } from '@/content/process';
import { companyDetails } from '@/content/company';
interface Props {
params: Promise<{ dzielnica: string }>;
}
export async function generateStaticParams() {
return getAllDistrictSlugs().map((d) => ({ dzielnica: d.slug }));
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { dzielnica } = await params;
const district = getDistrictBySlug(dzielnica);
if (!district) return { title: 'Nie znaleziono' };
return {
title: district.seoTitle,
description: district.seoDescription,
alternates: { canonical: `/klimatyzacja/wroclaw/${district.slug}` },
openGraph: {
title: district.seoTitle,
description: district.seoDescription,
},
};
}
export default async function DzielnicaPage({ params }: Props) {
const { dzielnica } = await params;
const district = getDistrictBySlug(dzielnica);
if (!district) notFound();
const otherDistricts = wroclawDistricts.filter((d) => d.slug !== district.slug);
const jsonLd = {
"@context": "https://schema.org",
"@type": "HVACBusiness",
"name": companyDetails.name,
"telephone": companyDetails.phone,
"email": companyDetails.email,
"url": `${process.env.NEXT_PUBLIC_BASE_URL || 'https://thermcool.pl'}/klimatyzacja/wroclaw/${district.slug}`,
"address": {
"@type": "PostalAddress",
"streetAddress": companyDetails.address.street,
"addressLocality": "Wrocław",
"postalCode": companyDetails.address.zipCode,
"addressCountry": "PL",
},
"areaServed": { "@type": "Place", "name": district.name },
"priceRange": "$$",
};
return (
<main>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<HeroSection
eyebrow={`Klimatyzacja ${district.name} · Wrocław · F-Gaz`}
title={`Montaż klimatyzacji — ${district.name}`}
subtitle={district.heroSubtitle}
ctaText="Zamów bezpłatną wycenę"
ctaLink="/kontakt"
secondaryCtaText="Zobacz klimatyzatory"
secondaryCtaLink="/sklep"
backgroundImage={district.heroImage}
features={[
'Bezpłatny audyt i dobór',
'Uprawnienia F-Gaz',
'Gwarancja do 5 lat',
`Dojazd na ${district.name}`,
]}
/>
<section className="py-16 md:py-20 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start">
<div>
<span className="text-xs font-semibold uppercase tracking-wider text-accent font-heading">
Klimatyzacja {district.name}
</span>
<h2 className="text-2xl md:text-3xl font-bold text-primary font-heading mt-2 mb-4">
Profesjonalny montaż klimatyzacji — {district.name}
</h2>
<p className="text-text-muted leading-relaxed mb-4">{district.introText}</p>
<p className="text-text-muted leading-relaxed">{district.localFacts}</p>
</div>
<div className="flex flex-col gap-4">
<div className="p-5 rounded-xl bg-slate-50 border border-border flex gap-4 items-start">
<Clock className="size-5 text-accent shrink-0 mt-0.5" />
<div>
<p className="font-semibold text-primary text-sm">Czas montażu</p>
<p className="text-text-muted text-sm mt-1">Standardowy montaż split trwa 4–8 godzin. Multisplit — 1–2 dni robocze.</p>
</div>
</div>
<div className="p-5 rounded-xl bg-slate-50 border border-border flex gap-4 items-start">
<MapPin className="size-5 text-accent shrink-0 mt-0.5" />
<div>
<p className="font-semibold text-primary text-sm">Zasięg: {district.name} i okolice</p>
<p className="text-text-muted text-sm mt-1">Obsługujemy całą dzielnicę i przyległe osiedla. Szybki dojazd, bez dodatkowych kosztów dojazdu w granicach Wrocławia.</p>
</div>
</div>
<div className="p-5 rounded-xl bg-accent-light border border-accent/20 flex gap-4 items-start">
<Phone className="size-5 text-accent shrink-0 mt-0.5" />
<div>
<p className="font-semibold text-primary text-sm">Bezpłatna wycena</p>
<p className="text-text-muted text-sm mt-1">Zadzwoń lub napisz — wyceniamy bezpłatnie, bez zobowiązań.</p>
<a href={`tel:${companyDetails.phoneRaw}`} className="inline-flex items-center gap-1.5 text-accent font-semibold text-sm mt-2 hover:underline">
{companyDetails.phone} <ArrowRight className="size-3.5" />
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<section className="py-12 bg-slate-50 border-t border-b border-border">
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<p className="text-base md:text-lg text-text-muted leading-relaxed italic">
{district.acHighlight}
</p>
</div>
</section>
<ProcessSteps
steps={acProcessSteps}
eyebrow="Jak Działamy"
title={`Montaż klimatyzacji — ${district.name} — krok po kroku`}
subtitle="Od pierwszego kontaktu do przekazania gotowej instalacji."
/>
<PricingTable />
<WhyUs />
<Testimonials />
<FaqAccordion category="klimatyzacja" />
{/* Inne dzielnice Wrocławia */}
<section className="py-16 bg-slate-50 border-t border-border">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-8">
<h2 className="text-xl md:text-2xl font-bold text-primary font-heading">
Klimatyzacja we Wrocławiu — inne dzielnice
</h2>
</div>
<div className="flex flex-wrap justify-center gap-3">
{otherDistricts.map((d) => (
<Link
key={d.slug}
href={`/klimatyzacja/wroclaw/${d.slug}`}
className="px-4 py-2 rounded-full bg-white border border-border text-sm font-medium text-primary hover:border-accent hover:text-accent transition-colors shadow-sm"
>
Klimatyzacja {d.name}
</Link>
))}
<Link
href="/klimatyzacja/wroclaw"
className="px-4 py-2 rounded-full bg-accent text-white border border-accent text-sm font-medium hover:bg-accent/90 transition-colors shadow-sm"
>
Klimatyzacja Wrocław →
</Link>
</div>
</div>
</section>
<CtaBanner
title={`Potrzebujesz klimatyzacji — ${district.name}?`}
subtitle="Odpowiemy w ciągu godziny i umówimy bezpłatny audyt w dogodnym terminie."
ctaText="Zadzwoń lub napisz"
ctaLink="/kontakt"
/>
</main>
);
}