merge(feature/correc-api): merge branch 'feature/correc-api' into feature/ajustes-form-medico
This commit is contained in:
commit
ed6e33890a
@ -10,34 +10,29 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, Di
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { MoreHorizontal, Plus, Search, Eye, Edit, Trash2, ArrowLeft } from "lucide-react";
|
||||
|
||||
import { Paciente, Endereco, listarPacientes, buscarPacientePorId, excluirPaciente } from "@/lib/api";
|
||||
import { Paciente, Endereco, listarPacientes, buscarPacientes, buscarPacientePorId, excluirPaciente } from "@/lib/api";
|
||||
import { PatientRegistrationForm } from "@/components/forms/patient-registration-form";
|
||||
|
||||
|
||||
function normalizePaciente(p: any): Paciente {
|
||||
const endereco: Endereco = {
|
||||
cep: p.endereco?.cep ?? p.cep ?? "",
|
||||
logradouro: p.endereco?.logradouro ?? p.street ?? "",
|
||||
numero: p.endereco?.numero ?? p.number ?? "",
|
||||
complemento: p.endereco?.complemento ?? p.complement ?? "",
|
||||
bairro: p.endereco?.bairro ?? p.neighborhood ?? "",
|
||||
cidade: p.endereco?.cidade ?? p.city ?? "",
|
||||
estado: p.endereco?.estado ?? p.state ?? "",
|
||||
};
|
||||
|
||||
return {
|
||||
id: String(p.id ?? p.uuid ?? p.paciente_id ?? ""),
|
||||
nome: p.full_name ?? "", // 👈 troca nome → full_name
|
||||
nome_social: p.social_name ?? null, // 👈 Supabase usa social_name
|
||||
full_name: p.full_name ?? p.name ?? p.nome ?? "",
|
||||
social_name: p.social_name ?? p.nome_social ?? null,
|
||||
cpf: p.cpf ?? "",
|
||||
rg: p.rg ?? p.document_number ?? null, // 👈 às vezes vem como document_number
|
||||
sexo: p.sexo ?? p.sex ?? null, // 👈 Supabase usa sex
|
||||
data_nascimento: p.data_nascimento ?? p.birth_date ?? null,
|
||||
telefone: p.telefone ?? p.phone_mobile ?? "",
|
||||
rg: p.rg ?? p.document_number ?? null,
|
||||
sex: p.sex ?? p.sexo ?? null,
|
||||
birth_date: p.birth_date ?? p.data_nascimento ?? null,
|
||||
phone_mobile: p.phone_mobile ?? p.telefone ?? "",
|
||||
email: p.email ?? "",
|
||||
endereco,
|
||||
observacoes: p.observacoes ?? p.notes ?? null,
|
||||
foto_url: p.foto_url ?? null,
|
||||
cep: p.cep ?? "",
|
||||
street: p.street ?? p.logradouro ?? "",
|
||||
number: p.number ?? p.numero ?? "",
|
||||
complement: p.complement ?? p.complemento ?? "",
|
||||
neighborhood: p.neighborhood ?? p.bairro ?? "",
|
||||
city: p.city ?? p.cidade ?? "",
|
||||
state: p.state ?? p.estado ?? "",
|
||||
notes: p.notes ?? p.observacoes ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -56,7 +51,12 @@ export default function PacientesPage() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await listarPacientes({ page: 1, limit: 20 });
|
||||
setPatients((data ?? []).map(normalizePaciente));
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
setPatients(data.map(normalizePaciente));
|
||||
} else {
|
||||
setPatients([]);
|
||||
}
|
||||
setError(null);
|
||||
} catch (e: any) {
|
||||
setPatients([]);
|
||||
@ -72,13 +72,23 @@ export default function PacientesPage() {
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
if (!search.trim()) return patients;
|
||||
const q = search.toLowerCase();
|
||||
const q = search.toLowerCase().trim();
|
||||
const qDigits = q.replace(/\D/g, "");
|
||||
|
||||
return patients.filter((p) => {
|
||||
const byName = (p.nome || "").toLowerCase().includes(q);
|
||||
const byCPF = (p.cpf || "").replace(/\D/g, "").includes(qDigits);
|
||||
const byId = String(p.id || "").includes(qDigits);
|
||||
return byName || byCPF || byId;
|
||||
// Busca por nome
|
||||
const byName = (p.full_name || "").toLowerCase().includes(q);
|
||||
|
||||
// Busca por CPF (remove formatação)
|
||||
const byCPF = qDigits.length >= 3 && (p.cpf || "").replace(/\D/g, "").includes(qDigits);
|
||||
|
||||
// Busca por ID (UUID completo ou parcial)
|
||||
const byId = (p.id || "").toLowerCase().includes(q);
|
||||
|
||||
// Busca por email
|
||||
const byEmail = (p.email || "").toLowerCase().includes(q);
|
||||
|
||||
return byName || byCPF || byId || byEmail;
|
||||
});
|
||||
}, [patients, search]);
|
||||
|
||||
@ -122,25 +132,33 @@ export default function PacientesPage() {
|
||||
const q = search.trim();
|
||||
if (!q) return loadAll();
|
||||
|
||||
|
||||
if (/^\d+$/.test(q)) {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Se parece com ID (UUID), busca diretamente
|
||||
if (q.includes('-') && q.length > 10) {
|
||||
const one = await buscarPacientePorId(q);
|
||||
setPatients(one ? [normalizePaciente(one)] : []);
|
||||
setError(one ? null : "Paciente não encontrado.");
|
||||
} catch (e: any) {
|
||||
setPatients([]);
|
||||
setError(e?.message || "Paciente não encontrado.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
// Limpa o campo de busca para que o filtro não interfira
|
||||
setSearch("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Para outros termos, usa busca avançada
|
||||
const results = await buscarPacientes(q);
|
||||
setPatients(results.map(normalizePaciente));
|
||||
setError(results.length === 0 ? "Nenhum paciente encontrado." : null);
|
||||
// Limpa o campo de busca para que o filtro não interfira
|
||||
setSearch("");
|
||||
|
||||
await loadAll();
|
||||
setTimeout(() => setSearch(q), 0);
|
||||
} catch (e: any) {
|
||||
setPatients([]);
|
||||
setError(e?.message || "Erro na busca.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) return <p>Carregando pacientes...</p>;
|
||||
@ -210,11 +228,11 @@ export default function PacientesPage() {
|
||||
{filtered.length > 0 ? (
|
||||
filtered.map((p) => (
|
||||
<TableRow key={p.id}>
|
||||
<TableCell className="font-medium">{p.nome || "(sem nome)"}</TableCell>
|
||||
<TableCell className="font-medium">{p.full_name || "(sem nome)"}</TableCell>
|
||||
<TableCell>{p.cpf || "-"}</TableCell>
|
||||
<TableCell>{p.telefone || "-"}</TableCell>
|
||||
<TableCell>{p.endereco?.cidade || "-"}</TableCell>
|
||||
<TableCell>{p.endereco?.estado || "-"}</TableCell>
|
||||
<TableCell>{p.phone_mobile || "-"}</TableCell>
|
||||
<TableCell>{p.city || "-"}</TableCell>
|
||||
<TableCell>{p.state || "-"}</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@ -258,13 +276,13 @@ export default function PacientesPage() {
|
||||
<DialogHeader>
|
||||
<DialogTitle>Detalhes do Paciente</DialogTitle>
|
||||
<DialogDescription>
|
||||
Informações detalhadas de {viewingPatient.nome}.
|
||||
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.nome}</span>
|
||||
<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>
|
||||
@ -272,17 +290,17 @@ export default function PacientesPage() {
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label className="text-right">Telefone</Label>
|
||||
<span className="col-span-3">{viewingPatient.telefone}</span>
|
||||
<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.endereco?.logradouro || ''}, ${viewingPatient.endereco?.numero || ''} - ${viewingPatient.endereco?.bairro || ''}, ${viewingPatient.endereco?.cidade || ''} - ${viewingPatient.endereco?.estado || ''}`}
|
||||
{`${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.observacoes || "Nenhuma"}</span>
|
||||
<span className="col-span-3">{viewingPatient.notes || "Nenhuma"}</span>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
|
||||
@ -7,6 +7,8 @@ import "react-quill/dist/quill.snow.css";
|
||||
import Link from "next/link";
|
||||
import ProtectedRoute from "@/components/ProtectedRoute";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import { buscarPacientes } from "@/lib/api";
|
||||
import { ApiTest } from "@/components/debug/ApiTest";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
@ -566,9 +568,143 @@ const ProfissionalPage = () => {
|
||||
};
|
||||
|
||||
|
||||
const renderPacientesSection = () => (
|
||||
const renderPacientesSection = () => {
|
||||
// Estados para busca de pacientes
|
||||
const [buscaPaciente, setBuscaPaciente] = useState("");
|
||||
const [pacientesBusca, setPacientesBusca] = useState<any[]>([]);
|
||||
const [carregandoBusca, setCarregandoBusca] = useState(false);
|
||||
const [erroBusca, setErroBusca] = useState<string | null>(null);
|
||||
|
||||
// Função para buscar pacientes
|
||||
const handleBuscarPaciente = async () => {
|
||||
if (!buscaPaciente.trim()) {
|
||||
setPacientesBusca([]);
|
||||
setErroBusca(null);
|
||||
return;
|
||||
}
|
||||
|
||||
setCarregandoBusca(true);
|
||||
setErroBusca(null);
|
||||
|
||||
try {
|
||||
// Importa a função de busca
|
||||
const { buscarPacientes } = await import("@/lib/api");
|
||||
const resultados = await buscarPacientes(buscaPaciente.trim());
|
||||
|
||||
if (resultados.length === 0) {
|
||||
setErroBusca("Nenhum paciente encontrado com os critérios informados.");
|
||||
setPacientesBusca([]);
|
||||
} else {
|
||||
// Transforma os dados da API para o formato usado no componente
|
||||
const pacientesFormatados = resultados.map(p => ({
|
||||
nome: p.full_name || "Nome não informado",
|
||||
cpf: p.cpf || "CPF não informado",
|
||||
idade: p.birth_date ? new Date().getFullYear() - new Date(p.birth_date).getFullYear() : "N/A",
|
||||
statusLaudo: "Pendente", // Status padrão
|
||||
id: p.id
|
||||
}));
|
||||
setPacientesBusca(pacientesFormatados);
|
||||
setErroBusca(null);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("Erro ao buscar pacientes:", error);
|
||||
setErroBusca(error.message || "Erro ao buscar pacientes. Tente novamente.");
|
||||
setPacientesBusca([]);
|
||||
} finally {
|
||||
setCarregandoBusca(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLimparBusca = () => {
|
||||
setBuscaPaciente("");
|
||||
setPacientesBusca([]);
|
||||
setErroBusca(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white shadow-md rounded-lg p-6">
|
||||
<h2 className="text-2xl font-bold mb-4">Gerenciamento de Pacientes</h2>
|
||||
|
||||
{/* Campo de busca */}
|
||||
<div className="mb-6 p-4 bg-gray-50 rounded-lg">
|
||||
<h3 className="text-lg font-semibold mb-3">Buscar Paciente</h3>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="Digite ID, CPF, nome ou email do paciente..."
|
||||
value={buscaPaciente}
|
||||
onChange={(e) => setBuscaPaciente(e.target.value)}
|
||||
onKeyDown={(e) => e.key === "Enter" && handleBuscarPaciente()}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleBuscarPaciente}
|
||||
disabled={carregandoBusca}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
{carregandoBusca ? (
|
||||
<>
|
||||
<div className="animate-spin h-4 w-4 border-2 border-white border-t-transparent rounded-full"></div>
|
||||
Buscando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<User className="h-4 w-4" />
|
||||
Buscar
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
{(buscaPaciente || pacientesBusca.length > 0 || erroBusca) && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleLimparBusca}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
Limpar
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Resultados da busca */}
|
||||
{erroBusca && (
|
||||
<div className="mt-3 p-3 bg-red-50 border border-red-200 rounded-md">
|
||||
<p className="text-red-700 text-sm">{erroBusca}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{pacientesBusca.length > 0 && (
|
||||
<div className="mt-4">
|
||||
<h4 className="text-md font-medium mb-2">Resultados da busca ({pacientesBusca.length}):</h4>
|
||||
<div className="space-y-2">
|
||||
{pacientesBusca.map((paciente, index) => (
|
||||
<div key={index} className="flex items-center justify-between p-3 bg-white border rounded-lg hover:shadow-sm">
|
||||
<div>
|
||||
<p className="font-medium">{paciente.nome}</p>
|
||||
<p className="text-sm text-gray-600">CPF: {paciente.cpf} • Idade: {paciente.idade} anos</p>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
handleAbrirProntuario(paciente);
|
||||
setActiveSection('prontuario');
|
||||
}}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<FolderOpen className="h-4 w-4" />
|
||||
Abrir Prontuário
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Tabela de pacientes padrão */}
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold mb-3">Pacientes Recentes</h3>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@ -612,7 +748,9 @@ const ProfissionalPage = () => {
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const renderProntuarioSection = () => (
|
||||
@ -2286,6 +2424,18 @@ function LaudoEditor() {
|
||||
);
|
||||
|
||||
|
||||
const renderDebugSection = () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold mb-4">Debug da API</h2>
|
||||
<p className="text-gray-600 mb-6">
|
||||
Use esta seção para testar a conectividade com a API e debugar problemas de busca de pacientes.
|
||||
</p>
|
||||
</div>
|
||||
<ApiTest />
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderActiveSection = () => {
|
||||
switch (activeSection) {
|
||||
case 'calendario':
|
||||
@ -2302,6 +2452,8 @@ function LaudoEditor() {
|
||||
return renderRelatoriosMedicosSection();
|
||||
case 'perfil':
|
||||
return renderPerfilSection();
|
||||
case 'debug':
|
||||
return renderDebugSection();
|
||||
default:
|
||||
return renderCalendarioSection();
|
||||
}
|
||||
@ -2396,6 +2548,14 @@ function LaudoEditor() {
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
Meu Perfil
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeSection === 'debug' ? 'default' : 'ghost'}
|
||||
className="w-full justify-start cursor-pointer hover:bg-primary hover:text-primary-foreground cursor-pointer"
|
||||
onClick={() => setActiveSection('debug')}
|
||||
>
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
Debug API
|
||||
</Button>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
|
||||
191
susconecta/components/debug/ApiTest.tsx
Normal file
191
susconecta/components/debug/ApiTest.tsx
Normal file
@ -0,0 +1,191 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { buscarPacientePorId, buscarPacientes, listarPacientes } from "@/lib/api";
|
||||
|
||||
export const ApiTest = () => {
|
||||
const [testId, setTestId] = useState("7ddbd1e2-1aee-4f7a-94f9-ee4c735ca276");
|
||||
const [resultado, setResultado] = useState<any>(null);
|
||||
const [erro, setErro] = useState<string | null>(null);
|
||||
const [carregando, setCarregando] = useState(false);
|
||||
|
||||
const testarConexao = async () => {
|
||||
setCarregando(true);
|
||||
setErro(null);
|
||||
setResultado(null);
|
||||
|
||||
try {
|
||||
console.log("Testando conexão com a API...");
|
||||
|
||||
// Primeiro teste básico
|
||||
const pacientes = await listarPacientes({ limit: 5 });
|
||||
console.log("Pacientes encontrados:", pacientes);
|
||||
|
||||
// Teste direto da API para ver estrutura
|
||||
const REST = "https://yuanqfswhberkoevtmfr.supabase.co/rest/v1";
|
||||
const headers: Record<string, string> = {
|
||||
apikey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl1YW5xZnN3aGJlcmtvZXZ0bWZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQ5NTQzNjksImV4cCI6MjA3MDUzMDM2OX0.g8Fm4XAvtX46zifBZnYVH4tVuQkqUH6Ia9CXQj4DztQ",
|
||||
Accept: "application/json",
|
||||
};
|
||||
|
||||
// Token do localStorage se disponível
|
||||
const token = localStorage.getItem("auth_token") || localStorage.getItem("token");
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
console.log("Headers sendo usados:", headers);
|
||||
|
||||
const directRes = await fetch(`${REST}/patients?limit=3&select=id,full_name,cpf,email`, {
|
||||
method: "GET",
|
||||
headers
|
||||
});
|
||||
|
||||
console.log("Status da resposta direta:", directRes.status);
|
||||
|
||||
if (directRes.ok) {
|
||||
const directData = await directRes.json();
|
||||
console.log("Dados diretos da API:", directData);
|
||||
|
||||
setResultado({
|
||||
tipo: "Conexão + Estrutura",
|
||||
data: {
|
||||
pacientes: pacientes,
|
||||
estruturaDireta: directData,
|
||||
statusCode: directRes.status,
|
||||
headers: Object.fromEntries(directRes.headers.entries())
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const errorText = await directRes.text();
|
||||
console.error("Erro na resposta direta:", errorText);
|
||||
setErro(`Erro ${directRes.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
} catch (error: any) {
|
||||
console.error("Erro na conexão:", error);
|
||||
setErro(error.message);
|
||||
} finally {
|
||||
setCarregando(false);
|
||||
}
|
||||
};
|
||||
|
||||
const testarBuscaPorId = async () => {
|
||||
if (!testId.trim()) {
|
||||
setErro("Digite um ID para buscar");
|
||||
return;
|
||||
}
|
||||
|
||||
setCarregando(true);
|
||||
setErro(null);
|
||||
setResultado(null);
|
||||
|
||||
try {
|
||||
console.log("Buscando paciente por ID:", testId);
|
||||
const paciente = await buscarPacientePorId(testId);
|
||||
setResultado({ tipo: "Busca por ID", data: paciente });
|
||||
} catch (error: any) {
|
||||
console.error("Erro na busca por ID:", error);
|
||||
setErro(error.message);
|
||||
} finally {
|
||||
setCarregando(false);
|
||||
}
|
||||
};
|
||||
|
||||
const testarBuscaGeral = async () => {
|
||||
if (!testId.trim()) {
|
||||
setErro("Digite um termo para buscar");
|
||||
return;
|
||||
}
|
||||
|
||||
setCarregando(true);
|
||||
setErro(null);
|
||||
setResultado(null);
|
||||
|
||||
try {
|
||||
console.log("Buscando pacientes:", testId);
|
||||
const pacientes = await buscarPacientes(testId);
|
||||
setResultado({ tipo: "Busca geral", data: pacientes });
|
||||
} catch (error: any) {
|
||||
console.error("Erro na busca geral:", error);
|
||||
setErro(error.message);
|
||||
} finally {
|
||||
setCarregando(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Card className="max-w-2xl mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>Teste da API - Pacientes</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
placeholder="Digite ID, CPF ou nome para buscar..."
|
||||
value={testId}
|
||||
onChange={(e) => setTestId(e.target.value)}
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button
|
||||
onClick={testarConexao}
|
||||
disabled={carregando}
|
||||
variant="outline"
|
||||
>
|
||||
{carregando ? "Testando..." : "Testar Conexão"}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={testarBuscaPorId}
|
||||
disabled={carregando || !testId.trim()}
|
||||
>
|
||||
{carregando ? "Buscando..." : "Buscar por ID"}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={testarBuscaGeral}
|
||||
disabled={carregando || !testId.trim()}
|
||||
variant="secondary"
|
||||
>
|
||||
{carregando ? "Buscando..." : "Busca Geral"}
|
||||
</Button>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{erro && (
|
||||
<div className="p-3 bg-red-50 border border-red-200 rounded-md">
|
||||
<p className="text-red-700 font-medium">Erro:</p>
|
||||
<p className="text-red-600 text-sm">{erro}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{resultado && (
|
||||
<div className="p-3 bg-green-50 border border-green-200 rounded-md">
|
||||
<p className="text-green-700 font-medium">Resultado ({resultado.tipo}):</p>
|
||||
<pre className="text-sm text-green-600 mt-2 overflow-auto">
|
||||
{JSON.stringify(resultado.data, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-xs text-gray-500 mt-4">
|
||||
<p>• <strong>Testar Conexão:</strong> Lista os primeiros 5 pacientes e verifica a estrutura da API</p>
|
||||
<p>• <strong>Buscar por ID:</strong> Busca um paciente específico por ID, CPF ou nome</p>
|
||||
<p>• <strong>Busca Geral:</strong> Busca avançada em múltiplos campos</p>
|
||||
<p className="mt-2 font-medium">Abra o console do navegador (F12) para ver logs detalhados da investigação.</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
56
susconecta/components/debug/ApiTestSimple.tsx
Normal file
56
susconecta/components/debug/ApiTestSimple.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { listarPacientes, buscarPacientePorId } from "@/lib/api";
|
||||
|
||||
export const ApiTestSimple = () => {
|
||||
const [resultado, setResultado] = useState<string>("");
|
||||
const [carregando, setCarregando] = useState(false);
|
||||
|
||||
const testarListarPacientes = async () => {
|
||||
setCarregando(true);
|
||||
try {
|
||||
const pacientes = await listarPacientes();
|
||||
setResultado(`✅ Sucesso! Encontrados ${pacientes.length} pacientes:\n${JSON.stringify(pacientes, null, 2)}`);
|
||||
} catch (error: any) {
|
||||
setResultado(`❌ Erro: ${error.message}`);
|
||||
} finally {
|
||||
setCarregando(false);
|
||||
}
|
||||
};
|
||||
|
||||
const testarBuscarPorId = async () => {
|
||||
setCarregando(true);
|
||||
const id = "7ddbd1e2-1aee-4f7a-94f9-ee4c735ca276";
|
||||
try {
|
||||
const paciente = await buscarPacientePorId(id);
|
||||
setResultado(`✅ Paciente encontrado:\n${JSON.stringify(paciente, null, 2)}`);
|
||||
} catch (error: any) {
|
||||
setResultado(`❌ Erro ao buscar ID ${id}: ${error.message}`);
|
||||
} finally {
|
||||
setCarregando(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 border rounded-lg max-w-4xl mx-auto">
|
||||
<h3 className="text-lg font-bold mb-4">Teste da API Mock</h3>
|
||||
|
||||
<div className="flex gap-2 mb-4">
|
||||
<Button onClick={testarListarPacientes} disabled={carregando}>
|
||||
{carregando ? "Testando..." : "Listar Pacientes"}
|
||||
</Button>
|
||||
<Button onClick={testarBuscarPorId} disabled={carregando}>
|
||||
{carregando ? "Testando..." : "Buscar ID Específico"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{resultado && (
|
||||
<div className="bg-gray-100 p-4 rounded-lg">
|
||||
<pre className="text-sm overflow-auto">{resultado}</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -182,17 +182,16 @@ function withPrefer(h: Record<string, string>, prefer: string) {
|
||||
}
|
||||
|
||||
// Parse genérico
|
||||
// Dentro de lib/api.ts
|
||||
async function parse<T>(res: Response): Promise<T> {
|
||||
let json: any = null;
|
||||
try {
|
||||
json = await res.json();
|
||||
} catch (err) {
|
||||
console.error("Erro ao parsear a resposta:", err); // Coloque esse log aqui
|
||||
console.error("Erro ao parsear a resposta:", err);
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
console.error("[API ERROR]", res.url, res.status, json); // Coloque esse log aqui
|
||||
console.error("[API ERROR]", res.url, res.status, json);
|
||||
const code = (json && (json.error?.code || json.code)) ?? res.status;
|
||||
const msg = (json && (json.error?.message || json.message)) ?? res.statusText;
|
||||
throw new Error(`${code}: ${msg}`);
|
||||
@ -230,6 +229,68 @@ export async function listarPacientes(params?: {
|
||||
return await parse<Paciente[]>(res);
|
||||
}
|
||||
|
||||
|
||||
// Nova função para busca avançada de pacientes
|
||||
export async function buscarPacientes(termo: string): Promise<Paciente[]> {
|
||||
if (!termo || termo.trim().length < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const searchTerm = termo.toLowerCase().trim();
|
||||
const digitsOnly = searchTerm.replace(/\D/g, '');
|
||||
|
||||
// Monta queries para buscar em múltiplos campos
|
||||
const queries = [];
|
||||
|
||||
// Busca por ID se parece com UUID
|
||||
if (searchTerm.includes('-') && searchTerm.length > 10) {
|
||||
queries.push(`id=eq.${searchTerm}`);
|
||||
}
|
||||
|
||||
// Busca por CPF (com e sem formatação)
|
||||
if (digitsOnly.length >= 11) {
|
||||
queries.push(`cpf=eq.${digitsOnly}`);
|
||||
} else if (digitsOnly.length >= 3) {
|
||||
queries.push(`cpf=ilike.*${digitsOnly}*`);
|
||||
}
|
||||
|
||||
// Busca por nome (usando ilike para busca case-insensitive)
|
||||
if (searchTerm.length >= 2) {
|
||||
queries.push(`full_name=ilike.*${searchTerm}*`);
|
||||
queries.push(`social_name=ilike.*${searchTerm}*`);
|
||||
}
|
||||
|
||||
// Busca por email se contém @
|
||||
if (searchTerm.includes('@')) {
|
||||
queries.push(`email=ilike.*${searchTerm}*`);
|
||||
}
|
||||
|
||||
const results: Paciente[] = [];
|
||||
const seenIds = new Set<string>();
|
||||
|
||||
// Executa as buscas e combina resultados únicos
|
||||
for (const query of queries) {
|
||||
try {
|
||||
const url = `${REST}/patients?${query}&limit=10`;
|
||||
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
||||
const arr = await parse<Paciente[]>(res);
|
||||
|
||||
if (arr?.length > 0) {
|
||||
for (const paciente of arr) {
|
||||
if (!seenIds.has(paciente.id)) {
|
||||
seenIds.add(paciente.id);
|
||||
results.push(paciente);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Erro na busca com query: ${query}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
return results.slice(0, 20); // Limita a 20 resultados
|
||||
}
|
||||
|
||||
export async function buscarPacientePorId(id: string | number): Promise<Paciente> {
|
||||
const url = `${REST}/patients?id=eq.${id}`;
|
||||
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
||||
|
||||
379
susconecta/package-lock.json
generated
379
susconecta/package-lock.json
generated
@ -2365,6 +2365,53 @@
|
||||
"node": ">=10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
"es-define-property": "^1.0.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"get-intrinsic": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001739",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
|
||||
@ -2659,6 +2706,40 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/define-properties": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||
@ -2685,6 +2766,20 @@
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.213",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.213.tgz",
|
||||
@ -2733,6 +2828,36 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-toolkit": {
|
||||
"version": "1.39.10",
|
||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz",
|
||||
@ -2800,6 +2925,24 @@
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/functions-have-names": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
||||
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/geist": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/geist/-/geist-1.4.2.tgz",
|
||||
@ -2809,6 +2952,30 @@
|
||||
"next": ">=13.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-nonce": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
|
||||
@ -2818,12 +2985,88 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
@ -2873,6 +3116,56 @@
|
||||
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-arguments": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
|
||||
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
"has-tostringtag": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-date-object": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
|
||||
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
"has-tostringtag": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-regex": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
"gopd": "^1.2.0",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
||||
@ -3182,6 +3475,15 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
@ -3352,6 +3654,31 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-is": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
@ -3749,6 +4076,26 @@
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
||||
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"set-function-name": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||
@ -3780,6 +4127,38 @@
|
||||
"integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/set-function-name": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
|
||||
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"functions-have-names": "^1.2.3",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/signature_pad": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-2.3.2.tgz",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user