Files
opencrm/frontend/src/pages/portal/PortalAuthorizations.tsx
T

121 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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>
);
}