Merge pull request 'feat(arguments): פופאפ פרופוזיציות גולמיות בלחיצה על "מסתמך על N"' (#166) from worktree-argument-claims-popover into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s

This commit was merged in pull request #166.
This commit is contained in:
2026-06-09 06:51:51 +00:00
3 changed files with 80 additions and 11 deletions

View File

@@ -335,18 +335,30 @@ async def get_legal_arguments(
case_id,
)
# Pull supporting claim ids for each argument in one round-trip.
# Pull supporting claims (id + full text) for each argument in one
# round-trip. ``supporting_claims`` stays id-only for backwards compat
# (counts, MCP consumers); ``supporting_propositions`` carries the text
# so the UI can show the raw propositions without an extra fetch.
arg_ids = [r["id"] for r in rows]
supporting: dict[UUID, list[str]] = {}
propositions: dict[UUID, list[dict]] = {}
if arg_ids:
joins = await conn.fetch(
"""SELECT argument_id, claim_id
FROM legal_argument_propositions
WHERE argument_id = ANY($1::uuid[])""",
"""SELECT lap.argument_id, lap.claim_id,
c.claim_text, c.source_document, c.claim_index
FROM legal_argument_propositions lap
JOIN claims c ON c.id = lap.claim_id
WHERE lap.argument_id = ANY($1::uuid[])
ORDER BY c.claim_index""",
arg_ids,
)
for j in joins:
supporting.setdefault(j["argument_id"], []).append(str(j["claim_id"]))
propositions.setdefault(j["argument_id"], []).append({
"id": str(j["claim_id"]),
"text": j["claim_text"],
"source_document": j["source_document"],
})
out: list[dict] = []
for r in rows:
@@ -354,5 +366,6 @@ async def get_legal_arguments(
d["id"] = str(d["id"])
d["case_id"] = str(d["case_id"])
d["supporting_claims"] = supporting.get(r["id"], [])
d["supporting_propositions"] = propositions.get(r["id"], [])
out.append(d)
return out

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 = {