import React, { useEffect, useMemo, useRef, useState } from "react"; import { Check, ArrowRight } from "lucide-react"; const cn = (...classes) => classes.filter(Boolean).join(" "); const Button = ({ children, variant = "primary", className, ...props }) => { const base = "inline-flex items-center justify-center gap-2 rounded-xl px-4 py-2.5 text-sm font-semibold transition active:scale-[0.99]"; const styles = { primary: "bg-zinc-900 text-white hover:bg-zinc-800 focus:outline-none focus:ring-2 focus:ring-zinc-300", secondary: "bg-white text-zinc-900 border border-zinc-200 hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-zinc-200", }; return ( ); }; const Currency = ({ value }) => { const formatted = useMemo(() => { const s = String(value); return s.replace(/\B(?=(\d{3})+(?!\d))/g, " "); }, [value]); return {formatted} ₽; }; const PricingCard = ({ plan, highlight, onSelect }) => (

{plan.name}

{plan.subtitle}

Вы получаете
    {plan.items.map((it, idx) => (
  • {it}
  • ))}
Съёмка
{plan.shooting}
Продление: {plan.overtime}
); const FAQItem = ({ q, a }) => (
{q} +
{a}
); export default function WeddingPricingNotionStyle() { const [toast, setToast] = useState(null); const toastTimerRef = useRef(null); useEffect(() => { return () => { if (toastTimerRef.current) window.clearTimeout(toastTimerRef.current); }; }, []); const plans = useMemo( () => [ { id: "S", name: "S", subtitle: "1 оператор (съёмка только необходимых для монтажа кадров) · до 8 часов", price: 80000, items: [ "Тизер в вертикальном формате до 1 мин", "Рилзы 10–15 секунд (до 10 шт)", "Срок монтажа от 1 до 5 дней", "Исходные материалы", ], shooting: "1 оператор · до 8 часов", overtime: "10 000 ₽/час", }, { id: "M", name: "M", subtitle: "1 оператор · до 10 часов", price: 150000, items: ["Авторский фильм 5–10 минут", "Тизер до 1 минуты", "Исходные материалы"], shooting: "1 оператор · до 10 часов", overtime: "15 000 ₽/час", }, { id: "L", name: "L", subtitle: "2 оператора · до 10 часов", price: 200000, items: ["Авторский фильм 7–12 минут", "Тизер до 1 минуты", "Исходные материалы"], shooting: "2 оператора · до 10 часов", overtime: "20 000 ₽/час", }, { id: "XL", name: "XL", subtitle: "3 оператора · работа осветителя (гаффера) · до 10 часов", price: 250000, items: [ "Фильм 10–15 минут", "Тизер до 1 минуты", "Рилзы 10–15 секунд (до 15 шт)", "Исходные материалы", ], shooting: "3 оператора + гаффер · до 10 часов", overtime: "25 000 ₽/час", }, ], [] ); const faqs = useMemo( () => [ { q: "Что значит “исходные материалы”?", a: "Все исходники со съёмки в исходном качестве (без цветокоррекции). Передача через облако или на ваш SSD.", }, { q: "Можно ли добавить второй день?", a: "Да. Добавляем отдельной строкой или считаем продлением по часам — как удобнее по таймингу.", }, { q: "Есть ли доп. услуги?", a: "Архивный фильм — 50 000 ₽, SDE — 45 000 ₽, срочный монтаж (5 дней) — 80 000 ₽.", }, ], [] ); const onSelect = (plan) => { setToast(`Выбрано: ${plan.name}`); if (toastTimerRef.current) window.clearTimeout(toastTimerRef.current); toastTimerRef.current = window.setTimeout(() => setToast(null), 2200); }; return (
Wedding Packages

Свадебные пакеты

S / M / L / XL — структура как в прайсе. Без лишнего.

{plans.map((p) => ( ))}
Дополнительно
Архивный фильм — 50 000 ₽ · SDE — 45 000 ₽ · Срочный монтаж (5 дней) — 80 000 ₽
Безнал +10% (налог), если нужен счёт.

FAQ

Коротко про процесс и материалы.

{faqs.map((f, idx) => ( ))}
{toast ? (
{toast}
) : null}
); }