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,77 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
|
||||
const LINES = ['$ status --infra', 'uptime: 99.98%', 'incidents_resolved: 1240+', 'avg_response_time: 15m'];
|
||||
|
||||
function cx(...args) {
|
||||
return args.filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
export default function Hero() {
|
||||
const [shown, setShown] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (shown >= LINES.length) return undefined;
|
||||
const timer = setTimeout(() => setShown((s) => s + 1), 450);
|
||||
return () => clearTimeout(timer);
|
||||
}, [shown]);
|
||||
|
||||
return (
|
||||
<section id="home" className="max-w-6xl mx-auto px-5 sm:px-8 pt-16 pb-20 grid md:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-widest text-emerald-500 mb-4 font-mono">
|
||||
> top-sysops.ru --about
|
||||
</p>
|
||||
<h1
|
||||
className="text-[clamp(1.5rem,7.5vw,3rem)] md:text-3xl lg:text-4xl leading-tight font-bold mb-6 font-display text-slate-900 dark:text-slate-100 break-words"
|
||||
style={{ hyphens: 'auto' }}
|
||||
lang="ru"
|
||||
>
|
||||
IT-аутсорсинг и техподдержка<br />
|
||||
инфраструктуры, за которую<br />
|
||||
можно не переживать
|
||||
</h1>
|
||||
<p className="text-base sm:text-lg mb-8 max-w-md text-slate-600 dark:text-slate-400">
|
||||
Администрирование серверов, кибербезопасность, сетевая инфраструктура и автоматизация бизнес-процессов
|
||||
с помощью ИИ — с гарантией отклика от 15 минут.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Link
|
||||
href="/uslugi"
|
||||
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"
|
||||
>
|
||||
Наши услуги <ArrowRight className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/kontakty"
|
||||
className="inline-flex items-center gap-2 px-5 py-3 rounded-md font-medium text-sm border transition-colors border-slate-300 hover:bg-slate-100 dark:border-slate-700 dark:hover:bg-slate-900"
|
||||
>
|
||||
Оставить заявку
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border p-5 shadow-sm font-mono bg-white border-slate-200 dark:bg-slate-900 dark:border-slate-800">
|
||||
<div className="flex items-center gap-1.5 mb-4">
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-rose-400" />
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-amber-400" />
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-emerald-400" />
|
||||
</div>
|
||||
<div className="space-y-2 text-sm">
|
||||
{LINES.slice(0, shown).map((line, i) => (
|
||||
<div key={line} className={cx(i === 0 ? 'text-emerald-500' : 'text-slate-700 dark:text-slate-300')}>
|
||||
{line}
|
||||
</div>
|
||||
))}
|
||||
<span className="inline-flex items-center gap-1 text-slate-700 dark:text-slate-300">
|
||||
{shown >= LINES.length && <span className="text-emerald-500">$</span>}
|
||||
<span className="inline-block w-2 h-4 bg-emerald-500 animate-pulse align-middle" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user