ERP-node/frontend/components/mail/MailTemplatePreviewModal.tsx

164 lines
6.4 KiB
TypeScript
Raw Normal View History

2025-10-01 16:15:53 +09:00
"use client";
import React, { useState } from 'react';
import { X, Eye, Mail, Code, Maximize2, Minimize2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { MailTemplate, renderTemplateToHtml, extractTemplateVariables } from '@/lib/api/mail';
interface MailTemplatePreviewModalProps {
isOpen: boolean;
onClose: () => void;
template: MailTemplate | null;
}
export default function MailTemplatePreviewModal({
isOpen,
onClose,
template,
}: MailTemplatePreviewModalProps) {
const [viewMode, setViewMode] = useState<'preview' | 'code'>('preview');
const [isFullscreen, setIsFullscreen] = useState(false);
const [variables, setVariables] = useState<Record<string, string>>({});
if (!isOpen || !template) return null;
const templateVariables = extractTemplateVariables(template);
const renderedHtml = renderTemplateToHtml(template, variables);
const handleVariableChange = (key: string, value: string) => {
setVariables((prev) => ({ ...prev, [key]: value }));
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div
className={`bg-white rounded-xl shadow-2xl overflow-hidden transition-all ${
isFullscreen ? 'w-full h-full' : 'max-w-6xl w-full max-h-[90vh]'
}`}
>
{/* 헤더 */}
<div className="sticky top-0 bg-gradient-to-r from-orange-500 to-orange-600 px-6 py-4 flex items-center justify-between z-10">
<div className="flex items-center gap-3">
<Eye className="w-6 h-6 text-white" />
<div>
<h2 className="text-xl font-bold text-white">{template.name}</h2>
<p className="text-sm text-orange-100">{template.subject}</p>
</div>
</div>
<div className="flex items-center gap-2">
<button
onClick={() => setViewMode(viewMode === 'preview' ? 'code' : 'preview')}
className="text-white hover:bg-white/20 rounded-lg px-3 py-2 transition flex items-center gap-2"
>
{viewMode === 'preview' ? (
<>
<Code className="w-4 h-4" />
</>
) : (
<>
<Eye className="w-4 h-4" />
</>
)}
</button>
<button
onClick={() => setIsFullscreen(!isFullscreen)}
className="text-white hover:bg-white/20 rounded-lg p-2 transition"
>
{isFullscreen ? (
<Minimize2 className="w-5 h-5" />
) : (
<Maximize2 className="w-5 h-5" />
)}
</button>
<button
onClick={onClose}
className="text-white hover:bg-white/20 rounded-lg p-2 transition"
>
<X className="w-5 h-5" />
</button>
</div>
</div>
{/* 본문 */}
<div className="flex h-full overflow-hidden">
{/* 왼쪽: 변수 입력 (변수가 있을 때만) */}
{templateVariables.length > 0 && (
<div className="w-80 bg-gray-50 border-r border-gray-200 p-6 overflow-y-auto">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Mail className="w-5 h-5 text-orange-500" />
릿
</h3>
<div className="space-y-4">
{templateVariables.map((variable) => (
<div key={variable}>
<label className="block text-sm font-medium text-gray-700 mb-1">
{variable}
</label>
<input
type="text"
value={variables[variable] || ''}
onChange={(e) => handleVariableChange(variable, e.target.value)}
placeholder={`{${variable}}`}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500"
/>
</div>
))}
</div>
<div className="mt-6 p-4 bg-accent border border-primary/20 rounded-lg">
2025-10-01 16:15:53 +09:00
<p className="text-xs text-blue-800">
💡 .
</p>
</div>
</div>
)}
{/* 오른쪽: 미리보기 또는 코드 */}
<div className="flex-1 overflow-y-auto p-6">
{viewMode === 'preview' ? (
<div className="bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden">
{/* 이메일 헤더 시뮬레이션 */}
<div className="bg-gray-100 px-6 py-4 border-b border-gray-200">
<div className="space-y-2 text-sm">
<div className="flex">
<span className="font-semibold text-muted-foreground w-20">:</span>
2025-10-01 16:15:53 +09:00
<span className="text-gray-900">{template.subject}</span>
</div>
<div className="flex">
<span className="font-semibold text-muted-foreground w-20">:</span>
2025-10-01 16:15:53 +09:00
<span className="text-gray-700">your-email@company.com</span>
</div>
<div className="flex">
<span className="font-semibold text-muted-foreground w-20">:</span>
2025-10-01 16:15:53 +09:00
<span className="text-gray-700">recipient@example.com</span>
</div>
</div>
</div>
{/* 이메일 본문 */}
<div
className="p-6"
dangerouslySetInnerHTML={{ __html: renderedHtml }}
/>
</div>
) : (
<div className="bg-gray-900 text-gray-100 p-6 rounded-lg font-mono text-sm overflow-x-auto">
<pre className="whitespace-pre-wrap break-words">{renderedHtml}</pre>
</div>
)}
</div>
</div>
{/* 푸터 */}
<div className="sticky bottom-0 bg-gray-50 border-t border-gray-200 px-6 py-4 flex justify-end gap-3">
<Button variant="outline" onClick={onClose}>
</Button>
</div>
</div>
</div>
);
}