import React from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Check, ChevronRight, ShieldCheck, ShoppingBag } from 'lucide-react'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Checkbox } from '@tamagui/checkbox'; import toast from 'react-hot-toast'; import { MobileShell } from './components/MobileShell'; import { MobileCard, CTAButton, PillBadge, SkeletonCard } from './components/Primitives'; import { useAdminTheme } from './theme'; import { getPackages, createTenantPaddleCheckout, Package } from '../api'; import { getApiErrorMessage } from '../lib/apiError'; import { useQuery } from '@tanstack/react-query'; export default function MobilePackageShopPage() { const { t } = useTranslation('management'); const navigate = useNavigate(); const { textStrong, muted, border, primary, surface, accentSoft } = useAdminTheme(); const [selectedPackage, setSelectedPackage] = React.useState(null); const { data: packages, isLoading } = useQuery({ queryKey: ['packages', 'endcustomer'], queryFn: () => getPackages('endcustomer'), }); if (isLoading) { return ( ); } if (selectedPackage) { return ( setSelectedPackage(null)} /> ); } return ( {t('shop.subtitle', 'Choose a package to unlock more features and limits.')} {packages?.map((pkg) => ( setSelectedPackage(pkg)} /> ))} ); } function PackageShopCard({ pkg, onSelect }: { pkg: Package; onSelect: () => void }) { const { textStrong, muted, border, primary, accentSoft } = useAdminTheme(); const { t } = useTranslation('management'); // Parse features if they are stored as JSON strings or objects // The API type says Record, but let's be safe const features = pkg.features; return ( {pkg.name} {new Intl.NumberFormat(undefined, { style: 'currency', currency: 'EUR' }).format(pkg.price)} {pkg.max_photos ? ( ) : ( )} {pkg.gallery_days ? ( ) : null} ); } function FeatureRow({ label }: { label: string }) { const { textStrong, primary } = useAdminTheme(); return ( {label} ) } function CheckoutConfirmation({ pkg, onCancel }: { pkg: Package; onCancel: () => void }) { const { t } = useTranslation('management'); const { textStrong, muted, border, primary, danger } = useAdminTheme(); const [agbAccepted, setAgbAccepted] = React.useState(false); const [withdrawalAccepted, setWithdrawalAccepted] = React.useState(false); const [busy, setBusy] = React.useState(false); const canProceed = agbAccepted && withdrawalAccepted; const handleCheckout = async () => { if (!canProceed || busy) return; setBusy(true); try { const { checkout_url } = await createTenantPaddleCheckout(pkg.id, { success_url: window.location.href, return_url: window.location.href, }); window.location.href = checkout_url; } catch (err) { toast.error(getApiErrorMessage(err, t('shop.errors.checkout', 'Checkout failed'))); setBusy(false); } }; return ( {t('shop.confirmSubtitle', 'You are upgrading to:')} {pkg.name} {new Intl.NumberFormat(undefined, { style: 'currency', currency: 'EUR' }).format(pkg.price)} {t('shop.legalTitle', 'Terms & Conditions')} setAgbAccepted(!!checked)} > setAgbAccepted(!agbAccepted)}> {t('shop.legal.agb', 'I agree to the Terms and Conditions and Privacy Policy.')} setWithdrawalAccepted(!!checked)} > setWithdrawalAccepted(!withdrawalAccepted)}> {t('shop.legal.withdrawal', 'I agree that the contract execution begins immediately and I lose my right of withdrawal.')} ); }