w-funnel/src/components/funnel/templates/CouponTemplate.tsx
2025-09-25 18:04:52 +02:00

188 lines
5.1 KiB
TypeScript

"use client";
import { useState } from "react";
import { LayoutQuestion } from "@/components/layout/LayoutQuestion/LayoutQuestion";
import type { LayoutQuestionProps } from "@/components/layout/LayoutQuestion/LayoutQuestion";
import type { ActionButtonProps } from "@/components/ui/ActionButton/ActionButton";
import type { BottomActionButtonProps } from "@/components/widgets/BottomActionButton/BottomActionButton";
import { Coupon } from "@/components/widgets/Coupon/Coupon";
import Typography from "@/components/ui/Typography/Typography";
import {
buildHeaderProgress,
buildTypographyProps,
shouldShowBackButton,
shouldShowHeader,
} from "@/lib/funnel/mappers";
import type { CouponScreenDefinition } from "@/lib/funnel/types";
interface CouponTemplateProps {
screen: CouponScreenDefinition;
onContinue: () => void;
canGoBack: boolean;
onBack: () => void;
defaultTexts?: { nextButton?: string; continueButton?: string };
}
export function CouponTemplate({
screen,
onContinue,
canGoBack,
onBack,
defaultTexts,
}: CouponTemplateProps) {
const [copiedCode, setCopiedCode] = useState<string | null>(null);
const showBackButton = shouldShowBackButton(screen.header, canGoBack);
const showHeader = shouldShowHeader(screen.header);
const handleCopyPromoCode = (code: string) => {
// Copy to clipboard
navigator.clipboard.writeText(code);
setCopiedCode(code);
// Reset copied state after 2 seconds
setTimeout(() => {
setCopiedCode(null);
}, 2000);
};
const actionButtonProps: ActionButtonProps | undefined = screen.bottomActionButton
? {
children: screen.bottomActionButton.text,
cornerRadius: screen.bottomActionButton.cornerRadius,
onClick: onContinue,
}
: {
children: defaultTexts?.continueButton || "Continue",
onClick: onContinue,
};
const bottomActionButtonProps: BottomActionButtonProps = {
actionButtonProps,
};
const layoutQuestionProps: Omit<LayoutQuestionProps, "children"> = {
headerProps: showHeader ? {
progressProps: buildHeaderProgress(screen.header?.progress),
onBack: showBackButton ? onBack : undefined,
showBackButton,
} : undefined,
title:
buildTypographyProps(screen.title, {
as: "h2",
defaults: {
font: "manrope",
weight: "bold",
align: "center",
},
}) ?? {
as: "h2",
children: screen.title.text,
},
subtitle: screen.subtitle ? buildTypographyProps(screen.subtitle, {
as: "p",
defaults: {
font: "inter",
weight: "medium",
color: "muted",
align: "center",
},
}) : undefined,
bottomActionButtonProps,
};
// Build coupon props from screen definition
const couponProps = {
title: buildTypographyProps(screen.coupon.title, {
as: "h3" as const,
defaults: {
font: "manrope",
weight: "bold",
color: "primary",
},
}) ?? {
as: "h3" as const,
children: screen.coupon.title.text,
},
offer: {
title: buildTypographyProps(screen.coupon.offer.title, {
as: "h3" as const,
defaults: {
font: "manrope",
weight: "black",
color: "card",
size: "4xl",
},
}) ?? {
as: "h3" as const,
children: screen.coupon.offer.title.text,
},
description: buildTypographyProps(screen.coupon.offer.description, {
as: "p" as const,
defaults: {
font: "inter",
weight: "semiBold",
color: "card",
},
}) ?? {
as: "p" as const,
children: screen.coupon.offer.description.text,
},
},
promoCode: buildTypographyProps(screen.coupon.promoCode, {
as: "span" as const,
defaults: {
font: "inter",
weight: "semiBold",
},
}) ?? {
as: "span" as const,
children: screen.coupon.promoCode.text,
},
footer: buildTypographyProps(screen.coupon.footer, {
as: "p" as const,
defaults: {
font: "inter",
weight: "medium",
color: "muted",
size: "sm",
},
}) ?? {
as: "p" as const,
children: screen.coupon.footer.text,
},
onCopyPromoCode: handleCopyPromoCode,
};
return (
<LayoutQuestion {...layoutQuestionProps}>
<div className="w-full flex flex-col items-center justify-center mt-[30px]">
{/* Coupon Widget */}
<div className="mb-8">
<Coupon {...couponProps} />
</div>
{/* Copy Success Message */}
{copiedCode && (
<div className="mb-4 p-3 bg-green-50 border border-green-200 rounded-lg">
<Typography
as="p"
size="sm"
color="success"
weight="medium"
align="center"
>
{screen.copiedMessage
? screen.copiedMessage.replace("{code}", copiedCode || "")
: `Промокод "${copiedCode}" скопирован!`
}
</Typography>
</div>
)}
</div>
</LayoutQuestion>
);
}