- 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,4 +1,4 @@
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Page } from './_util';
import { useParams, useSearchParams } from 'react-router-dom';
import { usePollGalleryDelta } from '../polling/usePollGalleryDelta';
@@ -12,8 +12,8 @@ import PhotoLightbox from './PhotoLightbox';
import { fetchEvent, getEventPackage, fetchStats, type EventData, type EventPackage, type EventStats } from '../services/eventApi';
export default function GalleryPage() {
const { token: slug } = useParams<{ token?: string }>();
const { photos, loading, newCount, acknowledgeNew } = usePollGalleryDelta(slug ?? '');
const { token } = useParams<{ token?: string }>();
const { photos, loading, newCount, acknowledgeNew } = usePollGalleryDelta(token ?? '');
const [filter, setFilter] = React.useState<GalleryFilter>('latest');
const [currentPhotoIndex, setCurrentPhotoIndex] = React.useState<number | null>(null);
const [hasOpenedPhoto, setHasOpenedPhoto] = useState(false);
@@ -38,15 +38,15 @@ export default function GalleryPage() {
// Load event and package info
useEffect(() => {
if (!slug) return;
if (!token) return;
const loadEventData = async () => {
try {
setEventLoading(true);
const [eventData, packageData, statsData] = await Promise.all([
fetchEvent(slug),
getEventPackage(slug),
fetchStats(slug),
fetchEvent(token),
getEventPackage(token),
fetchStats(token),
]);
setEvent(eventData);
setEventPackage(packageData);
@@ -59,7 +59,7 @@ export default function GalleryPage() {
};
loadEventData();
}, [slug]);
}, [token]);
const myPhotoIds = React.useMemo(() => {
try {
@@ -99,7 +99,7 @@ export default function GalleryPage() {
}
}
if (!slug) {
if (!token) {
return <Page title="Galerie"><p>Event nicht gefunden.</p></Page>;
}
@@ -236,7 +236,7 @@ export default function GalleryPage() {
currentIndex={currentPhotoIndex}
onClose={() => setCurrentPhotoIndex(null)}
onIndexChange={(index: number) => setCurrentPhotoIndex(index)}
slug={slug}
token={token}
/>
)}
</Page>