feat(frontend): convert ExportPreviewModal to editable textarea with reset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-13 12:59:44 -05:00
parent 0a67a846de
commit 808c8d49d1

View File

@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Copy, Download, Check } from 'lucide-react'
import { useState, useEffect } from 'react'
import { Copy, Download, Check, RotateCcw } from 'lucide-react'
import { Modal } from '@/components/common/Modal'
import { cn } from '@/lib/utils'
@@ -9,7 +9,9 @@ interface ExportPreviewModalProps {
content: string
filename: string
format: 'markdown' | 'text' | 'html' | 'psa'
onDownload: () => void
onDownload: (content: string) => void
includeSummary?: boolean
onToggleSummary?: (include: boolean) => void
}
export function ExportPreviewModal({
@@ -19,12 +21,20 @@ export function ExportPreviewModal({
filename,
format,
onDownload,
includeSummary = false,
onToggleSummary,
}: ExportPreviewModalProps) {
const [copied, setCopied] = useState(false)
const [editedContent, setEditedContent] = useState(content)
// Sync editedContent when content prop changes (new fetch / summary toggle)
useEffect(() => {
setEditedContent(content)
}, [content])
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(content)
await navigator.clipboard.writeText(editedContent)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
} catch (err) {
@@ -33,39 +43,79 @@ export function ExportPreviewModal({
}
const handleDownload = () => {
onDownload()
onDownload(editedContent)
onClose()
}
// Reset copied state when modal closes
const handleReset = () => {
setEditedContent(content)
}
const handleClose = () => {
setCopied(false)
onClose()
}
const isModified = editedContent !== content
return (
<Modal isOpen={isOpen} onClose={handleClose} title="Export Preview" size="xl">
{/* Filename and format info */}
<p className="mb-3 text-sm text-white/70">
Filename: <span className="font-mono text-white">{filename}</span>
<span className="ml-3 rounded bg-white/10 px-2 py-0.5 text-xs text-white/70">
{format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : 'Plain Text'}
</span>
</p>
{/* Content Preview */}
<div
className={cn(
'max-h-96 overflow-auto rounded-md border border-white/10 bg-black/50 p-4',
'font-mono text-sm text-white'
)}
>
<pre className="whitespace-pre-wrap">{content}</pre>
{/* Filename, format info, and controls */}
<div className="mb-3 flex flex-wrap items-center justify-between gap-2">
<p className="text-sm text-white/70">
Filename: <span className="font-mono text-white">{filename}</span>
<span className="ml-3 rounded bg-white/10 px-2 py-0.5 text-xs text-white/70">
{format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : format === 'psa' ? 'PSA' : 'Plain Text'}
</span>
{isModified && (
<span className="ml-2 text-xs text-yellow-400">(edited)</span>
)}
</p>
<div className="flex items-center gap-3">
{onToggleSummary && (
<label className="flex items-center gap-2 text-sm text-white/60 cursor-pointer">
<input
type="checkbox"
checked={includeSummary}
onChange={(e) => onToggleSummary(e.target.checked)}
className="h-4 w-4 rounded border-white/20 bg-black/50"
/>
Include Summary
</label>
)}
{isModified && (
<button
type="button"
onClick={handleReset}
className="flex items-center gap-1 text-xs text-white/40 hover:text-white"
title="Reset to original"
>
<RotateCcw className="h-3 w-3" />
Reset
</button>
)}
</div>
</div>
{/* Editable Content */}
<label htmlFor="export-content" className="sr-only">
Export content
</label>
<textarea
id="export-content"
value={editedContent}
onChange={(e) => setEditedContent(e.target.value)}
className={cn(
'h-96 w-full resize-y rounded-md border border-white/10 bg-black/50 p-4',
'font-mono text-sm text-white',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20'
)}
/>
{/* Actions */}
<div className="mt-4 flex items-center justify-end gap-2">
<button
type="button"
onClick={handleCopy}
className={cn(
'flex items-center gap-2 rounded-md border border-white/10 px-3 py-2 text-sm font-medium',
@@ -86,6 +136,7 @@ export function ExportPreviewModal({
)}
</button>
<button
type="button"
onClick={handleDownload}
className={cn(
'flex items-center gap-2 rounded-md bg-white px-3 py-2 text-sm font-medium text-black',