import React, { useState, useEffect, useMemo } from 'react'; import { Head, Link, usePage } from '@inertiajs/react'; import { useTranslation } from 'react-i18next'; import type { TFunction } from 'i18next'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; import { cn } from '@/lib/utils'; import MarketingLayout from '@/layouts/mainWebsite'; import { useAnalytics } from '@/hooks/useAnalytics'; import { useCtaExperiment } from '@/hooks/useCtaExperiment'; import { ArrowRight, ShoppingCart, Check, X, Users, Image, Shield, Star, Sparkles } from 'lucide-react'; interface Package { id: number; name: string; slug: string; description: string; description_breakdown: DescriptionEntry[]; gallery_duration_label?: string; price: number; events: number | null; features: string[]; max_events_per_year?: number | null; limits?: { max_photos?: number; max_guests?: number; max_tenants?: number; max_events_per_year?: number; gallery_days?: number; }; watermark_allowed?: boolean; branding_allowed?: boolean; } type DescriptionEntry = { title?: string | null; value: string; }; interface PackagesProps { endcustomerPackages: Package[]; resellerPackages: Package[]; } const Packages: React.FC = ({ endcustomerPackages, resellerPackages }) => { const [open, setOpen] = useState(false); const [selectedPackage, setSelectedPackage] = useState(null); const [currentStep, setCurrentStep] = useState<'overview' | 'deep' | 'testimonials'>('overview'); const { props } = usePage(); const { auth } = props as any; const { t } = useTranslation('marketing'); const { t: tCommon } = useTranslation('common'); const { variant: packagesHeroVariant, trackClick: trackPackagesHeroClick, } = useCtaExperiment('packages_hero_cta'); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const packageId = urlParams.get('package_id'); if (packageId) { const id = parseInt(packageId); const pkg = [...endcustomerPackages, ...resellerPackages].find(p => p.id === id); if (pkg) { setSelectedPackage(pkg); setOpen(true); setCurrentStep('overview'); } } }, [endcustomerPackages, resellerPackages]); const testimonials = [ { name: tCommon('testimonials.anna.name'), text: t('packages.testimonials.anna'), rating: 5 }, { name: tCommon('testimonials.max.name'), text: t('packages.testimonials.max'), rating: 5 }, { name: tCommon('testimonials.lisa.name'), text: t('packages.testimonials.lisa'), rating: 5 }, ]; const allPackages = [...endcustomerPackages, ...resellerPackages]; const selectHighlightPackageId = (packages: Package[]): number | null => { const count = packages.length; if (count <= 1) { return null; } const sortedByPrice = [...packages].sort((a, b) => a.price - b.price); if (count === 2) { return sortedByPrice[1]?.id ?? null; } if (count === 3) { return sortedByPrice[1]?.id ?? null; } return sortedByPrice[count - 2]?.id ?? null; }; const highlightEndcustomerId = useMemo( () => selectHighlightPackageId(endcustomerPackages), [endcustomerPackages], ); const highlightResellerId = useMemo( () => selectHighlightPackageId(resellerPackages), [resellerPackages], ); function isHighlightedPackage(pkg: Package, variant: 'endcustomer' | 'reseller') { return variant === 'reseller' ? pkg.id === highlightResellerId : pkg.id === highlightEndcustomerId; } const selectedVariant = useMemo<'endcustomer' | 'reseller'>(() => { if (!selectedPackage) return 'endcustomer'; return resellerPackages.some((pkg) => pkg.id === selectedPackage.id) ? 'reseller' : 'endcustomer'; }, [selectedPackage, resellerPackages]); const selectedHighlight = selectedPackage ? isHighlightedPackage(selectedPackage, selectedVariant) : false; const { trackEvent } = useAnalytics(); const handleCardClick = (pkg: Package, variant: 'endcustomer' | 'reseller') => { trackEvent({ category: 'marketing_packages', action: 'open_dialog', name: `${variant}:${pkg.name}`, value: pkg.price, }); setSelectedPackage(pkg); setCurrentStep('overview'); setOpen(true); }; const handleCtaClick = (pkg: Package, variant: 'endcustomer' | 'reseller') => { trackEvent({ category: 'marketing_packages', action: 'cta_dialog', name: `${variant}:${pkg.name}`, value: pkg.price, }); }; // nextStep entfernt, da Tabs nun parallel sind const getFeatureIcon = (feature: string) => { switch (feature) { case 'basic_uploads': return ; case 'unlimited_sharing': return ; case 'no_watermark': return ; case 'custom_tasks': return ; case 'advanced_analytics': return ; case 'priority_support': return ; case 'reseller_dashboard': return ; case 'custom_branding': return ; default: return ; } }; const getAccentTheme = (variant: 'endcustomer' | 'reseller') => ( variant === 'reseller' ? { gradient: 'from-amber-100/80 via-white to-white', ring: 'ring-amber-200 dark:ring-amber-500/40', badge: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-100', price: 'text-amber-500 dark:text-amber-300', buttonHighlight: 'bg-gradient-to-r from-amber-500 via-rose-400 to-pink-500 text-white hover:from-amber-500/95 hover:via-rose-400/95 hover:to-pink-500/95', buttonDefault: 'bg-gradient-to-r from-amber-50 via-white to-rose-50 text-amber-600 border border-amber-100/80 shadow-sm hover:from-amber-100 hover:via-rose-50 hover:to-white hover:text-amber-600 dark:from-amber-500/20 dark:via-amber-500/10 dark:to-rose-500/20 dark:text-amber-200 dark:border-amber-500/30', highlightShadow: 'shadow-[0_28px_65px_-20px_rgba(245,158,11,0.55)]', topBar: 'from-amber-400 via-rose-300 to-pink-400', ctaShadow: 'shadow-lg shadow-amber-500/25', } : { gradient: 'from-rose-100/80 via-white to-white', ring: 'ring-rose-200 dark:ring-rose-500/40', badge: 'bg-rose-100 text-rose-700 dark:bg-rose-500/20 dark:text-rose-100', price: 'text-rose-500 dark:text-rose-300', buttonHighlight: 'bg-gradient-to-r from-rose-500 via-pink-500 to-amber-400 text-white hover:from-rose-500/95 hover:via-pink-500/95 hover:to-amber-400/95', buttonDefault: 'bg-gradient-to-r from-rose-50 via-white to-pink-50 text-rose-600 border border-rose-100/80 shadow-sm hover:from-rose-100 hover:via-white hover:to-pink-100 hover:text-rose-600 dark:from-rose-500/15 dark:via-rose-500/10 dark:to-rose-500/20 dark:text-rose-200 dark:border-rose-500/30', highlightShadow: 'shadow-[0_28px_70px_-25px_rgba(244,63,94,0.55)]', topBar: 'from-rose-500 via-pink-400 to-amber-300', ctaShadow: 'shadow-lg shadow-rose-500/30', } ); type PackageMetric = { key: string; label: string; value: string; }; const resolvePackageMetrics = ( pkg: Package, variant: 'endcustomer' | 'reseller', t: TFunction, tCommon: TFunction, ): PackageMetric[] => { if (variant === 'reseller') { return [ { key: 'max_tenants', label: t('packages.max_tenants'), value: pkg.limits?.max_tenants ? pkg.limits.max_tenants.toLocaleString() : tCommon('unlimited'), }, { key: 'max_events_per_year', label: t('packages.max_events_year'), value: pkg.limits?.max_events_per_year ? pkg.limits.max_events_per_year.toLocaleString() : tCommon('unlimited'), }, { key: 'branding', label: t('packages.feature_custom_branding'), value: pkg.branding_allowed ? tCommon('included') : t('packages.feature_no_branding'), }, ]; } return [ { key: 'max_photos', label: t('packages.max_photos_label'), value: pkg.limits?.max_photos ? pkg.limits.max_photos.toLocaleString() : tCommon('unlimited'), }, { key: 'max_guests', label: t('packages.max_guests_label'), value: pkg.limits?.max_guests ? pkg.limits.max_guests.toLocaleString() : tCommon('unlimited'), }, { key: 'gallery_days', label: t('packages.gallery_days_label'), value: pkg.gallery_duration_label ?? (pkg.limits?.gallery_days ? pkg.limits.gallery_days.toLocaleString() : tCommon('unlimited')), }, ]; }; interface PackageCardProps { pkg: Package; variant: 'endcustomer' | 'reseller'; highlight?: boolean; onSelect?: (pkg: Package) => void; className?: string; showCTA?: boolean; ctaLabel?: string; compact?: boolean; } function PackageCard({ pkg, variant, highlight = false, onSelect, className, showCTA = true, ctaLabel, compact = false, }: PackageCardProps) { const { t } = useTranslation('marketing'); const { t: tCommon } = useTranslation('common'); const accent = getAccentTheme(variant); const priceLabel = pkg.price === 0 ? t('packages.free') : `${pkg.price.toLocaleString()} ${t('packages.currency.euro')}`; const cadenceLabel = variant === 'reseller' ? t('packages.billing_per_year') : t('packages.billing_per_event'); const typeLabel = variant === 'reseller' ? t('packages.subscription') : t('packages.one_time'); const badgeLabel = highlight ? (variant === 'reseller' ? t('packages.badge_best_value') : t('packages.badge_most_popular')) : pkg.price === 0 ? t('packages.badge_starter') : null; const featureBadges = pkg.features.slice(0, 4); const extraFeatureCount = Math.max(pkg.features.length - featureBadges.length, 0); const metrics = resolvePackageMetrics(pkg, variant, t, tCommon); return (
{typeLabel} {badgeLabel && ( {highlight && } {badgeLabel} )}
{pkg.name} {pkg.description}
{priceLabel} {pkg.price !== 0 && ( / {cadenceLabel} )}
{variant === 'endcustomer' && (

{pkg.events} × {t('packages.one_time')}

)}
{featureBadges.map((feature) => ( {getFeatureIcon(feature)} {t(`packages.feature_${feature}`)} ))} {pkg.watermark_allowed === false && ( {t('packages.no_watermark')} )} {pkg.branding_allowed && ( {t('packages.custom_branding')} )} {extraFeatureCount > 0 && ( {t('packages.more_features', { count: extraFeatureCount })} )}
{metrics.map((metric) => (

{metric.value}

{metric.label}

))}
{showCTA && onSelect && ( )} ); } return ( {/* Hero Section */}

{t('packages.hero_title')}

{t('packages.hero_description')}

{ trackPackagesHeroClick(); trackEvent({ category: 'marketing_packages', action: 'hero_cta', name: `endcustomer:${packagesHeroVariant}`, }); }} className={cn( 'rounded-full px-8 py-4 text-lg font-semibold font-sans-marketing transition duration-300', packagesHeroVariant === 'gradient' ? 'bg-gradient-to-r from-rose-500 via-pink-500 to-amber-400 text-white shadow-lg shadow-rose-500/40 hover:from-rose-500/95 hover:via-pink-500/95 hover:to-amber-400/95' : 'bg-white text-[#FFB6C1] hover:bg-gray-100 dark:bg-gray-800 dark:text-rose-200 dark:hover:bg-gray-700', )} > {packagesHeroVariant === 'gradient' ? t('packages.cta_explore_highlight') : t('packages.cta_explore')}

