Add export method dialog, extract shared Dialog primitive
Add export dialog with download/clipboard options and optional undo/redo history inclusion (default off). Extract shared Dialog component to ui/dialog.tsx, consolidating open/close lifecycle, backdrop click, and escape key handling from all 6 dialog components. Update spec to reflect export method dialog and optional history. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
94
apps/web/src/components/export-method-dialog.tsx
Normal file
94
apps/web/src/components/export-method-dialog.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import { Check, ClipboardCopy, Download, X } from "lucide-react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { Button } from "./ui/button.js";
|
||||
import { Dialog } from "./ui/dialog.js";
|
||||
|
||||
interface ExportMethodDialogProps {
|
||||
open: boolean;
|
||||
onDownload: (includeHistory: boolean) => void;
|
||||
onCopyToClipboard: (includeHistory: boolean) => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function ExportMethodDialog({
|
||||
open,
|
||||
onDownload,
|
||||
onCopyToClipboard,
|
||||
onClose,
|
||||
}: Readonly<ExportMethodDialogProps>) {
|
||||
const [includeHistory, setIncludeHistory] = useState(false);
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setIncludeHistory(false);
|
||||
setCopied(false);
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose} className="w-80">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<h2 className="font-semibold text-lg">Export Encounter</h2>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={handleClose}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<label className="mb-4 flex items-center gap-2 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={includeHistory}
|
||||
onChange={(e) => setIncludeHistory(e.target.checked)}
|
||||
className="accent-accent"
|
||||
/>
|
||||
<span className="text-foreground">Include undo/redo history</span>
|
||||
</label>
|
||||
<div className="flex flex-col gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-3 rounded-lg border border-border px-4 py-3 text-left text-foreground text-sm hover:bg-hover-neutral-bg"
|
||||
onClick={() => {
|
||||
onDownload(includeHistory);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
<Download className="h-5 w-5 text-muted-foreground" />
|
||||
<div>
|
||||
<div className="font-medium">Download file</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
Save as a JSON file
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-3 rounded-lg border border-border px-4 py-3 text-left text-foreground text-sm hover:bg-hover-neutral-bg"
|
||||
onClick={() => {
|
||||
onCopyToClipboard(includeHistory);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}}
|
||||
>
|
||||
{copied ? (
|
||||
<Check className="h-5 w-5 text-green-400" />
|
||||
) : (
|
||||
<ClipboardCopy className="h-5 w-5 text-muted-foreground" />
|
||||
)}
|
||||
<div>
|
||||
<div className="font-medium">
|
||||
{copied ? "Copied!" : "Copy to clipboard"}
|
||||
</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
Copy JSON to your clipboard
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user