- Add‑on Checkout auf Transactions + Transaction‑ID speichern: app/Services/Addons/EventAddonCheckoutService.php
- Paket/Marketing Checkout auf Transactions: app/Services/Paddle/PaddleCheckoutService.php
- Gift‑Voucher Checkout: Customer anlegen/finden + Transactions: app/Services/GiftVouchers/
GiftVoucherCheckoutService.php
- Tests aktualisiert: tests/Feature/Tenant/EventAddonCheckoutTest.php, tests/Unit/PaddleCheckoutServiceTest.php,
tests/Unit/GiftVoucherCheckoutServiceTest.php
133 lines
4.8 KiB
TypeScript
133 lines
4.8 KiB
TypeScript
import React from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { CalendarDays, Sparkles, Users } from 'lucide-react';
|
|
import { YStack, XStack } from '@tamagui/stacks';
|
|
import { SizableText as Text } from '@tamagui/text';
|
|
import { OnboardingShell } from '../components/OnboardingShell';
|
|
import { MobileCard, CTAButton } from '../components/Primitives';
|
|
import { ADMIN_HOME_PATH, ADMIN_WELCOME_BASE_PATH, ADMIN_WELCOME_PACKAGES_PATH, ADMIN_WELCOME_SUMMARY_PATH, adminPath } from '../../constants';
|
|
import { getTenantPackagesOverview, trackOnboarding } from '../../api';
|
|
import { getSelectedPackageId } from '../lib/onboardingSelection';
|
|
|
|
export default function WelcomeEventPage() {
|
|
const navigate = useNavigate();
|
|
const { t } = useTranslation('onboarding');
|
|
const selectedId = getSelectedPackageId();
|
|
|
|
const { data: overview } = useQuery({
|
|
queryKey: ['mobile', 'onboarding', 'packages-overview'],
|
|
queryFn: () => getTenantPackagesOverview({ force: true }),
|
|
staleTime: 60_000,
|
|
});
|
|
|
|
const hasActivePackage =
|
|
Boolean(overview?.activePackage) || Boolean(overview?.packages?.some((pkg) => pkg.active));
|
|
const handleSkip = React.useCallback(() => {
|
|
void trackOnboarding('dismissed');
|
|
navigate(ADMIN_HOME_PATH);
|
|
}, [navigate]);
|
|
|
|
const backTarget = selectedId
|
|
? ADMIN_WELCOME_SUMMARY_PATH
|
|
: hasActivePackage
|
|
? ADMIN_WELCOME_BASE_PATH
|
|
: ADMIN_WELCOME_PACKAGES_PATH;
|
|
|
|
return (
|
|
<OnboardingShell
|
|
eyebrow={t('eventSetup.layout.eyebrow', 'Step 4')}
|
|
title={t('eventSetup.layout.title', 'Prepare your first event')}
|
|
subtitle={t(
|
|
'eventSetup.layout.subtitle',
|
|
'Fill in a few details, invite co-hosts, and open your guest gallery for the big day.',
|
|
)}
|
|
onBack={() => navigate(backTarget)}
|
|
onSkip={handleSkip}
|
|
skipLabel={t('layout.jumpToDashboard', 'Jump to dashboard')}
|
|
>
|
|
<MobileCard space="$3">
|
|
<Text fontSize="$sm" fontWeight="800">
|
|
{t('eventSetup.step.title', 'Event setup in minutes')}
|
|
</Text>
|
|
<Text fontSize="$sm" color="#6b7280">
|
|
{t(
|
|
'eventSetup.step.description',
|
|
'We guide you through name, date, mood, and tasks. Afterwards you can moderate photos and support guests live.',
|
|
)}
|
|
</Text>
|
|
<YStack space="$2">
|
|
<FeatureRow
|
|
icon={Sparkles}
|
|
title={t('eventSetup.tiles.story.title', 'Story & mood')}
|
|
body={t('eventSetup.tiles.story.copy', 'Pick imagery, colours, and emotion cards for your event.')}
|
|
/>
|
|
<FeatureRow
|
|
icon={Users}
|
|
title={t('eventSetup.tiles.team.title', 'Organise your team')}
|
|
body={t('eventSetup.tiles.team.copy', 'Invite moderators or photographers and assign roles.')}
|
|
/>
|
|
<FeatureRow
|
|
icon={CalendarDays}
|
|
title={t('eventSetup.tiles.launch.title', 'Prepare go-live')}
|
|
body={t('eventSetup.tiles.launch.copy', 'Create QR codes, test the gallery, and align the run of show.')}
|
|
/>
|
|
</YStack>
|
|
</MobileCard>
|
|
|
|
<MobileCard space="$2">
|
|
<Text fontSize="$sm" fontWeight="800">
|
|
{t('eventSetup.cta.heading', 'Ready for your first event?')}
|
|
</Text>
|
|
<Text fontSize="$sm" color="#6b7280">
|
|
{t(
|
|
'eventSetup.cta.description',
|
|
"You're switching to the event manager. Assign tasks, invite members, and test the gallery. You can always return to the welcome journey.",
|
|
)}
|
|
</Text>
|
|
<CTAButton label={t('eventSetup.cta.button', 'Create event')} onPress={() => navigate(adminPath('/mobile/events/new'))} />
|
|
</MobileCard>
|
|
|
|
<YStack space="$2">
|
|
<CTAButton
|
|
label={t('eventSetup.actions.dashboard.button', 'Open dashboard')}
|
|
tone="ghost"
|
|
onPress={() => navigate(ADMIN_HOME_PATH)}
|
|
/>
|
|
<CTAButton
|
|
label={t('eventSetup.actions.events.button', 'Open event list')}
|
|
tone="ghost"
|
|
onPress={() => navigate(adminPath('/mobile/events'))}
|
|
/>
|
|
</YStack>
|
|
</OnboardingShell>
|
|
);
|
|
}
|
|
|
|
function FeatureRow({
|
|
icon: Icon,
|
|
title,
|
|
body,
|
|
}: {
|
|
icon: React.ComponentType<{ size?: number; color?: string }>;
|
|
title: string;
|
|
body: string;
|
|
}) {
|
|
return (
|
|
<XStack alignItems="center" space="$2">
|
|
<XStack width={34} height={34} borderRadius={12} backgroundColor="#e0f2fe" alignItems="center" justifyContent="center">
|
|
<Icon size={16} color="#0284c7" />
|
|
</XStack>
|
|
<YStack>
|
|
<Text fontSize="$sm" fontWeight="700">
|
|
{title}
|
|
</Text>
|
|
<Text fontSize="$xs" color="#6b7280">
|
|
{body}
|
|
</Text>
|
|
</YStack>
|
|
</XStack>
|
|
);
|
|
}
|