weitere perfektionierung der neuen mobile app
This commit is contained in:
@@ -11,6 +11,7 @@ import { getEvents, TenantEvent } from '../api';
|
||||
import { adminPath } from '../constants';
|
||||
import { isAuthError } from '../auth/tokens';
|
||||
import { getApiErrorMessage } from '../lib/apiError';
|
||||
import { useTheme } from '@tamagui/core';
|
||||
|
||||
export default function MobileEventsPage() {
|
||||
const { t } = useTranslation('management');
|
||||
@@ -19,6 +20,27 @@ export default function MobileEventsPage() {
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
const [query, setQuery] = React.useState('');
|
||||
const theme = useTheme();
|
||||
const text = String(theme.color?.val ?? '#111827');
|
||||
const muted = String(theme.gray?.val ?? '#4b5563');
|
||||
const subtle = String(theme.gray8?.val ?? '#6b7280');
|
||||
const border = String(theme.borderColor?.val ?? '#e5e7eb');
|
||||
const primary = String(theme.primary?.val ?? '#007AFF');
|
||||
const danger = String(theme.red10?.val ?? '#b91c1c');
|
||||
const surface = String(theme.surface?.val ?? '#ffffff');
|
||||
const baseInputStyle = React.useMemo<React.CSSProperties>(
|
||||
() => ({
|
||||
width: '100%',
|
||||
height: 38,
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${border}`,
|
||||
padding: '0 12px',
|
||||
fontSize: 13,
|
||||
background: surface,
|
||||
color: text,
|
||||
}),
|
||||
[border, surface, text],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
@@ -41,13 +63,13 @@ export default function MobileEventsPage() {
|
||||
onBack={() => navigate(-1)}
|
||||
headerActions={
|
||||
<Pressable>
|
||||
<Search size={18} color="#0f172a" />
|
||||
<Search size={18} color={text} />
|
||||
</Pressable>
|
||||
}
|
||||
>
|
||||
{error ? (
|
||||
<MobileCard>
|
||||
<Text fontWeight="700" color="#b91c1c">
|
||||
<Text fontWeight="700" color={danger}>
|
||||
{error}
|
||||
</Text>
|
||||
</MobileCard>
|
||||
@@ -60,16 +82,7 @@ export default function MobileEventsPage() {
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder={t('events.list.search', 'Search events')}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 38,
|
||||
borderRadius: 10,
|
||||
border: '1px solid #e5e7eb',
|
||||
padding: '0 12px',
|
||||
fontSize: 13,
|
||||
background: 'white',
|
||||
marginBottom: 12,
|
||||
}}
|
||||
style={{ ...baseInputStyle, marginBottom: 12 }}
|
||||
/>
|
||||
|
||||
{loading ? (
|
||||
@@ -83,7 +96,7 @@ export default function MobileEventsPage() {
|
||||
<Text fontSize="$md" fontWeight="700">
|
||||
{t('events.list.empty.title', 'Noch kein Event angelegt')}
|
||||
</Text>
|
||||
<Text fontSize="$sm" color="#4b5563" textAlign="center">
|
||||
<Text fontSize="$sm" color={muted} textAlign="center">
|
||||
{t('events.list.empty.description', 'Starte jetzt mit deinem ersten Event.')}
|
||||
</Text>
|
||||
<CTAButton label={t('events.actions.create', 'Create New Event')} onPress={() => navigate(adminPath('/events/new'))} />
|
||||
@@ -100,6 +113,11 @@ export default function MobileEventsPage() {
|
||||
<EventRow
|
||||
key={event.id}
|
||||
event={event}
|
||||
text={text}
|
||||
muted={muted}
|
||||
subtle={subtle}
|
||||
border={border}
|
||||
primary={primary}
|
||||
onOpen={(slug) => navigate(adminPath(`/mobile/events/${slug}`))}
|
||||
onEdit={(slug) => navigate(adminPath(`/mobile/events/${slug}/edit`))}
|
||||
/>
|
||||
@@ -110,31 +128,49 @@ export default function MobileEventsPage() {
|
||||
);
|
||||
}
|
||||
|
||||
function EventRow({ event, onOpen, onEdit }: { event: TenantEvent; onOpen: (slug: string) => void; onEdit: (slug: string) => void }) {
|
||||
function EventRow({
|
||||
event,
|
||||
text,
|
||||
muted,
|
||||
subtle,
|
||||
border,
|
||||
primary,
|
||||
onOpen,
|
||||
onEdit,
|
||||
}: {
|
||||
event: TenantEvent;
|
||||
text: string;
|
||||
muted: string;
|
||||
subtle: string;
|
||||
border: string;
|
||||
primary: string;
|
||||
onOpen: (slug: string) => void;
|
||||
onEdit: (slug: string) => void;
|
||||
}) {
|
||||
const status = resolveStatus(event);
|
||||
return (
|
||||
<MobileCard borderColor="#e2e8f0">
|
||||
<MobileCard borderColor={border}>
|
||||
<XStack justifyContent="space-between" alignItems="flex-start" space="$2">
|
||||
<YStack space="$1">
|
||||
<Text fontSize="$md" fontWeight="800" color="#111827">
|
||||
<Text fontSize="$md" fontWeight="800" color={text}>
|
||||
{renderName(event.name)}
|
||||
</Text>
|
||||
<XStack alignItems="center" space="$2">
|
||||
<CalendarDays size={14} color="#6b7280" />
|
||||
<Text fontSize="$sm" color="#4b5563">
|
||||
<CalendarDays size={14} color={subtle} />
|
||||
<Text fontSize="$sm" color={muted}>
|
||||
{formatDate(event.event_date)}
|
||||
</Text>
|
||||
</XStack>
|
||||
<XStack alignItems="center" space="$2">
|
||||
<MapPin size={14} color="#6b7280" />
|
||||
<Text fontSize="$sm" color="#4b5563">
|
||||
<MapPin size={14} color={subtle} />
|
||||
<Text fontSize="$sm" color={muted}>
|
||||
{resolveLocation(event)}
|
||||
</Text>
|
||||
</XStack>
|
||||
<PillBadge tone={status.tone}>{status.label}</PillBadge>
|
||||
</YStack>
|
||||
<Pressable onPress={() => onEdit(event.slug)}>
|
||||
<Text fontSize="$xl" color="#9ca3af">
|
||||
<Text fontSize="$xl" color={muted}>
|
||||
˅
|
||||
</Text>
|
||||
</Pressable>
|
||||
@@ -142,8 +178,8 @@ function EventRow({ event, onOpen, onEdit }: { event: TenantEvent; onOpen: (slug
|
||||
|
||||
<Pressable onPress={() => onOpen(event.slug)} style={{ marginTop: 8 }}>
|
||||
<XStack alignItems="center" justifyContent="flex-start" space="$2">
|
||||
<Plus size={16} color="#007AFF" />
|
||||
<Text fontSize="$sm" color="#007AFF" fontWeight="700">
|
||||
<Plus size={16} color={primary} />
|
||||
<Text fontSize="$sm" color={primary} fontWeight="700">
|
||||
Open event
|
||||
</Text>
|
||||
</XStack>
|
||||
|
||||
Reference in New Issue
Block a user