feat(halacha): כפתורי אישור/דחייה/שחזור inline ברכיב "הלכות שחולצו"
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 38s
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:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user