{t('packages.section_endcustomer')}

{endcustomerPackages.map((pkg) => ( handleCardClick(pkg, 'endcustomer')} /> ))}
{/* Comparison Section for Endcustomer */}

{t('packages.comparison_title')}

{t('packages.price')}
{endcustomerPackages.map((pkg) => (

{pkg.name}

{pkg.price === 0 ? t('packages.free') : `${pkg.price} ${t('packages.currency.euro')}`}

))}
{t('packages.max_photos_label')} {getFeatureIcon('max_photos')}
{endcustomerPackages.map((pkg) => (

{pkg.name}

{pkg.limits?.max_photos || tCommon('unlimited')}

))}
{t('packages.max_guests_label')} {getFeatureIcon('max_guests')}
{endcustomerPackages.map((pkg) => (

{pkg.name}

{pkg.limits?.max_guests || tCommon('unlimited')}

))}
{t('packages.gallery_days_label')} {getFeatureIcon('gallery_days')}
{endcustomerPackages.map((pkg) => (

{pkg.name}

{pkg.limits?.gallery_days || tCommon('unlimited')}

))}
{t('packages.watermark_label')} {getFeatureIcon('no_watermark')}
{endcustomerPackages.map((pkg) => (

{pkg.name}

{pkg.watermark_allowed === false ? : }
))}
{t('packages.feature')} {endcustomerPackages.map((pkg) => ( {pkg.name} ))} {t('packages.price')} {endcustomerPackages.map((pkg) => ( {pkg.price === 0 ? t('packages.free') : `${pkg.price} ${t('packages.currency.euro')}`} ))} {t('packages.max_photos_label')} {getFeatureIcon('max_photos')} {endcustomerPackages.map((pkg) => ( {pkg.limits?.max_photos || tCommon('unlimited')} ))} {t('packages.max_guests_label')} {getFeatureIcon('max_guests')} {endcustomerPackages.map((pkg) => ( {pkg.limits?.max_guests || tCommon('unlimited')} ))} {t('packages.gallery_days_label')} {getFeatureIcon('gallery_days')} {endcustomerPackages.map((pkg) => ( {pkg.limits?.gallery_days || tCommon('unlimited')} ))} {t('packages.watermark_label')} {getFeatureIcon('no_watermark')} {endcustomerPackages.map((pkg) => ( {pkg.watermark_allowed === false ? : } ))}

