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";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
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 { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
|
||||||
import { Label } from "@/components/ui/label";
|
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 { 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 {
|
function normalizePaciente(p: any): Paciente {
|
||||||
@ -33,6 +47,7 @@ function normalizePaciente(p: any): Paciente {
|
|||||||
city: p.city ?? p.cidade ?? "",
|
city: p.city ?? p.cidade ?? "",
|
||||||
state: p.state ?? p.estado ?? "",
|
state: p.state ?? p.estado ?? "",
|
||||||
notes: p.notes ?? p.observacoes ?? null,
|
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 [showForm, setShowForm] = useState(false);
|
||||||
const [editingId, setEditingId] = useState<string | null>(null);
|
const [editingId, setEditingId] = useState<string | null>(null);
|
||||||
const [viewingPatient, setViewingPatient] = useState<Paciente | 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() {
|
async function loadAll() {
|
||||||
try {
|
try {
|
||||||
@ -106,6 +129,96 @@ export default function PacientesPage() {
|
|||||||
setViewingPatient(patient);
|
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) {
|
async function handleDelete(id: string) {
|
||||||
if (!confirm("Excluir este paciente?")) return;
|
if (!confirm("Excluir este paciente?")) return;
|
||||||
try {
|
try {
|
||||||
@ -116,8 +229,22 @@ export default function PacientesPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSaved(p: Paciente) {
|
async function handleSaved(p: Paciente) {
|
||||||
const saved = normalizePaciente(p);
|
// 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) => {
|
setPatients((prev) => {
|
||||||
const i = prev.findIndex((x) => String(x.id) === String(saved.id));
|
const i = prev.findIndex((x) => String(x.id) === String(saved.id));
|
||||||
if (i < 0) return [saved, ...prev];
|
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 (loading) return <p>Carregando pacientes...</p>;
|
||||||
if (error) return <p className="text-red-500">{error}</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 (
|
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 className="flex items-center justify-between gap-4 flex-wrap">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold">Pacientes</h1>
|
<h1 className="text-2xl font-bold">Pacientes</h1>
|
||||||
@ -204,7 +340,7 @@ export default function PacientesPage() {
|
|||||||
onKeyDown={(e) => e.key === "Enter" && handleBuscarServidor()}
|
onKeyDown={(e) => e.key === "Enter" && handleBuscarServidor()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</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}>
|
<Button onClick={handleAdd}>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
Novo paciente
|
Novo paciente
|
||||||
@ -250,6 +386,10 @@ export default function PacientesPage() {
|
|||||||
<Edit className="mr-2 h-4 w-4" />
|
<Edit className="mr-2 h-4 w-4" />
|
||||||
Editar
|
Editar
|
||||||
</DropdownMenuItem>
|
</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">
|
<DropdownMenuItem onClick={() => handleDelete(String(p.id))} className="text-destructive">
|
||||||
<Trash2 className="mr-2 h-4 w-4" />
|
<Trash2 className="mr-2 h-4 w-4" />
|
||||||
Excluir
|
Excluir
|
||||||
@ -270,47 +410,19 @@ export default function PacientesPage() {
|
|||||||
</Table>
|
</Table>
|
||||||
</div>
|
</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>
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user