Files
blackheart-website/src/components/sections/Contact.tsx
diana.dolgolyova 27c1348f89 feat: admin panel with SQLite, auth, and calendar-style schedule editor
Complete admin panel for content management:
- SQLite database with better-sqlite3, seed script from content.ts
- Simple password auth with HMAC-signed cookies (Edge + Node compatible)
- 9 section editors: meta, hero, about, team, classes, schedule, pricing, FAQ, contact
- Team CRUD with image upload and drag reorder
- Schedule editor with Google Calendar-style visual timeline (colored blocks, overlap detection, click-to-add)
- All public components refactored to accept data props from DB (with fallback to static content)
- Middleware protecting /admin/* and /api/admin/* routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:59:12 +03:00

78 lines
2.9 KiB
TypeScript

import { MapPin, Phone, Clock, Instagram } from "lucide-react";
import { BRAND } from "@/lib/constants";
import { SectionHeading } from "@/components/ui/SectionHeading";
import { Reveal } from "@/components/ui/Reveal";
import { IconBadge } from "@/components/ui/IconBadge";
import type { ContactInfo } from "@/types/content";
interface ContactProps {
data: ContactInfo;
}
export function Contact({ data: contact }: ContactProps) {
return (
<section id="contact" className="relative section-padding bg-neutral-50 dark:bg-[#050505]">
<div className="section-divider absolute top-0 left-0 right-0" />
<div className="section-container grid items-center gap-12 lg:grid-cols-2">
<Reveal>
<SectionHeading>{contact.title}</SectionHeading>
<div className="mt-10 space-y-5">
{contact.addresses.map((address, i) => (
<div key={i} className="group flex items-center gap-4">
<IconBadge><MapPin size={18} /></IconBadge>
<p className="body-text">{address}</p>
</div>
))}
<div className="group flex items-center gap-4">
<IconBadge><Phone size={18} /></IconBadge>
<a
href={`tel:${contact.phone}`}
className="text-neutral-600 transition-colors hover:text-gold-dark dark:text-neutral-300 dark:hover:text-gold-light"
>
{contact.phone}
</a>
</div>
<div className="group flex items-center gap-4">
<IconBadge><Clock size={18} /></IconBadge>
<p className="body-text">{contact.workingHours}</p>
</div>
<div className="border-t border-neutral-200 pt-5 dark:border-white/[0.08]">
<div className="group flex items-center gap-4">
<IconBadge><Instagram size={18} /></IconBadge>
<a
href={contact.instagram}
target="_blank"
rel="noopener noreferrer"
className="text-neutral-600 transition-colors hover:text-gold-dark dark:text-neutral-300 dark:hover:text-gold-light"
>
{BRAND.instagramHandle}
</a>
</div>
</div>
</div>
</Reveal>
<Reveal>
<div className="overflow-hidden rounded-2xl border border-neutral-200 shadow-sm dark:border-white/[0.08] dark:shadow-[0_0_30px_rgba(201,169,110,0.05)]">
<iframe
src={contact.mapEmbedUrl}
width="100%"
height="380"
style={{ border: 0 }}
allowFullScreen
loading="lazy"
title="Карта"
className="dark:invert dark:hue-rotate-180 dark:brightness-95 dark:contrast-90"
/>
</div>
</Reveal>
</div>
</section>
);
}