Files
sag24-website/src/pages/Home.jsx
striker 3cb42a4466 Добавить пререндер, партнёров, реквизиты, SEO-улучшения
- SSR-пререндер через Vite + react-dom/server (entry-server.jsx, scripts/prerender.mjs)
- Секция партнёров: RU-CENTER, REG.RU, МТВ, КОНТУР
- Реквизиты компании в футере (ИНН, ОГРН, банк)
- Копирайт с 2011 года
- Логотип увеличен (h-8→h-12 навбар, h-7→h-10 футер)
- favicon.ico пересобран с 16×16, 32×32, 48×48 из logo.png
- og:image и twitter:image переключены на .png
- apple-touch-icon.png и og-image.png сгенерированы через sharp
- SSR-safe: localStorage и window.location проверяются на typeof

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 05:24:01 +03:00

225 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from 'react'
import { ChevronRight, Server, Shield, Headphones, Phone, Mail, MapPin, CheckCircle2 } from 'lucide-react'
import { useLanguage } from '../contexts/LanguageContext.jsx'
import { useReveal } from '../components/useReveal.js'
const serviceIcons = [Server, Shield, Headphones]
function ServiceCard({ icon: Icon, title, description, points }) {
const ref = useReveal()
return (
<div ref={ref} className="section-reveal bg-white border border-slate-200 rounded-xl p-8 hover:shadow-lg hover:border-blue-200 transition-all duration-300 flex flex-col gap-4">
<div className="w-12 h-12 bg-blue-50 rounded-lg flex items-center justify-center">
<Icon size={24} className="text-blue-700" />
</div>
<h3 className="text-xl font-bold text-slate-900">{title}</h3>
<p className="text-slate-600 text-sm leading-relaxed">{description}</p>
<ul className="flex flex-col gap-2 mt-auto pt-4 border-t border-slate-100">
{points.map((p, i) => (
<li key={i} className="flex items-center gap-2 text-sm text-slate-700">
<CheckCircle2 size={16} className="text-blue-600 flex-shrink-0" />
{p}
</li>
))}
</ul>
</div>
)
}
export default function Home() {
const { t } = useLanguage()
const [formState, setFormState] = useState({ name: '', company: '', message: '' })
const [submitted, setSubmitted] = useState(false)
const aboutRef = useReveal()
const contactRef = useReveal()
const services = t('services.items')
const stats = [t('about.stat1'), t('about.stat2'), t('about.stat3')]
const handleSubmit = (e) => {
e.preventDefault()
setSubmitted(true)
}
return (
<div>
{/* Hero */}
<section className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-900 via-blue-950 to-slate-900 relative overflow-hidden">
<div className="absolute inset-0 opacity-20">
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-blue-500 rounded-full blur-3xl" />
<div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-blue-700 rounded-full blur-3xl" />
</div>
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-32 text-center relative z-10">
<div className="inline-flex items-center gap-2 bg-blue-500/10 border border-blue-500/20 rounded-full px-4 py-1.5 mb-8">
<div className="w-2 h-2 bg-blue-400 rounded-full animate-pulse" />
<span className="text-blue-300 text-sm font-medium">IT-аутсорсинг · Безопасность · Поддержка</span>
</div>
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold text-white leading-tight mb-6">
{t('hero.title')}
</h1>
<p className="text-lg sm:text-xl text-slate-300 max-w-2xl mx-auto mb-10 leading-relaxed">
{t('hero.subtitle')}
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href="#contact" className="px-8 py-4 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-lg transition-all duration-300 flex items-center justify-center gap-2 group">
{t('hero.cta')}
<ChevronRight size={20} className="group-hover:translate-x-1 transition-transform" />
</a>
<a href="#services" className="px-8 py-4 border border-white/20 hover:border-white/40 text-white font-semibold rounded-lg transition-all duration-300">
{t('hero.ctaSecondary')}
</a>
</div>
</div>
</section>
{/* Services */}
<section id="services" className="py-24 bg-slate-50">
<div className="max-w-6xl mx-auto px-4 sm:px-6">
<div className="text-center mb-16">
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold text-slate-900 mb-4">{t('services.title')}</h2>
<p className="text-slate-500 text-lg max-w-2xl mx-auto">{t('services.subtitle')}</p>
</div>
<div className="grid md:grid-cols-3 gap-6">
{services.map((svc, i) => (
<ServiceCard key={i} icon={serviceIcons[i]} {...svc} />
))}
</div>
</div>
</section>
{/* About */}
<section id="about" className="py-24 bg-white">
<div className="max-w-6xl mx-auto px-4 sm:px-6">
<div ref={aboutRef} className="section-reveal grid md:grid-cols-2 gap-16 items-center">
<div>
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 mb-6">{t('about.title')}</h2>
<p className="text-slate-600 text-lg leading-relaxed mb-4">{t('about.text1')}</p>
<p className="text-slate-600 leading-relaxed">{t('about.text2')}</p>
</div>
<div className="grid grid-cols-3 gap-4">
{stats.map((s, i) => (
<div key={i} className="bg-slate-50 rounded-xl p-6 text-center border border-slate-100">
<div className="text-3xl font-bold text-blue-700 mb-1">{s.value}</div>
<div className="text-sm text-slate-500">{s.label}</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Partners */}
<section className="py-16 bg-slate-50 border-t border-slate-100">
<div className="max-w-6xl mx-auto px-4 sm:px-6">
<div className="text-center mb-10">
<h2 className="text-2xl sm:text-3xl font-bold text-slate-900 mb-2">{t('partners.title')}</h2>
<p className="text-slate-500">{t('partners.subtitle')}</p>
</div>
<div className="flex flex-wrap justify-center gap-4">
{[
{ name: 'RU-CENTER', sub: 'Руцентр' },
{ name: 'REG.RU', sub: 'Регистратор доменов' },
{ name: 'МТВ', sub: 'Телекоммуникации' },
{ name: 'КОНТУР', sub: 'Электронная отчётность' },
].map(p => (
<div key={p.name} className="bg-white border border-slate-200 rounded-xl px-8 py-5 flex flex-col items-center gap-1 min-w-[160px] hover:border-blue-200 hover:shadow-sm transition-all duration-200">
<span className="text-xl font-bold text-slate-800 tracking-tight">{p.name}</span>
<span className="text-xs text-slate-400">{p.sub}</span>
</div>
))}
</div>
</div>
</section>
{/* Contact */}
<section id="contact" className="py-24 bg-slate-900">
<div className="max-w-6xl mx-auto px-4 sm:px-6">
<div ref={contactRef} className="section-reveal grid md:grid-cols-2 gap-16">
<div>
<h2 className="text-3xl sm:text-4xl font-bold text-white mb-4">{t('contact.title')}</h2>
<p className="text-slate-400 text-lg mb-10">{t('contact.subtitle')}</p>
<div className="flex flex-col gap-6">
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-blue-500/10 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5">
<Phone size={20} className="text-blue-400" />
</div>
<div>
<div className="text-slate-400 text-xs uppercase tracking-wider mb-1">{t('contact.phone')}</div>
<div className="flex flex-col gap-1">
{t('contact.phones').map((phone, i) => (
<a key={i} href={`tel:${phone.replace(/\D/g,'')}`} className="text-white font-medium hover:text-blue-400 transition-colors">
{phone}
</a>
))}
</div>
</div>
</div>
<div className="flex items-center gap-4">
<div className="w-10 h-10 bg-blue-500/10 rounded-lg flex items-center justify-center flex-shrink-0">
<Mail size={20} className="text-blue-400" />
</div>
<div>
<div className="text-slate-400 text-xs uppercase tracking-wider mb-0.5">{t('contact.email')}</div>
<a href="mailto:info@sag24.ru" className="text-white font-medium hover:text-blue-400 transition-colors">info@sag24.ru</a>
</div>
</div>
<div className="flex items-center gap-4">
<div className="w-10 h-10 bg-blue-500/10 rounded-lg flex items-center justify-center flex-shrink-0">
<MapPin size={20} className="text-blue-400" />
</div>
<div>
<div className="text-slate-400 text-xs uppercase tracking-wider mb-0.5">{t('contact.address')}</div>
<span className="text-white font-medium">{t('contact.addressValue')}</span>
</div>
</div>
</div>
</div>
<div className="bg-white/5 border border-white/10 rounded-xl p-8">
{submitted ? (
<div className="flex flex-col items-center justify-center h-full gap-4 py-8">
<CheckCircle2 size={48} className="text-green-400" />
<p className="text-white text-center text-lg">{t('contact.formSuccess')}</p>
</div>
) : (
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
<input
type="text"
required
placeholder={t('contact.formName')}
value={formState.name}
onChange={e => setFormState({ ...formState, name: e.target.value })}
className="w-full bg-white/10 border border-white/10 rounded-lg px-4 py-3 text-white placeholder-slate-400 focus:outline-none focus:border-blue-500 transition-colors text-sm"
/>
<input
type="text"
placeholder={t('contact.formCompany')}
value={formState.company}
onChange={e => setFormState({ ...formState, company: e.target.value })}
className="w-full bg-white/10 border border-white/10 rounded-lg px-4 py-3 text-white placeholder-slate-400 focus:outline-none focus:border-blue-500 transition-colors text-sm"
/>
<textarea
required
rows={5}
placeholder={t('contact.formMessage')}
value={formState.message}
onChange={e => setFormState({ ...formState, message: e.target.value })}
className="w-full bg-white/10 border border-white/10 rounded-lg px-4 py-3 text-white placeholder-slate-400 focus:outline-none focus:border-blue-500 transition-colors text-sm resize-none"
/>
<button
type="submit"
className="w-full py-3 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-lg transition-colors"
>
{t('contact.formSubmit')}
</button>
</form>
)}
</div>
</div>
</div>
</section>
</div>
)
}