refactor(admin): split dsr/[requestId] page.tsx into colocated components
Split the 854-line DSR detail page into colocated components under _components/ and a data-loading hook under _hooks/. No behavior changes. page.tsx is now 172 LOC, all extracted files under 300 LOC. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import { DSRRequest } from '@/lib/sdk/dsr/types'
|
||||
|
||||
export function DSRDetailsTab({
|
||||
request,
|
||||
onShowIdentityModal,
|
||||
}: {
|
||||
request: DSRRequest
|
||||
onShowIdentityModal: () => void
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Request Info */}
|
||||
<div className="grid grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-500 mb-2">Antragsteller</h4>
|
||||
<div className="space-y-2">
|
||||
<div className="font-medium text-gray-900">{request.requester.name}</div>
|
||||
<div className="text-sm text-gray-600">{request.requester.email}</div>
|
||||
{request.requester.phone && (
|
||||
<div className="text-sm text-gray-600">{request.requester.phone}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-500 mb-2">Eingereicht</h4>
|
||||
<div className="space-y-2">
|
||||
<div className="font-medium text-gray-900">
|
||||
{new Date(request.receivedAt).toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
})}
|
||||
</div>
|
||||
<div className="text-sm text-gray-600">
|
||||
Quelle: {request.source === 'web_form' ? 'Kontaktformular' :
|
||||
request.source === 'email' ? 'E-Mail' :
|
||||
request.source === 'letter' ? 'Brief' :
|
||||
request.source === 'phone' ? 'Telefon' : request.source}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Identity Verification */}
|
||||
<div className={`
|
||||
p-4 rounded-xl border
|
||||
${request.identityVerification.verified
|
||||
? 'bg-green-50 border-green-200'
|
||||
: 'bg-yellow-50 border-yellow-200'
|
||||
}
|
||||
`}>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className={`
|
||||
w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0
|
||||
${request.identityVerification.verified ? 'bg-green-100' : 'bg-yellow-100'}
|
||||
`}>
|
||||
{request.identityVerification.verified ? (
|
||||
<svg className="w-4 h-4 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className={`font-medium ${request.identityVerification.verified ? 'text-green-800' : 'text-yellow-800'}`}>
|
||||
{request.identityVerification.verified
|
||||
? 'Identitaet verifiziert'
|
||||
: 'Identitaetspruefung ausstehend'
|
||||
}
|
||||
</div>
|
||||
{request.identityVerification.verified && (
|
||||
<div className="text-sm text-green-700 mt-1">
|
||||
Methode: {request.identityVerification.method === 'id_document' ? 'Ausweisdokument' :
|
||||
request.identityVerification.method === 'email' ? 'E-Mail' :
|
||||
request.identityVerification.method === 'existing_account' ? 'Bestehendes Konto' :
|
||||
request.identityVerification.method}
|
||||
{' | '}
|
||||
{new Date(request.identityVerification.verifiedAt!).toLocaleDateString('de-DE')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!request.identityVerification.verified && (
|
||||
<button
|
||||
onClick={onShowIdentityModal}
|
||||
className="px-3 py-1.5 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700 transition-colors text-sm"
|
||||
>
|
||||
Jetzt pruefen
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Request Text */}
|
||||
{request.requestText && (
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-500 mb-2">Anfragetext</h4>
|
||||
<div className="bg-gray-50 rounded-xl p-4 text-gray-700 whitespace-pre-wrap">
|
||||
{request.requestText}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Notes */}
|
||||
{request.notes && (
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-500 mb-2">Notizen</h4>
|
||||
<div className="bg-gray-50 rounded-xl p-4 text-gray-700">
|
||||
{request.notes}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user