From 140a2e442da41f56248dba284dd44842686734dd Mon Sep 17 00:00:00 2001 From: Chaim Date: Tue, 14 Apr 2026 05:55:46 +0000 Subject: [PATCH] Add drafts & feedback tab to case page, remove global feedback page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move draft management (export DOCX, download, upload revised version, mark final) and chair feedback into a new "טיוטות והערות" tab on the case detail page. Remove the standalone /feedback page and its nav link since feedback is now case-scoped. Also fix /api/admin/skills 500 error when Paperclip DB is unreachable by adding a connection timeout and graceful fallback to disk-only skills. Co-Authored-By: Claude Opus 4.6 (1M context) --- web-ui/src/app/cases/[caseNumber]/page.tsx | 11 + web-ui/src/app/feedback/page.tsx | 329 ------------- web-ui/src/components/app-shell.tsx | 1 - web-ui/src/components/cases/drafts-panel.tsx | 461 +++++++++++++++++++ web-ui/src/lib/api/exports.ts | 87 ++++ web-ui/src/lib/api/feedback.ts | 23 + web/app.py | 39 +- 7 files changed, 612 insertions(+), 339 deletions(-) delete mode 100644 web-ui/src/app/feedback/page.tsx create mode 100644 web-ui/src/components/cases/drafts-panel.tsx create mode 100644 web-ui/src/lib/api/exports.ts diff --git a/web-ui/src/app/cases/[caseNumber]/page.tsx b/web-ui/src/app/cases/[caseNumber]/page.tsx index 1c1a287..60c5165 100644 --- a/web-ui/src/app/cases/[caseNumber]/page.tsx +++ b/web-ui/src/app/cases/[caseNumber]/page.tsx @@ -13,6 +13,7 @@ import { WorkflowTimeline } from "@/components/cases/workflow-timeline"; import { StatusGuide } from "@/components/cases/status-guide"; import { StatusChanger } from "@/components/cases/status-changer"; import { DocumentsPanel } from "@/components/cases/documents-panel"; +import { DraftsPanel } from "@/components/cases/drafts-panel"; import { UploadSheet } from "@/components/documents/upload-sheet"; import { expectedOutcomes } from "@/lib/schemas/case"; import { useCase } from "@/lib/api/cases"; @@ -78,6 +79,9 @@ export default function CaseDetailPage({ )} + + טיוטות והערות + @@ -115,6 +119,13 @@ export default function CaseDetailPage({ + + + + diff --git a/web-ui/src/app/feedback/page.tsx b/web-ui/src/app/feedback/page.tsx deleted file mode 100644 index 1d5be98..0000000 --- a/web-ui/src/app/feedback/page.tsx +++ /dev/null @@ -1,329 +0,0 @@ -"use client"; - -import { useState } from "react"; -import Link from "next/link"; -import { AppShell } from "@/components/app-shell"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { - useFeedbackList, - useCreateFeedback, - useResolveFeedback, - CATEGORY_LABELS, - BLOCK_LABELS, - type FeedbackCategory, -} from "@/lib/api/feedback"; -import { toast } from "sonner"; - -const CATEGORY_COLORS: Record = { - missing_content: "bg-amber-100 text-amber-800 border-amber-200", - wrong_tone: "bg-purple-100 text-purple-800 border-purple-200", - wrong_structure: "bg-blue-100 text-blue-800 border-blue-200", - factual_error: "bg-red-100 text-red-800 border-red-200", - style: "bg-emerald-100 text-emerald-800 border-emerald-200", - other: "bg-gray-100 text-gray-800 border-gray-200", -}; - -export default function FeedbackPage() { - const [showResolved, setShowResolved] = useState(false); - const [filterCategory, setFilterCategory] = useState(""); - - const { data: feedbacks, isLoading } = useFeedbackList({ - category: filterCategory || undefined, - unresolved_only: !showResolved, - }); - - const resolveMutation = useResolveFeedback(); - - function handleResolve(id: string) { - resolveMutation.mutate( - { feedbackId: id, applied_to: [] }, - { - onSuccess: () => toast.success("ההערה סומנה כמטופלת"), - onError: () => toast.error("שגיאה בעדכון"), - }, - ); - } - - return ( - -
-
- -

הערות יו״ר על טיוטות

-

- תיעוד הערות דפנה על טיוטות החלטות. כל הערה מנותחת ומשפיעה על שיפור - כתיבת ההחלטות העתידיות. -

-
- -
- - {/* Toolbar */} -
- - - - - - - {feedbacks && ( - - {feedbacks.length} הערות - - )} -
- - {/* Feedback list */} - {isLoading ? ( - - - טוען... - - - ) : !feedbacks?.length ? ( - - - אין הערות{!showResolved ? " פתוחות" : ""} - {filterCategory ? ` בקטגוריה ${CATEGORY_LABELS[filterCategory as FeedbackCategory]}` : ""} - - - ) : ( -
- {feedbacks.map((fb) => ( - - -
- - {CATEGORY_LABELS[fb.category]} - - - {BLOCK_LABELS[fb.block_id] ?? fb.block_id} - - {fb.case_number && ( - - תיק {fb.case_number} - - )} - {fb.resolved && ( - - טופל - - )} - - {fb.created_at - ? new Date(fb.created_at).toLocaleDateString("he-IL") - : ""} - -
-
- -

{fb.feedback_text}

- - {fb.lesson_extracted && ( -
-

- לקח שהופק: -

-

- {fb.lesson_extracted} -

-
- )} - - {!fb.resolved && ( -
- -
- )} -
-
- ))} -
- )} -
-
- ); -} - -/* ── New feedback dialog ─────────────────────────────────── */ - -function NewFeedbackDialog() { - const [open, setOpen] = useState(false); - const createMutation = useCreateFeedback(); - - const [caseNumber, setCaseNumber] = useState(""); - const [blockId, setBlockId] = useState("block-yod"); - const [category, setCategory] = useState("missing_content"); - const [feedbackText, setFeedbackText] = useState(""); - const [lesson, setLesson] = useState(""); - - function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!feedbackText.trim()) return; - - createMutation.mutate( - { - case_number: caseNumber || undefined, - block_id: blockId, - feedback_text: feedbackText, - category, - lesson_extracted: lesson || undefined, - }, - { - onSuccess: () => { - toast.success("ההערה נרשמה בהצלחה"); - setOpen(false); - setCaseNumber(""); - setFeedbackText(""); - setLesson(""); - }, - onError: () => toast.error("שגיאה ברישום ההערה"), - }, - ); - } - - return ( - - - - - - - רישום הערת יו״ר - -
-
-
- - setCaseNumber(e.target.value)} - placeholder="1130-25" - /> -
-
- - -
-
- -
- - -
- -
- -