feat(arguments): פופאפ פרופוזיציות גולמיות בלחיצה על "מסתמך על N"

הקישור טיעון↔פרופוזיציות כבר נשמר ב-DB (legal_argument_propositions),
אך ה-UI הציג רק את המספר. מעשיר את get_legal_arguments באותו round-trip
(JOIN ל-claims) להחזיר supporting_propositions = {id, text, source_document},
ועוטף את שורת "מסתמך על N פרופוזיציות" ב-Popover שמציג את הטענות הגולמיות
verbatim עם מקור. שקיפות ועקיבוּת מהטיעון המאוגד חזרה לטענות-המקור.

- supporting_claims נשאר id-only (תאימות לאחור: מונה, צרכני MCP)
- supporting_propositions שדה חדש אופציונלי; fallback לטקסט סטטי כשחסר
- אין מסלול מקביל (G2) — העשרה של אותו endpoint; נרמול-במקור (G1)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 06:51:09 +00:00
parent c0af8c7cda
commit d4d2ab4d68
3 changed files with 80 additions and 11 deletions

View File

@@ -10,6 +10,11 @@ import {
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Skeleton } from "@/components/ui/skeleton";
import {
PARTY_LABELS_HE,
@@ -22,7 +27,7 @@ import {
type LegalArgumentPriority,
} from "@/lib/api/legal-arguments";
import { toast } from "sonner";
import { Loader2, RefreshCw, Sparkles } from "lucide-react";
import { ListTree, Loader2, RefreshCw, Sparkles } from "lucide-react";
const PRIORITY_BADGE_TONE: Record<LegalArgumentPriority, string> = {
threshold: "bg-danger-bg/60 text-danger-strong border-danger/40",
@@ -102,12 +107,55 @@ function PartySection({ party, args }: PartySectionProps) {
<p className="text-ink leading-relaxed whitespace-pre-line">
{arg.argument_body}
</p>
{arg.supporting_claims.length > 0 && (
<p className="text-ink-muted text-xs">
מסתמך על {arg.supporting_claims.length} פרופוזיציות
גולמיות.
</p>
)}
{arg.supporting_claims.length > 0 &&
(arg.supporting_propositions &&
arg.supporting_propositions.length > 0 ? (
<Popover>
<PopoverTrigger asChild>
<button
type="button"
className="text-gold-strong hover:text-gold inline-flex items-center gap-1 text-xs underline decoration-dotted underline-offset-2"
>
<ListTree className="size-3.5" aria-hidden />
מסתמך על {arg.supporting_claims.length}{" "}
פרופוזיציות גולמיות
</button>
</PopoverTrigger>
<PopoverContent
align="start"
className="max-h-96 w-96 overflow-y-auto"
>
<p className="text-ink-muted mb-2 text-xs font-medium">
הטענות הגולמיות שמהן אוגד הטיעון:
</p>
<ol className="space-y-2">
{arg.supporting_propositions.map((p, i) => (
<li
key={p.id}
className="border-rule border-s-2 ps-2 text-xs"
>
<span className="text-navy font-medium">
{i + 1}.
</span>{" "}
<span className="text-ink leading-relaxed">
{p.text}
</span>
{p.source_document && (
<span className="text-ink-muted mt-0.5 block">
מקור: {p.source_document}
</span>
)}
</li>
))}
</ol>
</PopoverContent>
</Popover>
) : (
<p className="text-ink-muted text-xs">
מסתמך על {arg.supporting_claims.length} פרופוזיציות
גולמיות.
</p>
))}
</div>
</AccordionContent>
</AccordionItem>

View File

@@ -22,6 +22,12 @@ export type LegalArgumentPriority =
| "procedural"
| "relief";
export type SupportingProposition = {
id: string;
text: string;
source_document: string | null;
};
export type LegalArgument = {
id: string;
case_id: string;
@@ -35,6 +41,8 @@ export type LegalArgument = {
created_at?: string;
updated_at?: string;
supporting_claims: string[];
/** Raw extracted propositions (id + full text) backing this argument. */
supporting_propositions?: SupportingProposition[];
};
export type LegalArgumentsResponse = {