Fix IA (max_tokens del modelo de razonamiento + fallback al gateway), sidebar con toggle arriba, busqueda de un solo campo (paciente/global), editar expediente, marketing en visitas, responsive de agenda; doc de diagnostico WhatsApp
This commit is contained in:
@@ -3,6 +3,7 @@ import { Fragment, useEffect, useState, useCallback } from 'react';
|
||||
import { Plus, Trash2, CreditCard, ShoppingCart, Search, Undo2, Download, Printer, ChevronDown, ChevronRight, Ban } from 'lucide-react';
|
||||
import Layout from '../components/Layout';
|
||||
import { usePatientDrawer } from '../components/PatientDrawer';
|
||||
import PatientCombobox from '../components/PatientCombobox';
|
||||
import TicketPrint from '../components/TicketPrint';
|
||||
import {
|
||||
Card,
|
||||
@@ -19,7 +20,7 @@ import {
|
||||
toast,
|
||||
badgeForSaleState,
|
||||
} from '../components/ui';
|
||||
import { odooApi, type Sale, type SaleLine, type Service, type Patient, type Doctor } from '../services/odoo';
|
||||
import { odooApi, type Sale, type SaleLine, type Service, type Doctor } from '../services/odoo';
|
||||
import { exportToExcel } from '../lib/exporter';
|
||||
import { useAuth } from '../lib/auth';
|
||||
import { DATE_PRESETS, rangeForPreset, readDateFilterPrefs, writeDateFilterPrefs, type DatePreset } from '../lib/dateRange';
|
||||
@@ -50,7 +51,6 @@ const Ventas: FC = () => {
|
||||
const puedeCancelar = ROLES_CANCELAN.includes(user?.role || '');
|
||||
const [sales, setSales] = useState<Sale[]>([]);
|
||||
const [services, setServices] = useState<Service[]>([]);
|
||||
const [patients, setPatients] = useState<Patient[]>([]);
|
||||
const [doctors, setDoctors] = useState<Doctor[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -81,7 +81,6 @@ const Ventas: FC = () => {
|
||||
const [pageSize, setPageSize] = useState(50);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [totalPages, setTotalPages] = useState(0);
|
||||
const [patientSearch, setPatientSearch] = useState('');
|
||||
|
||||
// ---- Rango de fechas recordado (presets) ----
|
||||
const saved = readDateFilterPrefs(FILTERS_KEY);
|
||||
@@ -154,20 +153,6 @@ const Ventas: FC = () => {
|
||||
setPage(1);
|
||||
}, [search]);
|
||||
|
||||
// Cargar pacientes para el selector (búsqueda server-side)
|
||||
useEffect(() => {
|
||||
if (!createOpen) return;
|
||||
const t = setTimeout(async () => {
|
||||
try {
|
||||
const res = await odooApi.getPatients({ search: patientSearch, page_size: 50 });
|
||||
if (res.status === 'success') setPatients(res.patients);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}, 250);
|
||||
return () => clearTimeout(t);
|
||||
}, [createOpen, patientSearch]);
|
||||
|
||||
const addLine = () =>
|
||||
setLines([...lines, emptyLine()]);
|
||||
|
||||
@@ -362,11 +347,6 @@ const Ventas: FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const patientOptions = [
|
||||
{ value: '', label: 'Seleccionar paciente...' },
|
||||
...patients.map((p) => ({ value: String(p.id), label: `${p.name} (${p.phone})` })),
|
||||
];
|
||||
|
||||
const serviceOptions = [
|
||||
{ value: '', label: 'Servicio...' },
|
||||
...services.map((s) => ({ value: String(s.id), label: `${s.name} — $${s.price}` })),
|
||||
@@ -694,17 +674,12 @@ const Ventas: FC = () => {
|
||||
}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
label="Buscar paciente"
|
||||
placeholder="Escribe nombre o teléfono..."
|
||||
value={patientSearch}
|
||||
onChange={(e) => setPatientSearch(e.target.value)}
|
||||
/>
|
||||
<Select
|
||||
<PatientCombobox
|
||||
label="Paciente *"
|
||||
options={patientOptions}
|
||||
value={patientId}
|
||||
onChange={(e) => setPatientId(e.target.value)}
|
||||
placeholder="Escribe nombre, apellidos o teléfono..."
|
||||
emptyHint="Sin resultados. Da de alta al paciente en Pacientes y vuelve a intentar."
|
||||
onChange={(id) => setPatientId(id)}
|
||||
/>
|
||||
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user