121 lines
4.5 KiB
TypeScript
121 lines
4.5 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||
import { gdprApi } from '../../services/api';
|
||
import type { RepresentativeAuthorization } from '../../types';
|
||
import {
|
||
FileCheck,
|
||
ShieldCheck,
|
||
ShieldAlert,
|
||
FileText,
|
||
} from 'lucide-react';
|
||
import Card from '../../components/ui/Card';
|
||
|
||
export default function PortalAuthorizations() {
|
||
const queryClient = useQueryClient();
|
||
|
||
const { data: authData, isLoading } = useQuery({
|
||
queryKey: ['my-authorizations'],
|
||
queryFn: () => gdprApi.getMyAuthorizations(),
|
||
});
|
||
|
||
const toggleMutation = useMutation({
|
||
mutationFn: ({ representativeId, grant }: { representativeId: number; grant: boolean }) =>
|
||
gdprApi.toggleMyAuthorization(representativeId, grant),
|
||
onSuccess: () => {
|
||
queryClient.invalidateQueries({ queryKey: ['my-authorizations'] });
|
||
queryClient.invalidateQueries({ queryKey: ['my-authorization-status'] });
|
||
},
|
||
});
|
||
|
||
const authorizations: RepresentativeAuthorization[] = authData?.data || [];
|
||
|
||
if (isLoading) {
|
||
return <div className="text-center py-8 text-gray-500">Laden...</div>;
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<div className="flex items-center gap-3 mb-6">
|
||
<FileCheck className="w-6 h-6 text-blue-600" />
|
||
<h1 className="text-2xl font-bold">Vollmachten</h1>
|
||
</div>
|
||
|
||
<Card className="mb-6">
|
||
<p className="text-sm text-gray-600">
|
||
Hier können Sie verwalten, welche Vertreter Zugriff auf Ihre Verträge und Daten haben.
|
||
Ohne Ihre Vollmacht kann ein Vertreter Ihre Daten nicht einsehen.
|
||
</p>
|
||
</Card>
|
||
|
||
{authorizations.length === 0 ? (
|
||
<Card>
|
||
<div className="text-center py-8 text-gray-500">
|
||
Keine Vollmachten vorhanden.
|
||
</div>
|
||
</Card>
|
||
) : (
|
||
<div className="space-y-3">
|
||
{authorizations.map((auth) => (
|
||
<Card key={auth.id}>
|
||
<div className="flex items-start justify-between">
|
||
<div className="flex items-start gap-3">
|
||
{auth.isGranted ? (
|
||
<ShieldCheck className="w-5 h-5 text-green-500 mt-0.5" />
|
||
) : (
|
||
<ShieldAlert className="w-5 h-5 text-yellow-500 mt-0.5" />
|
||
)}
|
||
<div>
|
||
<h4 className="font-medium">
|
||
{auth.representative?.firstName} {auth.representative?.lastName}
|
||
</h4>
|
||
<p className="text-sm text-gray-500 mt-0.5">
|
||
{auth.isGranted
|
||
? 'Hat Vollmacht, Ihre Daten einzusehen'
|
||
: 'Keine Vollmacht – kann Ihre Daten nicht einsehen'
|
||
}
|
||
</p>
|
||
{auth.documentPath && (
|
||
<p className="text-xs text-blue-600 mt-1 flex items-center gap-1">
|
||
<FileText className="w-3 h-3" />
|
||
Vollmacht liegt als Dokument vor
|
||
</p>
|
||
)}
|
||
{auth.grantedAt && auth.isGranted && (
|
||
<p className="text-xs text-gray-400 mt-1">
|
||
Erteilt am {new Date(auth.grantedAt).toLocaleDateString('de-DE', {
|
||
day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
||
})}
|
||
</p>
|
||
)}
|
||
</div>
|
||
</div>
|
||
<button
|
||
onClick={() => toggleMutation.mutate({
|
||
representativeId: auth.representativeId,
|
||
grant: !auth.isGranted,
|
||
})}
|
||
disabled={toggleMutation.isPending}
|
||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
|
||
auth.isGranted ? 'bg-green-500' : 'bg-gray-300'
|
||
}`}
|
||
>
|
||
<span
|
||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||
auth.isGranted ? 'translate-x-6' : 'translate-x-1'
|
||
}`}
|
||
/>
|
||
</button>
|
||
</div>
|
||
</Card>
|
||
))}
|
||
</div>
|
||
)}
|
||
|
||
{toggleMutation.isError && (
|
||
<div className="mt-4 p-3 bg-red-50 border border-red-200 rounded-lg text-sm text-red-700">
|
||
Fehler beim Speichern. Bitte versuchen Sie es erneut.
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|