feat: Replace initiative card N+1 queries with server-computed activity indicator

listInitiatives now returns an activity object (state, activePhase, phase
counts) derived server-side from phases, eliminating per-card listPhases
queries. Initiative cards show a StatusDot with pulse animation + label
instead of a static StatusBadge. Removed redundant View and Spawn Architect
buttons from cards. Added variant override prop to StatusDot.
This commit is contained in:
Lukas May
2026-03-03 12:49:07 +01:00
parent b74b59b906
commit 96386e1c3d
11 changed files with 167 additions and 96 deletions

View File

@@ -6,6 +6,7 @@ import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import type { ProcedureBuilder } from '../trpc.js';
import { requireInitiativeRepository, requireProjectRepository, requireTaskRepository } from './_helpers.js';
import { deriveInitiativeActivity } from './initiative-activity.js';
export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
return {
@@ -63,10 +64,22 @@ export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
}).optional())
.query(async ({ ctx, input }) => {
const repo = requireInitiativeRepository(ctx);
if (input?.status) {
return repo.findByStatus(input.status);
const initiatives = input?.status
? await repo.findByStatus(input.status)
: await repo.findAll();
if (ctx.phaseRepository) {
const phaseRepo = ctx.phaseRepository;
return Promise.all(initiatives.map(async (init) => {
const phases = await phaseRepo.findByInitiativeId(init.id);
return { ...init, activity: deriveInitiativeActivity(init, phases) };
}));
}
return repo.findAll();
return initiatives.map(init => ({
...init,
activity: deriveInitiativeActivity(init, []),
}));
}),
getInitiative: publicProcedure