- Wired the checkout wizard for Google “comfort login”: added Socialite controller + dependency, new Google env

hooks in config/services.php/.env.example, and updated wizard steps/controllers to store session payloads,
attach packages, and surface localized success/error states.
- Retooled payment handling for both Stripe and PayPal, adding richer status management in CheckoutController/
PayPalController, fallback flows in the wizard’s PaymentStep.tsx, and fresh feature tests for intent
creation, webhooks, and the wizard CTA.
- Introduced a consent-aware Matomo analytics stack: new consent context, cookie-banner UI, useAnalytics/
useCtaExperiment hooks, and MatomoTracker component, then instrumented marketing pages (Home, Packages,
Checkout) with localized copy and experiment tracking.
- Polished package presentation across marketing UIs by centralizing formatting in PresentsPackages, surfacing
localized description tables/placeholders, tuning badges/layouts, and syncing guest/marketing translations.
- Expanded docs & reference material (docs/prp/*, TODOs, public gallery overview) and added a Playwright smoke
test for the hero CTA while reconciling outstanding checklist items.
This commit is contained in:
Codex Agent
2025-10-19 11:41:03 +02:00
parent ae9b9160ac
commit a949c8d3af
113 changed files with 5169 additions and 712 deletions

View File

@@ -1,14 +1,12 @@
import React, { useCallback } from 'react';
import React from 'react';
import { Link } from '@inertiajs/react';
import { useTranslation } from 'react-i18next';
import { usePage } from '@inertiajs/react';
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
import { useAppearance } from '@/hooks/use-appearance';
import { useConsent } from '@/contexts/consent';
const Footer: React.FC = () => {
const { t } = useTranslation(['marketing', 'legal']);
const { t } = useTranslation(['marketing', 'legal', 'common']);
const { openPreferences } = useConsent();
return (
@@ -36,6 +34,15 @@ const Footer: React.FC = () => {
<li><Link href="/datenschutz" className="hover:text-pink-500 transition-colors">{t('legal:datenschutz')}</Link></li>
<li><Link href="/agb" className="hover:text-pink-500 transition-colors">{t('legal:agb')}</Link></li>
<li><Link href="/kontakt" className="hover:text-pink-500 transition-colors">{t('marketing:nav.contact')}</Link></li>
<li>
<button
type="button"
onClick={openPreferences}
className="hover:text-pink-500 transition-colors"
>
{t('common:consent.footer.manage_link')}
</button>
</li>
</ul>
</div>

View File

@@ -119,7 +119,7 @@ const Header: React.FC = () => {
<div className="container mx-auto px-4 py-4">
<div className="flex items-center justify-between">
<Link href={localizedPath('/')} className="flex items-center gap-4">
<img src="logo-transparent-md.png" alt="FotoSpiel.App Logo" className="h-12 w-auto" />
<img src="/logo-transparent-md.png" alt="FotoSpiel.App Logo" className="h-12 w-auto" />
<span className="text-2xl font-bold font-display text-pink-500">
FotoSpiel.App
</span>

View File

@@ -1,7 +1,8 @@
import React, { useEffect } from 'react';
import { Head, Link, usePage, router } from '@inertiajs/react';
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
import { Head, usePage, router } from '@inertiajs/react';
import { useTranslation } from 'react-i18next';
import MatomoTracker, { MatomoConfig } from '@/components/analytics/MatomoTracker';
import CookieBanner from '@/components/consent/CookieBanner';
interface MarketingLayoutProps {
children: React.ReactNode;
@@ -9,12 +10,15 @@ interface MarketingLayoutProps {
}
const MarketingLayout: React.FC<MarketingLayoutProps> = ({ children, title }) => {
const page = usePage<{ translations?: Record<string, Record<string, string>> }>();
const page = usePage<{
translations?: Record<string, Record<string, string>>;
locale?: string;
analytics?: { matomo?: MatomoConfig };
}>();
const { url } = page;
const { t } = useTranslation('marketing');
const i18n = useTranslation();
const { locale } = usePage().props as any;
const { localizedPath } = useLocalizedRoutes();
const { locale, analytics } = page.props;
useEffect(() => {
if (locale && i18n.i18n.language !== locale) {
@@ -61,6 +65,8 @@ const MarketingLayout: React.FC<MarketingLayoutProps> = ({ children, title }) =>
<link rel="canonical" href={canonicalUrl} />
<link rel="alternate" hrefLang="x-default" href="https://fotospiel.app/" />
</Head>
<MatomoTracker config={analytics?.matomo} />
<CookieBanner />
<div className="min-h-screen bg-white">
<header className="bg-white shadow-sm">
<div className="container mx-auto px-4 py-4">