// Copyright: (c) 2026 TWWIM UG. All rights reserved. import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Tag, CheckCircle2, AlertCircle, Users, Percent } from 'lucide-react'; import { PageLayout } from '@/components/shared'; import { useTranslation } from '@/i18n/TranslationProvider'; import { useRedeemCode } from './hooks/useRedeemCode'; import { useSubscription } from '@/features/subscription/hooks/useSubscription'; import { ActiveCampaignList } from '@/features/subscription/components/ActiveCampaignList'; import type { RedeemCodeResponse } from '@archer/api-interface/schemas/customer-api/response'; const codeSchema = z.object({ code: z.string().min(3).max(30).regex(/^[A-Z0-9_-]+$/i, 'Code must be alphanumeric (A-Z, 0-9, _, -)'), }); type CodeForm = z.infer; export function PromotionsPage() { const { t, locale } = useTranslation(); const redeemCode = useRedeemCode(); const { data: subscription } = useSubscription(); const [result, setResult] = useState(null); const activeCampaigns = subscription?.activeCampaigns ?? []; const { register, handleSubmit, formState: { errors }, reset } = useForm({ resolver: zodResolver(codeSchema), }); const onSubmit = (data: CodeForm) => { setResult(null); redeemCode.mutate(data.code, { onSuccess: (res) => { setResult(res); reset(); }, }); }; const errorMessage = redeemCode.error ? extractErrorMessage(redeemCode.error, t) : null; return ( {/* Code Input */}
{errors.code && (

{errors.code.message}

)}
{/* Error */} {errorMessage && (

{errorMessage}

)} {/* Success Result */} {result && }
{/* Active Campaigns */}
{activeCampaigns.length === 0 && (

{t('subscription.noCampaigns')}

)}
); } function RedeemResult({ result, locale, t }: { result: RedeemCodeResponse; locale: string; t: (key: string, params?: Record) => string }) { const isReferral = result.type === 'referral'; const Icon = isReferral ? Users : Percent; const campaignName = result.campaignName?.[locale] ?? result.campaignName?.['en'] ?? ''; return (
{isReferral ? t('promotions.success.referral') : t('promotions.success.promo')}
{isReferral && result.partnerName && ( {t('promotions.linkedToPartner', { name: result.partnerName })} )} {campaignName && ( {campaignName} {result.value !== undefined && result.valueUnit && ( ({formatValue(result.value, result.valueUnit, t)}) )} )}
{result.appliedEffect.kind !== 'none' && (

{t(`promotions.effect.${result.appliedEffect.kind}`)}

)}
); } function formatValue(value: number, unit: string, t: (key: string, params?: Record) => string): string { switch (unit) { case 'percentage': return t('subscription.campaignDiscount', { value }); case 'fixed_amount': return `${value} EUR`; case 'count': return t('subscription.campaignCapBoost', { value }); default: return `${value}`; } } function extractErrorMessage(error: unknown, t: (key: string) => string): string { const msg = error instanceof Error ? error.message : ''; if (msg.includes('already linked')) return t('promotions.error.alreadyReferred'); if (msg.includes('not found') || msg.includes('Invalid code')) return t('promotions.error.invalidCode'); if (msg.includes('not active')) return t('promotions.error.inactive'); if (msg.includes('expired')) return t('promotions.error.expired'); return t('promotions.error.generic'); }