Merge pull request 'adicionando-atualização-medicos' (#28) from feature/ajustes-form-medico into develop
Reviewed-on: #28
This commit is contained in:
commit
e85fbdeb15
@ -12,12 +12,12 @@ import { Badge } from "@/components/ui/badge";
|
|||||||
import { DoctorRegistrationForm } from "@/components/forms/doctor-registration-form";
|
import { DoctorRegistrationForm } from "@/components/forms/doctor-registration-form";
|
||||||
|
|
||||||
|
|
||||||
import { listarMedicos, excluirMedico, Medico } from "@/lib/api";
|
import { listarMedicos, excluirMedico, buscarMedicos, buscarMedicoPorId, Medico } from "@/lib/api";
|
||||||
|
|
||||||
function normalizeMedico(m: any): Medico {
|
function normalizeMedico(m: any): Medico {
|
||||||
return {
|
return {
|
||||||
id: String(m.id ?? m.uuid ?? ""),
|
id: String(m.id ?? m.uuid ?? ""),
|
||||||
nome: m.nome ?? m.full_name ?? "", // 👈 Supabase usa full_name
|
full_name: m.full_name ?? m.nome ?? "", // 👈 Correção: usar full_name como padrão
|
||||||
nome_social: m.nome_social ?? m.social_name ?? null,
|
nome_social: m.nome_social ?? m.social_name ?? null,
|
||||||
cpf: m.cpf ?? "",
|
cpf: m.cpf ?? "",
|
||||||
rg: m.rg ?? m.document_number ?? null,
|
rg: m.rg ?? m.document_number ?? null,
|
||||||
@ -39,6 +39,20 @@ function normalizeMedico(m: any): Medico {
|
|||||||
dados_bancarios: m.dados_bancarios ?? null,
|
dados_bancarios: m.dados_bancarios ?? null,
|
||||||
agenda_horario: m.agenda_horario ?? null,
|
agenda_horario: m.agenda_horario ?? null,
|
||||||
valor_consulta: m.valor_consulta ?? null,
|
valor_consulta: m.valor_consulta ?? null,
|
||||||
|
active: m.active ?? true,
|
||||||
|
cep: m.cep ?? "",
|
||||||
|
city: m.city ?? "",
|
||||||
|
complement: m.complement ?? null,
|
||||||
|
neighborhood: m.neighborhood ?? "",
|
||||||
|
number: m.number ?? "",
|
||||||
|
phone2: m.phone2 ?? null,
|
||||||
|
state: m.state ?? "",
|
||||||
|
street: m.street ?? "",
|
||||||
|
created_at: m.created_at ?? null,
|
||||||
|
created_by: m.created_by ?? null,
|
||||||
|
updated_at: m.updated_at ?? null,
|
||||||
|
updated_by: m.updated_by ?? null,
|
||||||
|
user_id: m.user_id ?? null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,33 +64,178 @@ export default function DoutoresPage() {
|
|||||||
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 [viewingDoctor, setViewingDoctor] = useState<Medico | null>(null);
|
const [viewingDoctor, setViewingDoctor] = useState<Medico | null>(null);
|
||||||
|
const [searchResults, setSearchResults] = useState<Medico[]>([]);
|
||||||
|
const [searchMode, setSearchMode] = useState(false);
|
||||||
|
const [searchTimeout, setSearchTimeout] = useState<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const list = await listarMedicos({ limit: 50 });
|
const list = await listarMedicos({ limit: 50 });
|
||||||
setDoctors((list ?? []).map(normalizeMedico));
|
const normalized = (list ?? []).map(normalizeMedico);
|
||||||
|
console.log('🏥 Médicos carregados:', normalized);
|
||||||
|
setDoctors(normalized);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Função para detectar se é um UUID válido
|
||||||
|
function isValidUUID(str: string): boolean {
|
||||||
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||||
|
return uuidRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função para buscar médicos no servidor
|
||||||
|
async function handleBuscarServidor(termoBusca?: string) {
|
||||||
|
const termo = (termoBusca || search).trim();
|
||||||
|
|
||||||
|
if (!termo) {
|
||||||
|
setSearchMode(false);
|
||||||
|
setSearchResults([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('🔍 Buscando médico por:', termo);
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// Se parece com UUID, tenta busca direta por ID
|
||||||
|
if (isValidUUID(termo)) {
|
||||||
|
console.log('📋 Detectado UUID, buscando por ID...');
|
||||||
|
try {
|
||||||
|
const medico = await buscarMedicoPorId(termo);
|
||||||
|
const normalizado = normalizeMedico(medico);
|
||||||
|
console.log('✅ Médico encontrado por ID:', normalizado);
|
||||||
|
setSearchResults([normalizado]);
|
||||||
|
setSearchMode(true);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ Não encontrado por ID, tentando busca geral...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busca geral
|
||||||
|
const resultados = await buscarMedicos(termo);
|
||||||
|
const normalizados = resultados.map(normalizeMedico);
|
||||||
|
console.log('📋 Resultados da busca geral:', normalizados);
|
||||||
|
|
||||||
|
setSearchResults(normalizados);
|
||||||
|
setSearchMode(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erro na busca:', error);
|
||||||
|
setSearchResults([]);
|
||||||
|
setSearchMode(true);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler para mudança no campo de busca com busca automática
|
||||||
|
function handleSearchChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
const valor = e.target.value;
|
||||||
|
setSearch(valor);
|
||||||
|
|
||||||
|
// Limpa o timeout anterior se existir
|
||||||
|
if (searchTimeout) {
|
||||||
|
clearTimeout(searchTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se limpar a busca, volta ao modo normal
|
||||||
|
if (!valor.trim()) {
|
||||||
|
setSearchMode(false);
|
||||||
|
setSearchResults([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busca automática com debounce ajustável
|
||||||
|
// Para IDs (UUID) longos, faz busca no servidor
|
||||||
|
// Para busca parcial, usa apenas filtro local
|
||||||
|
const isLikeUUID = valor.includes('-') && valor.length > 10;
|
||||||
|
const shouldSearchServer = isLikeUUID || valor.length >= 3;
|
||||||
|
|
||||||
|
if (shouldSearchServer) {
|
||||||
|
const debounceTime = isLikeUUID ? 300 : 500;
|
||||||
|
const newTimeout = setTimeout(() => {
|
||||||
|
handleBuscarServidor(valor);
|
||||||
|
}, debounceTime);
|
||||||
|
|
||||||
|
setSearchTimeout(newTimeout);
|
||||||
|
} else {
|
||||||
|
// Para termos curtos, apenas usa filtro local
|
||||||
|
setSearchMode(false);
|
||||||
|
setSearchResults([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler para Enter no campo de busca
|
||||||
|
function handleSearchKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleBuscarServidor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler para o botão de busca
|
||||||
|
function handleClickBuscar() {
|
||||||
|
handleBuscarServidor();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load();
|
load();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const filtered = useMemo(() => {
|
// Limpa o timeout quando o componente é desmontado
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (searchTimeout) {
|
||||||
|
clearTimeout(searchTimeout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [searchTimeout]);
|
||||||
|
|
||||||
|
// Lista de médicos a exibir (busca ou filtro local)
|
||||||
|
const displayedDoctors = useMemo(() => {
|
||||||
|
console.log('🔍 Filtro - search:', search, 'searchMode:', searchMode, 'doctors:', doctors.length, 'searchResults:', searchResults.length);
|
||||||
|
|
||||||
|
// Se não tem busca, mostra todos os médicos
|
||||||
if (!search.trim()) return doctors;
|
if (!search.trim()) return doctors;
|
||||||
const q = search.toLowerCase();
|
|
||||||
return doctors.filter((d) => {
|
const q = search.toLowerCase().trim();
|
||||||
const byName = (d.nome || "").toLowerCase().includes(q);
|
const qDigits = q.replace(/\D/g, "");
|
||||||
const byCrm = (d.crm || "").toLowerCase().includes(q);
|
|
||||||
|
// Se estamos em modo de busca (servidor), filtra os resultados da busca
|
||||||
|
const sourceList = searchMode ? searchResults : doctors;
|
||||||
|
console.log('🔍 Usando sourceList:', searchMode ? 'searchResults' : 'doctors', '- tamanho:', sourceList.length);
|
||||||
|
|
||||||
|
const filtered = sourceList.filter((d) => {
|
||||||
|
// Busca por nome
|
||||||
|
const byName = (d.full_name || "").toLowerCase().includes(q);
|
||||||
|
|
||||||
|
// Busca por CRM (remove formatação se necessário)
|
||||||
|
const byCrm = qDigits.length >= 3 && (d.crm || "").replace(/\D/g, "").includes(qDigits);
|
||||||
|
|
||||||
|
// Busca por ID (UUID completo ou parcial)
|
||||||
|
const byId = (d.id || "").toLowerCase().includes(q);
|
||||||
|
|
||||||
|
// Busca por email
|
||||||
|
const byEmail = (d.email || "").toLowerCase().includes(q);
|
||||||
|
|
||||||
|
// Busca por especialidade
|
||||||
const byEspecialidade = (d.especialidade || "").toLowerCase().includes(q);
|
const byEspecialidade = (d.especialidade || "").toLowerCase().includes(q);
|
||||||
return byName || byCrm || byEspecialidade;
|
|
||||||
|
const match = byName || byCrm || byId || byEmail || byEspecialidade;
|
||||||
|
if (match) {
|
||||||
|
console.log('✅ Match encontrado:', d.full_name, d.id, 'por:', { byName, byCrm, byId, byEmail, byEspecialidade });
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
});
|
});
|
||||||
}, [doctors, search]);
|
|
||||||
|
console.log('🔍 Resultados filtrados:', filtered.length);
|
||||||
|
return filtered;
|
||||||
|
}, [doctors, search, searchMode, searchResults]);
|
||||||
|
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
setEditingId(null);
|
setEditingId(null);
|
||||||
@ -139,7 +298,7 @@ setDoctors((list ?? []).map(normalizeMedico));
|
|||||||
<DoctorRegistrationForm
|
<DoctorRegistrationForm
|
||||||
inline
|
inline
|
||||||
mode={editingId ? "edit" : "create"}
|
mode={editingId ? "edit" : "create"}
|
||||||
doctorId={editingId ? Number(editingId) : null}
|
doctorId={editingId}
|
||||||
onSaved={handleSaved}
|
onSaved={handleSaved}
|
||||||
onClose={() => setShowForm(false)}
|
onClose={() => setShowForm(false)}
|
||||||
/>
|
/>
|
||||||
@ -156,15 +315,37 @@ setDoctors((list ?? []).map(normalizeMedico));
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||||
<Input
|
<Input
|
||||||
className="pl-8 w-80"
|
className="pl-8 w-80"
|
||||||
placeholder="Buscar por nome, CRM ou especialidade…"
|
placeholder="Digite para buscar por ID, nome, CRM ou especialidade…"
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={handleSearchChange}
|
||||||
|
onKeyDown={handleSearchKeyDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={handleClickBuscar}
|
||||||
|
disabled={loading || !search.trim()}
|
||||||
|
>
|
||||||
|
Buscar
|
||||||
|
</Button>
|
||||||
|
{searchMode && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
setSearch("");
|
||||||
|
setSearchMode(false);
|
||||||
|
setSearchResults([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Limpar
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<Button onClick={handleAdd} disabled={loading}>
|
<Button onClick={handleAdd} disabled={loading}>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
Novo Médico
|
Novo Médico
|
||||||
@ -190,10 +371,10 @@ setDoctors((list ?? []).map(normalizeMedico));
|
|||||||
Carregando…
|
Carregando…
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : filtered.length > 0 ? (
|
) : displayedDoctors.length > 0 ? (
|
||||||
filtered.map((doctor) => (
|
displayedDoctors.map((doctor) => (
|
||||||
<TableRow key={doctor.id}>
|
<TableRow key={doctor.id}>
|
||||||
<TableCell className="font-medium">{doctor.nome}</TableCell>
|
<TableCell className="font-medium">{doctor.full_name}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Badge variant="outline">{doctor.especialidade}</Badge>
|
<Badge variant="outline">{doctor.especialidade}</Badge>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@ -247,13 +428,13 @@ setDoctors((list ?? []).map(normalizeMedico));
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Detalhes do Médico</DialogTitle>
|
<DialogTitle>Detalhes do Médico</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Informações detalhadas de {viewingDoctor?.nome}.
|
Informações detalhadas de {viewingDoctor?.full_name}.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="grid gap-4 py-4">
|
<div className="grid gap-4 py-4">
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Nome</Label>
|
<Label className="text-right">Nome</Label>
|
||||||
<span className="col-span-3 font-medium">{viewingDoctor?.nome}</span>
|
<span className="col-span-3 font-medium">{viewingDoctor?.full_name}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Especialidade</Label>
|
<Label className="text-right">Especialidade</Label>
|
||||||
@ -282,7 +463,7 @@ setDoctors((list ?? []).map(normalizeMedico));
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
Mostrando {filtered.length} de {doctors.length}
|
Mostrando {displayedDoctors.length} {searchMode ? 'resultado(s) da busca' : `de ${doctors.length}`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,34 +10,29 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, Di
|
|||||||
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 } 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";
|
import { PatientRegistrationForm } from "@/components/forms/patient-registration-form";
|
||||||
|
|
||||||
|
|
||||||
function normalizePaciente(p: any): Paciente {
|
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 {
|
return {
|
||||||
id: String(p.id ?? p.uuid ?? p.paciente_id ?? ""),
|
id: String(p.id ?? p.uuid ?? p.paciente_id ?? ""),
|
||||||
nome: p.full_name ?? "", // 👈 troca nome → full_name
|
full_name: p.full_name ?? p.name ?? p.nome ?? "",
|
||||||
nome_social: p.social_name ?? null, // 👈 Supabase usa social_name
|
social_name: p.social_name ?? p.nome_social ?? null,
|
||||||
cpf: p.cpf ?? "",
|
cpf: p.cpf ?? "",
|
||||||
rg: p.rg ?? p.document_number ?? null, // 👈 às vezes vem como document_number
|
rg: p.rg ?? p.document_number ?? null,
|
||||||
sexo: p.sexo ?? p.sex ?? null, // 👈 Supabase usa sex
|
sex: p.sex ?? p.sexo ?? null,
|
||||||
data_nascimento: p.data_nascimento ?? p.birth_date ?? null,
|
birth_date: p.birth_date ?? p.data_nascimento ?? null,
|
||||||
telefone: p.telefone ?? p.phone_mobile ?? "",
|
phone_mobile: p.phone_mobile ?? p.telefone ?? "",
|
||||||
email: p.email ?? "",
|
email: p.email ?? "",
|
||||||
endereco,
|
cep: p.cep ?? "",
|
||||||
observacoes: p.observacoes ?? p.notes ?? null,
|
street: p.street ?? p.logradouro ?? "",
|
||||||
foto_url: p.foto_url ?? null,
|
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 {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const data = await listarPacientes({ page: 1, limit: 20 });
|
const data = await listarPacientes({ page: 1, limit: 20 });
|
||||||
setPatients((data ?? []).map(normalizePaciente));
|
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
setPatients(data.map(normalizePaciente));
|
||||||
|
} else {
|
||||||
|
setPatients([]);
|
||||||
|
}
|
||||||
setError(null);
|
setError(null);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setPatients([]);
|
setPatients([]);
|
||||||
@ -72,13 +72,23 @@ export default function PacientesPage() {
|
|||||||
|
|
||||||
const filtered = useMemo(() => {
|
const filtered = useMemo(() => {
|
||||||
if (!search.trim()) return patients;
|
if (!search.trim()) return patients;
|
||||||
const q = search.toLowerCase();
|
const q = search.toLowerCase().trim();
|
||||||
const qDigits = q.replace(/\D/g, "");
|
const qDigits = q.replace(/\D/g, "");
|
||||||
|
|
||||||
return patients.filter((p) => {
|
return patients.filter((p) => {
|
||||||
const byName = (p.nome || "").toLowerCase().includes(q);
|
// Busca por nome
|
||||||
const byCPF = (p.cpf || "").replace(/\D/g, "").includes(qDigits);
|
const byName = (p.full_name || "").toLowerCase().includes(q);
|
||||||
const byId = String(p.id || "").includes(qDigits);
|
|
||||||
return byName || byCPF || byId;
|
// 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]);
|
}, [patients, search]);
|
||||||
|
|
||||||
@ -122,25 +132,33 @@ export default function PacientesPage() {
|
|||||||
const q = search.trim();
|
const q = search.trim();
|
||||||
if (!q) return loadAll();
|
if (!q) return loadAll();
|
||||||
|
|
||||||
|
|
||||||
if (/^\d+$/.test(q)) {
|
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
// Se parece com ID (UUID), busca diretamente
|
||||||
|
if (q.includes('-') && q.length > 10) {
|
||||||
const one = await buscarPacientePorId(q);
|
const one = await buscarPacientePorId(q);
|
||||||
setPatients(one ? [normalizePaciente(one)] : []);
|
setPatients(one ? [normalizePaciente(one)] : []);
|
||||||
setError(one ? null : "Paciente não encontrado.");
|
setError(one ? null : "Paciente não encontrado.");
|
||||||
} catch (e: any) {
|
// Limpa o campo de busca para que o filtro não interfira
|
||||||
setPatients([]);
|
setSearch("");
|
||||||
setError(e?.message || "Paciente não encontrado.");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
return;
|
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();
|
} catch (e: any) {
|
||||||
setTimeout(() => setSearch(q), 0);
|
setPatients([]);
|
||||||
|
setError(e?.message || "Erro na busca.");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading) return <p>Carregando pacientes...</p>;
|
if (loading) return <p>Carregando pacientes...</p>;
|
||||||
@ -159,7 +177,7 @@ export default function PacientesPage() {
|
|||||||
<PatientRegistrationForm
|
<PatientRegistrationForm
|
||||||
inline
|
inline
|
||||||
mode={editingId ? "edit" : "create"}
|
mode={editingId ? "edit" : "create"}
|
||||||
patientId={editingId ? Number(editingId) : null}
|
patientId={editingId}
|
||||||
onSaved={handleSaved}
|
onSaved={handleSaved}
|
||||||
onClose={() => setShowForm(false)}
|
onClose={() => setShowForm(false)}
|
||||||
/>
|
/>
|
||||||
@ -210,11 +228,11 @@ export default function PacientesPage() {
|
|||||||
{filtered.length > 0 ? (
|
{filtered.length > 0 ? (
|
||||||
filtered.map((p) => (
|
filtered.map((p) => (
|
||||||
<TableRow key={p.id}>
|
<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.cpf || "-"}</TableCell>
|
||||||
<TableCell>{p.telefone || "-"}</TableCell>
|
<TableCell>{p.phone_mobile || "-"}</TableCell>
|
||||||
<TableCell>{p.endereco?.cidade || "-"}</TableCell>
|
<TableCell>{p.city || "-"}</TableCell>
|
||||||
<TableCell>{p.endereco?.estado || "-"}</TableCell>
|
<TableCell>{p.state || "-"}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@ -258,13 +276,13 @@ export default function PacientesPage() {
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Detalhes do Paciente</DialogTitle>
|
<DialogTitle>Detalhes do Paciente</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Informações detalhadas de {viewingPatient.nome}.
|
Informações detalhadas de {viewingPatient.full_name}.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="grid gap-4 py-4">
|
<div className="grid gap-4 py-4">
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Nome</Label>
|
<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>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">CPF</Label>
|
<Label className="text-right">CPF</Label>
|
||||||
@ -272,17 +290,17 @@ export default function PacientesPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Telefone</Label>
|
<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>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Endereço</Label>
|
<Label className="text-right">Endereço</Label>
|
||||||
<span className="col-span-3">
|
<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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label className="text-right">Observações</Label>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import "react-quill/dist/quill.snow.css";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import ProtectedRoute from "@/components/ProtectedRoute";
|
import ProtectedRoute from "@/components/ProtectedRoute";
|
||||||
import { useAuth } from "@/hooks/useAuth";
|
import { useAuth } from "@/hooks/useAuth";
|
||||||
|
import { buscarPacientes } from "@/lib/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@ -566,9 +567,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">
|
<div className="bg-white shadow-md rounded-lg p-6">
|
||||||
<h2 className="text-2xl font-bold mb-4">Gerenciamento de Pacientes</h2>
|
<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>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -612,7 +747,9 @@ const ProfissionalPage = () => {
|
|||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const renderProntuarioSection = () => (
|
const renderProntuarioSection = () => (
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Bell, Search, ChevronDown } from "lucide-react"
|
import { Bell, ChevronDown } from "lucide-react"
|
||||||
import { useAuth } from "@/hooks/useAuth"
|
import { useAuth } from "@/hooks/useAuth"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
@ -40,11 +40,6 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<div className="relative">
|
|
||||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4" />
|
|
||||||
<Input placeholder="Buscar paciente" className="pl-10 w-64" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button variant="ghost" size="icon">
|
<Button variant="ghost" size="icon">
|
||||||
<Bell className="h-4 w-4" />
|
<Bell className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
import { buscarPacientePorId } from "@/lib/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@ -21,8 +22,10 @@ import {
|
|||||||
listarAnexosMedico,
|
listarAnexosMedico,
|
||||||
adicionarAnexoMedico,
|
adicionarAnexoMedico,
|
||||||
removerAnexoMedico,
|
removerAnexoMedico,
|
||||||
MedicoInput,
|
MedicoInput, // 👈 importado do lib/api
|
||||||
|
Medico, // 👈 adicionado import do tipo Medico
|
||||||
} from "@/lib/api";
|
} from "@/lib/api";
|
||||||
|
;
|
||||||
|
|
||||||
import { buscarCepAPI } from "@/lib/api";
|
import { buscarCepAPI } from "@/lib/api";
|
||||||
|
|
||||||
@ -39,39 +42,16 @@ type DadosBancarios = {
|
|||||||
tipo_conta: string;
|
tipo_conta: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Medico = {
|
|
||||||
id: string;
|
|
||||||
nome?: string;
|
|
||||||
nome_social?: string | null;
|
|
||||||
cpf?: string;
|
|
||||||
rg?: string | null;
|
|
||||||
sexo?: string | null;
|
|
||||||
data_nascimento?: string | null;
|
|
||||||
telefone?: string;
|
|
||||||
celular?: string;
|
|
||||||
contato_emergencia?: string;
|
|
||||||
email?: string;
|
|
||||||
crm?: string;
|
|
||||||
estado_crm?: string;
|
|
||||||
rqe?: string;
|
|
||||||
formacao_academica?: FormacaoAcademica[];
|
|
||||||
curriculo_url?: string | null;
|
|
||||||
especialidade?: string;
|
|
||||||
observacoes?: string | null;
|
|
||||||
foto_url?: string | null;
|
|
||||||
tipo_vinculo?: string;
|
|
||||||
dados_bancarios?: DadosBancarios;
|
|
||||||
|
|
||||||
agenda_horario?: string;
|
|
||||||
valor_consulta?: number | string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Mode = "create" | "edit";
|
type Mode = "create" | "edit";
|
||||||
|
|
||||||
export interface DoctorRegistrationFormProps {
|
export interface DoctorRegistrationFormProps {
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
onOpenChange?: (open: boolean) => void;
|
onOpenChange?: (open: boolean) => void;
|
||||||
doctorId?: number | null;
|
doctorId?: string | number | null;
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
mode?: Mode;
|
mode?: Mode;
|
||||||
onSaved?: (medico: Medico) => void;
|
onSaved?: (medico: Medico) => void;
|
||||||
@ -80,7 +60,7 @@ export interface DoctorRegistrationFormProps {
|
|||||||
|
|
||||||
type FormData = {
|
type FormData = {
|
||||||
photo: File | null;
|
photo: File | null;
|
||||||
nome: string;
|
full_name: string; // Substitua 'nome' por 'full_name'
|
||||||
nome_social: string;
|
nome_social: string;
|
||||||
crm: string;
|
crm: string;
|
||||||
estado_crm: string;
|
estado_crm: string;
|
||||||
@ -107,14 +87,13 @@ type FormData = {
|
|||||||
anexos: File[];
|
anexos: File[];
|
||||||
tipo_vinculo: string;
|
tipo_vinculo: string;
|
||||||
dados_bancarios: DadosBancarios;
|
dados_bancarios: DadosBancarios;
|
||||||
|
|
||||||
agenda_horario: string;
|
agenda_horario: string;
|
||||||
valor_consulta: string;
|
valor_consulta: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const initial: FormData = {
|
const initial: FormData = {
|
||||||
photo: null,
|
photo: null,
|
||||||
nome: "",
|
full_name: "",
|
||||||
nome_social: "",
|
nome_social: "",
|
||||||
crm: "",
|
crm: "",
|
||||||
estado_crm: "",
|
estado_crm: "",
|
||||||
@ -128,7 +107,7 @@ const initial: FormData = {
|
|||||||
data_nascimento: "",
|
data_nascimento: "",
|
||||||
email: "",
|
email: "",
|
||||||
telefone: "",
|
telefone: "",
|
||||||
celular: "",
|
celular: "", // Aqui, 'celular' pode ser 'phone_mobile'
|
||||||
contato_emergencia: "",
|
contato_emergencia: "",
|
||||||
cep: "",
|
cep: "",
|
||||||
logradouro: "",
|
logradouro: "",
|
||||||
@ -152,6 +131,7 @@ const initial: FormData = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function DoctorRegistrationForm({
|
export function DoctorRegistrationForm({
|
||||||
open = true,
|
open = true,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
@ -175,46 +155,78 @@ export function DoctorRegistrationForm({
|
|||||||
let alive = true;
|
let alive = true;
|
||||||
async function load() {
|
async function load() {
|
||||||
if (mode === "edit" && doctorId) {
|
if (mode === "edit" && doctorId) {
|
||||||
const medico = await buscarMedicoPorId(doctorId);
|
try {
|
||||||
if (!alive) return;
|
console.log("[DoctorForm] Carregando médico ID:", doctorId);
|
||||||
setForm({
|
const medico = await buscarMedicoPorId(String(doctorId));
|
||||||
photo: null,
|
console.log("[DoctorForm] Dados recebidos do API:", medico);
|
||||||
nome: medico.nome ?? "",
|
console.log("[DoctorForm] Campos principais:", {
|
||||||
nome_social: medico.nome_social ?? "",
|
full_name: medico.full_name,
|
||||||
crm: medico.crm ?? "",
|
crm: medico.crm,
|
||||||
estado_crm: medico.estado_crm ?? "",
|
especialidade: medico.especialidade,
|
||||||
rqe: medico.rqe ?? "",
|
specialty: (medico as any).specialty,
|
||||||
formacao_academica: medico.formacao_academica ?? [],
|
cpf: medico.cpf,
|
||||||
curriculo: null,
|
email: medico.email
|
||||||
especialidade: medico.especialidade ?? "",
|
|
||||||
cpf: medico.cpf ?? "",
|
|
||||||
rg: medico.rg ?? "",
|
|
||||||
sexo: medico.sexo ?? "",
|
|
||||||
data_nascimento: medico.data_nascimento ?? "",
|
|
||||||
email: medico.email ?? "",
|
|
||||||
telefone: medico.telefone ?? "",
|
|
||||||
celular: medico.celular ?? "",
|
|
||||||
contato_emergencia: medico.contato_emergencia ?? "",
|
|
||||||
cep: "",
|
|
||||||
logradouro: "",
|
|
||||||
numero: "",
|
|
||||||
complemento: "",
|
|
||||||
bairro: "",
|
|
||||||
cidade: "",
|
|
||||||
estado: "",
|
|
||||||
observacoes: medico.observacoes ?? "",
|
|
||||||
anexos: [],
|
|
||||||
tipo_vinculo: medico.tipo_vinculo ?? "",
|
|
||||||
dados_bancarios: medico.dados_bancarios ?? { banco: "", agencia: "", conta: "", tipo_conta: "" },
|
|
||||||
agenda_horario: medico.agenda_horario ?? "",
|
|
||||||
valor_consulta: medico.valor_consulta ? String(medico.valor_consulta) : "",
|
|
||||||
});
|
});
|
||||||
|
console.log("[DoctorForm] Verificando especialidade:", {
|
||||||
|
'medico.especialidade': medico.especialidade,
|
||||||
|
'medico.specialty': (medico as any).specialty,
|
||||||
|
'typeof especialidade': typeof medico.especialidade,
|
||||||
|
'especialidade length': medico.especialidade?.length
|
||||||
|
});
|
||||||
|
if (!alive) return;
|
||||||
|
|
||||||
|
// Busca a especialidade em diferentes campos possíveis
|
||||||
|
const especialidade = medico.especialidade ||
|
||||||
|
(medico as any).specialty ||
|
||||||
|
(medico as any).speciality ||
|
||||||
|
"";
|
||||||
|
console.log('🎯 Especialidade encontrada:', especialidade);
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
photo: null,
|
||||||
|
full_name: String(medico.full_name || ""),
|
||||||
|
nome_social: String(medico.nome_social || ""),
|
||||||
|
crm: String(medico.crm || ""),
|
||||||
|
estado_crm: String(medico.estado_crm || ""),
|
||||||
|
rqe: String(medico.rqe || ""),
|
||||||
|
formacao_academica: Array.isArray(medico.formacao_academica) ? medico.formacao_academica : [],
|
||||||
|
curriculo: null,
|
||||||
|
especialidade: String(especialidade),
|
||||||
|
cpf: String(medico.cpf || ""),
|
||||||
|
rg: String(medico.rg || ""),
|
||||||
|
sexo: String(medico.sexo || ""),
|
||||||
|
data_nascimento: String(medico.data_nascimento || ""),
|
||||||
|
email: String(medico.email || ""),
|
||||||
|
telefone: String(medico.telefone || ""),
|
||||||
|
celular: String(medico.celular || ""),
|
||||||
|
contato_emergencia: String(medico.contato_emergencia || ""),
|
||||||
|
cep: String(medico.cep || ""),
|
||||||
|
logradouro: String(medico.street || ""),
|
||||||
|
numero: String(medico.number || ""),
|
||||||
|
complemento: String(medico.complement || ""),
|
||||||
|
bairro: String(medico.neighborhood || ""),
|
||||||
|
cidade: String(medico.city || ""),
|
||||||
|
estado: String(medico.state || ""),
|
||||||
|
observacoes: String(medico.observacoes || ""),
|
||||||
|
anexos: [],
|
||||||
|
tipo_vinculo: String(medico.tipo_vinculo || ""),
|
||||||
|
dados_bancarios: medico.dados_bancarios || { banco: "", agencia: "", conta: "", tipo_conta: "" },
|
||||||
|
agenda_horario: String(medico.agenda_horario || ""),
|
||||||
|
valor_consulta: medico.valor_consulta ? String(medico.valor_consulta) : "",
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("[DoctorForm] Dados do formulário preparados:", formData);
|
||||||
|
setForm(formData);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const list = await listarAnexosMedico(doctorId);
|
const list = await listarAnexosMedico(String(doctorId));
|
||||||
setServerAnexos(list ?? []);
|
setServerAnexos(list ?? []);
|
||||||
} catch {}
|
} catch (err) {
|
||||||
|
console.error("[DoctorForm] Erro ao carregar anexos:", err);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[DoctorForm] Erro ao carregar médico:", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
@ -228,6 +240,7 @@ export function DoctorRegistrationForm({
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function addFormacao() {
|
function addFormacao() {
|
||||||
setField("formacao_academica", [
|
setField("formacao_academica", [
|
||||||
...form.formacao_academica,
|
...form.formacao_academica,
|
||||||
@ -301,74 +314,90 @@ export function DoctorRegistrationForm({
|
|||||||
|
|
||||||
function validateLocal(): boolean {
|
function validateLocal(): boolean {
|
||||||
const e: Record<string, string> = {};
|
const e: Record<string, string> = {};
|
||||||
if (!form.nome.trim()) e.nome = "Nome é obrigatório";
|
|
||||||
|
if (!form.full_name.trim()) e.full_name = "Nome é obrigatório";
|
||||||
if (!form.cpf.trim()) e.cpf = "CPF é obrigatório";
|
if (!form.cpf.trim()) e.cpf = "CPF é obrigatório";
|
||||||
if (!form.crm.trim()) e.crm = "CRM é obrigatório";
|
if (!form.crm.trim()) e.crm = "CRM é obrigatório";
|
||||||
if (!form.especialidade.trim()) e.especialidade = "Especialidade é obrigatória";
|
if (!form.especialidade.trim()) e.especialidade = "Especialidade é obrigatória";
|
||||||
|
if (!form.cep.trim()) e.cep = "CEP é obrigatório"; // Verifique se o CEP está preenchido
|
||||||
|
if (!form.bairro.trim()) e.bairro = "Bairro é obrigatório"; // Verifique se o bairro está preenchido
|
||||||
|
if (!form.cidade.trim()) e.cidade = "Cidade é obrigatória"; // Verifique se a cidade está preenchida
|
||||||
|
|
||||||
setErrors(e);
|
setErrors(e);
|
||||||
return Object.keys(e).length === 0;
|
return Object.keys(e).length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function handleSubmit(ev: React.FormEvent) {
|
async function handleSubmit(ev: React.FormEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (!validateLocal()) return;
|
console.log("Submitting the form..."); // Verifique se a função está sendo chamada
|
||||||
|
|
||||||
|
if (!validateLocal()) {
|
||||||
|
console.log("Validation failed");
|
||||||
|
return; // Se a validação falhar, saia da função.
|
||||||
|
}
|
||||||
|
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
setErrors((e) => ({ ...e, submit: "" }));
|
setErrors((e) => ({ ...e, submit: "" }));
|
||||||
|
|
||||||
try {
|
|
||||||
const payload: MedicoInput = {
|
const payload: MedicoInput = {
|
||||||
nome: form.nome,
|
user_id: null,
|
||||||
nome_social: form.nome_social || null,
|
crm: form.crm || "",
|
||||||
cpf: form.cpf || null,
|
crm_uf: form.estado_crm || "",
|
||||||
|
specialty: form.especialidade || "",
|
||||||
|
full_name: form.full_name || "",
|
||||||
|
cpf: form.cpf || "",
|
||||||
|
email: form.email || "",
|
||||||
|
phone_mobile: form.celular || "",
|
||||||
|
phone2: form.telefone || null,
|
||||||
|
cep: form.cep || "",
|
||||||
|
street: form.logradouro || "",
|
||||||
|
number: form.numero || "",
|
||||||
|
complement: form.complemento || undefined,
|
||||||
|
neighborhood: form.bairro || undefined,
|
||||||
|
city: form.cidade || "",
|
||||||
|
state: form.estado || "",
|
||||||
|
birth_date: form.data_nascimento || null,
|
||||||
rg: form.rg || null,
|
rg: form.rg || null,
|
||||||
sexo: form.sexo || null,
|
active: true,
|
||||||
data_nascimento: form.data_nascimento || null,
|
created_by: null,
|
||||||
telefone: form.telefone || null,
|
updated_by: null,
|
||||||
celular: form.celular || null,
|
|
||||||
contato_emergencia: form.contato_emergencia || null,
|
|
||||||
email: form.email || null,
|
|
||||||
crm: form.crm,
|
|
||||||
estado_crm: form.estado_crm || null,
|
|
||||||
rqe: form.rqe || null,
|
|
||||||
formacao_academica: form.formacao_academica ?? [],
|
|
||||||
curriculo_url: null,
|
|
||||||
especialidade: form.especialidade,
|
|
||||||
observacoes: form.observacoes || null,
|
|
||||||
tipo_vinculo: form.tipo_vinculo || null,
|
|
||||||
dados_bancarios: form.dados_bancarios ?? null,
|
|
||||||
agenda_horario: form.agenda_horario || null,
|
|
||||||
valor_consulta: form.valor_consulta || null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Validação dos campos obrigatórios
|
||||||
|
const requiredFields = ['crm', 'crm_uf', 'specialty', 'full_name', 'cpf', 'email', 'phone_mobile', 'cep', 'street', 'number', 'city', 'state'];
|
||||||
|
const missingFields = requiredFields.filter(field => !payload[field as keyof MedicoInput]);
|
||||||
|
|
||||||
|
if (missingFields.length > 0) {
|
||||||
|
console.warn('⚠️ Campos obrigatórios vazios:', missingFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
console.log("📤 Payload being sent:", payload);
|
||||||
|
console.log("🔧 Mode:", mode, "DoctorId:", doctorId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mode === "edit" && !doctorId) {
|
||||||
|
throw new Error("ID do médico não fornecido para edição");
|
||||||
|
}
|
||||||
|
|
||||||
const saved = mode === "create"
|
const saved = mode === "create"
|
||||||
? await criarMedico(payload)
|
? await criarMedico(payload)
|
||||||
: await atualizarMedico(doctorId as number, payload);
|
: await atualizarMedico(String(doctorId), payload);
|
||||||
|
|
||||||
const medicoId = saved.id;
|
console.log("✅ Médico salvo com sucesso:", saved);
|
||||||
|
|
||||||
if (form.photo) {
|
|
||||||
try {
|
|
||||||
await uploadFotoMedico(medicoId, form.photo);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Falha ao enviar foto:", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form.anexos?.length) {
|
|
||||||
for (const f of form.anexos) {
|
|
||||||
try {
|
|
||||||
await adicionarAnexoMedico(medicoId, f);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Falha ao enviar anexo:", f.name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSaved?.(saved);
|
onSaved?.(saved);
|
||||||
if (inline) onClose?.();
|
setSubmitting(false);
|
||||||
else onOpenChange?.(false);
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
console.error("❌ Erro ao salvar médico:", err);
|
||||||
|
console.error("❌ Detalhes do erro:", {
|
||||||
|
message: err?.message,
|
||||||
|
status: err?.status,
|
||||||
|
stack: err?.stack
|
||||||
|
});
|
||||||
setErrors((e) => ({ ...e, submit: err?.message || "Erro ao salvar médico" }));
|
setErrors((e) => ({ ...e, submit: err?.message || "Erro ao salvar médico" }));
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
@ -376,6 +405,10 @@ export function DoctorRegistrationForm({
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function handlePhoto(e: React.ChangeEvent<HTMLInputElement>) {
|
function handlePhoto(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
const f = e.target.files?.[0];
|
const f = e.target.files?.[0];
|
||||||
if (!f) return;
|
if (!f) return;
|
||||||
@ -449,8 +482,10 @@ export function DoctorRegistrationForm({
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Nome *</Label>
|
<Label>Nome *</Label>
|
||||||
<Input value={form.nome} onChange={(e) => setField("nome", e.target.value)} className={errors.nome ? "border-destructive" : ""} />
|
<Input value={form.full_name} onChange={(e) => setField("full_name", e.target.value)} />
|
||||||
{errors.nome && <p className="text-sm text-destructive">{errors.nome}</p>}
|
|
||||||
|
|
||||||
|
{errors.full_name && <p className="text-sm text-destructive">{errors.full_name}</p>}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Nome Social</Label>
|
<Label>Nome Social</Label>
|
||||||
@ -473,7 +508,11 @@ export function DoctorRegistrationForm({
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Especialidade *</Label>
|
<Label>Especialidade *</Label>
|
||||||
<Input value={form.especialidade} onChange={(e) => setField("especialidade", e.target.value)} className={errors.especialidade ? "border-destructive" : ""} />
|
<Input
|
||||||
|
value={form.especialidade} // Mantenha o nome no form como 'especialidade'
|
||||||
|
onChange={(e) => setField("especialidade", e.target.value)} // Envia o valor correto
|
||||||
|
className={errors.especialidade ? "border-destructive" : ""}
|
||||||
|
/>
|
||||||
{errors.especialidade && <p className="text-sm text-destructive">{errors.especialidade}</p>}
|
{errors.especialidade && <p className="text-sm text-destructive">{errors.especialidade}</p>}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -482,6 +521,7 @@ export function DoctorRegistrationForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Currículo</Label>
|
<Label>Currículo</Label>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@ -629,6 +669,7 @@ export function DoctorRegistrationForm({
|
|||||||
<Label>E-mail</Label>
|
<Label>E-mail</Label>
|
||||||
<Input value={form.email} onChange={(e) => setField("email", e.target.value)} />
|
<Input value={form.email} onChange={(e) => setField("email", e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Telefone</Label>
|
<Label>Telefone</Label>
|
||||||
<Input
|
<Input
|
||||||
@ -637,6 +678,16 @@ export function DoctorRegistrationForm({
|
|||||||
placeholder="(XX) XXXXX-XXXX"
|
placeholder="(XX) XXXXX-XXXX"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Celular</Label>
|
||||||
|
<Input
|
||||||
|
value={form.celular}
|
||||||
|
onChange={(e) => setField("celular", formatPhone(e.target.value))}
|
||||||
|
placeholder="(XX) XXXXX-XXXX"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -703,11 +754,14 @@ export function DoctorRegistrationForm({
|
|||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Agenda/Horário</Label>
|
<Label>Agenda/Horário</Label>
|
||||||
<Textarea
|
// Dentro do form, apenas exiba o campo se precisar dele visualmente, mas não envie
|
||||||
|
<textarea
|
||||||
value={form.agenda_horario}
|
value={form.agenda_horario}
|
||||||
onChange={(e) => setField("agenda_horario", e.target.value)}
|
onChange={(e) => setField("agenda_horario", e.target.value)}
|
||||||
placeholder="Descreva os dias e horários de atendimento"
|
placeholder="Descreva os dias e horários de atendimento"
|
||||||
|
disabled={true} // Torne o campo apenas visual, sem enviar
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
@ -37,7 +37,7 @@ type Mode = "create" | "edit";
|
|||||||
export interface PatientRegistrationFormProps {
|
export interface PatientRegistrationFormProps {
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
onOpenChange?: (open: boolean) => void;
|
onOpenChange?: (open: boolean) => void;
|
||||||
patientId?: number | null;
|
patientId?: string | number | null;
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
mode?: Mode;
|
mode?: Mode;
|
||||||
onSaved?: (paciente: Paciente) => void;
|
onSaved?: (paciente: Paciente) => void;
|
||||||
@ -51,7 +51,7 @@ type FormData = {
|
|||||||
cpf: string;
|
cpf: string;
|
||||||
rg: string;
|
rg: string;
|
||||||
sexo: string;
|
sexo: string;
|
||||||
data_nascimento: string;
|
birth_date: string; // 👈 corrigido
|
||||||
email: string;
|
email: string;
|
||||||
telefone: string;
|
telefone: string;
|
||||||
cep: string;
|
cep: string;
|
||||||
@ -72,7 +72,7 @@ const initial: FormData = {
|
|||||||
cpf: "",
|
cpf: "",
|
||||||
rg: "",
|
rg: "",
|
||||||
sexo: "",
|
sexo: "",
|
||||||
data_nascimento: "",
|
birth_date: "", // 👈 corrigido
|
||||||
email: "",
|
email: "",
|
||||||
telefone: "",
|
telefone: "",
|
||||||
cep: "",
|
cep: "",
|
||||||
@ -86,6 +86,8 @@ const initial: FormData = {
|
|||||||
anexos: [],
|
anexos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function PatientRegistrationForm({
|
export function PatientRegistrationForm({
|
||||||
open = true,
|
open = true,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
@ -110,30 +112,33 @@ export function PatientRegistrationForm({
|
|||||||
async function load() {
|
async function load() {
|
||||||
if (mode !== "edit" || patientId == null) return;
|
if (mode !== "edit" || patientId == null) return;
|
||||||
try {
|
try {
|
||||||
|
console.log("[PatientForm] Carregando paciente ID:", patientId);
|
||||||
const p = await buscarPacientePorId(String(patientId));
|
const p = await buscarPacientePorId(String(patientId));
|
||||||
|
console.log("[PatientForm] Dados recebidos:", p);
|
||||||
setForm((s) => ({
|
setForm((s) => ({
|
||||||
...s,
|
...s,
|
||||||
nome: p.nome || "",
|
nome: p.full_name || "", // 👈 trocar nome → full_name
|
||||||
nome_social: p.nome_social || "",
|
nome_social: p.social_name || "",
|
||||||
cpf: p.cpf || "",
|
cpf: p.cpf || "",
|
||||||
rg: p.rg || "",
|
rg: p.rg || "",
|
||||||
sexo: p.sexo || "",
|
sexo: p.sex || "",
|
||||||
data_nascimento: (p.data_nascimento as string) || "",
|
birth_date: p.birth_date || "", // 👈 trocar data_nascimento → birth_date
|
||||||
telefone: p.telefone || "",
|
telefone: p.phone_mobile || "",
|
||||||
email: p.email || "",
|
email: p.email || "",
|
||||||
cep: p.endereco?.cep || "",
|
cep: p.cep || "",
|
||||||
logradouro: p.endereco?.logradouro || "",
|
logradouro: p.street || "",
|
||||||
numero: p.endereco?.numero || "",
|
numero: p.number || "",
|
||||||
complemento: p.endereco?.complemento || "",
|
complemento: p.complement || "",
|
||||||
bairro: p.endereco?.bairro || "",
|
bairro: p.neighborhood || "",
|
||||||
cidade: p.endereco?.cidade || "",
|
cidade: p.city || "",
|
||||||
estado: p.endereco?.estado || "",
|
estado: p.state || "",
|
||||||
observacoes: p.observacoes || "",
|
observacoes: p.notes || "",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const ax = await listarAnexos(String(patientId)).catch(() => []);
|
const ax = await listarAnexos(String(patientId)).catch(() => []);
|
||||||
setServerAnexos(Array.isArray(ax) ? ax : []);
|
setServerAnexos(Array.isArray(ax) ? ax : []);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[PatientForm] Erro ao carregar paciente:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
@ -187,27 +192,27 @@ export function PatientRegistrationForm({
|
|||||||
|
|
||||||
function toPayload(): PacienteInput {
|
function toPayload(): PacienteInput {
|
||||||
return {
|
return {
|
||||||
nome: form.nome,
|
full_name: form.nome, // 👈 troca 'nome' por 'full_name'
|
||||||
nome_social: form.nome_social || null,
|
social_name: form.nome_social || null,
|
||||||
cpf: form.cpf,
|
cpf: form.cpf,
|
||||||
rg: form.rg || null,
|
rg: form.rg || null,
|
||||||
sexo: form.sexo || null,
|
sex: form.sexo || null,
|
||||||
data_nascimento: form.data_nascimento || null,
|
birth_date: form.birth_date || null, // 👈 troca data_nascimento → birth_date
|
||||||
telefone: form.telefone || null,
|
phone_mobile: form.telefone || null,
|
||||||
email: form.email || null,
|
email: form.email || null,
|
||||||
endereco: {
|
cep: form.cep || null,
|
||||||
cep: form.cep || undefined,
|
street: form.logradouro || null,
|
||||||
logradouro: form.logradouro || undefined,
|
number: form.numero || null,
|
||||||
numero: form.numero || undefined,
|
complement: form.complemento || null,
|
||||||
complemento: form.complemento || undefined,
|
neighborhood: form.bairro || null,
|
||||||
bairro: form.bairro || undefined,
|
city: form.cidade || null,
|
||||||
cidade: form.cidade || undefined,
|
state: form.estado || null,
|
||||||
estado: form.estado || undefined,
|
notes: form.observacoes || null,
|
||||||
},
|
|
||||||
observacoes: form.observacoes || null,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function handleSubmit(ev: React.FormEvent) {
|
async function handleSubmit(ev: React.FormEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (!validateLocal()) return;
|
if (!validateLocal()) return;
|
||||||
@ -418,7 +423,8 @@ export function PatientRegistrationForm({
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Data de Nascimento</Label>
|
<Label>Data de Nascimento</Label>
|
||||||
<Input type="date" value={form.data_nascimento} onChange={(e) => setField("data_nascimento", e.target.value)} />
|
<Input type="date" value={form.birth_date} onChange={(e) => setField("birth_date", e.target.value)} />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@ -26,32 +26,44 @@ export type Endereco = {
|
|||||||
// ===== PACIENTES =====
|
// ===== PACIENTES =====
|
||||||
export type Paciente = {
|
export type Paciente = {
|
||||||
id: string;
|
id: string;
|
||||||
nome?: string;
|
full_name: string;
|
||||||
nome_social?: string | null;
|
social_name?: string | null;
|
||||||
cpf?: string;
|
cpf?: string;
|
||||||
rg?: string | null;
|
rg?: string | null;
|
||||||
sexo?: string | null;
|
sex?: string | null;
|
||||||
data_nascimento?: string | null;
|
birth_date?: string | null;
|
||||||
telefone?: string;
|
phone_mobile?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
endereco?: Endereco;
|
cep?: string | null;
|
||||||
observacoes?: string | null;
|
street?: string | null;
|
||||||
foto_url?: string | null;
|
number?: string | null;
|
||||||
|
complement?: string | null;
|
||||||
|
neighborhood?: string | null;
|
||||||
|
city?: string | null;
|
||||||
|
state?: string | null;
|
||||||
|
notes?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PacienteInput = {
|
export type PacienteInput = {
|
||||||
nome: string;
|
full_name: string;
|
||||||
nome_social?: string | null;
|
social_name?: string | null;
|
||||||
cpf: string;
|
cpf: string;
|
||||||
rg?: string | null;
|
rg?: string | null;
|
||||||
sexo?: string | null;
|
sex?: string | null;
|
||||||
data_nascimento?: string | null;
|
birth_date?: string | null;
|
||||||
telefone?: string | null;
|
phone_mobile?: string | null;
|
||||||
email?: string | null;
|
email?: string | null;
|
||||||
endereco?: Endereco;
|
cep?: string | null;
|
||||||
observacoes?: string | null;
|
street?: string | null;
|
||||||
|
number?: string | null;
|
||||||
|
complement?: string | null;
|
||||||
|
neighborhood?: string | null;
|
||||||
|
city?: string | null;
|
||||||
|
state?: string | null;
|
||||||
|
notes?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// ===== MÉDICOS =====
|
// ===== MÉDICOS =====
|
||||||
export type FormacaoAcademica = {
|
export type FormacaoAcademica = {
|
||||||
instituicao: string;
|
instituicao: string;
|
||||||
@ -66,9 +78,10 @@ export type DadosBancarios = {
|
|||||||
tipo_conta: string;
|
tipo_conta: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ===== MÉDICOS =====
|
||||||
export type Medico = {
|
export type Medico = {
|
||||||
id: string;
|
id: string;
|
||||||
nome?: string;
|
full_name: string; // Altere 'nome' para 'full_name'
|
||||||
nome_social?: string | null;
|
nome_social?: string | null;
|
||||||
cpf?: string;
|
cpf?: string;
|
||||||
rg?: string | null;
|
rg?: string | null;
|
||||||
@ -90,32 +103,51 @@ export type Medico = {
|
|||||||
dados_bancarios?: DadosBancarios;
|
dados_bancarios?: DadosBancarios;
|
||||||
agenda_horario?: string;
|
agenda_horario?: string;
|
||||||
valor_consulta?: number | string;
|
valor_consulta?: number | string;
|
||||||
|
active?: boolean;
|
||||||
|
cep?: string;
|
||||||
|
city?: string;
|
||||||
|
complement?: string;
|
||||||
|
neighborhood?: string;
|
||||||
|
number?: string;
|
||||||
|
phone2?: string;
|
||||||
|
state?: string;
|
||||||
|
street?: string;
|
||||||
|
created_at?: string;
|
||||||
|
created_by?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
updated_by?: string;
|
||||||
|
user_id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ===== MÉDICOS =====
|
||||||
|
// ...existing code...
|
||||||
export type MedicoInput = {
|
export type MedicoInput = {
|
||||||
nome: string;
|
user_id?: string | null;
|
||||||
nome_social?: string | null;
|
|
||||||
cpf?: string | null;
|
|
||||||
rg?: string | null;
|
|
||||||
sexo?: string | null;
|
|
||||||
data_nascimento?: string | null;
|
|
||||||
telefone?: string | null;
|
|
||||||
celular?: string | null;
|
|
||||||
contato_emergencia?: string | null;
|
|
||||||
email?: string | null;
|
|
||||||
crm: string;
|
crm: string;
|
||||||
estado_crm?: string | null;
|
crm_uf: string;
|
||||||
rqe?: string | null;
|
specialty: string;
|
||||||
formacao_academica?: FormacaoAcademica[];
|
full_name: string;
|
||||||
curriculo_url?: string | null;
|
cpf: string;
|
||||||
especialidade: string;
|
email: string;
|
||||||
observacoes?: string | null;
|
phone_mobile: string;
|
||||||
tipo_vinculo?: string | null;
|
phone2?: string | null;
|
||||||
dados_bancarios?: DadosBancarios | null;
|
cep: string;
|
||||||
agenda_horario?: string | null;
|
street: string;
|
||||||
valor_consulta?: number | string | null;
|
number: string;
|
||||||
|
complement?: string;
|
||||||
|
neighborhood?: string;
|
||||||
|
city: string;
|
||||||
|
state: string;
|
||||||
|
birth_date: string | null;
|
||||||
|
rg?: string | null;
|
||||||
|
active?: boolean;
|
||||||
|
created_by?: string | null;
|
||||||
|
updated_by?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===== CONFIG =====
|
// ===== CONFIG =====
|
||||||
const API_BASE =
|
const API_BASE =
|
||||||
process.env.NEXT_PUBLIC_API_BASE ?? "https://yuanqfswhberkoevtmfr.supabase.co";
|
process.env.NEXT_PUBLIC_API_BASE ?? "https://yuanqfswhberkoevtmfr.supabase.co";
|
||||||
@ -154,16 +186,21 @@ async function parse<T>(res: Response): Promise<T> {
|
|||||||
let json: any = null;
|
let json: any = null;
|
||||||
try {
|
try {
|
||||||
json = await res.json();
|
json = await res.json();
|
||||||
} catch {}
|
} catch (err) {
|
||||||
|
console.error("Erro ao parsear a resposta:", err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
console.error("[API ERROR]", res.url, res.status, json);
|
console.error("[API ERROR]", res.url, res.status, json);
|
||||||
const code = (json && (json.error?.code || json.code)) ?? res.status;
|
const code = (json && (json.error?.code || json.code)) ?? res.status;
|
||||||
const msg = (json && (json.error?.message || json.message)) ?? res.statusText;
|
const msg = (json && (json.error?.message || json.message)) ?? res.statusText;
|
||||||
throw new Error(`${code}: ${msg}`);
|
throw new Error(`${code}: ${msg}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (json?.data ?? json) as T;
|
return (json?.data ?? json) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Helper de paginação (Range/Range-Unit)
|
// Helper de paginação (Range/Range-Unit)
|
||||||
function rangeHeaders(page?: number, limit?: number): Record<string, string> {
|
function rangeHeaders(page?: number, limit?: number): Record<string, string> {
|
||||||
if (!page || !limit) return {};
|
if (!page || !limit) return {};
|
||||||
@ -192,6 +229,68 @@ export async function listarPacientes(params?: {
|
|||||||
return await parse<Paciente[]>(res);
|
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> {
|
export async function buscarPacientePorId(id: string | number): Promise<Paciente> {
|
||||||
const url = `${REST}/patients?id=eq.${id}`;
|
const url = `${REST}/patients?id=eq.${id}`;
|
||||||
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
||||||
@ -262,34 +361,189 @@ export async function listarMedicos(params?: {
|
|||||||
return await parse<Medico[]>(res);
|
return await parse<Medico[]>(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nova função para busca avançada de médicos
|
||||||
|
export async function buscarMedicos(termo: string): Promise<Medico[]> {
|
||||||
|
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 CRM (com e sem formatação)
|
||||||
|
if (digitsOnly.length >= 3) {
|
||||||
|
queries.push(`crm=ilike.*${digitsOnly}*`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busca por nome (usando ilike para busca case-insensitive)
|
||||||
|
if (searchTerm.length >= 2) {
|
||||||
|
queries.push(`full_name=ilike.*${searchTerm}*`);
|
||||||
|
queries.push(`nome_social=ilike.*${searchTerm}*`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busca por email se contém @
|
||||||
|
if (searchTerm.includes('@')) {
|
||||||
|
queries.push(`email=ilike.*${searchTerm}*`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busca por especialidade
|
||||||
|
if (searchTerm.length >= 2) {
|
||||||
|
queries.push(`specialty=ilike.*${searchTerm}*`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: Medico[] = [];
|
||||||
|
const seenIds = new Set<string>();
|
||||||
|
|
||||||
|
// Executa as buscas e combina resultados únicos
|
||||||
|
for (const query of queries) {
|
||||||
|
try {
|
||||||
|
const url = `${REST}/doctors?${query}&limit=10`;
|
||||||
|
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
||||||
|
const arr = await parse<Medico[]>(res);
|
||||||
|
|
||||||
|
if (arr?.length > 0) {
|
||||||
|
for (const medico of arr) {
|
||||||
|
if (!seenIds.has(medico.id)) {
|
||||||
|
seenIds.add(medico.id);
|
||||||
|
results.push(medico);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Erro na busca com query: ${query}`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.slice(0, 20); // Limita a 20 resultados
|
||||||
|
}
|
||||||
|
|
||||||
export async function buscarMedicoPorId(id: string | number): Promise<Medico> {
|
export async function buscarMedicoPorId(id: string | number): Promise<Medico> {
|
||||||
|
// Primeiro tenta buscar no Supabase (dados reais)
|
||||||
|
try {
|
||||||
const url = `${REST}/doctors?id=eq.${id}`;
|
const url = `${REST}/doctors?id=eq.${id}`;
|
||||||
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
const res = await fetch(url, { method: "GET", headers: baseHeaders() });
|
||||||
const arr = await parse<Medico[]>(res);
|
const arr = await parse<Medico[]>(res);
|
||||||
if (!arr?.length) throw new Error("404: Médico não encontrado");
|
if (arr && arr.length > 0) {
|
||||||
|
console.log('✅ Médico encontrado no Supabase:', arr[0]);
|
||||||
|
console.log('🔍 Campo especialidade no médico:', {
|
||||||
|
especialidade: arr[0].especialidade,
|
||||||
|
specialty: (arr[0] as any).specialty,
|
||||||
|
hasEspecialidade: !!arr[0].especialidade,
|
||||||
|
hasSpecialty: !!((arr[0] as any).specialty)
|
||||||
|
});
|
||||||
return arr[0];
|
return arr[0];
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('⚠️ Erro ao buscar no Supabase, tentando mock API:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se não encontrar no Supabase, tenta o mock API
|
||||||
|
try {
|
||||||
|
const url = `https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctors/${id}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
if (res.status === 404) {
|
||||||
|
throw new Error("404: Médico não encontrado");
|
||||||
|
}
|
||||||
|
throw new Error(`Erro ao buscar médico: ${res.status} ${res.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const medico = await res.json();
|
||||||
|
console.log('✅ Médico encontrado no Mock API:', medico);
|
||||||
|
return medico as Medico;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erro ao buscar médico em ambas as APIs:', error);
|
||||||
|
throw new Error("404: Médico não encontrado");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dentro de lib/api.ts
|
||||||
export async function criarMedico(input: MedicoInput): Promise<Medico> {
|
export async function criarMedico(input: MedicoInput): Promise<Medico> {
|
||||||
const url = `${REST}/doctors`;
|
console.log("Enviando os dados para a API:", input); // Log para depuração
|
||||||
|
|
||||||
|
const url = `${REST}/doctors`; // Endpoint de médicos
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: withPrefer({ ...baseHeaders(), "Content-Type": "application/json" }, "return=representation"),
|
headers: withPrefer({ ...baseHeaders(), "Content-Type": "application/json" }, "return=representation"),
|
||||||
body: JSON.stringify(input),
|
body: JSON.stringify(input), // Enviando os dados padronizados
|
||||||
});
|
});
|
||||||
const arr = await parse<Medico[] | Medico>(res);
|
|
||||||
return Array.isArray(arr) ? arr[0] : (arr as Medico);
|
const arr = await parse<Medico[] | Medico>(res); // Resposta da API
|
||||||
|
return Array.isArray(arr) ? arr[0] : (arr as Medico); // Retorno do médico
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export async function atualizarMedico(id: string | number, input: MedicoInput): Promise<Medico> {
|
export async function atualizarMedico(id: string | number, input: MedicoInput): Promise<Medico> {
|
||||||
|
console.log(`🔄 Tentando atualizar médico ID: ${id}`);
|
||||||
|
console.log(`📤 Payload original:`, input);
|
||||||
|
|
||||||
|
// Criar um payload limpo apenas com campos básicos que sabemos que existem
|
||||||
|
const cleanPayload = {
|
||||||
|
full_name: input.full_name,
|
||||||
|
crm: input.crm,
|
||||||
|
specialty: input.specialty,
|
||||||
|
email: input.email,
|
||||||
|
phone_mobile: input.phone_mobile,
|
||||||
|
cpf: input.cpf,
|
||||||
|
cep: input.cep,
|
||||||
|
street: input.street,
|
||||||
|
number: input.number,
|
||||||
|
city: input.city,
|
||||||
|
state: input.state,
|
||||||
|
active: input.active ?? true
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`📤 Payload limpo:`, cleanPayload);
|
||||||
|
|
||||||
|
// Atualizar apenas no Supabase (dados reais)
|
||||||
|
try {
|
||||||
const url = `${REST}/doctors?id=eq.${id}`;
|
const url = `${REST}/doctors?id=eq.${id}`;
|
||||||
|
console.log(`🌐 URL de atualização: ${url}`);
|
||||||
|
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: withPrefer({ ...baseHeaders(), "Content-Type": "application/json" }, "return=representation"),
|
headers: withPrefer({ ...baseHeaders(), "Content-Type": "application/json" }, "return=representation"),
|
||||||
body: JSON.stringify(input),
|
body: JSON.stringify(cleanPayload),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(`📡 Resposta do servidor: ${res.status} ${res.statusText}`);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
const arr = await parse<Medico[] | Medico>(res);
|
const arr = await parse<Medico[] | Medico>(res);
|
||||||
return Array.isArray(arr) ? arr[0] : (arr as Medico);
|
const result = Array.isArray(arr) ? arr[0] : (arr as Medico);
|
||||||
|
console.log('✅ Médico atualizado no Supabase:', result);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// Vamos tentar ver o erro detalhado
|
||||||
|
const errorText = await res.text();
|
||||||
|
console.error(`❌ Erro detalhado do Supabase:`, {
|
||||||
|
status: res.status,
|
||||||
|
statusText: res.statusText,
|
||||||
|
response: errorText,
|
||||||
|
headers: Object.fromEntries(res.headers.entries())
|
||||||
|
});
|
||||||
|
throw new Error(`Supabase error: ${res.status} ${res.statusText} - ${errorText}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erro ao atualizar médico:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function excluirMedico(id: string | number): Promise<void> {
|
export async function excluirMedico(id: string | number): Promise<void> {
|
||||||
|
|||||||
139
susconecta/package-lock.json
generated
139
susconecta/package-lock.json
generated
@ -4086,6 +4086,53 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001739",
|
"version": "1.0.30001739",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
|
||||||
@ -4578,10 +4625,51 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
"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",
|
||||||
|
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||||
|
=======
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||||
|
>>>>>>> origin/develop
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@ -4727,6 +4815,8 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/es-abstract": {
|
"node_modules/es-abstract": {
|
||||||
"version": "1.24.0",
|
"version": "1.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
|
||||||
@ -4796,6 +4886,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
@ -4814,6 +4905,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/es-iterator-helpers": {
|
"node_modules/es-iterator-helpers": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
|
||||||
@ -4842,6 +4935,7 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/es-object-atoms": {
|
"node_modules/es-object-atoms": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
@ -4854,6 +4948,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/es-set-tostringtag": {
|
"node_modules/es-set-tostringtag": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
@ -4901,6 +4997,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/es-toolkit": {
|
"node_modules/es-toolkit": {
|
||||||
"version": "1.39.10",
|
"version": "1.39.10",
|
||||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz",
|
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz",
|
||||||
@ -5767,6 +5864,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/function.prototype.name": {
|
"node_modules/function.prototype.name": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
|
||||||
@ -5788,6 +5887,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/functions-have-names": {
|
"node_modules/functions-have-names": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
||||||
@ -5806,6 +5906,8 @@
|
|||||||
"next": ">=13.2.0"
|
"next": ">=13.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/generator-function": {
|
"node_modules/generator-function": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
|
||||||
@ -5816,6 +5918,7 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
@ -5862,6 +5965,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/get-symbol-description": {
|
"node_modules/get-symbol-description": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
|
||||||
@ -5936,6 +6041,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
@ -5955,6 +6061,8 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/graphemer": {
|
"node_modules/graphemer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||||
@ -5985,6 +6093,7 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/has-property-descriptors": {
|
"node_modules/has-property-descriptors": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
@ -5997,6 +6106,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/has-proto": {
|
"node_modules/has-proto": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
|
||||||
@ -6013,6 +6124,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/has-symbols": {
|
"node_modules/has-symbols": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
@ -6182,6 +6294,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/is-array-buffer": {
|
"node_modules/is-array-buffer": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||||
@ -6326,6 +6440,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/is-date-object": {
|
"node_modules/is-date-object": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
|
||||||
@ -6342,6 +6457,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/is-extglob": {
|
"node_modules/is-extglob": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
@ -6454,6 +6571,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/is-regex": {
|
"node_modules/is-regex": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||||
@ -6472,6 +6590,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/is-set": {
|
"node_modules/is-set": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
|
||||||
@ -6630,6 +6750,7 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/jiti": {
|
"node_modules/jiti": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
||||||
@ -7091,6 +7212,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@ -7141,6 +7264,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
@ -7342,6 +7466,8 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
@ -7355,6 +7481,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/object-is": {
|
"node_modules/object-is": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||||
@ -7380,6 +7507,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/object.assign": {
|
"node_modules/object.assign": {
|
||||||
"version": "4.1.7",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
|
||||||
@ -7538,6 +7667,7 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/pako": {
|
"node_modules/pako": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||||
@ -8070,6 +8200,8 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/regexp-tree": {
|
"node_modules/regexp-tree": {
|
||||||
"version": "0.1.27",
|
"version": "0.1.27",
|
||||||
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
|
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
|
||||||
@ -8080,6 +8212,7 @@
|
|||||||
"regexp-tree": "bin/regexp-tree"
|
"regexp-tree": "bin/regexp-tree"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/regexp.prototype.flags": {
|
"node_modules/regexp.prototype.flags": {
|
||||||
"version": "1.5.4",
|
"version": "1.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
||||||
@ -8100,6 +8233,8 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/regjsparser": {
|
"node_modules/regjsparser": {
|
||||||
"version": "0.12.0",
|
"version": "0.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz",
|
||||||
@ -8126,6 +8261,7 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/reselect": {
|
"node_modules/reselect": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||||
@ -8333,6 +8469,8 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"node_modules/set-proto": {
|
"node_modules/set-proto": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
|
||||||
@ -8490,6 +8628,7 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> origin/develop
|
||||||
"node_modules/signature_pad": {
|
"node_modules/signature_pad": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-2.3.2.tgz",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user