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:
M-Gabrielly 2025-10-09 03:32:08 -03:00
parent 1ce6628e4a
commit 2dd9526e45

View File

@ -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>
);
}