fix(build): Wrap map in React.Fragment to resolve JSX parsing error
Envolve a expressao filtered.map em React.Fragment no pacientes/page.tsx para tentar resolver um erro de parsing JSX no compilador do Next.js.
This commit is contained in:
parent
1ce6628e4a
commit
2dd9526e45
@ -1,4 +1,3 @@
|
||||
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
@ -8,10 +7,25 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { MoreHorizontal, Plus, Search, Eye, Edit, Trash2, ArrowLeft } from "lucide-react";
|
||||
import { MoreHorizontal, Plus, Search, Eye, Edit, Trash2, ArrowLeft, ShieldCheck } from "lucide-react";
|
||||
|
||||
import { Paciente, Endereco, listarPacientes, buscarPacientes, buscarPacientePorId, excluirPaciente } from "@/lib/api";
|
||||
import {
|
||||
Paciente,
|
||||
listarPacientes,
|
||||
buscarPacientes,
|
||||
buscarPacientePorId,
|
||||
excluirPaciente,
|
||||
listarAutorizacoesUsuario,
|
||||
atualizarAutorizacoesUsuario,
|
||||
type AuthorizationRole,
|
||||
} from "@/lib/api";
|
||||
import { PatientRegistrationForm } from "@/components/forms/patient-registration-form";
|
||||
import { getCurrentUser, atualizarPaciente } from "@/lib/api";
|
||||
import {
|
||||
UpdateAuthorizationsDialog,
|
||||
type AuthorizationState,
|
||||
} from "@/components/dialogs/update-authorizations-dialog";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
|
||||
function normalizePaciente(p: any): Paciente {
|
||||
@ -33,6 +47,7 @@ function normalizePaciente(p: any): Paciente {
|
||||
city: p.city ?? p.cidade ?? "",
|
||||
state: p.state ?? p.estado ?? "",
|
||||
notes: p.notes ?? p.observacoes ?? null,
|
||||
user_id: p.user_id ?? p.usuario_id ?? p.userId ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -46,6 +61,14 @@ export default function PacientesPage() {
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [editingId, setEditingId] = useState<string | null>(null);
|
||||
const [viewingPatient, setViewingPatient] = useState<Paciente | null>(null);
|
||||
const [authDialogOpen, setAuthDialogOpen] = useState(false);
|
||||
const [authTargetPatient, setAuthTargetPatient] = useState<Paciente | null>(null);
|
||||
const [authInitialRoles, setAuthInitialRoles] = useState<AuthorizationState | null>(null);
|
||||
const [authorizationsLoading, setAuthorizationsLoading] = useState(false);
|
||||
const [authorizationsError, setAuthorizationsError] = useState<string | null>(null);
|
||||
const [authorizationsSubmitDisabled, setAuthorizationsSubmitDisabled] = useState(false);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
async function loadAll() {
|
||||
try {
|
||||
@ -106,6 +129,96 @@ export default function PacientesPage() {
|
||||
setViewingPatient(patient);
|
||||
}
|
||||
|
||||
async function handleOpenAuthorizations(patient: Paciente) {
|
||||
setAuthTargetPatient(patient);
|
||||
setAuthDialogOpen(true);
|
||||
setAuthorizationsLoading(!!patient.user_id);
|
||||
setAuthorizationsError(null);
|
||||
setAuthInitialRoles(null);
|
||||
setAuthorizationsSubmitDisabled(false);
|
||||
|
||||
if (!patient.user_id) {
|
||||
setAuthorizationsError(
|
||||
"Este paciente ainda não possui um usuário vinculado. Cadastre ou vincule um usuário para gerenciar autorizações.",
|
||||
);
|
||||
setAuthInitialRoles({ paciente: true, medico: false });
|
||||
setAuthorizationsSubmitDisabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const roles = await listarAutorizacoesUsuario(patient.user_id);
|
||||
if (!roles.length) {
|
||||
setAuthInitialRoles({ paciente: true, medico: false });
|
||||
} else {
|
||||
setAuthInitialRoles({
|
||||
paciente: roles.includes("paciente"),
|
||||
medico: roles.includes("medico"),
|
||||
});
|
||||
}
|
||||
} catch (e: any) {
|
||||
setAuthorizationsError(e?.message || "Erro ao carregar autorizações.");
|
||||
} finally {
|
||||
setAuthorizationsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleAuthDialogOpenChange(open: boolean) {
|
||||
if (!open) {
|
||||
setAuthDialogOpen(false);
|
||||
setAuthTargetPatient(null);
|
||||
setAuthInitialRoles(null);
|
||||
setAuthorizationsError(null);
|
||||
setAuthorizationsLoading(false);
|
||||
setAuthorizationsSubmitDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleConfirmAuthorizations(selection: AuthorizationState) {
|
||||
if (!authTargetPatient?.user_id) {
|
||||
toast({
|
||||
title: "Usuário não vinculado",
|
||||
description: "Não foi possível atualizar as autorizações porque o usuário não está vinculado.",
|
||||
variant: "destructive",
|
||||
});
|
||||
setAuthorizationsError(
|
||||
"Vincule este paciente a um usuário antes de ajustar as autorizações.",
|
||||
);
|
||||
setAuthorizationsSubmitDisabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[Auth] Confirm clicked", selection, "targetUserId=", authTargetPatient?.user_id);
|
||||
setAuthorizationsLoading(true);
|
||||
setAuthorizationsError(null);
|
||||
|
||||
const selectedRoles: AuthorizationRole[] = [];
|
||||
if (selection.paciente) selectedRoles.push("paciente");
|
||||
if (selection.medico) selectedRoles.push("medico");
|
||||
|
||||
try {
|
||||
console.log("[Auth] Updating roles to server:", selectedRoles);
|
||||
const result = await atualizarAutorizacoesUsuario(authTargetPatient.user_id, selectedRoles);
|
||||
console.log("[Auth] Update result:", result);
|
||||
toast({
|
||||
title: "Autorizações atualizadas",
|
||||
description: "As permissões deste paciente foram atualizadas com sucesso.",
|
||||
});
|
||||
setAuthDialogOpen(false);
|
||||
setAuthTargetPatient(null);
|
||||
setAuthInitialRoles(null);
|
||||
await loadAll();
|
||||
} catch (e: any) {
|
||||
toast({
|
||||
title: "Erro ao atualizar autorizações",
|
||||
description: e?.message || "Não foi possível atualizar as autorizações.",
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setAuthorizationsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(id: string) {
|
||||
if (!confirm("Excluir este paciente?")) return;
|
||||
try {
|
||||
@ -116,8 +229,22 @@ export default function PacientesPage() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleSaved(p: Paciente) {
|
||||
const saved = normalizePaciente(p);
|
||||
async function handleSaved(p: Paciente) {
|
||||
// Normaliza e atualiza localmente
|
||||
let saved = normalizePaciente(p);
|
||||
// Vincula o registro de paciente ao usuário autenticado
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
// Preparar payload apenas com campos de PacienteInput e user_id
|
||||
const { id: _id, user_id: _oldUserId, ...rest } = saved;
|
||||
const payload = { ...rest, user_id: user.id };
|
||||
const linked = await atualizarPaciente(saved.id, payload);
|
||||
saved = normalizePaciente(linked);
|
||||
} catch (e) {
|
||||
// Se falhar, mantém saved original
|
||||
console.warn("Falha ao vincular usuário ao paciente:", e);
|
||||
}
|
||||
// Atualiza lista com o registro vinculado
|
||||
setPatients((prev) => {
|
||||
const i = prev.findIndex((x) => String(x.id) === String(saved.id));
|
||||
if (i < 0) return [saved, ...prev];
|
||||
@ -161,6 +288,10 @@ export default function PacientesPage() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleBuscarClick() {
|
||||
void handleBuscarServidor();
|
||||
}
|
||||
|
||||
if (loading) return <p>Carregando pacientes...</p>;
|
||||
if (error) return <p className="text-red-500">{error}</p>;
|
||||
|
||||
@ -185,8 +316,13 @@ export default function PacientesPage() {
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
'[Page] Rendering dialog, passing onConfirm. Typeof handleConfirmAuthorizations is:',
|
||||
typeof handleConfirmAuthorizations,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-6 p-6 bg-background">
|
||||
<div className="flex h-full flex-col space-y-6 p-6 bg-background">
|
||||
<div className="flex items-center justify-between gap-4 flex-wrap">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Pacientes</h1>
|
||||
@ -204,7 +340,7 @@ export default function PacientesPage() {
|
||||
onKeyDown={(e) => e.key === "Enter" && handleBuscarServidor()}
|
||||
/>
|
||||
</div>
|
||||
<Button variant="secondary" onClick={handleBuscarServidor} className="hover:bg-primary hover:text-white">Buscar</Button>
|
||||
<Button variant="secondary" onClick={handleBuscarClick} className="hover:bg-primary hover:text-white">Buscar</Button>
|
||||
<Button onClick={handleAdd}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Novo paciente
|
||||
@ -250,6 +386,10 @@ export default function PacientesPage() {
|
||||
<Edit className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleOpenAuthorizations(p)}>
|
||||
<ShieldCheck className="mr-2 h-4 w-4" />
|
||||
Atualizar autorizações
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleDelete(String(p.id))} className="text-destructive">
|
||||
<Trash2 className="mr-2 h-4 w-4" />
|
||||
Excluir
|
||||
@ -270,47 +410,19 @@ export default function PacientesPage() {
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
{viewingPatient && (
|
||||
<Dialog open={!!viewingPatient} onOpenChange={() => setViewingPatient(null)}>
|
||||
<DialogContent className="max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Detalhes do Paciente</DialogTitle>
|
||||
<DialogDescription>
|
||||
Informações detalhadas de {viewingPatient.full_name}.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">Nome</Label>
|
||||
<span className="col-span-3 font-medium">{viewingPatient.full_name}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">CPF</Label>
|
||||
<span className="col-span-3">{viewingPatient.cpf}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">Telefone</Label>
|
||||
<span className="col-span-3">{viewingPatient.phone_mobile}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">Endereço</Label>
|
||||
<span className="col-span-3">
|
||||
{`${viewingPatient.street || ''}, ${viewingPatient.number || ''} - ${viewingPatient.neighborhood || ''}, ${viewingPatient.city || ''} - ${viewingPatient.state || ''}`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">Observações</Label>
|
||||
<span className="col-span-3">{viewingPatient.notes || "Nenhuma"}</span>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button onClick={() => setViewingPatient(null)}>Fechar</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
|
||||
<div className="text-sm text-muted-foreground">Mostrando {filtered.length} de {patients.length}</div>
|
||||
|
||||
<UpdateAuthorizationsDialog
|
||||
open={authDialogOpen}
|
||||
entityType="paciente"
|
||||
entityName={authTargetPatient?.full_name}
|
||||
initialRoles={authInitialRoles ?? undefined}
|
||||
loading={authorizationsLoading}
|
||||
error={authorizationsError}
|
||||
disableSubmit={authorizationsSubmitDisabled}
|
||||
onOpenChange={handleAuthDialogOpenChange}
|
||||
onConfirm={handleConfirmAuthorizations}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user