mirror of
https://github.com/willchen96/mike.git
synced 2026-06-20 21:18:07 +02:00
Sync CourtListener verification and document safety updates
- Refine CourtListener citation verification, bulk lookup logging, and API fallback behavior - Persist cancelled chat stream output and render cancellation as the final assistant message - Add document/version deletion safety fixes and shared warning/modal UI updates - Sync document panel, case law panel, and response UI styling refinements - Harden OSS sync script to preserve local env, dependency, and generated files
This commit is contained in:
parent
44e868eb42
commit
f32a194b33
24 changed files with 2494 additions and 1222 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { createPortal } from "react-dom";
|
||||
import type { ReactNode } from "react";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { Loader2, Trash2 } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type ConfirmStatus = "idle" | "loading" | "complete";
|
||||
|
|
@ -37,14 +37,20 @@ export function ConfirmPopup({
|
|||
const resolvedConfirmDisabled = confirmDisabled || confirmStatus !== "idle";
|
||||
const normalizedConfirmLabel =
|
||||
typeof confirmLabel === "string" ? confirmLabel : "Confirm";
|
||||
const isDeleteAction = normalizedConfirmLabel.toLowerCase() === "delete";
|
||||
const resolvedConfirmLabel =
|
||||
confirmStatus === "loading" ? (
|
||||
<span className="inline-flex items-center gap-1.5">
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
<span className="inline-flex h-full items-center gap-1.5">
|
||||
<Loader2 className="h-3 w-3 shrink-0 animate-spin" />
|
||||
{progressiveLabel(normalizedConfirmLabel)}
|
||||
</span>
|
||||
) : confirmStatus === "complete" ? (
|
||||
completedLabel(normalizedConfirmLabel)
|
||||
) : isDeleteAction ? (
|
||||
<span className="inline-flex h-full items-center gap-1.5">
|
||||
<Trash2 className="h-3 w-3 shrink-0" />
|
||||
{confirmLabel}
|
||||
</span>
|
||||
) : (
|
||||
confirmLabel
|
||||
);
|
||||
|
|
@ -53,17 +59,19 @@ export function ConfirmPopup({
|
|||
<div className="pointer-events-none fixed inset-x-0 bottom-5 z-[230] flex justify-center px-4">
|
||||
<div
|
||||
className={cn(
|
||||
"pointer-events-auto w-[min(92vw,520px)] rounded-2xl border border-white/70 bg-white/58 px-4 py-3 text-sm shadow-[0_8px_24px_rgba(15,23,42,0.13),inset_0_1px_0_rgba(255,255,255,0.92),inset_0_-10px_24px_rgba(255,255,255,0.2)] backdrop-blur-2xl",
|
||||
"pointer-events-auto w-[min(92vw,520px)] rounded-2xl border border-white/70 bg-white px-4 py-3 text-sm shadow-[0_4px_14px_rgba(15,23,42,0.08),inset_0_1px_0_rgba(255,255,255,0.92)] backdrop-blur-2xl",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{title && (
|
||||
<div className="text-sm font-medium text-gray-950">
|
||||
<div className="text-sm font-medium text-gray-950 mb-3">
|
||||
{title}
|
||||
</div>
|
||||
)}
|
||||
{message && (
|
||||
<div className={cn("text-xs text-gray-700", title && "mt-1")}>
|
||||
<div
|
||||
className={cn("text-xs text-gray-700", title && "mt-1")}
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -71,7 +79,7 @@ export function ConfirmPopup({
|
|||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="rounded-full px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-100"
|
||||
className="px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:text-gray-950"
|
||||
>
|
||||
{cancelLabel}
|
||||
</button>
|
||||
|
|
@ -79,7 +87,12 @@ export function ConfirmPopup({
|
|||
type="button"
|
||||
onClick={onConfirm}
|
||||
disabled={resolvedConfirmDisabled}
|
||||
className="rounded-full bg-gray-950 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-40"
|
||||
className={cn(
|
||||
"inline-flex h-7 items-center justify-center rounded-full px-3.5 text-xs font-medium leading-none text-white backdrop-blur-xl transition-all active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-40 disabled:active:scale-100",
|
||||
isDeleteAction
|
||||
? "border border-red-700/35 bg-red-600/90 shadow-[0_3px_9px_rgba(127,29,29,0.16),inset_0_1px_0_rgba(255,255,255,0.22),inset_0_-4px_9px_rgba(127,29,29,0.18)] hover:bg-red-600"
|
||||
: "border border-gray-700/40 bg-gray-950/88 shadow-[0_3px_9px_rgba(15,23,42,0.16),inset_0_1px_0_rgba(255,255,255,0.22),inset_0_-4px_9px_rgba(15,23,42,0.2)] hover:bg-gray-900/90",
|
||||
)}
|
||||
aria-busy={confirmBusy}
|
||||
>
|
||||
{resolvedConfirmLabel}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ export function Modal({
|
|||
>
|
||||
<div
|
||||
className={cn(
|
||||
"w-full rounded-2xl shadow-2xl flex h-[600px] flex-col",
|
||||
"w-full rounded-2xl flex h-[600px] flex-col",
|
||||
sizeClassName[size],
|
||||
"border border-white/70 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur-2xl",
|
||||
"border border-white/70 bg-white/94 shadow-[0_12px_36px_rgba(15,23,42,0.1)] backdrop-blur-2xl",
|
||||
className,
|
||||
)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
|
@ -123,7 +123,7 @@ export function Modal({
|
|||
{hasFooter && (
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-4 py-3",
|
||||
"flex items-center gap-3 p-4",
|
||||
secondaryAction || footerInfo
|
||||
? "justify-between"
|
||||
: "justify-end",
|
||||
|
|
@ -181,14 +181,14 @@ function ModalActionButton({
|
|||
return (
|
||||
<button
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center gap-1.5 rounded-lg px-4 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40",
|
||||
"inline-flex items-center justify-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-all disabled:cursor-not-allowed disabled:opacity-40",
|
||||
variant === "primary" &&
|
||||
"bg-gray-900 text-white hover:bg-gray-700",
|
||||
variant === "secondary" && "text-gray-600 hover:bg-gray-100",
|
||||
"rounded-full border border-gray-700/40 bg-gray-950/88 text-white shadow-[0_3px_9px_rgba(15,23,42,0.16),inset_0_1px_0_rgba(255,255,255,0.22),inset_0_-4px_9px_rgba(15,23,42,0.2)] backdrop-blur-xl hover:bg-gray-900/90 active:scale-[0.98] disabled:active:scale-100",
|
||||
variant === "secondary" && "text-gray-600 hover:text-gray-950",
|
||||
fallbackVariant === "secondary" &&
|
||||
"border border-gray-200 hover:bg-gray-50",
|
||||
"rounded-full border border-gray-200/80 bg-gray-100/70 shadow-[0_1px_4px_rgba(15,23,42,0.045),inset_0_1px_0_rgba(255,255,255,0.78),inset_0_-3px_8px_rgba(148,163,184,0.14)] backdrop-blur-xl hover:bg-gray-100",
|
||||
variant === "danger" &&
|
||||
"bg-red-600 text-white hover:bg-red-700",
|
||||
"rounded-full border border-red-700/35 bg-red-600/90 text-white shadow-[0_3px_9px_rgba(127,29,29,0.16),inset_0_1px_0_rgba(255,255,255,0.22),inset_0_-4px_9px_rgba(127,29,29,0.18)] backdrop-blur-xl hover:bg-red-600 active:scale-[0.98] disabled:active:scale-100",
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ export function OwnerOnlyModal({
|
|||
onClose={onClose}
|
||||
title={title}
|
||||
message={body}
|
||||
icon={<Lock className="mt-0.5 h-3.5 w-3.5 shrink-0 text-red-600" />}
|
||||
primaryAction={{ label: "OK", onClick: onClose }}
|
||||
icon={<Lock className="h-3.5 w-3.5 shrink-0 text-red-600" />}
|
||||
>
|
||||
{ownerEmail && (
|
||||
<p className="mt-1 text-xs text-gray-600">
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ export function WarningPopup({
|
|||
}: WarningPopupProps) {
|
||||
if (!open) return null;
|
||||
|
||||
const warningIcon = icon ?? (
|
||||
<AlertCircle className="h-3 w-3 shrink-0 text-red-600" />
|
||||
);
|
||||
|
||||
return createPortal(
|
||||
<div className="pointer-events-none fixed left-1/2 top-5 z-[220] w-[min(92vw,520px)] -translate-x-1/2 px-4">
|
||||
<div
|
||||
|
|
@ -44,16 +48,21 @@ export function WarningPopup({
|
|||
className,
|
||||
)}
|
||||
>
|
||||
{icon ?? (
|
||||
<AlertCircle className="mt-0.5 h-3.5 w-3.5 shrink-0 text-red-600" />
|
||||
)}
|
||||
<div className="min-w-0 flex-1 self-center text-gray-900">
|
||||
<div className="min-w-0 flex-1 self-center text-red-600">
|
||||
{title && (
|
||||
<div className="font-medium text-gray-950">
|
||||
<div className="flex items-center gap-1.5 font-medium mb-1">
|
||||
{warningIcon}
|
||||
{title}
|
||||
</div>
|
||||
)}
|
||||
{message && <div>{message}</div>}
|
||||
{message && (
|
||||
<div
|
||||
className={cn(!title && "flex items-start gap-1.5")}
|
||||
>
|
||||
{!title && warningIcon}
|
||||
<span className="min-w-0">{message}</span>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
{(primaryAction || secondaryAction) && (
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
|
|
@ -72,7 +81,7 @@ export function WarningPopup({
|
|||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="shrink-0 text-gray-700 transition-colors hover:text-gray-950"
|
||||
className="shrink-0 text-red-700 transition-colors hover:text-red-500"
|
||||
aria-label="Dismiss warning"
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
|
|
|
|||
|
|
@ -207,7 +207,6 @@ export type AssistantEvent =
|
|||
url: string;
|
||||
pdfUrl?: string | null;
|
||||
dateFiled?: string | null;
|
||||
judges?: string | null;
|
||||
case?: Extract<AssistantEvent, { type: "case_opinions" }>["case"];
|
||||
}
|
||||
| {
|
||||
|
|
@ -288,7 +287,6 @@ export type CaseCitationAnnotation = {
|
|||
url?: string | null;
|
||||
pdfUrl?: string | null;
|
||||
dateFiled?: string | null;
|
||||
judges?: string | null;
|
||||
quotes: CaseCitationQuote[];
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue