Observer dashboard extraction, PDF reports, jury UX overhaul, and miscellaneous improvements
- Extract observer dashboard to client component, add PDF export button - Add PDF report generator with jsPDF for analytics reports - Overhaul jury evaluation page with improved layout and UX - Add new analytics endpoints for observer/admin reports - Improve round creation/edit forms with better settings - Fix filtering rules page, CSV export dialog, notification bell - Update auth, prisma schema, and various type fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,12 +37,10 @@ import {
|
||||
Users,
|
||||
ClipboardList,
|
||||
CheckCircle2,
|
||||
PieChart,
|
||||
TrendingUp,
|
||||
GitCompare,
|
||||
UserCheck,
|
||||
Globe,
|
||||
Printer,
|
||||
} from 'lucide-react'
|
||||
import { formatDateOnly } from '@/lib/utils'
|
||||
import {
|
||||
@@ -57,6 +55,7 @@ import {
|
||||
JurorConsistencyChart,
|
||||
DiversityMetricsChart,
|
||||
} from '@/components/charts'
|
||||
import { ExportPdfButton } from '@/components/shared/export-pdf-button'
|
||||
|
||||
function ReportsOverview() {
|
||||
const { data: programs, isLoading } = trpc.program.list.useQuery({ includeRounds: true })
|
||||
@@ -631,6 +630,19 @@ function DiversityTab() {
|
||||
}
|
||||
|
||||
export default function ReportsPage() {
|
||||
const [pdfRoundId, setPdfRoundId] = useState<string | null>(null)
|
||||
|
||||
const { data: pdfPrograms } = trpc.program.list.useQuery({ includeRounds: true })
|
||||
const pdfRounds = pdfPrograms?.flatMap((p) =>
|
||||
p.rounds.map((r) => ({ id: r.id, name: r.name, programName: `${p.year} Edition` }))
|
||||
) || []
|
||||
|
||||
if (pdfRounds.length && !pdfRoundId) {
|
||||
setPdfRoundId(pdfRounds[0].id)
|
||||
}
|
||||
|
||||
const selectedPdfRound = pdfRounds.find((r) => r.id === pdfRoundId)
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
@@ -666,16 +678,27 @@ export default function ReportsPage() {
|
||||
Diversity
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
window.print()
|
||||
}}
|
||||
>
|
||||
<Printer className="mr-2 h-4 w-4" />
|
||||
Export PDF
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Select value={pdfRoundId || ''} onValueChange={setPdfRoundId}>
|
||||
<SelectTrigger className="w-[220px]">
|
||||
<SelectValue placeholder="Select round for PDF" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{pdfRounds.map((round) => (
|
||||
<SelectItem key={round.id} value={round.id}>
|
||||
{round.programName} - {round.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{pdfRoundId && (
|
||||
<ExportPdfButton
|
||||
roundId={pdfRoundId}
|
||||
roundName={selectedPdfRound?.name}
|
||||
programName={selectedPdfRound?.programName}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TabsContent value="overview">
|
||||
|
||||
Reference in New Issue
Block a user