@@ -8,10 +8,6 @@ import { SubsectionCard } from "@/components/compose/subsection-card";
import { PrecedentsSection } from "@/components/compose/precedents-section" ;
import { Markdown } from "@/components/ui/markdown" ;
import { useCase } from "@/lib/api/cases" ;
import {
useCaseLearningStatus ,
type CaseLearningStatus ,
} from "@/lib/api/learning" ;
import { useResearchAnalysis } from "@/lib/api/research" ;
import { useCasePrecedents } from "@/lib/api/precedents" ;
@@ -24,45 +20,6 @@ import { useCasePrecedents } from "@/lib/api/precedents";
* verification moved to their own top-level tabs; /compose was deleted.
*/
// ── Staged-pipeline indicator text — derived from the live learning-status,
// same source as the drafts-panel LearningStatusBadges. ──────────────────────
function voiceLearningText ( s? : CaseLearningStatus ) : string {
if ( ! s ? . final_uploaded ) return "ממתין להעלאת הסופי" ;
const v = s . voice_learning ;
if ( v . outcome === "succeeded" ) {
const bits = [ ` ${ v . lessons_count } לקחים הופקו ` ] ;
if ( v . lessons_proposed > 0 ) bits . push ( ` ${ v . lessons_proposed } הוצעו לאישור ` ) ;
return ` ✓ הושלם · ${ bits . join ( " · " ) } ` ;
}
if ( v . outcome === "failed" ) return v . error ? ` ✗ נכשל — ${ v . error } ` : "✗ נכשל" ;
return "ממתין להרצה" ;
}
function halachaExtractionText ( s? : CaseLearningStatus ) : string {
if ( ! s ? . final_uploaded ) return "ממתין להעלאת הסופי" ;
const h = s . halacha_extraction ;
if ( ! h . enrolled_in_corpus )
return h . not_enrolled_reason ? ? "לא נכנס לקורפוס-הפסיקה" ;
switch ( h . status ) {
case "completed" :
return ` ✓ הושלם · חולצו ${ h . halachot_count } · ${ h . approved } אושרו · ${ h . rejected } נדחו ` ;
case "processing" :
return "רץ עכשיו…" ;
case "pending" :
case "busy" :
return "בתור" ;
case "partial" :
return ` חלקי · חולצו ${ h . halachot_count } ` ;
case "failed" :
case "extraction_failed" :
return "✗ נכשל" ;
case "no_chunks" :
return "אין טקסט לחילוץ" ;
default :
return "ממתין להרצה" ;
}
}
function ProseSection ( { title , content } : { title : string ; content? : string } ) {
if ( ! content ? . trim ( ) ) return null ;
return (
@@ -75,7 +32,9 @@ function ProseSection({ title, content }: { title: string; content?: string }) {
) ;
}
// ── "השלמה והעברה" rail card — DOCX export, analysis upload/download (real) ──
// ── "ייצוא ועדכון הניתוח" rail card — round-trips the analysis-and-research.md
// research analysis: export DOCX, upload an updated version, download the raw MD.
// (Post-final learning status lives on the drafts tab, not here — #226.) ──────
function FinishRail ( {
caseNumber ,
hasAnalysis ,
@@ -88,7 +47,6 @@ function FinishRail({
const fileRef = useRef < HTMLInputElement > ( null ) ;
const [ uploading , setUploading ] = useState ( false ) ;
const [ uploadMsg , setUploadMsg ] = useState < { ok : boolean ; text : string } | null > ( null ) ;
const learning = useCaseLearningStatus ( caseNumber ) ;
async function handleUpload ( file : File ) {
setUploading ( true ) ;
@@ -119,9 +77,12 @@ function FinishRail({
}
return (
< Card className = "bg-surface border-rule shadow-sm" >
< Card className = "bg-surface border-rule shadow-sm h-full " >
< CardContent className = "px-4 py-4" >
< h3 className = "text-navy text-[0.9rem] font-semibold mb-3 " > ה ש ל מ ה ו ה עב ר ה < / h3 >
< h3 className = "text-navy text-[0.9rem] font-semibold mb-1 " > י י צ ו א ו עד כ ו ן ה נ י ת ו ח < / h3 >
< p className = "text-[0.72rem] text-ink-muted mb-3" >
פ ע ו ל ו ת ע ל ק ו ב ץ נ י ת ו ח - ה מ ח ק ר ( analysis - and - research . md ) .
< / p >
< input
ref = { fileRef }
@@ -176,16 +137,6 @@ function FinishRail({
{ uploadMsg . text }
< / p >
) }
{ /* stage indicators — informational pointers, not actions */ }
< div className = "mt-3 space-y-0" >
< div className = "text-[0.78rem] text-ink-muted pt-2 border-t border-rule-soft" >
< b className = "text-navy" > ה ר ץ ל מ י ד ת - ק ו ל < / b > — { voiceLearningText ( learning . data ) }
< / div >
< div className = "text-[0.78rem] text-ink-muted pt-2 mt-2 border-t border-rule-soft" >
< b className = "text-navy" > ה ר ץ א י מ ו ת - ה ל כ ו ת < / b > — { halachaExtractionText ( learning . data ) }
< / div >
< / div >
< / CardContent >
< / Card >
) ;
@@ -214,10 +165,6 @@ export function PositionsPanel({ caseNumber }: { caseNumber: string }) {
return (
< div className = "space-y-4" >
< p className = "text-ink-muted text-[0.78rem]" >
ס ו ג י ו ת - ה מ ח ל ו ק ת ו ע מ ד ו ת ה צ ד ד י ם . ע ו ר ך ע מ ד ת - ה י ו ״ ר נ ש מ ר א ו ט ו מ ט י ת ו מ ז י ן א ת ב ל ו ק י ׳ ( ד י ו ן ו ה כ ר ע ה ) .
< / p >
{ analysis . isPending ? (
< Card className = "bg-surface border-rule shadow-sm" >
< CardContent className = "px-6 py-5 space-y-3" >
@@ -322,9 +269,10 @@ export function PositionsPanel({ caseNumber }: { caseNumber: string }) {
< / div >
) : null }
{ /* case-level פסיקה מצורפת + finish/ export g ates (INV-IA3: not removed) */ }
< div className = "grid gap-4 lg:grid-cols-2 items-start pt-2" >
< Card className = "bg-surface border-rule shadow-sm " >
{ /* case-level פסיקה מצורפת + analysis export/upd ate (INV-IA3: not removed).
items-stretch keeps both cards the same height (#226). */ }
< div className = "grid gap-4 lg:grid-cols-2 items-stretch pt-2 " >
< Card className = "bg-surface border-rule shadow-sm h-full" >
< CardContent className = "px-5 py-4" >
< h3 className = "text-navy text-[0.9rem] font-semibold mb-1" > פ ס י ק ה מ צ ו ר פ ת < / h3 >
< p className = "text-[0.72rem] text-ink-muted mb-3" >