feat: semi-finalist tracker dashboard, account reminders, search + UX fixes
- Add getSemiFinalistStats query with per-category/per-award breakdown - Add sendAccountReminders mutation with invite token generation and dedup - Add SemiFinalistTracker dashboard widget with progress bars and remind buttons - Add ACCOUNT_REMINDER email template - Extend project search to match team member name/email (7 locations) - Fix Passed count deduplication: count distinct projects, not round-state rows - Fix role switcher: visible pills above user section, auto-refresh session on mount Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ import { ActivityFeed } from '@/components/dashboard/activity-feed'
|
||||
import { CategoryBreakdown } from '@/components/dashboard/category-breakdown'
|
||||
import { DashboardSkeleton } from '@/components/dashboard/dashboard-skeleton'
|
||||
import { RecentEvaluations } from '@/components/dashboard/recent-evaluations'
|
||||
import { SemiFinalistTracker } from '@/components/dashboard/semi-finalist-tracker'
|
||||
|
||||
type DashboardContentProps = {
|
||||
editionId: string
|
||||
@@ -125,6 +126,10 @@ export function DashboardContent({ editionId, sessionName }: DashboardContentPro
|
||||
{ limit: 8 },
|
||||
{ enabled: !!editionId, refetchInterval: 5_000 }
|
||||
)
|
||||
const { data: semiFinalistStats } = trpc.dashboard.getSemiFinalistStats.useQuery(
|
||||
{ editionId },
|
||||
{ enabled: !!editionId, refetchInterval: 60_000 }
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
return <DashboardSkeleton />
|
||||
@@ -271,7 +276,18 @@ export function DashboardContent({ editionId, sessionName }: DashboardContentPro
|
||||
<SmartActions actions={nextActions} />
|
||||
</AnimatedCard>
|
||||
|
||||
<AnimatedCard index={6}>
|
||||
{semiFinalistStats && semiFinalistStats.byCategory.length > 0 && (
|
||||
<AnimatedCard index={6}>
|
||||
<SemiFinalistTracker
|
||||
byCategory={semiFinalistStats.byCategory}
|
||||
byAward={semiFinalistStats.byAward}
|
||||
unactivatedProjects={semiFinalistStats.unactivatedProjects}
|
||||
editionId={editionId}
|
||||
/>
|
||||
</AnimatedCard>
|
||||
)}
|
||||
|
||||
<AnimatedCard index={7}>
|
||||
<ActivityFeed activity={liveActivity ?? recentActivity} />
|
||||
</AnimatedCard>
|
||||
</div>
|
||||
@@ -280,12 +296,12 @@ export function DashboardContent({ editionId, sessionName }: DashboardContentPro
|
||||
{/* Bottom Full Width */}
|
||||
<div className="grid gap-6 lg:grid-cols-12">
|
||||
<div className="lg:col-span-8">
|
||||
<AnimatedCard index={7}>
|
||||
<AnimatedCard index={8}>
|
||||
<GeographicSummaryCard programId={editionId} />
|
||||
</AnimatedCard>
|
||||
</div>
|
||||
<div className="lg:col-span-4">
|
||||
<AnimatedCard index={8}>
|
||||
<AnimatedCard index={9}>
|
||||
<CategoryBreakdown
|
||||
categories={categoryBreakdown}
|
||||
issues={oceanIssueBreakdown}
|
||||
|
||||
Reference in New Issue
Block a user