feat(halacha): כפתורי אישור/דחייה/שחזור inline ברכיב "הלכות שחולצו"
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 38s

ExtractedHalachotSection היה read-only — הוסף כפתורי פעולה לכל הלכה לפי
review_status: נדחתה → אשר/שחזר לתור · מאושרת → בטל אישור/דחה ·
ממתינה → אשר/דחה. משתמש ב-useUpdateHalacha שמרענן את detail query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 12:27:48 +00:00
parent 68a77c11b6
commit 59ff4e31cf

View File

@@ -1,9 +1,12 @@
"use client"; "use client";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { Check, X, RotateCcw } from "lucide-react";
import { toast } from "sonner";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { CorroborationBadge } from "@/components/precedents/corroboration-badge"; import { CorroborationBadge } from "@/components/precedents/corroboration-badge";
import type { Halacha } from "@/lib/api/precedent-library"; import { useUpdateHalacha, type Halacha } from "@/lib/api/precedent-library";
const RULE_TYPE_LABELS: Record<string, string> = { const RULE_TYPE_LABELS: Record<string, string> = {
binding: "הלכה מחייבת", binding: "הלכה מחייבת",
@@ -47,13 +50,26 @@ export function ReviewStatusPill({ status }: { status: Halacha["review_status"]
); );
} }
/* Read-only roll-up of every halacha extracted from a precedent — /* Roll-up of every halacha extracted from a precedent — approved +
* approved + pending + rejected. The "ממתין לאישור" tab only surfaces * pending + rejected. The "ממתין לאישור" tab surfaces pending items
* pending items globally; this section is the per-case view. To act on * globally; this section is the per-case view, with inline status
* an item (approve / edit / reject), go to the review tab — keeping the * actions so the chair can flip a single ruling (e.g. approve one that
* surfaces separated avoids duplicate review UX in two places. */ * was rejected) without leaving the precedent. */
export function ExtractedHalachotSection({ halachot }: { halachot: Halacha[] }) { export function ExtractedHalachotSection({ halachot }: { halachot: Halacha[] }) {
const [filter, setFilter] = useState<StatusFilter>("all"); const [filter, setFilter] = useState<StatusFilter>("all");
const update = useUpdateHalacha();
const setStatus = async (
h: Halacha,
status: "approved" | "rejected" | "pending_review",
) => {
try {
await update.mutateAsync({ id: h.id, patch: { review_status: status } });
toast.success("עודכן");
} catch (e) {
toast.error(e instanceof Error ? e.message : "שגיאה");
}
};
const counts = useMemo(() => { const counts = useMemo(() => {
const c = { all: halachot.length, approved: 0, pending: 0, rejected: 0 }; const c = { all: halachot.length, approved: 0, pending: 0, rejected: 0 };
@@ -204,6 +220,62 @@ export function ExtractedHalachotSection({ halachot }: { halachot: Halacha[] })
))} ))}
</div> </div>
) : null} ) : null}
{/* Inline status actions — contextual per current review_status */}
<div className="flex items-center gap-2 justify-end pt-2 border-t border-rule-soft">
{h.review_status === "rejected" && (
<>
<Button size="sm" variant="ghost" disabled={update.isPending}
onClick={() => setStatus(h, "pending_review")}
className="text-ink-muted hover:text-navy">
<RotateCcw className="w-3.5 h-3.5 me-1" />
שחזר לתור
</Button>
<Button size="sm" disabled={update.isPending}
onClick={() => setStatus(h, "approved")}
className="bg-gold text-navy hover:bg-gold-deep">
<Check className="w-3.5 h-3.5 me-1" />
אשר
</Button>
</>
)}
{(h.review_status === "approved" || h.review_status === "published") && (
<>
<Button size="sm" variant="ghost" disabled={update.isPending}
onClick={() => setStatus(h, "pending_review")}
className="text-ink-muted hover:text-navy">
<RotateCcw className="w-3.5 h-3.5 me-1" />
בטל אישור
</Button>
<Button size="sm" variant="ghost" disabled={update.isPending}
onClick={() => {
if (window.confirm("לדחות הלכה זו?")) setStatus(h, "rejected");
}}
className="text-danger hover:text-danger hover:bg-danger-bg">
<X className="w-3.5 h-3.5 me-1" />
דחה
</Button>
</>
)}
{h.review_status === "pending_review" && (
<>
<Button size="sm" variant="ghost" disabled={update.isPending}
onClick={() => {
if (window.confirm("לדחות הלכה זו?")) setStatus(h, "rejected");
}}
className="text-danger hover:text-danger hover:bg-danger-bg">
<X className="w-3.5 h-3.5 me-1" />
דחה
</Button>
<Button size="sm" disabled={update.isPending}
onClick={() => setStatus(h, "approved")}
className="bg-gold text-navy hover:bg-gold-deep">
<Check className="w-3.5 h-3.5 me-1" />
אשר
</Button>
</>
)}
</div>
</li> </li>
))} ))}
</ol> </ol>