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>
205 lines
6.1 KiB
TypeScript
205 lines
6.1 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import {
|
|
DSRRequest,
|
|
DSRCommunication,
|
|
DSRVerifyIdentityRequest,
|
|
} from '@/lib/sdk/dsr/types'
|
|
import {
|
|
fetchSDKDSR,
|
|
verifyDSRIdentity,
|
|
assignDSR,
|
|
extendDSRDeadline,
|
|
completeDSR,
|
|
rejectDSR,
|
|
fetchDSRCommunications,
|
|
sendDSRCommunication,
|
|
fetchDSRExceptionChecks,
|
|
initDSRExceptionChecks,
|
|
updateDSRExceptionCheck,
|
|
fetchDSRHistory,
|
|
} from '@/lib/sdk/dsr/api'
|
|
|
|
export function useDSRDetail(requestId: string) {
|
|
const [request, setRequest] = useState<DSRRequest | null>(null)
|
|
const [communications, setCommunications] = useState<DSRCommunication[]>([])
|
|
const [history, setHistory] = useState<any[]>([])
|
|
const [exceptionChecks, setExceptionChecks] = useState<any[]>([])
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
|
|
// Load data from SDK backend
|
|
useEffect(() => {
|
|
const loadData = async () => {
|
|
setIsLoading(true)
|
|
try {
|
|
const found = await fetchSDKDSR(requestId)
|
|
if (found) {
|
|
setRequest(found)
|
|
// Load communications, history, and exception checks in parallel
|
|
const [comms, hist] = await Promise.all([
|
|
fetchDSRCommunications(requestId).catch(() => []),
|
|
fetchDSRHistory(requestId).catch(() => []),
|
|
])
|
|
setCommunications(comms.map((c: any) => ({
|
|
id: c.id,
|
|
dsrId: c.dsr_id,
|
|
type: c.communication_type,
|
|
channel: c.channel,
|
|
subject: c.subject,
|
|
content: c.content,
|
|
createdAt: c.created_at,
|
|
createdBy: c.created_by,
|
|
sentAt: c.sent_at,
|
|
sentBy: c.sent_by,
|
|
})))
|
|
setHistory(hist)
|
|
|
|
// Load exception checks for erasure requests
|
|
if (found.type === 'erasure') {
|
|
try {
|
|
const checks = await fetchDSRExceptionChecks(requestId)
|
|
if (checks.length === 0) {
|
|
// Auto-initialize if none exist
|
|
const initialized = await initDSRExceptionChecks(requestId)
|
|
setExceptionChecks(initialized)
|
|
} else {
|
|
setExceptionChecks(checks)
|
|
}
|
|
} catch {
|
|
setExceptionChecks([])
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load DSR:', error)
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
loadData()
|
|
}, [requestId])
|
|
|
|
const handleVerifyIdentity = async (verification: DSRVerifyIdentityRequest) => {
|
|
if (!request) return
|
|
try {
|
|
const updated = await verifyDSRIdentity(request.id, {
|
|
method: verification.method,
|
|
notes: verification.notes,
|
|
document_ref: verification.documentRef,
|
|
})
|
|
setRequest(updated)
|
|
fetchDSRHistory(requestId).then(setHistory).catch(() => {})
|
|
} catch (err) {
|
|
console.error('Failed to verify identity:', err)
|
|
}
|
|
}
|
|
|
|
const handleAssign = async () => {
|
|
if (!request) return
|
|
const assignee = prompt('Zuweisen an (Name/ID):')
|
|
if (!assignee) return
|
|
try {
|
|
const updated = await assignDSR(request.id, assignee)
|
|
setRequest(updated)
|
|
fetchDSRHistory(requestId).then(setHistory).catch(() => {})
|
|
} catch (err) {
|
|
console.error('Failed to assign:', err)
|
|
}
|
|
}
|
|
|
|
const handleExtendDeadline = async () => {
|
|
if (!request) return
|
|
const reason = prompt('Grund fuer die Fristverlaengerung:')
|
|
if (!reason) return
|
|
const daysStr = prompt('Um wie viele Tage verlaengern? (Standard: 60)', '60')
|
|
const days = parseInt(daysStr || '60', 10) || 60
|
|
try {
|
|
const updated = await extendDSRDeadline(request.id, reason, days)
|
|
setRequest(updated)
|
|
fetchDSRHistory(requestId).then(setHistory).catch(() => {})
|
|
} catch (err) {
|
|
console.error('Failed to extend deadline:', err)
|
|
}
|
|
}
|
|
|
|
const handleComplete = async () => {
|
|
if (!request) return
|
|
const summary = prompt('Zusammenfassung der Bearbeitung:')
|
|
if (summary === null) return
|
|
try {
|
|
const updated = await completeDSR(request.id, summary || undefined)
|
|
setRequest(updated)
|
|
fetchDSRHistory(requestId).then(setHistory).catch(() => {})
|
|
} catch (err) {
|
|
console.error('Failed to complete:', err)
|
|
}
|
|
}
|
|
|
|
const handleReject = async () => {
|
|
if (!request) return
|
|
const reason = prompt('Ablehnungsgrund:')
|
|
if (!reason) return
|
|
const legalBasis = prompt('Rechtsgrundlage (optional):')
|
|
try {
|
|
const updated = await rejectDSR(request.id, reason, legalBasis || undefined)
|
|
setRequest(updated)
|
|
fetchDSRHistory(requestId).then(setHistory).catch(() => {})
|
|
} catch (err) {
|
|
console.error('Failed to reject:', err)
|
|
}
|
|
}
|
|
|
|
const handleSendCommunication = async (message: any) => {
|
|
if (!request) return
|
|
try {
|
|
const result = await sendDSRCommunication(requestId, {
|
|
communication_type: message.type || 'outgoing',
|
|
channel: message.channel || 'email',
|
|
subject: message.subject,
|
|
content: message.content,
|
|
})
|
|
const newComm: DSRCommunication = {
|
|
id: result.id,
|
|
dsrId: result.dsr_id,
|
|
type: result.communication_type,
|
|
channel: result.channel,
|
|
subject: result.subject,
|
|
content: result.content,
|
|
createdAt: result.created_at,
|
|
createdBy: result.created_by || 'Current User',
|
|
sentAt: result.sent_at,
|
|
sentBy: result.sent_by,
|
|
}
|
|
setCommunications(prev => [newComm, ...prev])
|
|
} catch (err) {
|
|
console.error('Failed to send communication:', err)
|
|
}
|
|
}
|
|
|
|
const handleExceptionCheckChange = async (checkId: string, applies: boolean, notes?: string) => {
|
|
try {
|
|
const updated = await updateDSRExceptionCheck(requestId, checkId, { applies, notes })
|
|
setExceptionChecks(prev => prev.map(c => c.id === checkId ? updated : c))
|
|
} catch (err) {
|
|
console.error('Failed to update exception check:', err)
|
|
}
|
|
}
|
|
|
|
return {
|
|
request,
|
|
setRequest,
|
|
communications,
|
|
history,
|
|
exceptionChecks,
|
|
isLoading,
|
|
handleVerifyIdentity,
|
|
handleAssign,
|
|
handleExtendDeadline,
|
|
handleComplete,
|
|
handleReject,
|
|
handleSendCommunication,
|
|
handleExceptionCheckChange,
|
|
}
|
|
}
|