Fix demo task readiness and gate event creation
This commit is contained in:
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { AlertCircle, Bell, CalendarDays, Camera, CheckCircle2, ChevronRight, Circle, Download, Heart, Image as ImageIcon, Layout, ListTodo, Megaphone, QrCode, Settings, ShieldCheck, Sparkles, TrendingUp, Tv, Users } from 'lucide-react';
|
||||
import { AlertCircle, Bell, CalendarDays, Camera, CheckCircle2, ChevronRight, Circle, Download, Heart, Image as ImageIcon, Layout, ListTodo, Megaphone, Plus, QrCode, Settings, ShieldCheck, Sparkles, TrendingUp, Tv, Users } from 'lucide-react';
|
||||
import { Button } from '@tamagui/button';
|
||||
import { Card } from '@tamagui/card';
|
||||
import { YGroup } from '@tamagui/group';
|
||||
@@ -19,7 +19,7 @@ import toast from 'react-hot-toast';
|
||||
import { MobileShell } from './components/MobileShell';
|
||||
import { ADMIN_EVENTS_PATH, adminPath } from '../constants';
|
||||
import { useEventContext } from '../context/EventContext';
|
||||
import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto, updateEvent, getLiveShowQueue } from '../api';
|
||||
import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto, updateEvent, getLiveShowQueue, getTenantPackagesOverview, type TenantPackageSummary } from '../api';
|
||||
import { formatEventDate } from '../lib/events';
|
||||
import { useAuth } from '../auth/context';
|
||||
import { ADMIN_ACTION_COLORS, useAdminTheme } from './theme';
|
||||
@@ -37,6 +37,59 @@ function translateLimits(t: any) {
|
||||
return (key: string, options?: any) => t(`management:limits.${key}`, key, options);
|
||||
}
|
||||
|
||||
function collectActivePackages(
|
||||
overview: { packages: TenantPackageSummary[]; activePackage: TenantPackageSummary | null } | null
|
||||
): TenantPackageSummary[] {
|
||||
if (!overview) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const packages = overview.packages ?? [];
|
||||
const activePackage = overview.activePackage;
|
||||
const activeList = packages.filter((pkg) => pkg.active);
|
||||
|
||||
if (activePackage && !activeList.some((pkg) => pkg.id === activePackage.id) && activePackage.active) {
|
||||
return [activePackage, ...activeList];
|
||||
}
|
||||
|
||||
return activeList;
|
||||
}
|
||||
|
||||
function toNumber(value: unknown): number | null {
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === 'string' && value.trim() !== '') {
|
||||
const parsed = Number(value);
|
||||
if (Number.isFinite(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function resellerHasRemainingEvents(pkg: TenantPackageSummary): boolean {
|
||||
if (pkg.package_type !== 'reseller') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const remaining = toNumber(pkg.remaining_events);
|
||||
if (remaining !== null) {
|
||||
return remaining > 0;
|
||||
}
|
||||
|
||||
const limits = (pkg.package_limits ?? {}) as Record<string, unknown>;
|
||||
const limitMaxEvents = toNumber(limits.max_events_per_year);
|
||||
if (limitMaxEvents === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const usedEvents = toNumber(pkg.used_events) ?? 0;
|
||||
return limitMaxEvents > usedEvents;
|
||||
}
|
||||
|
||||
// --- TAMAGUI-ALIGNED PRIMITIVES ---
|
||||
|
||||
function DashboardCard({
|
||||
@@ -129,6 +182,7 @@ export default function MobileDashboardPage() {
|
||||
const { user } = useAuth();
|
||||
const theme = useAdminTheme();
|
||||
const isMember = user?.role === 'member';
|
||||
const isSuperAdmin = user?.role === 'super_admin' || user?.role === 'superadmin';
|
||||
|
||||
// --- LOGIC ---
|
||||
const memberPermissions = React.useMemo(() => {
|
||||
@@ -178,6 +232,29 @@ export default function MobileDashboardPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const { data: packagesOverview, isLoading: packagesLoading } = useQuery({
|
||||
queryKey: ['mobile', 'dashboard', 'packages-overview'],
|
||||
enabled: !isMember && !isSuperAdmin,
|
||||
queryFn: () => getTenantPackagesOverview({ force: true }),
|
||||
});
|
||||
|
||||
const canCreateEvent = React.useMemo(() => {
|
||||
if (!canManageEvents) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isSuperAdmin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMember || packagesLoading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const activePackages = collectActivePackages(packagesOverview ?? null);
|
||||
return activePackages.some((pkg) => resellerHasRemainingEvents(pkg));
|
||||
}, [canManageEvents, isSuperAdmin, isMember, packagesLoading, packagesOverview]);
|
||||
|
||||
const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -265,6 +342,7 @@ export default function MobileDashboardPage() {
|
||||
permissions={memberPermissions}
|
||||
isMember={isMember}
|
||||
isCompleted={isCompleted}
|
||||
canCreateEvent={canCreateEvent}
|
||||
/>
|
||||
|
||||
{/* 5. RECENT PHOTOS */}
|
||||
@@ -627,7 +705,7 @@ function PulseStrip({ event, stats, liveShowApprovedCount }: any) {
|
||||
return <KpiStrip items={items} />;
|
||||
}
|
||||
|
||||
function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted }: any) {
|
||||
function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted, canCreateEvent }: any) {
|
||||
const theme = useAdminTheme();
|
||||
const { t } = useTranslation(['management', 'dashboard']);
|
||||
const slug = event?.slug;
|
||||
@@ -649,6 +727,7 @@ function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted }
|
||||
].filter(Boolean) as ToolItem[];
|
||||
|
||||
const adminItems: ToolItem[] = [
|
||||
canCreateEvent ? { label: t('management:events.list.actions.create', 'Create Event'), icon: Plus, path: `/mobile/events/new`, color: theme.primary } : null,
|
||||
{ label: t('management:mobileDashboard.shortcutAnalytics', 'Analytics'), icon: TrendingUp, path: `/mobile/events/${slug}/analytics`, color: ADMIN_ACTION_COLORS.analytics },
|
||||
!isCompleted ? { label: t('events.recap.exportTitleShort', 'Exports'), icon: Download, path: `/mobile/exports`, color: ADMIN_ACTION_COLORS.recap } : null,
|
||||
{ label: t('management:mobileProfile.settings', 'Settings'), icon: Settings, path: `/mobile/events/${slug}/edit`, color: ADMIN_ACTION_COLORS.settings },
|
||||
|
||||
Reference in New Issue
Block a user