fix(halachot): ספירת-תור אמיתית + עדכון-חי בתגי-הכרעה (#6/#7/#8) #273
@@ -6719,6 +6719,12 @@ async def precedent_library_stats() -> dict:
|
|||||||
halachot_approved = await conn.fetchval(
|
halachot_approved = await conn.fetchval(
|
||||||
"SELECT COUNT(*) FROM halachot WHERE review_status IN ('approved', 'published')"
|
"SELECT COUNT(*) FROM halachot WHERE review_status IN ('approved', 'published')"
|
||||||
)
|
)
|
||||||
|
halachot_rejected = await conn.fetchval(
|
||||||
|
"SELECT COUNT(*) FROM halachot WHERE review_status = 'rejected'"
|
||||||
|
)
|
||||||
|
halachot_deferred = await conn.fetchval(
|
||||||
|
"SELECT COUNT(*) FROM halachot WHERE review_status = 'deferred'"
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"precedents_total": int(total or 0),
|
"precedents_total": int(total or 0),
|
||||||
"by_practice_area": [
|
"by_practice_area": [
|
||||||
@@ -6732,6 +6738,8 @@ async def precedent_library_stats() -> dict:
|
|||||||
"halachot_total": int(halachot_total or 0),
|
"halachot_total": int(halachot_total or 0),
|
||||||
"halachot_pending": int(halachot_pending or 0),
|
"halachot_pending": int(halachot_pending or 0),
|
||||||
"halachot_approved": int(halachot_approved or 0),
|
"halachot_approved": int(halachot_approved or 0),
|
||||||
|
"halachot_rejected": int(halachot_rejected or 0),
|
||||||
|
"halachot_deferred": int(halachot_deferred or 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { CorroborationBadge } from "./corroboration-badge";
|
|||||||
import { practiceAreaLabel } from "./practice-area";
|
import { practiceAreaLabel } from "./practice-area";
|
||||||
import {
|
import {
|
||||||
useHalachotPending, useHalachotByStatus, useUpdateHalacha, useBatchReviewHalachot,
|
useHalachotPending, useHalachotByStatus, useUpdateHalacha, useBatchReviewHalachot,
|
||||||
isExtractionFixItem, type Halacha,
|
useLibraryStats, isExtractionFixItem, type Halacha,
|
||||||
} from "@/lib/api/precedent-library";
|
} from "@/lib/api/precedent-library";
|
||||||
import { AuthorityBadge, ruleTypeLabel } from "./halacha-meta";
|
import { AuthorityBadge, ruleTypeLabel } from "./halacha-meta";
|
||||||
|
|
||||||
@@ -979,13 +979,6 @@ function PendingPanel() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Count badge for tabs ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function useHalachaCount(status: string) {
|
|
||||||
const { data } = useHalachotByStatus(status, 1000);
|
|
||||||
return data?.count ?? data?.items.length ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Main export ──────────────────────────────────────────────────────────────
|
// ─── Main export ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
type Tab = "pending" | "rejected" | "approved";
|
type Tab = "pending" | "rejected" | "approved";
|
||||||
@@ -998,16 +991,16 @@ const TAB_LABELS: Record<Tab, string> = {
|
|||||||
|
|
||||||
export function HalachaReviewPanel() {
|
export function HalachaReviewPanel() {
|
||||||
const [tab, setTab] = useState<Tab>("pending");
|
const [tab, setTab] = useState<Tab>("pending");
|
||||||
const { data: pendingData } = useHalachotPending({ limit: 500 });
|
|
||||||
const rejectedCount = useHalachaCount("rejected");
|
|
||||||
const approvedCount = useHalachaCount("approved");
|
|
||||||
|
|
||||||
const pendingCount = pendingData?.items.length ?? null;
|
// Real COUNT(*) totals from the stats endpoint — not the limit-capped
|
||||||
|
// /api/halachot len(rows), which pinned these chips at 500/1000/1000 and only
|
||||||
|
// refreshed on navigation. The stats query polls, so the chips track live (#6/#7/#8).
|
||||||
|
const { data: stats } = useLibraryStats();
|
||||||
|
|
||||||
const counts: Record<Tab, number | null> = {
|
const counts: Record<Tab, number | null> = {
|
||||||
pending: pendingCount,
|
pending: stats?.halachot_pending ?? null,
|
||||||
rejected: rejectedCount,
|
rejected: stats?.halachot_rejected ?? null,
|
||||||
approved: approvedCount,
|
approved: stats?.halachot_approved ?? null,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ export type LibraryStats = {
|
|||||||
halachot_total: number;
|
halachot_total: number;
|
||||||
halachot_pending: number;
|
halachot_pending: number;
|
||||||
halachot_approved: number;
|
halachot_approved: number;
|
||||||
|
halachot_rejected: number;
|
||||||
|
halachot_deferred: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ListFilters = {
|
export type ListFilters = {
|
||||||
@@ -301,7 +303,11 @@ export function useLibraryStats() {
|
|||||||
queryKey: libraryKeys.stats(),
|
queryKey: libraryKeys.stats(),
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
apiRequest<LibraryStats>("/api/precedent-library/stats", { signal }),
|
apiRequest<LibraryStats>("/api/precedent-library/stats", { signal }),
|
||||||
staleTime: 60_000,
|
staleTime: 30_000,
|
||||||
|
// The halacha-review tab counts ride on this (real COUNT(*) — not the
|
||||||
|
// limit-capped /api/halachot len), so poll so the chips track approvals
|
||||||
|
// live instead of only refreshing on navigation (#6/#7/#8).
|
||||||
|
refetchInterval: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user