{t('packages.section_reseller')}

{resellerPackages.map((pkg) => ( handleCardClick(pkg, 'reseller')} /> ))}
{/* FAQ Section */}

{t('packages.faq_title')}

{t('packages.faq_free')}

{t('packages.faq_free_desc')}

{t('packages.faq_upgrade')}

{t('packages.faq_upgrade_desc')}

{t('packages.faq_reseller')}

{t('packages.faq_reseller_desc')}

{t('packages.faq_payment')}

{t('packages.faq_payment_desc')}

{/* Modal */} {selectedPackage && (
{selectedVariant === 'reseller' ? t('packages.subscription') : t('packages.one_time')} {selectedHighlight && ( {selectedVariant === 'reseller' ? t('packages.badge_best_value') : t('packages.badge_most_popular')} )}
{selectedPackage.name}
{selectedPackage.price === 0 ? t('packages.free') : `${selectedPackage.price.toLocaleString()} ${t('packages.currency.euro')}`} {selectedPackage.price !== 0 && ( / {selectedVariant === 'reseller' ? t('packages.billing_per_year') : t('packages.billing_per_event')} )}
{selectedPackage.description && (

{selectedPackage.description}

)}
{t('packages.details')} {t('packages.more_details_tab')} {t('packages.customer_opinions')} {(() => { const accent = getAccentTheme(selectedVariant); const metrics = resolvePackageMetrics(selectedPackage, selectedVariant, t, tCommon); const topFeatureBadges = selectedPackage.features.slice(0, 3); const hasMoreFeatures = selectedPackage.features.length > topFeatureBadges.length; const quickFacts = metrics.slice(0, 2); const showDeepLink = hasMoreFeatures || (selectedPackage.description_breakdown?.length ?? 0) > 0; return (
{t('packages.feature_highlights')}
{topFeatureBadges.map((feature) => ( {getFeatureIcon(feature)} {t(`packages.feature_${feature}`)} ))} {selectedPackage.watermark_allowed === false && ( {t('packages.no_watermark')} )} {selectedPackage.branding_allowed && ( {t('packages.custom_branding')} )}
{showDeepLink && ( )}

{t('packages.order_hint')}

{t('packages.quick_facts')}

{t('packages.quick_facts_hint')}

    {quickFacts.map((metric) => (
  • {metric.value}

    {metric.label}

  • ))}
{showDeepLink && ( )}
); })()} {(() => { const accent = getAccentTheme(selectedVariant); const metrics = resolvePackageMetrics(selectedPackage, selectedVariant, t, tCommon); const descriptionEntries = selectedPackage.description_breakdown ?? []; const entriesWithTitle = descriptionEntries.filter((entry) => entry.title); const entriesWithoutTitle = descriptionEntries.filter((entry) => !entry.title); return (
{t('packages.features_label')} {selectedHighlight && ( {t('packages.badge_deep_dive')} )}
{selectedPackage.features.map((feature) => ( {getFeatureIcon(feature)} {t(`packages.feature_${feature}`)} ))} {selectedPackage.watermark_allowed === false && ( {t('packages.no_watermark')} )} {selectedPackage.branding_allowed && ( {t('packages.custom_branding')} )}
{metrics.length > 0 && (

{t('packages.limits_label')}

{t('packages.limits_label_hint')}

{metrics.map((metric) => (

{metric.value}

{metric.label}

))}
)} {descriptionEntries.length > 0 && (

{t('packages.breakdown_label')}

{t('packages.breakdown_label_hint')}

{entriesWithTitle.length > 0 && ( {entriesWithTitle.map((entry, index) => ( {entry.title} {entry.value} ))} )} {entriesWithoutTitle.length > 0 && (
{entriesWithoutTitle.map((entry, index) => (
{entry.value}
))}
)}
)}
); })()}

{t('packages.what_customers_say')}

{testimonials.map((testimonial, index) => (

“{testimonial.text}”

{testimonial.name}
{[...Array(testimonial.rating)].map((_, i) => ( ))}
))}
)} {/* Testimonials Section entfernt, da nun im Dialog */}
); }; Packages.layout = (page: React.ReactNode) => page; export default Packages;