refactor: 전체 프론트엔드 하드코딩 색상 → CSS 변수 일괄 치환
447+ 파일, 4500+ 줄 변경: - gray-* → border/bg-muted/text-foreground/text-muted-foreground - blue-* → primary/ring - red-* → destructive - green-* → emerald (일관성) - indigo-* → primary - yellow/orange → amber (통일) - dark mode 변형도 시맨틱 토큰으로 변환 Made-with: Cursor
This commit is contained in:
@@ -516,12 +516,12 @@ ${data.originalBody}`;
|
||||
toast({
|
||||
title: (
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-5 h-5 text-green-500" />
|
||||
<CheckCircle2 className="w-5 h-5 text-emerald-500" />
|
||||
<span>메일 발송 완료!</span>
|
||||
</div>
|
||||
) as any,
|
||||
description: `${to.length}명${cc.length > 0 ? ` (참조 ${cc.length}명)` : ""}${bcc.length > 0 ? ` (숨은참조 ${bcc.length}명)` : ""}${attachments.length > 0 ? ` (첨부파일 ${attachments.length}개)` : ""}에게 메일이 성공적으로 발송되었습니다.`,
|
||||
className: "border-green-500 bg-green-50",
|
||||
className: "border-emerald-500 bg-emerald-50",
|
||||
});
|
||||
|
||||
// 알림 갱신 이벤트 발생
|
||||
@@ -544,7 +544,7 @@ ${data.originalBody}`;
|
||||
toast({
|
||||
title: (
|
||||
<div className="flex items-center gap-2">
|
||||
<AlertCircle className="w-5 h-5 text-red-500" />
|
||||
<AlertCircle className="w-5 h-5 text-destructive" />
|
||||
<span>메일 발송 실패</span>
|
||||
</div>
|
||||
) as any,
|
||||
@@ -781,7 +781,7 @@ ${data.originalBody}`;
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CheckCircle2 className="w-4 h-4 text-green-500" />
|
||||
<CheckCircle2 className="w-4 h-4 text-emerald-500" />
|
||||
<span>
|
||||
{new Date(lastSaved).toLocaleTimeString('ko-KR', {
|
||||
hour: '2-digit',
|
||||
@@ -895,7 +895,7 @@ ${data.originalBody}`;
|
||||
{to.map((email) => (
|
||||
<div
|
||||
key={email}
|
||||
className="flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-700 rounded-md text-sm"
|
||||
className="flex items-center gap-1 px-2 py-1 bg-primary/10 text-primary rounded-md text-sm"
|
||||
>
|
||||
<span>{email}</span>
|
||||
<button
|
||||
@@ -933,12 +933,12 @@ ${data.originalBody}`;
|
||||
{cc.map((email) => (
|
||||
<div
|
||||
key={email}
|
||||
className="flex items-center gap-1 px-2 py-1 bg-green-100 text-green-700 rounded-md text-sm"
|
||||
className="flex items-center gap-1 px-2 py-1 bg-emerald-100 text-emerald-700 rounded-md text-sm"
|
||||
>
|
||||
<span>{email}</span>
|
||||
<button
|
||||
onClick={() => removeEmail(email, "cc")}
|
||||
className="hover:bg-green-200 rounded p-0.5"
|
||||
className="hover:bg-emerald-200 rounded p-0.5"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
@@ -1222,7 +1222,7 @@ ${data.originalBody}`;
|
||||
<div
|
||||
key={component.id}
|
||||
style={{ height: `${component.height || 20}px` }}
|
||||
className="bg-background rounded flex items-center justify-center text-xs text-gray-400"
|
||||
className="bg-background rounded flex items-center justify-center text-xs text-muted-foreground/70"
|
||||
>
|
||||
여백
|
||||
</div>
|
||||
@@ -1236,7 +1236,7 @@ ${data.originalBody}`;
|
||||
{component.logoSrc && <img src={component.logoSrc} alt="로고" className="h-10" />}
|
||||
<span className="font-bold text-lg">{component.brandName}</span>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">{component.sendDate}</span>
|
||||
<span className="text-sm text-muted-foreground">{component.sendDate}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -1245,13 +1245,13 @@ ${data.originalBody}`;
|
||||
return (
|
||||
<div key={component.id} className="border rounded-lg overflow-hidden">
|
||||
{component.tableTitle && (
|
||||
<div className="bg-gray-50 px-4 py-2 font-semibold border-b">{component.tableTitle}</div>
|
||||
<div className="bg-muted px-4 py-2 font-semibold border-b">{component.tableTitle}</div>
|
||||
)}
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
{component.rows?.map((row: any, i: number) => (
|
||||
<tr key={i} className={i % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
|
||||
<td className="px-4 py-2 font-medium text-gray-600 w-1/3 border-r">{row.label}</td>
|
||||
<tr key={i} className={i % 2 === 0 ? 'bg-white' : 'bg-muted'}>
|
||||
<td className="px-4 py-2 font-medium text-muted-foreground w-1/3 border-r">{row.label}</td>
|
||||
<td className="px-4 py-2">{row.value}</td>
|
||||
</tr>
|
||||
))}
|
||||
@@ -1263,9 +1263,9 @@ ${data.originalBody}`;
|
||||
case 'alertBox':
|
||||
return (
|
||||
<div key={component.id} className={`p-4 rounded-lg border-l-4 ${
|
||||
component.alertType === 'info' ? 'bg-blue-50 border-blue-500 text-blue-800' :
|
||||
component.alertType === 'info' ? 'bg-primary/10 border-primary text-primary' :
|
||||
component.alertType === 'warning' ? 'bg-amber-50 border-amber-500 text-amber-800' :
|
||||
component.alertType === 'danger' ? 'bg-red-50 border-red-500 text-red-800' :
|
||||
component.alertType === 'danger' ? 'bg-destructive/10 border-destructive text-red-800' :
|
||||
'bg-emerald-50 border-emerald-500 text-emerald-800'
|
||||
}`}>
|
||||
{component.alertTitle && <div className="font-bold mb-1">{component.alertTitle}</div>}
|
||||
@@ -1275,13 +1275,13 @@ ${data.originalBody}`;
|
||||
|
||||
case 'divider':
|
||||
return (
|
||||
<hr key={component.id} className="border-gray-300" style={{ borderWidth: `${component.height || 1}px` }} />
|
||||
<hr key={component.id} className="border-input" style={{ borderWidth: `${component.height || 1}px` }} />
|
||||
);
|
||||
|
||||
case 'footer':
|
||||
return (
|
||||
<div key={component.id} className="text-center text-sm text-gray-500 py-4 border-t bg-gray-50">
|
||||
{component.companyName && <div className="font-semibold text-gray-700">{component.companyName}</div>}
|
||||
<div key={component.id} className="text-center text-sm text-muted-foreground py-4 border-t bg-muted">
|
||||
{component.companyName && <div className="font-semibold text-foreground">{component.companyName}</div>}
|
||||
{(component.ceoName || component.businessNumber) && (
|
||||
<div className="mt-1">
|
||||
{component.ceoName && <span>대표: {component.ceoName}</span>}
|
||||
@@ -1297,7 +1297,7 @@ ${data.originalBody}`;
|
||||
{component.email && <span>Email: {component.email}</span>}
|
||||
</div>
|
||||
)}
|
||||
{component.copyright && <div className="mt-2 text-xs text-gray-400">{component.copyright}</div>}
|
||||
{component.copyright && <div className="mt-2 text-xs text-muted-foreground/70">{component.copyright}</div>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1318,9 +1318,9 @@ ${data.originalBody}`;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<div className="bg-gradient-to-r from-green-50 to-emerald-50 px-4 py-3 border-t border-green-200">
|
||||
<p className="text-sm text-green-800 flex items-center gap-2 font-medium">
|
||||
<CheckCircle2 className="w-4 h-4 text-green-600" />
|
||||
<div className="bg-gradient-to-r from-green-50 to-emerald-50 px-4 py-3 border-t border-emerald-200">
|
||||
<p className="text-sm text-emerald-800 flex items-center gap-2 font-medium">
|
||||
<CheckCircle2 className="w-4 h-4 text-emerald-600" />
|
||||
위 내용으로 메일이 발송됩니다
|
||||
</p>
|
||||
</div>
|
||||
@@ -1396,7 +1396,7 @@ ${data.originalBody}`;
|
||||
onChange={handleFileSelect}
|
||||
className="hidden"
|
||||
/>
|
||||
<Upload className="w-12 h-12 mx-auto text-gray-400 mb-3" />
|
||||
<Upload className="w-12 h-12 mx-auto text-muted-foreground/70 mb-3" />
|
||||
<p className="text-sm text-muted-foreground mb-1">
|
||||
파일을 드래그하거나 클릭하여 선택하세요
|
||||
</p>
|
||||
@@ -1430,7 +1430,7 @@ ${data.originalBody}`;
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => removeFile(index)}
|
||||
className="flex-shrink-0 text-red-500 hover:text-red-600 hover:bg-red-50"
|
||||
className="flex-shrink-0 text-destructive hover:text-destructive hover:bg-destructive/10"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</Button>
|
||||
@@ -1530,7 +1530,7 @@ ${data.originalBody}`;
|
||||
<div key={index} className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<File className="w-3 h-3" />
|
||||
<span className="truncate">{file.name}</span>
|
||||
<span className="text-gray-400">({formatFileSize(file.size)})</span>
|
||||
<span className="text-muted-foreground/70">({formatFileSize(file.size)})</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user