Dafna asked for a single page under the prod site listing everything she needs
to approve, so nothing is forgotten — the visible embodiment of INV-G10 (human
gates) and INV-QA1 (halacha backlog must be visible).
Backend — GET /api/chair/pending aggregates every pending chair gate, each as a
direct source query (count + sample + action link):
- halachot review backlog (review_status='pending_review') + oldest
- open missing precedents
- unresolved chair_feedback
- qa_failed cases
- gold-set review (FU-5, file-based, best-effort: total vs source='chair')
Frontend — /approvals page ("מרכז אישורים"):
- src/lib/api/chair.ts — usePendingApprovals() (hand-typed until next api:types)
- src/app/approvals/page.tsx — card per category, severity-coloured count, sample
rows, oldest-pending date, link to where each is handled; live (60s refetch)
- app-shell nav: "מרכז אישורים" in the work group + total-pending badge (quiet at 0)
Live counts at build time surfaced the value immediately: 226 open missing
precedents, 178 pending halachot, 20 unapplied feedback notes, 1 qa_failed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { apiRequest } from "./client";
|
|
|
|
/**
|
|
* Chair approval center (INV-G10) — aggregates every pending human-gate item
|
|
* (halacha approvals, missing precedents, unapplied feedback, QA-failed cases,
|
|
* gold-set review) so nothing Dafna must approve is forgotten.
|
|
*
|
|
* Hand-typed (not from the generated types.ts) because /api/chair/pending is a
|
|
* new endpoint; switch to the generated type after the next `npm run api:types`.
|
|
*/
|
|
export type ApprovalSeverity = "high" | "medium" | "low" | "ok";
|
|
|
|
export type ApprovalSample = { text: string; source: string };
|
|
|
|
export type ApprovalCategory = {
|
|
key: string;
|
|
label: string;
|
|
description: string;
|
|
count: number;
|
|
severity: ApprovalSeverity;
|
|
href: string | null;
|
|
oldest_at?: string | null;
|
|
sample?: ApprovalSample[];
|
|
extra?: { total: number; reviewed: number };
|
|
};
|
|
|
|
export type PendingApprovals = {
|
|
total_pending: number;
|
|
generated_at: string;
|
|
categories: ApprovalCategory[];
|
|
};
|
|
|
|
export function usePendingApprovals() {
|
|
return useQuery({
|
|
queryKey: ["chair", "pending"],
|
|
queryFn: () => apiRequest<PendingApprovals>("/api/chair/pending"),
|
|
refetchInterval: 60_000,
|
|
staleTime: 30_000,
|
|
});
|
|
}
|