Files
breakpilot-compliance/admin-compliance/app/sdk/document-generator/_components/TemplateLibrary.tsx
Sharang Parnerkar eeb9931d87 refactor(admin): split document-generator page.tsx into colocated components
Split 1130-LOC document-generator page into _components and _constants
modules. page.tsx now 243 LOC (wire-up only). Behavior preserved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 23:01:56 +02:00

139 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { LegalTemplateResult } from '@/lib/sdk/types'
import { CATEGORIES } from '../_constants'
import LibraryCard from './LibraryCard'
interface TemplateLibraryProps {
allTemplates: LegalTemplateResult[]
filteredTemplates: LegalTemplateResult[]
isLoadingLibrary: boolean
activeCategory: string
onCategoryChange: (cat: string) => void
activeLanguage: 'all' | 'de' | 'en'
onLanguageChange: (lang: 'all' | 'de' | 'en') => void
librarySearch: string
onSearchChange: (q: string) => void
expandedPreviewId: string | null
onTogglePreview: (id: string) => void
onUseTemplate: (t: LegalTemplateResult) => void
}
export default function TemplateLibrary({
allTemplates,
filteredTemplates,
isLoadingLibrary,
activeCategory,
onCategoryChange,
activeLanguage,
onLanguageChange,
librarySearch,
onSearchChange,
expandedPreviewId,
onTogglePreview,
onUseTemplate,
}: TemplateLibraryProps) {
return (
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="px-6 py-4 border-b border-gray-100 flex items-center justify-between flex-wrap gap-3">
<h2 className="font-semibold text-gray-900">Template-Bibliothek</h2>
<div className="flex items-center gap-1 bg-gray-100 rounded-lg p-1">
{(['all', 'de', 'en'] as const).map((lang) => (
<button
key={lang}
onClick={() => onLanguageChange(lang)}
className={`px-3 py-1.5 text-xs rounded-md font-medium transition-colors ${
activeLanguage === lang
? 'bg-white text-gray-900 shadow-sm'
: 'text-gray-500 hover:text-gray-700'
}`}
>
{lang === 'all' ? 'Alle' : lang.toUpperCase()}
</button>
))}
</div>
</div>
{/* Category pills */}
<div className="px-6 py-3 border-b border-gray-100 flex gap-2 flex-wrap">
{CATEGORIES.map((cat) => {
const count = cat.types === null
? allTemplates.filter(t => activeLanguage === 'all' || t.language === activeLanguage).length
: allTemplates.filter(t =>
cat.types!.includes(t.templateType || '') &&
(activeLanguage === 'all' || t.language === activeLanguage)
).length
return (
<button
key={cat.key}
onClick={() => onCategoryChange(cat.key)}
className={`px-3 py-1.5 rounded-full text-xs font-medium transition-colors ${
activeCategory === cat.key
? 'bg-purple-600 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
{cat.label}
{count > 0 && (
<span className={`ml-1.5 ${activeCategory === cat.key ? 'text-purple-200' : 'text-gray-400'}`}>
{count}
</span>
)}
</button>
)
})}
</div>
{/* Search */}
<div className="px-6 py-3 border-b border-gray-100">
<div className="relative">
<svg className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<input
type="text"
value={librarySearch}
onChange={(e) => onSearchChange(e.target.value)}
placeholder="Vorlage suchen... (optional)"
className="w-full pl-9 pr-4 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-400"
/>
{librarySearch && (
<button
onClick={() => onSearchChange('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
×
</button>
)}
</div>
</div>
{/* Template grid */}
<div className="p-6">
{isLoadingLibrary ? (
<div className="flex items-center justify-center h-40">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600" />
</div>
) : filteredTemplates.length === 0 ? (
<div className="text-center py-12 text-gray-500">
<div className="text-4xl mb-3">📄</div>
<p>Keine Vorlagen für diese Auswahl</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{filteredTemplates.map((template) => (
<LibraryCard
key={template.id}
template={template}
expanded={expandedPreviewId === template.id}
onTogglePreview={() => onTogglePreview(template.id)}
onUse={() => onUseTemplate(template)}
/>
))}
</div>
)}
</div>
</div>
)
}