Initial commit: TopSysOps site + admin panel
Multi-page public site (Next.js), Node/Express backend with Postgres, and Vite admin/account app, restructured from a single-page layout into dedicated service, promotions, cases, about, FAQ, and blog pages for SEO. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013otXCiTZsxdZ4SJKZ9wUky
This commit is contained in:
commit
130c5382cd
108 files changed
+7146
No files matched your search
@@ -0,0 +1,73 @@
|
||||
import Link from 'next/link';
|
||||
import { MapPin, Phone, Mail, Clock, ArrowRight } from 'lucide-react';
|
||||
import Reveal from '../Reveal.jsx';
|
||||
import SectionHeading from '../SectionHeading.jsx';
|
||||
|
||||
export default function Contact({ contact, compact = false }) {
|
||||
const rows = contact
|
||||
? [
|
||||
{ icon: MapPin, label: 'Адрес', value: contact.address },
|
||||
{ icon: Phone, label: 'Телефон', value: contact.phone },
|
||||
{ icon: Mail, label: 'Email', value: contact.email },
|
||||
{ icon: Clock, label: 'Режим работы', value: contact.hours },
|
||||
].filter((r) => r.value)
|
||||
: [];
|
||||
|
||||
if (compact) {
|
||||
return (
|
||||
<section id="contact" className="max-w-6xl mx-auto px-5 sm:px-8 py-16">
|
||||
<Reveal>
|
||||
<div className="rounded-lg border p-6 sm:p-8 flex flex-col sm:flex-row items-start sm:items-center gap-6 justify-between bg-white border-slate-200 dark:bg-slate-900 dark:border-slate-800">
|
||||
<div>
|
||||
<h3 className="font-bold text-lg mb-2 font-display">Оставить заявку</h3>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||
{contact?.phone && `${contact.phone} · `}
|
||||
{contact?.email}
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
href="/kontakty"
|
||||
className="inline-flex items-center gap-2 px-5 py-3 rounded-md bg-emerald-500 text-white font-medium text-sm hover:bg-emerald-600 transition-colors whitespace-nowrap"
|
||||
>
|
||||
Все контакты <ArrowRight className="h-4 w-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</Reveal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section id="contact" className="max-w-6xl mx-auto px-5 sm:px-8 py-20">
|
||||
<SectionHeading eyebrow="contact --reach-us" title="Контакты" />
|
||||
<div className="grid md:grid-cols-2 gap-5">
|
||||
<Reveal>
|
||||
<div className="rounded-lg border p-5 h-full bg-white border-slate-200 dark:bg-slate-900 dark:border-slate-800">
|
||||
<div className="space-y-5">
|
||||
{rows.map((r) => {
|
||||
const Icon = r.icon;
|
||||
return (
|
||||
<div key={r.label} className="flex items-start gap-3">
|
||||
<Icon className="h-4 w-4 text-emerald-500 mt-0.5" />
|
||||
<div>
|
||||
<div className="text-xs text-slate-400 dark:text-slate-500">{r.label}</div>
|
||||
<div className="text-sm">{r.value}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{rows.length === 0 && <p className="text-sm text-slate-400">Контакты пока не заполнены.</p>}
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
{contact?.map_embed && (
|
||||
<Reveal delay={100}>
|
||||
<div className="rounded-lg border overflow-hidden h-64 md:h-full bg-white border-slate-200 dark:bg-slate-900 dark:border-slate-800">
|
||||
<iframe title="Карта офиса TopSysOps" className="w-full h-full" src={contact.map_embed} />
|
||||
</div>
|
||||
</Reveal>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user