165 lines
5.0 KiB
TypeScript
165 lines
5.0 KiB
TypeScript
"use client";
|
||
|
||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||
|
||
import { ListTemplate } from "@/components/funnel/templates/ListTemplate";
|
||
import { InfoTemplate } from "@/components/funnel/templates/InfoTemplate";
|
||
import { DateTemplate } from "@/components/funnel/templates/DateTemplate";
|
||
import { FormTemplate } from "@/components/funnel/templates/FormTemplate";
|
||
import { TextTemplate } from "@/components/funnel/templates/TextTemplate";
|
||
import { CouponTemplate } from "@/components/funnel/templates/CouponTemplate";
|
||
import { useBuilderSelectedScreen } from "@/lib/admin/builder/context";
|
||
|
||
export function BuilderPreview() {
|
||
const selectedScreen = useBuilderSelectedScreen();
|
||
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
||
const [formData, setFormData] = useState<Record<string, string>>({});
|
||
const [dateData, setDateData] = useState<[number, number, number]>([0, 0, 0]);
|
||
|
||
useEffect(() => {
|
||
if (!selectedScreen) {
|
||
setSelectedIds([]);
|
||
setFormData({});
|
||
setDateData([0, 0, 0]);
|
||
return;
|
||
}
|
||
|
||
setSelectedIds((prev) => {
|
||
if (prev.length === 0) {
|
||
return prev;
|
||
}
|
||
return [];
|
||
});
|
||
}, [selectedScreen]);
|
||
|
||
const handleSelectionChange = useCallback((ids: string[]) => {
|
||
setSelectedIds((prev) => {
|
||
if (prev.length === ids.length && prev.every((value, index) => value === ids[index])) {
|
||
return prev;
|
||
}
|
||
return ids;
|
||
});
|
||
}, []);
|
||
|
||
const handleFormChange = useCallback((data: Record<string, string>) => {
|
||
setFormData(data);
|
||
}, []);
|
||
|
||
const handleDateChange = useCallback((data: [number, number, number]) => {
|
||
setDateData(data);
|
||
}, []);
|
||
|
||
const renderScreenPreview = useCallback(() => {
|
||
if (!selectedScreen) return null;
|
||
|
||
const commonProps = {
|
||
showGradient: false,
|
||
canGoBack: false,
|
||
onBack: () => {},
|
||
onContinue: () => {}, // Mock continue handler for preview
|
||
};
|
||
|
||
switch (selectedScreen.template) {
|
||
case "list":
|
||
return (
|
||
<ListTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
selectedOptionIds={selectedIds}
|
||
onSelectionChange={handleSelectionChange}
|
||
/>
|
||
);
|
||
|
||
case "info":
|
||
return (
|
||
<InfoTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
/>
|
||
);
|
||
|
||
case "date":
|
||
return (
|
||
<DateTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
selectedDate={{ month: "", day: "", year: "" }}
|
||
onDateChange={() => {}}
|
||
/>
|
||
);
|
||
|
||
case "form":
|
||
return (
|
||
<FormTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
formData={formData}
|
||
onFormDataChange={handleFormChange}
|
||
/>
|
||
);
|
||
|
||
case "text":
|
||
return (
|
||
<TextTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
/>
|
||
);
|
||
|
||
case "coupon":
|
||
return (
|
||
<CouponTemplate
|
||
{...commonProps}
|
||
screen={selectedScreen as any}
|
||
/>
|
||
);
|
||
|
||
default:
|
||
return (
|
||
<div className="flex h-32 items-center justify-center rounded-lg border border-dashed border-border text-sm text-muted-foreground">
|
||
Предпросмотр для типа “{(selectedScreen as any).template}” не поддерживается.
|
||
</div>
|
||
);
|
||
}
|
||
}, [selectedScreen, selectedIds, formData, handleSelectionChange, handleFormChange]);
|
||
|
||
const preview = useMemo(() => {
|
||
if (!selectedScreen) {
|
||
return (
|
||
<div className="flex items-center justify-center mx-auto" style={{ height: '600px', width: '320px' }}>
|
||
<div className="flex items-center justify-center rounded-lg border border-dashed border-border bg-muted/30 text-sm text-muted-foreground w-full h-full">
|
||
Выберите экран для предпросмотра
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// Используем пропорции современных iPhone (19.5:9 = ~2.17:1)
|
||
const PREVIEW_WIDTH = 320;
|
||
const PREVIEW_HEIGHT = Math.round(PREVIEW_WIDTH * 2.17); // ~694px
|
||
|
||
return (
|
||
<div className="mx-auto" style={{ width: PREVIEW_WIDTH }}>
|
||
{/* Mobile Frame - Simple Border */}
|
||
<div
|
||
className="relative bg-white rounded-2xl border-4 border-gray-300 shadow-lg overflow-hidden"
|
||
style={{
|
||
height: PREVIEW_HEIGHT,
|
||
width: PREVIEW_WIDTH
|
||
}}
|
||
>
|
||
{/* Screen Content - Scrollable */}
|
||
<div
|
||
className="w-full h-full overflow-y-auto overflow-x-hidden bg-white [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"
|
||
style={{ height: PREVIEW_HEIGHT }}
|
||
>
|
||
{renderScreenPreview()}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}, [renderScreenPreview, selectedScreen]);
|
||
|
||
return preview;
|
||
}
|