neues Admin UI Layout eingeführt. Alle Tests auf den neusten Stand gebracht.

This commit is contained in:
Codex Agent
2025-12-30 10:24:06 +01:00
parent 902e78cae9
commit efe2f25b3e
85 changed files with 95235 additions and 19197 deletions

View File

@@ -10,6 +10,7 @@ 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';
import { ADMIN_COLORS } from '../theme';
export default function WelcomeEventPage() {
const navigate = useNavigate();
@@ -51,7 +52,7 @@ export default function WelcomeEventPage() {
<Text fontSize="$sm" fontWeight="800">
{t('eventSetup.step.title', 'Event setup in minutes')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{t(
'eventSetup.step.description',
'We guide you through name, date, mood, and tasks. Afterwards you can moderate photos and support guests live.',
@@ -80,7 +81,7 @@ export default function WelcomeEventPage() {
<Text fontSize="$sm" fontWeight="800">
{t('eventSetup.cta.heading', 'Ready for your first event?')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{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.",
@@ -116,14 +117,21 @@ function FeatureRow({
}) {
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
width={34}
height={34}
borderRadius={12}
backgroundColor={ADMIN_COLORS.accentSoft}
alignItems="center"
justifyContent="center"
>
<Icon size={16} color={ADMIN_COLORS.primary} />
</XStack>
<YStack>
<Text fontSize="$sm" fontWeight="700">
{title}
</Text>
<Text fontSize="$xs" color="#6b7280">
<Text fontSize="$xs" color={ADMIN_COLORS.textMuted}>
{body}
</Text>
</YStack>

View File

@@ -15,6 +15,7 @@ import {
ADMIN_WELCOME_PACKAGES_PATH,
adminPath,
} from '../../constants';
import { ADMIN_COLORS } from '../theme';
export default function WelcomeLandingPage() {
const navigate = useNavigate();
@@ -50,7 +51,7 @@ export default function WelcomeLandingPage() {
<Text fontSize="$lg" fontWeight="900">
{t('hero.title', 'Design the next Fotospiel experience')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{t(
'hero.description',
'In just a few steps you guide guests through a magical photo journey complete with storytelling, tasks, and a moderated gallery.',
@@ -117,8 +118,15 @@ function FeatureCard({
<MobileCard space="$2">
<XStack alignItems="center" justifyContent="space-between">
<XStack alignItems="center" space="$2">
<XStack width={36} height={36} borderRadius={12} backgroundColor="#e0f2fe" alignItems="center" justifyContent="center">
<Icon size={18} color="#0284c7" />
<XStack
width={36}
height={36}
borderRadius={12}
backgroundColor={ADMIN_COLORS.accentSoft}
alignItems="center"
justifyContent="center"
>
<Icon size={18} color={ADMIN_COLORS.primary} />
</XStack>
<Text fontSize="$sm" fontWeight="800">
{title}
@@ -126,7 +134,7 @@ function FeatureCard({
</XStack>
{badge ? <PillBadge tone="muted">{badge}</PillBadge> : null}
</XStack>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{body}
</Text>
</MobileCard>

View File

@@ -11,10 +11,12 @@ import { MobileCard, CTAButton, PillBadge } from '../components/Primitives';
import { getPackages, getTenantPackagesOverview, Package, trackOnboarding } from '../../api';
import { ADMIN_WELCOME_BASE_PATH, ADMIN_WELCOME_EVENT_PATH, ADMIN_WELCOME_SUMMARY_PATH, adminPath } from '../../constants';
import { getSelectedPackageId, setSelectedPackageId } from '../lib/onboardingSelection';
import { useAdminTheme } from '../theme';
export default function WelcomePackagesPage() {
const navigate = useNavigate();
const { t } = useTranslation('onboarding');
const { muted } = useAdminTheme();
const [selectedId, setSelectedId] = React.useState<number | null>(() => getSelectedPackageId());
const { data: overview } = useQuery({
@@ -60,7 +62,7 @@ export default function WelcomePackagesPage() {
>
{isLoading ? (
<MobileCard>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={muted}>
{t('packages.state.loading', 'Loading packages …')}
</Text>
</MobileCard>
@@ -69,7 +71,7 @@ export default function WelcomePackagesPage() {
<Text fontSize="$sm" fontWeight="700">
{t('packages.state.errorTitle', 'Failed to load')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={muted}>
{t('packages.state.errorDescription', 'Please try again or contact support.')}
</Text>
</MobileCard>
@@ -78,7 +80,7 @@ export default function WelcomePackagesPage() {
<Text fontSize="$sm" fontWeight="700">
{t('packages.state.emptyTitle', 'Catalogue is empty')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={muted}>
{t('packages.state.emptyDescription', 'No packages are currently available. Reach out to support to enable new offers.')}
</Text>
</MobileCard>
@@ -99,7 +101,7 @@ export default function WelcomePackagesPage() {
<Text fontSize="$sm" fontWeight="800">
{t('packages.step.title', 'Activate the right plan')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={muted}>
{t('packages.step.description', 'Secure capacity for your next event. Upgrade at any time only pay for what you need.')}
</Text>
</MobileCard>
@@ -132,6 +134,7 @@ function PackageCard({
onSelect: () => void;
}) {
const { t } = useTranslation('onboarding');
const { primary, border, accentSoft, muted } = useAdminTheme();
const badges = [
t('packages.card.badges.photos', { count: pkg.max_photos ?? t('summary.details.infinity', '∞') }),
t('packages.card.badges.guests', { count: pkg.max_guests ?? t('summary.details.infinity', '∞') }),
@@ -140,17 +143,17 @@ function PackageCard({
return (
<Pressable onPress={onSelect}>
<MobileCard borderColor={selected ? '#2563eb' : '#e5e7eb'} space="$2">
<MobileCard borderColor={selected ? primary : border} space="$2">
<XStack alignItems="center" justifyContent="space-between">
<XStack alignItems="center" space="$2">
<XStack width={36} height={36} borderRadius={12} backgroundColor="#e0f2fe" alignItems="center" justifyContent="center">
<PackageIcon size={18} color="#0ea5e9" />
<XStack width={36} height={36} borderRadius={12} backgroundColor={accentSoft} alignItems="center" justifyContent="center">
<PackageIcon size={18} color={primary} />
</XStack>
<YStack>
<Text fontSize="$sm" fontWeight="800">
{pkg.name}
</Text>
<Text fontSize="$xs" color="#6b7280">
<Text fontSize="$xs" color={muted}>
{t('packages.card.description', 'Ready for your next event right away.')}
</Text>
</YStack>
@@ -168,8 +171,8 @@ function PackageCard({
</XStack>
{selected ? (
<XStack alignItems="center" space="$1">
<Check size={14} color="#2563eb" />
<Text fontSize="$xs" color="#2563eb" fontWeight="700">
<Check size={14} color={primary} />
<Text fontSize="$xs" color={primary} fontWeight="700">
{t('packages.card.selected', 'Selected')}
</Text>
</XStack>

View File

@@ -10,6 +10,7 @@ import { MobileCard, CTAButton, PillBadge } from '../components/Primitives';
import { getPackages, getTenantPackagesOverview } from '../../api';
import { ADMIN_WELCOME_BASE_PATH, ADMIN_WELCOME_EVENT_PATH, ADMIN_WELCOME_PACKAGES_PATH, adminPath } from '../../constants';
import { getSelectedPackageId } from '../lib/onboardingSelection';
import { ADMIN_COLORS } from '../theme';
type SummaryPackage = {
id: number;
@@ -78,7 +79,7 @@ export default function WelcomeSummaryPage() {
>
{loading ? (
<MobileCard>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{t('summary.state.loading', 'Checking available packages …')}
</Text>
</MobileCard>
@@ -87,7 +88,7 @@ export default function WelcomeSummaryPage() {
<Text fontSize="$sm" fontWeight="800">
{t('summary.state.missingTitle', 'No package selected')}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{t('summary.state.missingDescription', 'Select a package first or refresh if data changed.')}
</Text>
<CTAButton label={t('summary.footer.back', 'Back to package selection')} onPress={() => navigate(ADMIN_WELCOME_PACKAGES_PATH)} />
@@ -96,14 +97,21 @@ export default function WelcomeSummaryPage() {
<MobileCard space="$3">
<XStack alignItems="center" justifyContent="space-between">
<XStack alignItems="center" space="$2">
<XStack width={36} height={36} borderRadius={12} backgroundColor="#e0f2fe" alignItems="center" justifyContent="center">
<PackageIcon size={18} color="#0ea5e9" />
<XStack
width={36}
height={36}
borderRadius={12}
backgroundColor={ADMIN_COLORS.accentSoft}
alignItems="center"
justifyContent="center"
>
<PackageIcon size={18} color={ADMIN_COLORS.primary} />
</XStack>
<YStack>
<Text fontSize="$sm" fontWeight="800">
{resolvedPackage.name}
</Text>
<Text fontSize="$xs" color="#6b7280">
<Text fontSize="$xs" color={ADMIN_COLORS.textMuted}>
{resolvedPackage.active
? t('summary.details.section.statusActive', 'Already purchased')
: t('summary.details.section.statusInactive', 'Not purchased yet')}
@@ -139,8 +147,8 @@ export default function WelcomeSummaryPage() {
{resolvedPackage.active ? (
<XStack alignItems="center" space="$2">
<CheckCircle2 size={18} color="#22c55e" />
<Text fontSize="$sm" color="#16a34a" fontWeight="700">
<CheckCircle2 size={18} color={ADMIN_COLORS.success} />
<Text fontSize="$sm" color={ADMIN_COLORS.success} fontWeight="700">
{t('summary.details.section.statusActive', 'Already purchased')}
</Text>
</XStack>
@@ -162,10 +170,10 @@ export default function WelcomeSummaryPage() {
],
}) as string[]).map((item) => (
<XStack key={item} space="$2">
<Text fontSize="$xs" color="#6b7280">
<Text fontSize="$xs" color={ADMIN_COLORS.textMuted}>
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{item}
</Text>
</XStack>
@@ -194,10 +202,10 @@ export default function WelcomeSummaryPage() {
function SummaryRow({ label, value }: { label: string; value: string }) {
return (
<XStack alignItems="center" justifyContent="space-between">
<Text fontSize="$sm" color="#111827">
<Text fontSize="$sm" color={ADMIN_COLORS.text}>
{label}
</Text>
<Text fontSize="$sm" color="#6b7280">
<Text fontSize="$sm" color={ADMIN_COLORS.textMuted}>
{value}
</Text>
</XStack>