Split 879-LOC page.tsx into 187 LOC with 11 colocated components, _types.ts and _constants.ts for the industry templates module. Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import type { IndustryTemplate, DetailTab } from '../_types'
|
|
import { DETAIL_TABS } from '../_constants'
|
|
import { VVTTab } from './VVTTab'
|
|
import { TOMTab } from './TOMTab'
|
|
import { RiskTab } from './RiskTab'
|
|
|
|
export function DetailContent({
|
|
detail,
|
|
activeTab,
|
|
onTabChange,
|
|
applying,
|
|
onApply,
|
|
}: {
|
|
detail: IndustryTemplate
|
|
activeTab: DetailTab
|
|
onTabChange: (tab: DetailTab) => void
|
|
applying: boolean
|
|
onApply: () => void
|
|
}) {
|
|
return (
|
|
<div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
|
|
<div className="flex border-b border-slate-200 bg-slate-50">
|
|
{DETAIL_TABS.map((tab) => {
|
|
const isActive = activeTab === tab.key
|
|
let count = 0
|
|
if (tab.key === 'vvt') count = detail.vvt_templates?.length || 0
|
|
if (tab.key === 'tom') count = detail.tom_recommendations?.length || 0
|
|
if (tab.key === 'risks') count = detail.risk_scenarios?.length || 0
|
|
|
|
return (
|
|
<button
|
|
key={tab.key}
|
|
onClick={() => onTabChange(tab.key)}
|
|
className={`flex-1 px-4 py-3 text-sm font-medium transition-colors relative ${
|
|
isActive
|
|
? 'text-emerald-700 bg-white border-b-2 border-emerald-500'
|
|
: 'text-slate-500 hover:text-slate-700 hover:bg-slate-100'
|
|
}`}
|
|
>
|
|
{tab.label}
|
|
{count > 0 && (
|
|
<span
|
|
className={`ml-1.5 inline-flex items-center justify-center px-1.5 py-0.5 rounded-full text-xs ${
|
|
isActive
|
|
? 'bg-emerald-100 text-emerald-700'
|
|
: 'bg-slate-200 text-slate-500'
|
|
}`}
|
|
>
|
|
{count}
|
|
</span>
|
|
)}
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
|
|
<div className="p-6">
|
|
{activeTab === 'vvt' && <VVTTab templates={detail.vvt_templates || []} />}
|
|
{activeTab === 'tom' && <TOMTab recommendations={detail.tom_recommendations || []} />}
|
|
{activeTab === 'risks' && <RiskTab scenarios={detail.risk_scenarios || []} />}
|
|
</div>
|
|
|
|
<div className="px-6 py-4 border-t border-slate-200 bg-slate-50">
|
|
<div className="flex items-center justify-between">
|
|
<p className="text-sm text-slate-500">
|
|
Importiert alle Vorlagen, Empfehlungen und Szenarien in Ihr System.
|
|
</p>
|
|
<button
|
|
onClick={onApply}
|
|
disabled={applying}
|
|
className={`inline-flex items-center gap-2 px-5 py-2.5 rounded-lg text-sm font-semibold text-white transition-all ${
|
|
applying
|
|
? 'bg-emerald-400 cursor-not-allowed'
|
|
: 'bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 shadow-sm hover:shadow-md'
|
|
}`}
|
|
>
|
|
{applying ? (
|
|
<>
|
|
<svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
|
</svg>
|
|
Wird angewendet...
|
|
</>
|
|
) : (
|
|
<>
|
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
|
</svg>
|
|
Branchenpaket anwenden
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|