admin mobile: improve small-screen readability across checklist, tabs, badges, and headers
This commit is contained in:
@@ -980,8 +980,8 @@ function PackageCard({
|
|||||||
backgroundColor={isActive ? accentSoft : undefined}
|
backgroundColor={isActive ? accentSoft : undefined}
|
||||||
gap="$2"
|
gap="$2"
|
||||||
>
|
>
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$md" fontWeight="800" color={textStrong}>
|
<Text fontSize="$md" fontWeight="800" color={textStrong} flex={1} minWidth={0}>
|
||||||
{pkg.package_name ?? t('mobileBilling.packageFallback', 'Package')}
|
{pkg.package_name ?? t('mobileBilling.packageFallback', 'Package')}
|
||||||
</Text>
|
</Text>
|
||||||
{label ? <PillBadge tone="success">{label}</PillBadge> : null}
|
{label ? <PillBadge tone="success">{label}</PillBadge> : null}
|
||||||
@@ -1262,8 +1262,8 @@ function AddonRow({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MobileCard borderColor={border} padding="$3" gap="$1.5">
|
<MobileCard borderColor={border} padding="$3" gap="$1.5">
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={textStrong}>
|
<Text fontSize="$sm" fontWeight="700" color={textStrong} flex={1} minWidth={0}>
|
||||||
{addon.label ?? addon.addon_key}
|
{addon.label ?? addon.addon_key}
|
||||||
</Text>
|
</Text>
|
||||||
<PillBadge tone={status.tone}>{status.text}</PillBadge>
|
<PillBadge tone={status.tone}>{status.text}</PillBadge>
|
||||||
@@ -1271,11 +1271,11 @@ function AddonRow({
|
|||||||
{!hideEventLink && eventName ? (
|
{!hideEventLink && eventName ? (
|
||||||
eventPath ? (
|
eventPath ? (
|
||||||
<Pressable onPress={() => navigate(eventPath)}>
|
<Pressable onPress={() => navigate(eventPath)}>
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$xs" color={textStrong} fontWeight="600">
|
<Text fontSize="$xs" color={textStrong} fontWeight="600" flex={1} minWidth={0}>
|
||||||
{eventName}
|
{eventName}
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="$xs" color={primary} fontWeight="700">
|
<Text fontSize="$xs" color={primary} fontWeight="700" flexShrink={0}>
|
||||||
{t('mobileBilling.openEvent', 'Open event')}
|
{t('mobileBilling.openEvent', 'Open event')}
|
||||||
</Text>
|
</Text>
|
||||||
</XStack>
|
</XStack>
|
||||||
@@ -1316,8 +1316,8 @@ function EventAddonRow({ addon }: { addon: EventAddonSummary }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MobileCard borderColor={border} padding="$3" gap="$1.5">
|
<MobileCard borderColor={border} padding="$3" gap="$1.5">
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={textStrong}>
|
<Text fontSize="$sm" fontWeight="700" color={textStrong} flex={1} minWidth={0}>
|
||||||
{addon.label ?? addon.key}
|
{addon.label ?? addon.key}
|
||||||
</Text>
|
</Text>
|
||||||
<PillBadge tone={status.tone}>{status.text}</PillBadge>
|
<PillBadge tone={status.tone}>{status.text}</PillBadge>
|
||||||
|
|||||||
@@ -629,9 +629,9 @@ function LifecycleHero({
|
|||||||
paddingHorizontal="$3"
|
paddingHorizontal="$3"
|
||||||
onPress={() => navigate(adminPath(nextStep.targetPath))}
|
onPress={() => navigate(adminPath(nextStep.targetPath))}
|
||||||
title={
|
title={
|
||||||
<XStack alignItems="center" gap="$2">
|
<XStack alignItems="flex-start" gap="$2" flex={1} minWidth={0}>
|
||||||
<Circle size={18} color={theme.primary} strokeWidth={2.5} />
|
<Circle size={18} color={theme.primary} strokeWidth={2.5} />
|
||||||
<Text fontSize="$sm" fontWeight="700" color={theme.textStrong}>
|
<Text fontSize="$sm" fontWeight="700" color={theme.textStrong} flexShrink={1}>
|
||||||
{nextStep.label}
|
{nextStep.label}
|
||||||
</Text>
|
</Text>
|
||||||
</XStack>
|
</XStack>
|
||||||
@@ -644,8 +644,17 @@ function LifecycleHero({
|
|||||||
) : undefined
|
) : undefined
|
||||||
}
|
}
|
||||||
iconAfter={
|
iconAfter={
|
||||||
<XStack alignItems="center" gap="$1">
|
<XStack alignItems="center" gap="$1" maxWidth="52%" flexShrink={1}>
|
||||||
<PillBadge tone="success">{nextStep.ctaLabel}</PillBadge>
|
<Text
|
||||||
|
fontSize="$xs"
|
||||||
|
fontWeight="700"
|
||||||
|
color={theme.primary}
|
||||||
|
textAlign="right"
|
||||||
|
numberOfLines={2}
|
||||||
|
flexShrink={1}
|
||||||
|
>
|
||||||
|
{nextStep.ctaLabel}
|
||||||
|
</Text>
|
||||||
<ChevronRight size={16} color={theme.muted} />
|
<ChevronRight size={16} color={theme.muted} />
|
||||||
</XStack>
|
</XStack>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,11 +335,11 @@ export default function MobileEventGuestNotificationsPage() {
|
|||||||
<YStack gap="$2">
|
<YStack gap="$2">
|
||||||
{history.map((item) => (
|
{history.map((item) => (
|
||||||
<MobileCard key={item.id} gap="$2" borderColor={border}>
|
<MobileCard key={item.id} gap="$2" borderColor={border}>
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$sm" fontWeight="800" color={textStrong}>
|
<Text fontSize="$sm" fontWeight="800" color={textStrong} flex={1} minWidth={0}>
|
||||||
{item.title || t('guestMessages.history.untitled', 'Untitled')}
|
{item.title || t('guestMessages.history.untitled', 'Untitled')}
|
||||||
</Text>
|
</Text>
|
||||||
<XStack gap="$1.5" alignItems="center">
|
<XStack gap="$1.5" alignItems="center" flexWrap="wrap" justifyContent="flex-end">
|
||||||
<PillBadge tone={item.status === 'active' ? 'success' : 'muted'}>
|
<PillBadge tone={item.status === 'active' ? 'success' : 'muted'}>
|
||||||
{t(`guestMessages.status.${item.status}`, item.status)}
|
{t(`guestMessages.status.${item.status}`, item.status)}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
@@ -353,8 +353,8 @@ export default function MobileEventGuestNotificationsPage() {
|
|||||||
<Text fontSize="$sm" color={text}>
|
<Text fontSize="$sm" color={text}>
|
||||||
{item.body ?? t('guestMessages.history.noBody', 'No body provided.')}
|
{item.body ?? t('guestMessages.history.noBody', 'No body provided.')}
|
||||||
</Text>
|
</Text>
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<XStack gap="$1.5" alignItems="center">
|
<XStack gap="$1.5" alignItems="center" flexWrap="wrap" flex={1} minWidth={0}>
|
||||||
<PillBadge tone="muted">{t(`guestMessages.type.${item.type}`, item.type)}</PillBadge>
|
<PillBadge tone="muted">{t(`guestMessages.type.${item.type}`, item.type)}</PillBadge>
|
||||||
{item.target_identifier ? (
|
{item.target_identifier ? (
|
||||||
<PillBadge tone="muted">
|
<PillBadge tone="muted">
|
||||||
@@ -376,7 +376,7 @@ export default function MobileEventGuestNotificationsPage() {
|
|||||||
</PillBadge>
|
</PillBadge>
|
||||||
)}
|
)}
|
||||||
</XStack>
|
</XStack>
|
||||||
<Text fontSize="$xs" color={mutedText}>
|
<Text fontSize="$xs" color={mutedText} flexShrink={0}>
|
||||||
{formatGuestMessageDate(item.created_at, locale)}
|
{formatGuestMessageDate(item.created_at, locale)}
|
||||||
</Text>
|
</Text>
|
||||||
</XStack>
|
</XStack>
|
||||||
|
|||||||
@@ -358,15 +358,15 @@ export default function MobileEventMembersPage() {
|
|||||||
const statusInfo = resolveStatus(member.status);
|
const statusInfo = resolveStatus(member.status);
|
||||||
return (
|
return (
|
||||||
<MobileCard key={member.id} padding="$3" borderColor={border}>
|
<MobileCard key={member.id} padding="$3" borderColor={border}>
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2">
|
||||||
<YStack gap="$1">
|
<YStack gap="$1" flex={1} minWidth={0}>
|
||||||
<Text fontSize="$sm" fontWeight="700" color={textStrong}>
|
<Text fontSize="$sm" fontWeight="700" color={textStrong} numberOfLines={2}>
|
||||||
{member.name || member.email || t('events.members.fallbackName', 'Guest')}
|
{member.name || member.email || t('events.members.fallbackName', 'Guest')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="$xs" color={muted}>
|
<Text fontSize="$xs" color={muted} numberOfLines={2}>
|
||||||
{member.email ?? ''}
|
{member.email ?? ''}
|
||||||
</Text>
|
</Text>
|
||||||
<XStack gap="$1.5" alignItems="center">
|
<XStack gap="$1.5" alignItems="center" flexWrap="wrap">
|
||||||
<PillBadge tone={statusInfo.tone}>
|
<PillBadge tone={statusInfo.tone}>
|
||||||
{statusInfo.label}
|
{statusInfo.label}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
|
|||||||
@@ -200,60 +200,72 @@ export default function MobileEventRecapPage() {
|
|||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
>
|
>
|
||||||
<Tabs.List gap="$2">
|
<Tabs.List gap="$1" flexWrap="wrap">
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
value="overview"
|
value="overview"
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
paddingHorizontal="$3"
|
flexBasis="calc(33.333% - 4px)"
|
||||||
|
minWidth={108}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
borderRadius="$4"
|
borderRadius="$4"
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
fontSize="$sm"
|
fontSize="$xs"
|
||||||
fontWeight={activeTab === 'overview' ? '700' : '600'}
|
fontWeight={activeTab === 'overview' ? '700' : '600'}
|
||||||
color={activeTab === 'overview' ? text : muted}
|
color={activeTab === 'overview' ? text : muted}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
|
numberOfLines={2}
|
||||||
>
|
>
|
||||||
{t('events.recap.tabs.overview', 'Overview')}
|
{t('events.recap.tabs.overview', 'Overview')}
|
||||||
</Text>
|
</Text>
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
value="engagement"
|
value="engagement"
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
paddingHorizontal="$3"
|
flexBasis="calc(33.333% - 4px)"
|
||||||
|
minWidth={108}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
borderRadius="$4"
|
borderRadius="$4"
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
fontSize="$sm"
|
fontSize="$xs"
|
||||||
fontWeight={activeTab === 'engagement' ? '700' : '600'}
|
fontWeight={activeTab === 'engagement' ? '700' : '600'}
|
||||||
color={activeTab === 'engagement' ? text : muted}
|
color={activeTab === 'engagement' ? text : muted}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
|
numberOfLines={2}
|
||||||
>
|
>
|
||||||
{t('events.recap.tabs.engagement', 'Engagement')}
|
{t('events.recap.tabs.engagement', 'Engagement')}
|
||||||
</Text>
|
</Text>
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
value="compliance"
|
value="compliance"
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
paddingHorizontal="$3"
|
flexBasis="calc(33.333% - 4px)"
|
||||||
|
minWidth={108}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
borderRadius="$4"
|
borderRadius="$4"
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
fontSize="$sm"
|
fontSize="$xs"
|
||||||
fontWeight={activeTab === 'compliance' ? '700' : '600'}
|
fontWeight={activeTab === 'compliance' ? '700' : '600'}
|
||||||
color={activeTab === 'compliance' ? text : muted}
|
color={activeTab === 'compliance' ? text : muted}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
|
numberOfLines={2}
|
||||||
>
|
>
|
||||||
{t('events.recap.tabs.compliance', 'Compliance')}
|
{t('events.recap.tabs.compliance', 'Compliance')}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -263,8 +275,8 @@ export default function MobileEventRecapPage() {
|
|||||||
<Tabs.Content value="overview" paddingTop="$2">
|
<Tabs.Content value="overview" paddingTop="$2">
|
||||||
<YStack gap="$4">
|
<YStack gap="$4">
|
||||||
<MobileCard gap="$3">
|
<MobileCard gap="$3">
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<YStack gap="$1">
|
<YStack gap="$1" flex={1} minWidth={0}>
|
||||||
<Text fontSize="$xl" fontWeight="800" color={textStrong}>
|
<Text fontSize="$xl" fontWeight="800" color={textStrong}>
|
||||||
{t('events.recap.completedTitle', 'Event abgeschlossen')}
|
{t('events.recap.completedTitle', 'Event abgeschlossen')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -1176,31 +1176,45 @@ export default function MobileEventTasksPage() {
|
|||||||
borderRadius={16}
|
borderRadius={16}
|
||||||
borderWidth={1}
|
borderWidth={1}
|
||||||
borderColor={border}
|
borderColor={border}
|
||||||
overflow="hidden"
|
overflow="visible"
|
||||||
gap="$0"
|
gap="$1"
|
||||||
|
flexWrap="wrap"
|
||||||
|
padding="$1"
|
||||||
>
|
>
|
||||||
{[
|
{[
|
||||||
{ value: 'assigned', label: t('events.tasks.tabs.tasks', 'Tasks') },
|
{ value: 'assigned', label: t('events.tasks.tabs.tasks', 'Tasks') },
|
||||||
{ value: 'library', label: t('events.tasks.tabs.library', 'Task Library') },
|
{ value: 'library', label: t('events.tasks.tabs.library', 'Task Library') },
|
||||||
{ value: 'emotions', label: t('events.tasks.tabs.emotions', 'Emotions') },
|
{ value: 'emotions', label: t('events.tasks.tabs.emotions', 'Emotions') },
|
||||||
{ value: 'collections', label: t('events.tasks.tabs.collections', 'Collections') },
|
{ value: 'collections', label: t('events.tasks.tabs.collections', 'Collections') },
|
||||||
].map((tab, index, arr) => {
|
].map((tab) => {
|
||||||
const isActive = activeTab === tab.value;
|
const isActive = activeTab === tab.value;
|
||||||
return (
|
return (
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
key={tab.value}
|
key={tab.value}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
|
flexBasis="calc(50% - 4px)"
|
||||||
|
minWidth={132}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
borderRightWidth={index === arr.length - 1 ? 0 : 1}
|
borderWidth={1}
|
||||||
borderRightColor={border}
|
borderColor={isActive ? withAlpha(primary, 0.45) : border}
|
||||||
|
borderRadius={12}
|
||||||
|
backgroundColor={isActive ? withAlpha(primary, 0.12) : surface}
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text fontSize="$sm" fontWeight={isActive ? '700' : '600'} color={isActive ? text : muted}>
|
<Text
|
||||||
|
fontSize="$xs"
|
||||||
|
fontWeight={isActive ? '700' : '600'}
|
||||||
|
color={isActive ? text : muted}
|
||||||
|
numberOfLines={2}
|
||||||
|
textAlign="center"
|
||||||
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</Text>
|
</Text>
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
@@ -1232,6 +1246,7 @@ export default function MobileEventTasksPage() {
|
|||||||
<XStack
|
<XStack
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap="$1.5"
|
gap="$1.5"
|
||||||
|
flexShrink={1}
|
||||||
paddingVertical="$2"
|
paddingVertical="$2"
|
||||||
paddingHorizontal="$3"
|
paddingHorizontal="$3"
|
||||||
borderRadius={14}
|
borderRadius={14}
|
||||||
@@ -1239,14 +1254,16 @@ export default function MobileEventTasksPage() {
|
|||||||
borderColor={border}
|
borderColor={border}
|
||||||
backgroundColor={surface}
|
backgroundColor={surface}
|
||||||
>
|
>
|
||||||
<Text fontSize={11} fontWeight="700" color={text}>
|
<YStack flexShrink={1} minWidth={0} maxWidth={128}>
|
||||||
{t('events.tasks.emotionFilterShort', 'Emotion')}
|
<Text fontSize={11} fontWeight="700" color={text} numberOfLines={1}>
|
||||||
</Text>
|
{t('events.tasks.emotionFilterShort', 'Emotion')}
|
||||||
<Text fontSize={11} color={muted}>
|
</Text>
|
||||||
{emotionFilter
|
<Text fontSize={11} color={muted} numberOfLines={1}>
|
||||||
? emotions.find((e) => String(e.id) === emotionFilter)?.name ?? t('events.tasks.customEmotion', 'Custom emotion')
|
{emotionFilter
|
||||||
: t('events.tasks.allEmotions', 'All')}
|
? emotions.find((e) => String(e.id) === emotionFilter)?.name ?? t('events.tasks.customEmotion', 'Custom emotion')
|
||||||
</Text>
|
: t('events.tasks.allEmotions', 'All')}
|
||||||
|
</Text>
|
||||||
|
</YStack>
|
||||||
<ChevronDown size={14} color={muted} />
|
<ChevronDown size={14} color={muted} />
|
||||||
</XStack>
|
</XStack>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|||||||
@@ -449,11 +449,11 @@ function EventListItem({
|
|||||||
const stats = buildEventListStats(event);
|
const stats = buildEventListStats(event);
|
||||||
return (
|
return (
|
||||||
<YStack gap="$1.5">
|
<YStack gap="$1.5">
|
||||||
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$md" fontWeight="800" color={text}>
|
<Text fontSize="$md" fontWeight="800" color={text} flex={1} minWidth={0}>
|
||||||
{renderName(event.name, t)}
|
{renderName(event.name, t)}
|
||||||
</Text>
|
</Text>
|
||||||
<XStack alignItems="center" gap="$1.5">
|
<XStack alignItems="center" gap="$1.5" flexWrap="wrap" justifyContent="flex-end">
|
||||||
<PillBadge tone={statusTone}>{statusLabel}</PillBadge>
|
<PillBadge tone={statusTone}>{statusLabel}</PillBadge>
|
||||||
{onEdit ? (
|
{onEdit ? (
|
||||||
<Pressable onPress={() => onEdit(event.slug)}>
|
<Pressable onPress={() => onEdit(event.slug)}>
|
||||||
|
|||||||
@@ -239,10 +239,10 @@ function PackageShopCard({
|
|||||||
backgroundColor={isActive ? '$green1' : undefined}
|
backgroundColor={isActive ? '$green1' : undefined}
|
||||||
style={{ opacity: isSubdued ? 0.6 : 1 }}
|
style={{ opacity: isSubdued ? 0.6 : 1 }}
|
||||||
>
|
>
|
||||||
<XStack justifyContent="space-between" alignItems="flex-start">
|
<XStack justifyContent="space-between" alignItems="flex-start" gap="$2" flexWrap="wrap">
|
||||||
<YStack gap="$1">
|
<YStack gap="$1" flex={1} minWidth={0}>
|
||||||
<XStack gap="$2" alignItems="center">
|
<XStack gap="$2" alignItems="center" flexWrap="wrap">
|
||||||
<Text fontSize="$lg" fontWeight="800" color={textStrong}>
|
<Text fontSize="$lg" fontWeight="800" color={textStrong} flexShrink={1}>
|
||||||
{pkg.name}
|
{pkg.name}
|
||||||
</Text>
|
</Text>
|
||||||
{isRecommended && <PillBadge tone="warning">{t('shop.badges.recommended', 'Recommended')}</PillBadge>}
|
{isRecommended && <PillBadge tone="warning">{t('shop.badges.recommended', 'Recommended')}</PillBadge>}
|
||||||
@@ -255,12 +255,12 @@ function PackageShopCard({
|
|||||||
{!isResellerCatalog && isActive ? <PillBadge tone="success">{t('shop.badges.active', 'Active')}</PillBadge> : null}
|
{!isResellerCatalog && isActive ? <PillBadge tone="success">{t('shop.badges.active', 'Active')}</PillBadge> : null}
|
||||||
</XStack>
|
</XStack>
|
||||||
|
|
||||||
<XStack gap="$2" alignItems="center">
|
<XStack gap="$2" alignItems="center" flexWrap="wrap">
|
||||||
<Text fontSize="$md" color={primary} fontWeight="700">
|
<Text fontSize="$md" color={primary} fontWeight="700">
|
||||||
{new Intl.NumberFormat(undefined, { style: 'currency', currency: 'EUR' }).format(pkg.price)}
|
{new Intl.NumberFormat(undefined, { style: 'currency', currency: 'EUR' }).format(pkg.price)}
|
||||||
</Text>
|
</Text>
|
||||||
{statusLabel && (
|
{statusLabel && (
|
||||||
<Text fontSize="$xs" color={muted} fontWeight="600">
|
<Text fontSize="$xs" color={muted} fontWeight="600" flexShrink={1}>
|
||||||
• {statusLabel}
|
• {statusLabel}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -583,41 +583,49 @@ export default function MobileProfileAccountPage() {
|
|||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
>
|
>
|
||||||
<Tabs.List gap="$2">
|
<Tabs.List gap="$1" flexWrap="wrap">
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
value="account"
|
value="account"
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
paddingHorizontal="$3"
|
flexBasis="calc(50% - 4px)"
|
||||||
|
minWidth={132}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
borderRadius="$4"
|
borderRadius="$4"
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
fontSize="$sm"
|
fontSize="$xs"
|
||||||
fontWeight={activeTab === 'account' ? '700' : '600'}
|
fontWeight={activeTab === 'account' ? '700' : '600'}
|
||||||
color={activeTab === 'account' ? text : muted}
|
color={activeTab === 'account' ? text : muted}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
|
numberOfLines={2}
|
||||||
>
|
>
|
||||||
{t('profile.tabs.account', 'Account')}
|
{t('profile.tabs.account', 'Account')}
|
||||||
</Text>
|
</Text>
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
value="branding"
|
value="branding"
|
||||||
flex={1}
|
flexGrow={1}
|
||||||
paddingVertical="$2.5"
|
flexShrink={1}
|
||||||
paddingHorizontal="$3"
|
flexBasis="calc(50% - 4px)"
|
||||||
|
minWidth={132}
|
||||||
|
paddingVertical="$2"
|
||||||
|
paddingHorizontal="$2"
|
||||||
borderRadius="$4"
|
borderRadius="$4"
|
||||||
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
hoverStyle={{ backgroundColor: '$backgroundHover' }}
|
||||||
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
pressStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
activeStyle={{ backgroundColor: '$backgroundPress' }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
fontSize="$sm"
|
fontSize="$xs"
|
||||||
fontWeight={activeTab === 'branding' ? '700' : '600'}
|
fontWeight={activeTab === 'branding' ? '700' : '600'}
|
||||||
color={activeTab === 'branding' ? text : muted}
|
color={activeTab === 'branding' ? text : muted}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
|
numberOfLines={2}
|
||||||
>
|
>
|
||||||
{t('profile.tabs.branding', 'Standard-Branding')}
|
{t('profile.tabs.branding', 'Standard-Branding')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ export default function MobileSettingsPage() {
|
|||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<YStack gap="$2">
|
<YStack gap="$2">
|
||||||
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<YStack flex={1} gap="$1">
|
<YStack flex={1} gap="$1">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||||
{t('mobileSettings.deviceStatus.notifications.label', 'Notifications')}
|
{t('mobileSettings.deviceStatus.notifications.label', 'Notifications')}
|
||||||
@@ -351,7 +351,7 @@ export default function MobileSettingsPage() {
|
|||||||
{permissionLabel(devicePermissions.notifications)}
|
{permissionLabel(devicePermissions.notifications)}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
</XStack>
|
</XStack>
|
||||||
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<YStack flex={1} gap="$1">
|
<YStack flex={1} gap="$1">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||||
{t('mobileSettings.deviceStatus.camera.label', 'Camera')}
|
{t('mobileSettings.deviceStatus.camera.label', 'Camera')}
|
||||||
@@ -364,7 +364,7 @@ export default function MobileSettingsPage() {
|
|||||||
{permissionLabel(devicePermissions.camera)}
|
{permissionLabel(devicePermissions.camera)}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
</XStack>
|
</XStack>
|
||||||
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<YStack flex={1} gap="$1">
|
<YStack flex={1} gap="$1">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||||
{t('mobileSettings.deviceStatus.storage.label', 'Offline storage')}
|
{t('mobileSettings.deviceStatus.storage.label', 'Offline storage')}
|
||||||
@@ -377,7 +377,7 @@ export default function MobileSettingsPage() {
|
|||||||
{storageLabel(devicePermissions.storage)}
|
{storageLabel(devicePermissions.storage)}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
</XStack>
|
</XStack>
|
||||||
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<YStack flex={1} gap="$1">
|
<YStack flex={1} gap="$1">
|
||||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||||
{t('mobileSettings.deviceStatus.connection.label', 'Connection')}
|
{t('mobileSettings.deviceStatus.connection.label', 'Connection')}
|
||||||
|
|||||||
@@ -39,19 +39,21 @@ export function SetupChecklist({
|
|||||||
<YStack>
|
<YStack>
|
||||||
<Pressable onPress={() => setCollapsed(!collapsed)}>
|
<Pressable onPress={() => setCollapsed(!collapsed)}>
|
||||||
<YStack padding="$3" paddingVertical="$2.5" gap="$2">
|
<YStack padding="$3" paddingVertical="$2.5" gap="$2">
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
<XStack alignItems="flex-start" justifyContent="space-between" gap="$2" flexWrap="wrap">
|
||||||
<XStack alignItems="center" gap="$2">
|
<XStack alignItems="center" gap="$2" flex={1} minWidth={0} flexWrap="wrap">
|
||||||
<Text fontSize="$xs" fontWeight="700" color={theme.muted} textTransform="uppercase" letterSpacing={1}>
|
<Text fontSize="$xs" fontWeight="700" color={theme.muted} textTransform="uppercase" letterSpacing={1}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
{isAllComplete ? (
|
{isAllComplete ? (
|
||||||
<CheckCircle2 size={14} color={theme.successText} />
|
<CheckCircle2 size={14} color={theme.successText} />
|
||||||
) : (
|
) : (
|
||||||
<PillBadge tone="warning">{t('readiness.pending', 'Noch offen')}</PillBadge>
|
<XStack flexShrink={0}>
|
||||||
|
<PillBadge tone="warning">{t('readiness.pending', 'Noch offen')}</PillBadge>
|
||||||
|
</XStack>
|
||||||
)}
|
)}
|
||||||
</XStack>
|
</XStack>
|
||||||
|
|
||||||
<XStack alignItems="center" gap="$2">
|
<XStack alignItems="center" justifyContent="flex-end" gap="$2" flexShrink={0}>
|
||||||
<Text fontSize="$xs" color={theme.muted} fontWeight="600">
|
<Text fontSize="$xs" color={theme.muted} fontWeight="600">
|
||||||
{completedCount}/{steps.length}
|
{completedCount}/{steps.length}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -89,7 +91,7 @@ export function SetupChecklist({
|
|||||||
backgroundColor={isNext ? theme.surfaceMuted : 'transparent'}
|
backgroundColor={isNext ? theme.surfaceMuted : 'transparent'}
|
||||||
onPress={() => navigate(adminPath(step.targetPath))}
|
onPress={() => navigate(adminPath(step.targetPath))}
|
||||||
title={
|
title={
|
||||||
<XStack alignItems="center" gap="$2.5">
|
<XStack alignItems="flex-start" gap="$2.5" flex={1} minWidth={0}>
|
||||||
{step.isComplete ? (
|
{step.isComplete ? (
|
||||||
<CheckCircle2 size={18} color={theme.successText} />
|
<CheckCircle2 size={18} color={theme.successText} />
|
||||||
) : isNext ? (
|
) : isNext ? (
|
||||||
@@ -102,6 +104,7 @@ export function SetupChecklist({
|
|||||||
fontWeight={isNext ? '700' : '500'}
|
fontWeight={isNext ? '700' : '500'}
|
||||||
color={step.isComplete ? theme.muted : theme.textStrong}
|
color={step.isComplete ? theme.muted : theme.textStrong}
|
||||||
textDecorationLine={step.isComplete ? 'line-through' : 'none'}
|
textDecorationLine={step.isComplete ? 'line-through' : 'none'}
|
||||||
|
flexShrink={1}
|
||||||
>
|
>
|
||||||
{step.label}
|
{step.label}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
Reference in New Issue
Block a user