diff --git a/frontend/components/SearchSelect.tsx b/frontend/components/SearchSelect.tsx new file mode 100644 index 0000000..3bc509d --- /dev/null +++ b/frontend/components/SearchSelect.tsx @@ -0,0 +1,66 @@ +import React, { useState } from 'react'; +import { Search, X, Check, ChevronDown } from 'lucide-react'; + +export interface SelectOption { value: string; label: string; hint?: string } + +// Dropdown genérico que abre um modal com busca — substitui setBusca(e.target.value)} placeholder="Buscar…" + className="w-full pl-9 pr-3 py-2.5 rounded-xl border border-gray-200 text-sm outline-none focus:border-teal-400" /> + + +
+ {filtrados.length === 0 ? ( +

Nada encontrado.

+ ) : filtrados.map(o => ( + + ))} +
+ + + )} + + ); +}; diff --git a/frontend/views/LancarGTO.tsx b/frontend/views/LancarGTO.tsx index 026cfa9..b92cd3e 100644 --- a/frontend/views/LancarGTO.tsx +++ b/frontend/views/LancarGTO.tsx @@ -14,6 +14,7 @@ import { } from 'lucide-react'; import { PageHeader } from '../components/PageHeader.tsx'; import { ProteticoPicker } from '../components/ProteticoPicker.tsx'; +import { SearchSelect } from '../components/SearchSelect.tsx'; import { HybridBackend } from '../services/backend.ts'; import { Paciente, Dentista, Procedimento, Especialidade } from '../types.ts'; import { useToast } from '../contexts/ToastContext.tsx'; @@ -457,10 +458,10 @@ export const LancarGTO: React.FC = () => { 02. Especialidade
- + options={especialidades.map(es => ({ value: es.id, label: es.nome }))} + placeholder="ESCOLHA A ÁREA..." title="Especialidade" + /> {selectedEsp && isProtese && (
@@ -484,18 +483,17 @@ export const LancarGTO: React.FC = () => {
) : ( <> - + /> {selectedProduto && ( <> @@ -543,21 +541,20 @@ export const LancarGTO: React.FC = () => {

Cadastre em Procedimentos para usá-lo aqui

) : ( - + /> )} {selectedProc && ( @@ -588,28 +585,23 @@ export const LancarGTO: React.FC = () => {
03. Dentista Executor
- + />
- + />
); diff --git a/frontend/views/ProteseView.tsx b/frontend/views/ProteseView.tsx index 0806a44..b403fde 100644 --- a/frontend/views/ProteseView.tsx +++ b/frontend/views/ProteseView.tsx @@ -6,6 +6,7 @@ import { useConfirm } from '../contexts/ConfirmContext.tsx'; import { PageHeader } from '../components/PageHeader.tsx'; import { rotulosPaciente } from '../utils/pacienteLabel.ts'; import { ProteticoPicker } from '../components/ProteticoPicker.tsx'; +import { SearchSelect } from '../components/SearchSelect.tsx'; const fmtBRL = (v: number) => 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 }); const dataBR = (d: string) => (d || '').slice(0, 10).split('-').reverse().join('/'); @@ -159,10 +160,10 @@ const NovaOSModal: React.FC<{ onClose: () => void; onSaved: () => void }> = ({ o
{form.protetico_id && produtos.length > 0 ? ( - +
set('produto_id', v)} + options={produtos.map(p => ({ value: p.id, label: p.nome, hint: fmtBRL(p.preco) }))} + placeholder="Selecione..." title="Produto do laboratório" + className="w-full px-3 py-2 rounded-xl border border-gray-200 text-sm" />
) : ( set('tipo', e.target.value)} placeholder={form.protetico_id ? 'Sem catálogo — descreva o trabalho' : 'Selecione o laboratório primeiro'} disabled={!form.protetico_id} className="w-full mt-1 px-3 py-2 rounded-xl border border-gray-200 text-sm disabled:bg-gray-50" /> @@ -174,10 +175,10 @@ const NovaOSModal: React.FC<{ onClose: () => void; onSaved: () => void }> = ({ o {/* Dentista */}
- +
set('dentista_id', v)} + options={dentistas.map(d => ({ value: d.id, label: d.nome }))} + placeholder="—" title="Dentista" + className="w-full px-3 py-2 rounded-xl border border-gray-200 text-sm" />
{/* Material + cor + dentes */}
@@ -1008,6 +1009,7 @@ const CotacoesClinicaModal: React.FC<{ onClose: () => void; onEscolhida: () => v const [dentes, setDentes] = useState(''); const [prazo, setPrazo] = useState(''); const [sel, setSel] = useState([]); + const [buscaLab, setBuscaLab] = useState(''); const [busy, setBusy] = useState(false); const carregar = useCallback(() => HybridBackend.getRfqs().then(r => setRfqs(Array.isArray(r) ? r : [])).catch(() => setRfqs([])), []); @@ -1050,8 +1052,12 @@ const CotacoesClinicaModal: React.FC<{ onClose: () => void; onEscolhida: () => v

Laboratórios a convidar

+
+ + setBuscaLab(e.target.value)} placeholder="Buscar laboratório…" className="w-full pl-8 pr-3 py-2 bg-gray-50 border border-gray-100 rounded-xl text-sm outline-none focus:border-violet-400" /> +
- {labs.map(l => ( + {labs.filter(l => !buscaLab.trim() || (l.nome || '').toLowerCase().includes(buscaLab.toLowerCase()) || (l.email || '').toLowerCase().includes(buscaLab.toLowerCase())).map(l => (