Some checks failed
Build + Deploy / build-admin-compliance (push) Successful in 2m9s
Build + Deploy / build-backend-compliance (push) Failing after 3m24s
Build + Deploy / build-ai-sdk (push) Successful in 52s
Build + Deploy / build-developer-portal (push) Successful in 1m15s
Build + Deploy / build-tts (push) Successful in 1m23s
Build + Deploy / build-document-crawler (push) Successful in 38s
Build + Deploy / build-dsms-gateway (push) Successful in 27s
CI / branch-name (push) Has been skipped
Build + Deploy / trigger-orca (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 18s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m42s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 41s
CI / test-python-backend (push) Successful in 41s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 16s
Backend gibt variables manchmal als {} (Objekt) statt [] (Array)
zurueck. (template.variables || []).map() greift nicht weil {}
truthy ist. Fix: Array.isArray() Check in TemplateCard + EditorTab.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
'use client'
|
|
|
|
import { CATEGORIES, EmailTemplate, STATUS_BADGE } from '../_types'
|
|
|
|
interface TemplateCardProps {
|
|
template: EmailTemplate
|
|
onEdit: () => void
|
|
}
|
|
|
|
export function TemplateCard({ template, onEdit }: TemplateCardProps) {
|
|
const cat = CATEGORIES[template.category] || CATEGORIES.general
|
|
const version = template.latest_version
|
|
const status = version ? (STATUS_BADGE[version.status] || STATUS_BADGE.draft) : STATUS_BADGE.draft
|
|
|
|
return (
|
|
<div
|
|
className="bg-white border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow cursor-pointer"
|
|
onClick={onEdit}
|
|
>
|
|
<div className="flex items-start justify-between mb-2">
|
|
<div>
|
|
<h3 className="font-medium text-gray-900 text-sm">{template.name}</h3>
|
|
<span className={`inline-block mt-1 px-2 py-0.5 rounded text-xs ${cat.bgColor} ${cat.color}`}>
|
|
{cat.label}
|
|
</span>
|
|
</div>
|
|
<span className={`px-2 py-0.5 rounded text-xs ${status.color}`}>{status.label}</span>
|
|
</div>
|
|
{template.description && (
|
|
<p className="text-xs text-gray-500 mt-2 line-clamp-2">{template.description}</p>
|
|
)}
|
|
<div className="mt-3 flex flex-wrap gap-1">
|
|
{(Array.isArray(template.variables) ? template.variables : []).slice(0, 4).map(v => (
|
|
<span key={v} className="px-1.5 py-0.5 bg-gray-50 text-gray-500 rounded text-xs font-mono">
|
|
{`{{${v}}}`}
|
|
</span>
|
|
))}
|
|
{Array.isArray(template.variables) && template.variables.length > 4 && (
|
|
<span className="text-xs text-gray-400">+{template.variables.length - 4}</span>
|
|
)}
|
|
</div>
|
|
{version && (
|
|
<div className="mt-3 text-xs text-gray-400">
|
|
v{version.version} · {version.created_at ? new Date(version.created_at).toLocaleDateString('de-DE') : ''}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|