Files
breakpilot-compliance/admin-compliance/app/sdk/dsb-portal/_components/MandantCard.tsx
Sharang Parnerkar 6c883fb12e refactor(admin): split loeschfristen + dsb-portal page.tsx into colocated components
Split two oversized page files into _components/ directories following
Next.js 15 conventions and the 500-LOC hard cap:

- loeschfristen/page.tsx (2322 LOC -> 412 LOC orchestrator + 6 components)
- dsb-portal/page.tsx (2068 LOC -> 135 LOC orchestrator + 9 components)

All component files stay under 500 lines. Build verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:51:16 +02:00

70 lines
2.5 KiB
TypeScript

'use client'
import React from 'react'
import { AssignmentOverview, ASSIGNMENT_STATUS_LABELS, ASSIGNMENT_STATUS_COLORS, formatDate } from './types'
import { Badge, ComplianceBar, HoursBar, IconTask, IconCalendar } from './ui-primitives'
export function MandantCard({
assignment,
onClick,
}: {
assignment: AssignmentOverview
onClick: () => void
}) {
return (
<div
onClick={onClick}
className="bg-white rounded-xl border border-gray-200 p-5 hover:border-purple-400 hover:shadow-lg cursor-pointer transition-all group"
>
{/* Header */}
<div className="flex items-start justify-between mb-3">
<div className="min-w-0">
<h3 className="font-semibold text-gray-900 truncate group-hover:text-purple-700 transition-colors">
{assignment.tenant_name}
</h3>
<p className="text-xs text-gray-400 font-mono">{assignment.tenant_slug}</p>
</div>
<Badge
label={ASSIGNMENT_STATUS_LABELS[assignment.status] || assignment.status}
className={ASSIGNMENT_STATUS_COLORS[assignment.status] || 'bg-gray-100 text-gray-600'}
/>
</div>
{/* Compliance Score */}
<div className="mb-3">
<div className="flex items-center justify-between text-xs text-gray-500 mb-1">
<span>Compliance-Score</span>
</div>
<ComplianceBar score={assignment.compliance_score} />
</div>
{/* Hours */}
<div className="mb-3">
<div className="flex items-center justify-between text-xs text-gray-500 mb-1">
<span>Stunden diesen Monat</span>
</div>
<HoursBar used={assignment.hours_this_month} budget={assignment.hours_budget} />
</div>
{/* Footer: Tasks */}
<div className="flex items-center justify-between pt-3 border-t border-gray-100">
<div className="flex items-center gap-1 text-sm text-gray-600">
<IconTask className="w-4 h-4" />
<span>{assignment.open_task_count} offene Aufgaben</span>
</div>
{assignment.urgent_task_count > 0 && (
<Badge label={`${assignment.urgent_task_count} dringend`} className="bg-red-100 text-red-700 border-red-200" />
)}
</div>
{/* Next deadline */}
{assignment.next_deadline && (
<div className="flex items-center gap-1 mt-2 text-xs text-gray-400">
<IconCalendar className="w-3 h-3" />
<span>Naechste Frist: {formatDate(assignment.next_deadline)}</span>
</div>
)}
</div>
)
}