132 lines
4.2 KiB
TypeScript
132 lines
4.2 KiB
TypeScript
"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";
|
||
|
||
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";
|
||
};
|
||
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";
|
||
};
|
||
actionButtonOptions?: {
|
||
defaultText: string;
|
||
disabled: boolean;
|
||
onClick: () => void;
|
||
};
|
||
|
||
// Дополнительные props для BottomActionButton
|
||
childrenUnderButton?: React.ReactNode;
|
||
|
||
// Контент 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,
|
||
childrenUnderButton,
|
||
children,
|
||
}: TemplateLayoutProps) {
|
||
// 🎛️ ЦЕНТРАЛИЗОВАННАЯ ЛОГИКА BOTTOM BUTTON
|
||
const {
|
||
elementRef: bottomActionButtonRef,
|
||
} = useDynamicSize<HTMLDivElement>({
|
||
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 ? (
|
||
<PrivacyTermsConsent
|
||
className="mt-5"
|
||
privacyPolicy={{
|
||
href: "/privacy",
|
||
children: "Privacy Policy"
|
||
}}
|
||
termsOfUse={{
|
||
href: "/terms",
|
||
children: "Terms of use"
|
||
}}
|
||
/>
|
||
) : null;
|
||
|
||
// Комбинируем переданный childrenUnderButton с автоматическим PrivacyTermsConsent
|
||
const finalChildrenUnderButton = (
|
||
<>
|
||
{childrenUnderButton}
|
||
{autoPrivacyTermsConsent}
|
||
</>
|
||
);
|
||
|
||
// 🎨 ЦЕНТРАЛИЗОВАННЫЙ РЕНДЕРИНГ
|
||
return (
|
||
<div className="w-full">
|
||
<LayoutQuestion {...layoutQuestionProps}>
|
||
{children}
|
||
</LayoutQuestion>
|
||
|
||
{bottomActionButtonProps && (
|
||
<BottomActionButton
|
||
{...bottomActionButtonProps}
|
||
ref={bottomActionButtonRef}
|
||
childrenUnderButton={finalChildrenUnderButton}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|