- 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:
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user