Mejoras integrales: visitas, POS, WACRM, reportes, temas y módulos legacy
- Módulo Visitas completo (auto desde agenda, insumos con descargo de inventario, fotos antes/después y documentos, receta imprimible) - Punto de Venta (catálogo + ticket sticky, cobro con cambio, pago con puntos monedero, ticket imprimible) - WACRM: leads automáticos desde WhatsApp, asignación de conversaciones y leads a agentes, conversión lead→paciente, ficha del paciente en chat - Pacientes: completitud de expediente, alertas clínicas, historial unificado con detalle, foto, WhatsApp, estado de cuenta, filtros rápidos (VIP/recientes/médico), documentos (expediente escaneado + galería) - Agenda: vistas por médico y por hora, filtros rápidos (libres, primera vez, check-in, no-show), modal de acciones, bloqueos por médico, drag&drop para mover citas - Reportes: 18 pestañas (diario, cortes, ingresos, inventario, adeudos, comisiones, pagos, devoluciones, top clientes, horas, paquetes, vendedores, concentrado, recomendaciones, KPIs) con exportación Excel - Temas: nuevo tema Clásico (look legacy AdminLTE) con submenús tipo treeview, selector de tema; accesos rápidos personalizables con 3 presentaciones; búsqueda global; notificaciones reales - Configuración: secciones (clínica, usuarios con permisos por sección, recetas, catálogos de diagnósticos y procedimientos) - Inventario: alertas de caducidad y sugerencia de compra, cron diario que descuenta artículos caducados, compras/bajas - Consultas Médicas, página Expedientes, importadores delta (citas/visitas legacy idempotentes), depuración de duplicados - Infra: tema Tailwind conectado (@config), gzip en nginx, secuencias Odoo corregidas (noupdate, company_id), rollback en validaciones
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
Calendar,
|
||||
Users,
|
||||
@@ -40,6 +41,7 @@ import {
|
||||
} from '../components/ui';
|
||||
import { odooApi, type DashboardStats, type Appointment, type Service, type ChartPoint } from '../services/odoo';
|
||||
import { useTheme } from '../lib/theme';
|
||||
import { useAuth } from '../lib/auth';
|
||||
|
||||
const formatCurrency = (value: number) =>
|
||||
new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN', maximumFractionDigits: 0 }).format(value);
|
||||
@@ -76,6 +78,8 @@ const StatCard: FC<StatCardProps> = ({ title, value, icon, trend, loading }) =>
|
||||
|
||||
const Dashboard: FC = () => {
|
||||
const { theme } = useTheme();
|
||||
const { user } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const isHomeNest = theme === 'homenest';
|
||||
const [stats, setStats] = useState<DashboardStats | null>(null);
|
||||
const [chartData, setChartData] = useState<ChartPoint[]>([]);
|
||||
@@ -256,10 +260,10 @@ const Dashboard: FC = () => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-3 shrink-0">
|
||||
<Button variant="primary" size="md">
|
||||
<Button variant="primary" size="md" onClick={() => navigate('/agenda')}>
|
||||
<Calendar size={16} className="mr-2" /> Nueva cita
|
||||
</Button>
|
||||
<Button variant="outline" size="md">
|
||||
<Button variant="outline" size="md" onClick={() => navigate('/reportes')}>
|
||||
<TrendingUp size={16} className="mr-2" /> Ver reportes
|
||||
</Button>
|
||||
</div>
|
||||
@@ -277,10 +281,10 @@ const Dashboard: FC = () => {
|
||||
) : (
|
||||
<>
|
||||
<PageHeader title="Dashboard" subtitle="Resumen general de la clínica">
|
||||
<Button variant="outline" size="sm">
|
||||
<Sparkles size={16} className="mr-2" />
|
||||
Bienvenido
|
||||
</Button>
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-medium bg-theme-accent-bg text-theme-heading">
|
||||
<Sparkles size={16} />
|
||||
Bienvenido{user?.name ? `, ${user.name.split(' ')[0]}` : ''}
|
||||
</span>
|
||||
</PageHeader>
|
||||
|
||||
<div className="bg-gradient-to-r from-[#EDA588] to-[#C7BCDD] rounded-2xl p-6 sm:p-8 text-white mb-6 sm:mb-8 shadow-sm">
|
||||
@@ -292,7 +296,7 @@ const Dashboard: FC = () => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="shrink-0">
|
||||
<Button variant="secondary" size="sm" className="bg-theme-surface/20 text-white border-white/30 hover:bg-theme-surface/30">
|
||||
<Button variant="secondary" size="sm" className="bg-theme-surface/20 text-white border-white/30 hover:bg-theme-surface/30" onClick={() => navigate('/reportes')}>
|
||||
<TrendingUp size={16} className="mr-2" />
|
||||
Ver reportes
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user