feat(ui): פאנל אישור-תכניות — טאב /precedents + מרכז-אישורים (PR-B)
הטמעת ה-UI למרשם-התכניות אחרי אישור-עיצוב ב-Claude Design (מוקאפ 22-plans-review). - web-ui/src/lib/api/plans.ts: hooks (usePlansPending, usePlanDuplicates, useUpsertPlan, useUpdatePlan, useReviewPlan, useMergePlans) + טיפוס Plan מקומי. - plans-review-panel.tsx: כרטיס-תכנית עם משפט-הציטוט הקנוני (כפי שייכתב בבלוק ט), שדות-תוקף, סימון חוסר-תאריך, באנר "כפילות אפשרית → מזג לכאן" (find_similar_plans, מיזוג ידני — G10), עריכה/הוספה inline עם תצוגה-מקדימה חיה של הציטוט. - precedents/page.tsx: טאב "תכניות" + PlansPendingPill + deep-link tab=plans. - web/app.py: href קטגוריית-התכניות במרכז-האישורים → /precedents?tab=plans. - api:types: types.ts מחודש מ-openapi החי (5 נתיבי /api/plans). מרכז-האישורים (/approvals) מרנדר קטגוריות גנרית — קטגוריית-התכניות (PR-A) מופיעה אוטומטית. אימות: api:types ✓, tsc --noEmit ✓, lint exit=0 (ללא אזהרות חדשות). Invariants: G10 (אישור אנושי + מיזוג ידני) · INV-AH (ציטוט דטרמיניסטי, תצוגה-מקדימה תואמת format_plan_citation) · INV-IA (שער-אחד: טאב קיים + מרכז-אישורים, ללא עמוד חדש) · X6 (UI↔API, apiRequest + טיפוסים). עבר שער-העיצוב Claude Design (feedback_claude_design_gate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,8 +7,10 @@ import { AppShell } from "@/components/app-shell";
|
||||
import { LibraryListPanel } from "@/components/precedents/library-list-panel";
|
||||
import { LibrarySearchPanel } from "@/components/precedents/library-search-panel";
|
||||
import { HalachaReviewPanel } from "@/components/precedents/halacha-review-panel";
|
||||
import { PlansReviewPanel } from "@/components/precedents/plans-review-panel";
|
||||
import { LibraryStatsPanel } from "@/components/precedents/library-stats-panel";
|
||||
import { useHalachotPending } from "@/lib/api/precedent-library";
|
||||
import { usePlansPending } from "@/lib/api/plans";
|
||||
import { useMissingPrecedents } from "@/lib/api/missing-precedents";
|
||||
|
||||
/**
|
||||
@@ -47,13 +49,18 @@ function PendingPill() {
|
||||
return <CountPill n={data?.count ?? 0} tone="warn" />;
|
||||
}
|
||||
|
||||
function PlansPendingPill() {
|
||||
const { data } = usePlansPending();
|
||||
return <CountPill n={data?.count ?? 0} tone="warn" />;
|
||||
}
|
||||
|
||||
function IncomingPill() {
|
||||
// "פסיקה נכנסת" = open missing-precedents waiting for the chair to upload.
|
||||
const { data } = useMissingPrecedents({ status: "open", limit: 1 });
|
||||
return <CountPill n={data?.by_status?.open ?? 0} tone="info" />;
|
||||
}
|
||||
|
||||
const PRECEDENT_TABS = new Set(["library", "search", "review", "incoming", "stats"]);
|
||||
const PRECEDENT_TABS = new Set(["library", "search", "review", "plans", "incoming", "stats"]);
|
||||
|
||||
export default function PrecedentsPage() {
|
||||
// Controlled so a deep link like /precedents?tab=review (e.g. from a pending
|
||||
@@ -92,6 +99,7 @@ export default function PrecedentsPage() {
|
||||
{ value: "library", label: "ספרייה", pill: null },
|
||||
{ value: "search", label: "חיפוש בקורפוס", pill: null },
|
||||
{ value: "review", label: "תור הלכות", pill: <PendingPill /> },
|
||||
{ value: "plans", label: "תכניות", pill: <PlansPendingPill /> },
|
||||
{
|
||||
value: "incoming",
|
||||
label: "פסיקה נכנסת",
|
||||
@@ -123,6 +131,10 @@ export default function PrecedentsPage() {
|
||||
<HalachaReviewPanel />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="plans" className="mt-0">
|
||||
<PlansReviewPanel />
|
||||
</TabsContent>
|
||||
|
||||
{/* "פסיקה נכנסת" — the incoming/missing-precedent queue. Kept as a
|
||||
tab per the mockup; full management lives on /missing-precedents. */}
|
||||
<TabsContent value="incoming" className="mt-0">
|
||||
|
||||
Reference in New Issue
Block a user