"use client"; import React from "react"; import { LayoutQuestion } from "@/components/layout/LayoutQuestion/LayoutQuestion"; import { BottomActionButton } from "@/components/widgets/BottomActionButton/BottomActionButton"; import PrivacyTermsConsent from "@/components/widgets/PrivacyTermsConsent/PrivacyTermsConsent"; import { useDynamicSize } from "@/hooks/DOM/useDynamicSize"; import { buildLayoutQuestionProps, buildTemplateBottomActionButtonProps, } from "@/lib/funnel/mappers"; import type { ScreenDefinition } from "@/lib/funnel/types"; import { cn } from "@/lib/utils"; interface TemplateLayoutProps { screen: ScreenDefinition; canGoBack: boolean; onBack: () => void; screenProgress?: { current: number; total: number }; // Настройки template titleDefaults?: { font?: "manrope" | "inter" | "geistSans" | "geistMono"; weight?: "regular" | "medium" | "semiBold" | "bold" | "extraBold" | "black"; align?: "left" | "center" | "right"; size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl"; color?: | "default" | "primary" | "secondary" | "destructive" | "success" | "card" | "accent" | "muted"; className?: string; }; subtitleDefaults?: { font?: "manrope" | "inter" | "geistSans" | "geistMono"; weight?: "regular" | "medium" | "semiBold" | "bold" | "extraBold" | "black"; color?: | "default" | "primary" | "secondary" | "destructive" | "success" | "card" | "accent" | "muted"; align?: "left" | "center" | "right"; size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl"; className?: string; }; actionButtonOptions?: { defaultText: string; disabled: boolean; onClick: () => void; }; // Дополнительные props для BottomActionButton childrenAboveButton?: React.ReactNode; childrenUnderButton?: React.ReactNode; // Дополнительные props для Title childrenAboveTitle?: React.ReactNode; // Переопределения стилей LayoutQuestion (контент и обертка контента) contentProps?: React.ComponentProps<"div">; childrenWrapperProps?: React.ComponentProps<"div">; // Контент template children: React.ReactNode; } /** * Централизованный layout wrapper для всех templates * Устраняет дублирование логики Header и BottomActionButton */ export function TemplateLayout({ screen, canGoBack, onBack, screenProgress, titleDefaults = { font: "manrope", weight: "bold", align: "left", size: "2xl", color: "default", }, subtitleDefaults = { font: "manrope", weight: "medium", color: "default", align: "left", size: "lg", }, actionButtonOptions, childrenAboveButton, childrenUnderButton, childrenAboveTitle, contentProps, childrenWrapperProps, children, }: TemplateLayoutProps) { // 🎛️ ЦЕНТРАЛИЗОВАННАЯ ЛОГИКА BOTTOM BUTTON const { elementRef: bottomActionButtonRef } = useDynamicSize({ defaultHeight: 132, }); // 🎯 ЦЕНТРАЛИЗОВАННАЯ ЛОГИКА HEADER const layoutQuestionProps = buildLayoutQuestionProps({ screen, titleDefaults, subtitleDefaults, canGoBack, onBack, screenProgress, }); // 🎯 ЦЕНТРАЛИЗОВАННАЯ ЛОГИКА BOTTOM BUTTON PROPS const bottomActionButtonProps = actionButtonOptions ? buildTemplateBottomActionButtonProps({ screen, actionButtonOptions, }) : undefined; // 🎯 Автоматически создаем PrivacyTermsConsent с фиксированными настройками const shouldShowPrivacyTermsConsent = "bottomActionButton" in screen && screen.bottomActionButton?.showPrivacyTermsConsent === true; const autoPrivacyTermsConsent = shouldShowPrivacyTermsConsent ? ( ) : null; // Комбинируем переданный childrenUnderButton с автоматическим PrivacyTermsConsent const finalChildrenUnderButton = ( <> {childrenUnderButton} {autoPrivacyTermsConsent} ); // 🎨 ЦЕНТРАЛИЗОВАННЫЙ РЕНДЕРИНГ return (
{children} {bottomActionButtonProps && ( )}
); }