Add auto-refresh polling across all admin and jury pages
- Round detail page: 15s for live data (projects, assignments, scores, workload), 30s for config, 60s for static data - Filtering dashboard: 15s for results/stats, 30s for rules (job status already 2s) - Project states table: 15s polling - Coverage report: 15s polling - Jury round page: 30s for assignments and round data - Deliberation session: 10s polling for live vote updates - Admin dashboard: 30s for stats Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8e5fc18da6
commit
93f4ad4b31
|
|
@ -253,7 +253,7 @@ function getActionIcon(action: string) {
|
|||
export function DashboardContent({ editionId, sessionName }: DashboardContentProps) {
|
||||
const { data, isLoading, error } = trpc.dashboard.getStats.useQuery(
|
||||
{ editionId },
|
||||
{ enabled: !!editionId, retry: 1 }
|
||||
{ enabled: !!editionId, retry: 1, refetchInterval: 30_000 }
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
|
|
|
|||
|
|
@ -151,26 +151,35 @@ export default function RoundDetailPage() {
|
|||
const utils = trpc.useUtils()
|
||||
|
||||
// ── Core data queries ──────────────────────────────────────────────────
|
||||
const { data: round, isLoading } = trpc.round.getById.useQuery({ id: roundId })
|
||||
const { data: projectStates } = trpc.roundEngine.getProjectStates.useQuery({ roundId })
|
||||
const { data: round, isLoading } = trpc.round.getById.useQuery(
|
||||
{ id: roundId },
|
||||
{ refetchInterval: 30_000 },
|
||||
)
|
||||
const { data: projectStates } = trpc.roundEngine.getProjectStates.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const competitionId = round?.competitionId ?? ''
|
||||
|
||||
const { data: juryGroups } = trpc.juryGroup.list.useQuery(
|
||||
{ competitionId },
|
||||
{ enabled: !!competitionId },
|
||||
{ enabled: !!competitionId, refetchInterval: 30_000 },
|
||||
)
|
||||
const { data: fileRequirements } = trpc.file.listRequirements.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 30_000 },
|
||||
)
|
||||
const { data: fileRequirements } = trpc.file.listRequirements.useQuery({ roundId })
|
||||
|
||||
// Fetch awards linked to this round
|
||||
const { data: competition } = trpc.competition.getById.useQuery(
|
||||
{ id: competitionId },
|
||||
{ enabled: !!competitionId },
|
||||
{ enabled: !!competitionId, refetchInterval: 60_000 },
|
||||
)
|
||||
const programId = competition?.programId
|
||||
const { data: awards } = trpc.specialAward.list.useQuery(
|
||||
{ programId: programId! },
|
||||
{ enabled: !!programId },
|
||||
{ enabled: !!programId, refetchInterval: 60_000 },
|
||||
)
|
||||
const roundAwards = awards?.filter((a) => a.evaluationRoundId === roundId) ?? []
|
||||
|
||||
|
|
@ -1184,6 +1193,7 @@ export default function RoundDetailPage() {
|
|||
function RoundUnassignedQueue({ roundId }: { roundId: string }) {
|
||||
const { data: unassigned, isLoading } = trpc.roundAssignment.unassignedQueue.useQuery(
|
||||
{ roundId, requiredReviews: 3 },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
@ -1235,7 +1245,10 @@ function RoundUnassignedQueue({ roundId }: { roundId: string }) {
|
|||
// ── Jury Progress Table ──────────────────────────────────────────────────
|
||||
|
||||
function JuryProgressTable({ roundId }: { roundId: string }) {
|
||||
const { data: workload, isLoading } = trpc.analytics.getJurorWorkload.useQuery({ roundId })
|
||||
const { data: workload, isLoading } = trpc.analytics.getJurorWorkload.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
|
@ -1291,7 +1304,10 @@ function JuryProgressTable({ roundId }: { roundId: string }) {
|
|||
// ── Score Distribution ───────────────────────────────────────────────────
|
||||
|
||||
function ScoreDistribution({ roundId }: { roundId: string }) {
|
||||
const { data: dist, isLoading } = trpc.analytics.getRoundScoreDistribution.useQuery({ roundId })
|
||||
const { data: dist, isLoading } = trpc.analytics.getRoundScoreDistribution.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const maxCount = useMemo(() =>
|
||||
dist ? Math.max(...dist.globalDistribution.map((b) => b.count), 1) : 1,
|
||||
|
|
@ -1428,7 +1444,10 @@ function IndividualAssignmentsTable({ roundId }: { roundId: string }) {
|
|||
const [newProjectId, setNewProjectId] = useState('')
|
||||
|
||||
const utils = trpc.useUtils()
|
||||
const { data: assignments, isLoading } = trpc.assignment.listByStage.useQuery({ roundId })
|
||||
const { data: assignments, isLoading } = trpc.assignment.listByStage.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const deleteMutation = trpc.assignment.delete.useMutation({
|
||||
onSuccess: () => {
|
||||
|
|
@ -1573,7 +1592,10 @@ function EvaluationCriteriaEditor({ roundId }: { roundId: string }) {
|
|||
}>>([])
|
||||
|
||||
const utils = trpc.useUtils()
|
||||
const { data: form, isLoading } = trpc.evaluation.getForm.useQuery({ roundId })
|
||||
const { data: form, isLoading } = trpc.evaluation.getForm.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 30_000 },
|
||||
)
|
||||
|
||||
const upsertMutation = trpc.evaluation.upsertForm.useMutation({
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ export default function JuryRoundDetailPage() {
|
|||
|
||||
const { data: assignments, isLoading } = trpc.roundAssignment.getMyAssignments.useQuery(
|
||||
{ roundId },
|
||||
{ enabled: !!roundId }
|
||||
{ enabled: !!roundId, refetchInterval: 30_000 }
|
||||
)
|
||||
|
||||
const { data: round } = trpc.round.getById.useQuery(
|
||||
{ id: roundId },
|
||||
{ enabled: !!roundId }
|
||||
{ enabled: !!roundId, refetchInterval: 30_000 }
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ export default function JuryDeliberationPage({ params: paramsPromise }: { params
|
|||
const params = use(paramsPromise);
|
||||
const utils = trpc.useUtils();
|
||||
|
||||
const { data: session, isLoading } = trpc.deliberation.getSession.useQuery({
|
||||
sessionId: params.sessionId
|
||||
});
|
||||
const { data: session, isLoading } = trpc.deliberation.getSession.useQuery(
|
||||
{ sessionId: params.sessionId },
|
||||
{ refetchInterval: 10_000 },
|
||||
);
|
||||
|
||||
const submitVoteMutation = trpc.deliberation.submitVote.useMutation({
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ interface CoverageReportProps {
|
|||
}
|
||||
|
||||
export function CoverageReport({ roundId }: CoverageReportProps) {
|
||||
const { data: coverage, isLoading } = trpc.roundAssignment.coverageReport.useQuery({
|
||||
roundId,
|
||||
requiredReviews: 3,
|
||||
})
|
||||
const { data: coverage, isLoading } = trpc.roundAssignment.coverageReport.useQuery(
|
||||
{ roundId, requiredReviews: 3 },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -108,13 +108,18 @@ export function FilteringDashboard({ competitionId, roundId }: FilteringDashboar
|
|||
// -- Queries --
|
||||
const { data: stats, isLoading: statsLoading } = trpc.filtering.getResultStats.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const { data: latestJob, isLoading: jobLoading } = trpc.filtering.getLatestJob.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const { data: rules } = trpc.filtering.getRules.useQuery({ roundId })
|
||||
const { data: rules } = trpc.filtering.getRules.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 30_000 },
|
||||
)
|
||||
|
||||
const { data: resultsPage, isLoading: resultsLoading } = trpc.filtering.getResults.useQuery(
|
||||
{
|
||||
|
|
@ -123,6 +128,7 @@ export function FilteringDashboard({ competitionId, roundId }: FilteringDashboar
|
|||
page,
|
||||
perPage: 25,
|
||||
},
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const { data: jobStatus } = trpc.filtering.getJobStatus.useQuery(
|
||||
|
|
@ -1089,7 +1095,10 @@ function FilteringRulesSection({ roundId }: { roundId: string }) {
|
|||
|
||||
const utils = trpc.useUtils()
|
||||
|
||||
const { data: rules, isLoading } = trpc.filtering.getRules.useQuery({ roundId })
|
||||
const { data: rules, isLoading } = trpc.filtering.getRules.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 30_000 },
|
||||
)
|
||||
|
||||
const createMutation = trpc.filtering.createRule.useMutation({
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ export function ProjectStatesTable({ competitionId, roundId }: ProjectStatesTabl
|
|||
|
||||
const { data: projectStates, isLoading } = trpc.roundEngine.getProjectStates.useQuery(
|
||||
{ roundId },
|
||||
{ refetchInterval: 15_000 },
|
||||
)
|
||||
|
||||
const transitionMutation = trpc.roundEngine.transitionProject.useMutation({
|
||||
|
|
|
|||
Loading…
Reference in New Issue