Merge pull request 'fix(halachot): ספירת-תור אמיתית + עדכון-חי בתגי-הכרעה (#6/#7/#8)' (#273) from worktree-halacha-real-counts into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m31s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s

This commit was merged in pull request #273.
This commit is contained in:
2026-06-16 08:48:49 +00:00
3 changed files with 23 additions and 16 deletions

View File

@@ -6719,6 +6719,12 @@ async def precedent_library_stats() -> dict:
halachot_approved = await conn.fetchval(
"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 {
"precedents_total": int(total or 0),
"by_practice_area": [
@@ -6732,6 +6738,8 @@ async def precedent_library_stats() -> dict:
"halachot_total": int(halachot_total or 0),
"halachot_pending": int(halachot_pending or 0),
"halachot_approved": int(halachot_approved or 0),
"halachot_rejected": int(halachot_rejected or 0),
"halachot_deferred": int(halachot_deferred or 0),
}

View File

@@ -11,7 +11,7 @@ import { CorroborationBadge } from "./corroboration-badge";
import { practiceAreaLabel } from "./practice-area";
import {
useHalachotPending, useHalachotByStatus, useUpdateHalacha, useBatchReviewHalachot,
isExtractionFixItem, type Halacha,
useLibraryStats, isExtractionFixItem, type Halacha,
} from "@/lib/api/precedent-library";
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 ──────────────────────────────────────────────────────────────
type Tab = "pending" | "rejected" | "approved";
@@ -998,16 +991,16 @@ const TAB_LABELS: Record<Tab, string> = {
export function HalachaReviewPanel() {
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> = {
pending: pendingCount,
rejected: rejectedCount,
approved: approvedCount,
pending: stats?.halachot_pending ?? null,
rejected: stats?.halachot_rejected ?? null,
approved: stats?.halachot_approved ?? null,
};
return (

View File

@@ -188,6 +188,8 @@ export type LibraryStats = {
halachot_total: number;
halachot_pending: number;
halachot_approved: number;
halachot_rejected: number;
halachot_deferred: number;
};
export type ListFilters = {
@@ -301,7 +303,11 @@ export function useLibraryStats() {
queryKey: libraryKeys.stats(),
queryFn: ({ 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,
});
}