riseup-squad20/susconecta/components/dialogs/update-authorizations-dialog.tsx

199 lines
5.8 KiB
TypeScript

"use client";
import React, { useState, useEffect, useMemo } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Loader2, ShieldCheck } from "lucide-react";
import type { AuthorizationRole } from "@/lib/api";
export type AuthorizationState = {
paciente: boolean;
medico: boolean;
};
export interface UpdateAuthorizationsDialogProperties {
open: boolean;
entityType: "paciente" | "medico";
entityName?: string | null;
initialRoles?: Partial<AuthorizationState> | null;
loading?: boolean;
error?: string | null;
disableSubmit?: boolean;
onOpenChange: (open: boolean) => void;
onConfirm: (roles: AuthorizationState) => void;
}
const DEFAULT_ROLES: AuthorizationState = { paciente: false, medico: false };
export function UpdateAuthorizationsDialog({
open,
entityType,
entityName,
initialRoles,
loading = false,
error,
disableSubmit = false,
onOpenChange,
onConfirm,
}: UpdateAuthorizationsDialogProperties) {
const [roles, setRoles] = useState<AuthorizationState>(DEFAULT_ROLES);
console.log("[Dialog] render", {
open,
initialRoles,
loading,
disableSubmit,
roles,
});
useEffect(() => {
console.log("[Dialog] useEffect open change", open, initialRoles);
if (open) {
setRoles({
paciente: initialRoles?.paciente ?? entityType === "paciente",
medico: initialRoles?.medico ?? entityType === "medico",
});
}
}, [open, initialRoles, entityType]);
// Debug: log when roles state changes
useEffect(() => {
console.log("[Dialog] roles updated", roles);
}, [roles]);
const title = useMemo(
() =>
entityType === "paciente"
? "Atualizar autorizações do paciente"
: "Atualizar autorizações do médico",
[entityType],
);
const description = useMemo(
() =>
entityName
? `Defina quais tipos de acesso ${entityName} poderá utilizar no sistema.`
: "Defina quem pode acessar este perfil.",
[entityName],
);
function handleToggle(
role: AuthorizationRole,
value: boolean | "indeterminate",
) {
console.log("[Dialog] toggle", role, value);
setRoles((previous) => ({ ...previous, [role]: value === true }));
}
const handleSave = () => {
console.log("[Dialog] handleSave called with roles:", roles);
console.log(
"[Dialog] About to call onConfirm. Typeof onConfirm is:",
typeof onConfirm,
);
if (typeof onConfirm === "function") {
onConfirm(roles);
// Não fecha aqui - deixa o componente pai fechar após processar
} else {
console.error("[Dialog] onConfirm is NOT a function! It is:", onConfirm);
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<ShieldCheck className="h-5 w-5" />
{title}
</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<div className="space-y-6">
<div className="space-y-4">
<div className="flex items-start gap-3 rounded-lg border p-4">
<Checkbox
id="auth-paciente"
checked={roles.paciente}
disabled={loading}
onCheckedChange={(value) => handleToggle("paciente", value)}
/>
<div>
<Label htmlFor="auth-paciente">Acesso como paciente</Label>
<p className="text-sm text-muted-foreground">
Permite que este usuário acesse o portal do paciente.
</p>
</div>
</div>
<div className="flex items-start gap-3 rounded-lg border p-4">
<Checkbox
id="auth-medico"
checked={roles.medico}
disabled={loading}
onCheckedChange={(value) => handleToggle("medico", value)}
/>
<div>
<Label htmlFor="auth-medico">Acesso como médico</Label>
<p className="text-sm text-muted-foreground">
Permite que este usuário acesse o portal profissional.
</p>
</div>
</div>
</div>
<Alert>
<AlertDescription>
Você pode habilitar as duas opções para permitir login como
paciente e médico usando as mesmas credenciais.
</AlertDescription>
</Alert>
{error && (
<Alert variant="destructive">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
</div>
<DialogFooter className="gap-4">
<Button
variant="outline"
onClick={() => onOpenChange(false)}
disabled={loading}
>
Cancelar
</Button>
{/* Debug: botão nativo para garantir onClick */}
<button
type="button"
onClick={() => {
console.log("[Debug Save] native button clicked", {
loading,
disableSubmit,
roles,
});
handleSave();
}}
disabled={loading}
className="inline-flex items-center justify-center rounded-md bg-primary text-primary-foreground px-4 py-2 disabled:opacity-50"
>
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}Salvar
alterações
</button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}