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

138 lines
5.0 KiB
TypeScript

"use client";
import React from "react";
import { Mail, Edit2, Trash2, Eye, Copy, Calendar } from "lucide-react";
import { Button } from "@/components/ui/button";
import { MailTemplate } from "@/lib/api/mail";
interface MailTemplateCardProps {
template: MailTemplate;
onEdit: (template: MailTemplate) => void;
onDelete: (template: MailTemplate) => void;
onPreview: (template: MailTemplate) => void;
onDuplicate?: (template: MailTemplate) => void;
}
export default function MailTemplateCard({
template,
onEdit,
onDelete,
onPreview,
onDuplicate,
}: MailTemplateCardProps) {
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString("ko-KR", {
year: "numeric",
month: "2-digit",
day: "2-digit",
});
};
const getCategoryColor = (category?: string) => {
const colors: Record<string, string> = {
welcome: "bg-primary/20 text-blue-700 border-blue-300",
promotion: "bg-purple-100 text-purple-700 border-purple-300",
notification: "bg-green-100 text-green-700 border-green-300",
newsletter: "bg-orange-100 text-orange-700 border-orange-300",
system: "bg-muted text-foreground border",
};
return colors[category || ""] || "bg-muted text-foreground border";
};
return (
<div className="group overflow-hidden rounded-xl border bg-white shadow-sm transition-all duration-300 hover:shadow-lg">
{/* 헤더 */}
<div className="from-muted to-muted border border-b bg-gradient-to-r p-4">
<div className="flex items-start justify-between">
<div className="flex flex-1 items-start gap-3">
<div className="rounded-lg bg-white p-2 shadow-sm">
<Mail className="text-primary h-5 w-5" />
</div>
<div className="min-w-0 flex-1">
<h3 className="text-foreground truncate font-semibold">{template.name}</h3>
<p className="text-muted-foreground mt-1 truncate text-sm">{template.subject}</p>
</div>
</div>
{template.category && (
<span className={`rounded-full border px-2 py-1 text-xs ${getCategoryColor(template.category)}`}>
{template.category}
</span>
)}
</div>
</div>
{/* 본문 미리보기 */}
<div className="space-y-3 p-4">
<div className="bg-muted/30 min-h-[100px] rounded-lg border p-3">
<p className="text-muted-foreground mb-2 text-xs"> {template.components.length}</p>
<div className="space-y-1">
{template.components.slice(0, 3).map((component, idx) => (
<div key={idx} className="text-muted-foreground flex items-center gap-2 text-xs">
<div className="h-1.5 w-1.5 rounded-full bg-orange-400" />
<span className="capitalize">{component.type}</span>
{component.type === "text" && component.content && (
<span className="flex-1 truncate text-gray-400">
{component.content.replace(/<[^>]*>/g, "").substring(0, 30)}...
</span>
)}
</div>
))}
{template.components.length > 3 && (
<p className="pl-3.5 text-xs text-gray-400">+{template.components.length - 3} </p>
)}
</div>
</div>
{/* 메타 정보 */}
<div className="text-muted-foreground flex items-center gap-3 border-t pt-2 text-xs">
<div className="flex items-center gap-1">
<Calendar className="h-3.5 w-3.5" />
<span>{formatDate(template.createdAt)}</span>
</div>
{template.updatedAt !== template.createdAt && <span className="text-gray-400"></span>}
</div>
</div>
{/* 액션 버튼 */}
<div className="flex gap-2 p-4 pt-0">
<Button
size="sm"
variant="outline"
className="hover:bg-accent hover:text-primary flex-1 hover:border-blue-300"
onClick={() => onPreview(template)}
>
<Eye className="mr-1 h-4 w-4" />
</Button>
<Button
size="sm"
variant="outline"
className="flex-1 hover:border-green-300 hover:bg-green-50 hover:text-green-600"
onClick={() => onEdit(template)}
>
<Edit2 className="mr-1 h-4 w-4" />
</Button>
{onDuplicate && (
<Button
size="sm"
variant="outline"
className="hover:border-purple-300 hover:bg-purple-50 hover:text-purple-600"
onClick={() => onDuplicate(template)}
>
<Copy className="h-4 w-4" />
</Button>
)}
<Button
size="sm"
variant="outline"
className="hover:bg-destructive/10 hover:text-destructive hover:border-red-300"
onClick={() => onDelete(template)}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
);
}