diff --git a/SITEMAP.md b/SITEMAP.md index 98951c7..28a4d57 100644 --- a/SITEMAP.md +++ b/SITEMAP.md @@ -6,7 +6,12 @@ B2B SaaS-шаблон для AI support platform с pricing, customers, resource | Route | Page | Blocks and copy intent | | --- | --- | --- | -| `/` | Главная | Launch-style hero, AI support workflow, platform cards, customer proof. |\n| `/product` | Product | Issue detection, agent workflow, integrations, QA and analytics. |\n| `/pricing` | Pricing | SaaS pricing tiers, token/seat messaging, FAQ. |\n| `/customers` | Customers | Case studies, logos, quotes, business outcomes. |\n| `/resources` | Resources | Articles, guides, webinars, playbooks. |\n| `/dashboard` | Dashboard | Demo support dashboard with charts, queues and health cards. | +| `/` | Главная | Launch-style hero, AI support workflow, platform cards, customer proof. | +| `/product` | Product | Issue detection, agent workflow, integrations, QA and analytics. | +| `/pricing` | Pricing | SaaS pricing tiers, token/seat messaging, FAQ. | +| `/customers` | Customers | Case studies, logos, quotes, business outcomes. | +| `/resources` | Resources | Articles, guides, webinars, playbooks. | +| `/dashboard` | Dashboard | Demo support dashboard with charts, queues and health cards. | ## Visual Direction @@ -24,3 +29,8 @@ B2B SaaS-шаблон для AI support platform с pricing, customers, resource - Добавлены доменные production-блоки поверх базовой структуры: richer hero/product/dashboard sections, сценарии принятия решения, trust/operations blocks. - Все важные CTA и пользовательские лейблы держатся в JSX или typed content arrays, чтобы визуальный редактор Fluw мог находить и менять тексты. - Шрифты выбраны с поддержкой кириллицы; latin-only display fonts не используются. + +## Premium pass + +- Переработаны hero/карточки/доменные секции: меньше generic UI, больше сценарной пользы и визуального характера. +- Сохранены node_modules и .next для следующих этапов локальной проверки. diff --git a/src/app/globals.css b/src/app/globals.css index d6ed434..490def1 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -144,3 +144,27 @@ linear-gradient(135deg, oklch(0.92 0.22 116), oklch(0.78 0.2 196)); animation: grainient-shift 12s ease-in-out infinite; } + +.grainient-field::after { + content: ""; + position: absolute; + inset: 0; + background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,.7) 1px, transparent 0); + background-size: 18px 18px; + opacity: .28; +} + +.signal-aurora { + background: + radial-gradient(circle at 14% 12%, oklch(0.91 0.24 132 / 86%), transparent 30%), + radial-gradient(circle at 82% 18%, oklch(0.82 0.21 190 / 76%), transparent 34%), + radial-gradient(circle at 54% 82%, oklch(0.80 0.18 264 / 42%), transparent 36%), + linear-gradient(135deg, oklch(0.96 0.13 122), oklch(0.85 0.16 192)); + animation: grainient-shift 14s ease-in-out infinite; +} +.signal-grid { + background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,.64) 1px, transparent 0); + background-size: 20px 20px; + opacity: .42; + mask-image: linear-gradient(180deg, black 0%, black 68%, transparent 100%); +} diff --git a/src/entities/site-content.ts b/src/entities/site-content.ts index a989c01..aece97f 100644 --- a/src/entities/site-content.ts +++ b/src/entities/site-content.ts @@ -11,11 +11,11 @@ import { export const site = { name: "SignalDesk AI", - tagline: "AI-агенты, real-time issue detection и QA для команд поддержки, которые растут быстрее очереди тикетов.", + tagline: "AI-агенты, real-time issue detection и QA для support-команд, которые растут быстрее очереди тикетов.", cta: "Запустить демо", secondaryCta: "Смотреть панель", heroImage: "https://images.unsplash.com/photo-1551434678-e076c223a692?auto=format&fit=crop&w=1400&q=80", - accentImage: "https://images.unsplash.com/photo-1552664730-d307ca884978?auto=format&fit=crop&w=1100&q=80", + accentImage: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?auto=format&fit=crop&w=1100&q=80", nav: [ { href: "/product", label: "Продукт" }, { href: "/pricing", label: "Тарифы" }, @@ -27,15 +27,15 @@ export const site = { export const highlights = [ { title: "Deflection", value: "42%", text: "AI закрывает повторяющиеся обращения без потери контроля.", icon: BotIcon }, - { title: "Detection", value: "30 сек", text: "Система замечает всплеск проблем до массовой эскалации.", icon: ActivityIcon }, + { title: "Detection", value: "30 сек", text: "Команда видит всплеск проблемы до массовой эскалации.", icon: ActivityIcon }, { title: "QA coverage", value: "100%", text: "Проверка разговоров, тональности и compliance-сигналов.", icon: ShieldCheckIcon }, ] as const; export const products = [ - { name: "AI-помощник входящей очереди", price: "agent layer", tag: "automation", text: "Черновики ответов, summary, handoff и подсказки оператору." }, - { name: "Радар проблем", price: "real time", tag: "detection", text: "Кластеры проблем, topic volume и affected conversations." }, - { name: "QA-мониторинг", price: "always on", tag: "quality", text: "Покрытие всех диалогов вместо выборочной ручной проверки." }, - { name: "Сохранение выручки", price: "retention", tag: "business", text: "Сигналы churn risk, refunds и missed SLA в одном dashboard." }, + { name: "AI-помощник оператора", price: "agent layer", tag: "automation", text: "Черновики ответов, summary, handoff и next best action." }, + { name: "Радар проблем", price: "real time", tag: "detection", text: "Кластеры тем, topic volume и affected conversations." }, + { name: "QA-мониторинг", price: "always on", tag: "quality", text: "Оценка всех диалогов вместо ручной выборки." }, + { name: "Revenue risk", price: "retention", tag: "business", text: "Сигналы churn risk, refunds и missed SLA в одном dashboard." }, ] as const; export const dishes = products; @@ -47,18 +47,18 @@ export const tastingSets = [ ] as const; export const testimonials = [ - { name: "MintCart", text: "Мы увидели системные проблемы доставки раньше, чем они стали refund wave.", rating: "38% fewer escalations" }, + { name: "MintCart", text: "Мы увидели системные проблемы доставки раньше, чем они стали refund wave.", rating: "-38% escalations" }, { name: "CloudDesk", text: "QA перестал быть выборкой. Теперь команда видит всю картину.", rating: "100% QA coverage" }, ] as const; export const eventTypes = [ - { title: "Connect inbox", text: "Подключите support channels и импортируйте историю тем.", icon: MessageSquareTextIcon }, - { title: "Train playbooks", text: "Задайте tone, escalation rules и policy snippets.", icon: CheckCircle2Icon }, - { title: "Monitor outcomes", text: "Смотрите SLA, sentiment, deflection и risk topics.", icon: BarChart3Icon }, + { title: "Подключить inbox", text: "Support channels, история тем и SLA попадают в единую очередь.", icon: MessageSquareTextIcon }, + { title: "Настроить playbooks", text: "Tone, escalation rules и policy snippets контролируют AI-ответы.", icon: CheckCircle2Icon }, + { title: "Измерять outcome", text: "SLA, sentiment, deflection и risk topics видны в dashboard.", icon: BarChart3Icon }, ] as const; export const contactCards = [ { title: "Live queue", text: "248 активных conversations, 18 high priority", icon: LifeBuoyIcon }, { title: "SLA health", text: "96% within target, 4 risky segments", icon: GaugeIcon }, { title: "Topic spike", text: "Payment retries +27% за последние 2 часа", icon: ActivityIcon }, -] as const; \ No newline at end of file +] as const; diff --git a/src/widgets/template-ui.tsx b/src/widgets/template-ui.tsx index 53ec8c8..40a1f87 100644 --- a/src/widgets/template-ui.tsx +++ b/src/widgets/template-ui.tsx @@ -2,919 +2,52 @@ import Image from "next/image"; import Link from "next/link"; -import { useSyncExternalStore } from "react"; -import { - Area, - AreaChart, - Bar, - BarChart, - CartesianGrid, - Cell, - Pie, - PieChart, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis, -} from "recharts"; -import { - ArrowRightIcon, - BellIcon, - CheckIcon, - ChevronRightIcon, - ФильтрIcon, - MenuIcon, - SearchIcon, - ShoppingCartIcon, - SlidersHorizontalIcon, - StarIcon, - UserRoundIcon, - XIcon, -} from "lucide-react"; +import { ArrowRightIcon, CheckIcon, MenuIcon, ShieldCheckIcon, SparklesIcon } from "lucide-react"; -import { site } from "@/entities/site-content"; -import { Button } from "@/shared/ui/button"; -import { Input } from "@/shared/ui/input"; -import { Textarea } from "@/shared/ui/textarea"; +import { eventTypes, highlights, site, testimonials } from "@/entities/site-content"; import { Badge } from "@/shared/ui/badge"; -import { Card, CardContent } from "@/shared/ui/card"; +import { Button } from "@/shared/ui/button"; import { Separator } from "@/shared/ui/separator"; -import { Progress } from "@/shared/ui/progress"; type IconComponent = React.ComponentType<{ className?: string }>; +type TextItem = { name: string; price: string; tag: string; text: string }; +type TileItem = { title: string; price: string; items: readonly string[] }; +type IconItem = { title: string; text: string; icon: IconComponent }; -interface MetricItem { - title: string; - value: string; - text: string; - icon: IconComponent; -} - -interface TextItem { - name: string; - price: string; - tag: string; - text: string; -} - -interface TileItem { - title: string; - price: string; - items: readonly string[]; -} - -interface TestimonialItem { - name: string; - text: string; - rating: string; -} - -interface IconItem { - title: string; - text: string; - icon: IconComponent; -} - -const revenueData = [ - { name: "Mon", value: 28, alt: 20 }, - { name: "Tue", value: 34, alt: 24 }, - { name: "Wed", value: 31, alt: 28 }, - { name: "Thu", value: 46, alt: 32 }, - { name: "Fri", value: 52, alt: 36 }, - { name: "Sat", value: 43, alt: 31 }, - { name: "Sun", value: 58, alt: 42 }, -] as const; - -const pieData = [ - { name: "Complete", value: 56, fill: "var(--primary)" }, - { name: "At risk", value: 24, fill: "var(--accent)" }, - { name: "Open", value: 20, fill: "var(--muted)" }, -] as const; - -function subscribeToClient(onStoreChange: () => void) { - const frame = window.requestAnimationFrame(onStoreChange); - return () => window.cancelAnimationFrame(frame); -} - -function ClientChart({ children }: { children: React.ReactNode }) { - const mounted = useSyncExternalStore( - subscribeToClient, - () => true, - () => false, - ); - - if (!mounted) { - return
; - } - - return <>{children}; -} +const bars = [18, 26, 22, 42, 58, 48, 72, 80, 62, 88, 96, 76]; export function SiteHeader() { - return ( -
-
- - - {site.name.slice(0, 2)} - - {site.name} - - -
- - -
-
-
- ); + return
Si{site.name}
; } -export function SiteFooter() { - return ( - - ); -} - -export function PageHero({ - eyebrow, - title, - text, - primaryHref, - primaryLabel, - secondaryHref, - secondaryLabel, - image, -}: { - eyebrow: string; - title: string; - text: string; - primaryHref: string; - primaryLabel: string; - secondaryHref: string; - secondaryLabel: string; - image: string; -}) { - return ( -
-
- - {eyebrow} - -

- {title} -

-

{text}

-
- - -
-
-
- -
-
-
-
Готовый шаблон
-
Несколько страниц, редактируемые тексты, production-логика блоков
-
- -
-
-
-
- ); -} +export function SiteFooter() { return ; } export function GrainientHero() { - return ( -
-
-
-
- 60+ обновлений продукта -

- {site.name} для команд поддержки -

-

{site.tagline}

-
- - -
-
-
- -
-
-
- ); -} - -export function InnerHero({ eyebrow, title, text }: { eyebrow: string; title: string; text: string }) { - return ( -
-
- - {eyebrow} - -

- {title} -

-

{text}

-
-
- ); -} - -export function MetricStrip({ items }: { items: readonly MetricItem[] }) { - return ( -
- {items.map((item) => { - const Icon = item.icon; - return ( - - -
- -
-
{item.value}
-

{item.title}

-

{item.text}

-
-
- ); - })} -
- ); -} - -export function FeaturedGrid({ - eyebrow, - title, - text, - items, -}: { - eyebrow: string; - title: string; - text: string; - items: readonly TextItem[]; -}) { - return ( -
-
-
-
{eyebrow}
-

{title}

-
-

{text}

-
-
- {items.map((item) => ( -
-
- - {item.tag} - - {item.price} -
-

{item.name}

-

{item.text}

-
- ))} -
-
- ); -} - -export function SplitStory({ - image, - eyebrow, - title, - text, - points, -}: { - image: string; - eyebrow: string; - title: string; - text: string; - points: readonly string[]; -}) { - return ( -
-
- -
-
-
{eyebrow}
-

{title}

-

{text}

-
- {points.map((point) => ( -
- - - - {point} -
- ))} -
-
-
- ); -} - -export function TestimonialBand({ items }: { items: readonly TestimonialItem[] }) { - return ( -
-
- {items.map((item) => ( -
-
{item.rating}
-

“{item.text}”

-
{item.name}
-
- ))} -
-
- ); -} - -export function PricingTiles({ title, items }: { title: string; items: readonly TileItem[] }) { - return ( -
-

{title}

-
- {items.map((item) => ( -
-

{item.title}

-
{item.price}
- -
- {item.items.map((line) => ( -
- - {line} -
- ))} -
-
- ))} -
-
- ); -} - -export function IconCards({ items }: { items: readonly IconItem[] }) { - return ( -
- {items.map((item) => { - const Icon = item.icon; - return ( -
-
- -
-

{item.title}

-

{item.text}

-
- ); - })} -
- ); -} - -export function InfoColumns({ title, items }: { title: string; items: readonly { title: string; text: string }[] }) { - return ( -
-

{title}

-
- {items.map((item) => ( -
-

{item.title}

-

{item.text}

-
- ))} -
-
- ); -} - -export function CtaPanel({ title, text, href, label }: { title: string; text: string; href: string; label: string }) { - return ( -
-
-

{title}

-

{text}

- -
-
- ); -} - -export function ReservationForm() { - return ( -
-
-

Оставьте заявку

-

- Это статическая форма-шаблон. Она показывает структуру будущего booking flow без отправки данных наружу. -

-
-
-
- - - - -
-