Files
initiative/apps/web/src/components/export-method-dialog.tsx
Lukas f4fb69dbc7
All checks were successful
CI / check (push) Successful in 1m13s
CI / build-image (push) Has been skipped
Add jsinspect-plus structural duplication gate, extract shared helpers
Add jsinspect-plus (AST-based structural duplication detector) to pnpm
check with threshold 50 / min 3 instances. Fix all findings:

- Extract condition icon/color maps to shared condition-styles.ts
- Extract useClickOutside hook (5 components)
- Extract dispatchAction + resolveAndRename in use-encounter
- Extract runEncounterAction in application layer (13 use cases)
- Extract findCombatant helper in domain (9 functions)
- Extract TraitSection in stat-block (4 trait rendering blocks)
- Extract DialogHeader in dialog.tsx (4 dialogs)

Net result: -263 lines across 40 files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:16:54 +01:00

94 lines
2.7 KiB
TypeScript

import { Check, ClipboardCopy, Download } from "lucide-react";
import { useCallback, useState } from "react";
import { Dialog, DialogHeader } from "./ui/dialog.js";
import { Input } from "./ui/input.js";
interface ExportMethodDialogProps {
open: boolean;
onDownload: (includeHistory: boolean, filename: string) => void;
onCopyToClipboard: (includeHistory: boolean) => void;
onClose: () => void;
}
export function ExportMethodDialog({
open,
onDownload,
onCopyToClipboard,
onClose,
}: Readonly<ExportMethodDialogProps>) {
const [includeHistory, setIncludeHistory] = useState(false);
const [filename, setFilename] = useState("");
const [copied, setCopied] = useState(false);
const handleClose = useCallback(() => {
setIncludeHistory(false);
setFilename("");
setCopied(false);
onClose();
}, [onClose]);
return (
<Dialog open={open} onClose={handleClose} className="w-80">
<DialogHeader title="Export Encounter" onClose={handleClose} />
<div className="mb-3">
<Input
type="text"
value={filename}
onChange={(e) => setFilename(e.target.value)}
placeholder="Filename (optional)"
/>
</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, filename);
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>
);
}