Update dashboard KPIs for live show and auto-approval
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, 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, 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 } from '../api';
|
||||
import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto, updateEvent, getLiveShowQueue } from '../api';
|
||||
import { formatEventDate } from '../lib/events';
|
||||
import { useAuth } from '../auth/context';
|
||||
import { ADMIN_ACTION_COLORS, useAdminTheme } from './theme';
|
||||
@@ -164,6 +164,19 @@ export default function MobileDashboardPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const { data: liveShowApprovedCount = 0 } = useQuery({
|
||||
queryKey: ['mobile', 'dashboard', 'live-show-approved', activeEvent?.slug],
|
||||
enabled: Boolean(activeEvent?.slug),
|
||||
queryFn: async () => {
|
||||
if (!activeEvent?.slug) return 0;
|
||||
const result = await getLiveShowQueue(activeEvent.slug, { liveStatus: 'approved', perPage: 1 });
|
||||
if (result.photos.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return result.meta.total ?? result.photos.length;
|
||||
},
|
||||
});
|
||||
|
||||
const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -232,7 +245,7 @@ export default function MobileDashboardPage() {
|
||||
|
||||
{/* 2. PULSE STRIP */}
|
||||
<Separator backgroundColor={theme.border} opacity={0.6} />
|
||||
<PulseStrip event={activeEvent} stats={stats} />
|
||||
<PulseStrip event={activeEvent} stats={stats} liveShowApprovedCount={liveShowApprovedCount} />
|
||||
</YStack>
|
||||
</DashboardCard>
|
||||
|
||||
@@ -559,36 +572,52 @@ function LifecycleHero({
|
||||
);
|
||||
}
|
||||
|
||||
function PulseStrip({ event, stats }: any) {
|
||||
function PulseStrip({ event, stats, liveShowApprovedCount }: any) {
|
||||
const theme = useAdminTheme();
|
||||
const { t } = useTranslation('management');
|
||||
const { t } = useTranslation(['management', 'dashboard']);
|
||||
const uploadCount = stats?.uploads_total ?? event?.photo_count ?? 0;
|
||||
const guestCount = event?.active_invites_count ?? event?.total_invites_count ?? 0;
|
||||
const pendingCount = stats?.pending_photos ?? event?.pending_photo_count ?? 0;
|
||||
const likesTotal = stats?.likes_total ?? stats?.likes ?? 0;
|
||||
const showPending = (event?.settings?.guest_upload_visibility ?? 'review') !== 'immediate';
|
||||
const approvedCount = typeof liveShowApprovedCount === 'number' ? liveShowApprovedCount : 0;
|
||||
|
||||
return (
|
||||
<KpiStrip items={[
|
||||
{
|
||||
icon: ImageIcon,
|
||||
value: uploadCount,
|
||||
label: t('management:events.list.stats.photos', 'Photos'),
|
||||
color: theme.primary,
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
value: guestCount,
|
||||
label: t('management:events.list.stats.guests', 'Guests'),
|
||||
tone: 'neutral',
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
value: pendingCount,
|
||||
label: t('management:photos.filters.pending', 'Pending'),
|
||||
note: pendingCount > 0 ? t('management:common.actionNeeded', 'Review') : undefined,
|
||||
color: pendingCount > 0 ? '#8B5CF6' : theme.textMuted,
|
||||
},
|
||||
]} />
|
||||
);
|
||||
const items = [
|
||||
{
|
||||
icon: ImageIcon,
|
||||
value: uploadCount,
|
||||
label: t('management:events.list.stats.photos', 'Photos'),
|
||||
color: theme.primary,
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
value: guestCount,
|
||||
label: t('management:events.list.stats.guests', 'Guests'),
|
||||
tone: 'neutral' as const,
|
||||
},
|
||||
{
|
||||
icon: Tv,
|
||||
value: approvedCount,
|
||||
label: t('dashboard:kpis.liveShowApproved', 'Live Show approved'),
|
||||
color: ADMIN_ACTION_COLORS.liveShow,
|
||||
},
|
||||
showPending
|
||||
? {
|
||||
icon: ShieldCheck,
|
||||
value: pendingCount,
|
||||
label: t('management:photos.filters.pending', 'Pending'),
|
||||
note: pendingCount > 0 ? t('management:common.actionNeeded', 'Review') : undefined,
|
||||
color: pendingCount > 0 ? '#8B5CF6' : theme.textMuted,
|
||||
}
|
||||
: {
|
||||
icon: Heart,
|
||||
value: likesTotal,
|
||||
label: t('dashboard:kpis.likesTotal', 'Likes total'),
|
||||
color: ADMIN_ACTION_COLORS.images,
|
||||
},
|
||||
];
|
||||
|
||||
return <KpiStrip items={items} />;
|
||||
}
|
||||
|
||||
function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted }: any) {
|
||||
|
||||
Reference in New Issue
Block a user