Enforce tenant member permissions
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-16 13:33:36 +01:00
parent df60be826d
commit 7aa0a4c847
22 changed files with 592 additions and 112 deletions

View File

@@ -20,10 +20,13 @@ import { useBackNavigation } from './hooks/useBackNavigation';
import { buildEventStatusCounts, filterEventsByStatus, resolveEventStatusKey, type EventStatusKey } from './lib/eventFilters';
import { buildEventListStats } from './lib/eventListStats';
import { useAdminTheme } from './theme';
import { useAuth } from '../auth/context';
export default function MobileEventsPage() {
const { t } = useTranslation('management');
const navigate = useNavigate();
const { user } = useAuth();
const isMember = user?.role === 'member';
const [events, setEvents] = React.useState<TenantEvent[]>([]);
const [loading, setLoading] = React.useState(true);
const [error, setError] = React.useState<string | null>(null);
@@ -139,7 +142,9 @@ export default function MobileEventsPage() {
<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'))} />
{!isMember ? (
<CTAButton label={t('events.actions.create', 'Create New Event')} onPress={() => navigate(adminPath('/events/new'))} />
) : null}
</YStack>
</Card>
) : (
@@ -149,15 +154,17 @@ export default function MobileEventsPage() {
statusFilter={statusFilter}
onStatusChange={setStatusFilter}
onOpen={(slug) => navigate(adminPath(`/mobile/events/${slug}`))}
onEdit={(slug) => navigate(adminPath(`/mobile/events/${slug}/edit`))}
onEdit={!isMember ? (slug) => navigate(adminPath(`/mobile/events/${slug}/edit`)) : undefined}
/>
)}
<FloatingActionButton
label={t('events.actions.create', 'Create New Event')}
icon={Plus}
onPress={() => navigate(adminPath('/mobile/events/new'))}
/>
{!isMember ? (
<FloatingActionButton
label={t('events.actions.create', 'Create New Event')}
icon={Plus}
onPress={() => navigate(adminPath('/mobile/events/new'))}
/>
) : null}
</MobileShell>
);
}
@@ -175,7 +182,7 @@ function EventsList({
statusFilter: EventStatusKey;
onStatusChange: (value: EventStatusKey) => void;
onOpen: (slug: string) => void;
onEdit: (slug: string) => void;
onEdit?: (slug: string) => void;
}) {
const { t } = useTranslation('management');
const { text, muted, subtle, border, primary, surface, surfaceMuted, accentSoft, accent, shadow } = useAdminTheme();
@@ -350,7 +357,7 @@ function EventRow({
statusLabel: string;
statusTone: 'success' | 'warning' | 'muted';
onOpen: (slug: string) => void;
onEdit: (slug: string) => void;
onEdit?: (slug: string) => void;
}) {
const { t } = useTranslation('management');
const stats = buildEventListStats(event);
@@ -386,11 +393,13 @@ function EventRow({
</XStack>
<PillBadge tone={statusTone}>{statusLabel}</PillBadge>
</YStack>
<Pressable onPress={() => onEdit(event.slug)}>
<Text fontSize="$xl" color={muted}>
˅
</Text>
</Pressable>
{onEdit ? (
<Pressable onPress={() => onEdit(event.slug)}>
<Text fontSize="$xl" color={muted}>
˅
</Text>
</Pressable>
) : null}
</XStack>
<XStack alignItems="center" space="$2" flexWrap="wrap">