From 7b54e401040e3a9f52b4eb52f693df0a33cd9c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Consultor=C3=ADa=20Alcaraz=20Salazar?= Date: Tue, 29 Sep 2026 23:11:58 +0000 Subject: [PATCH] Agenda: colores de estado mas fuertes y boton de En curso - Badge y bloques de la cuadricula: cada estado con su color propio y fuerte (pendiente=ambar, confirmada=esmeralda, llego/en cabina=cielo, en curso=violeta, completada=gris, cancelo/no show=rosa). Antes varios compartian tonos pastel casi iguales. La leyenda del grid usa los mismos colores. - badgeForAppointmentState: llego e en_curso tenian variant de pendiente (se veian igual); ahora arrived y progress, y no_show/waitlist tienen las suyas. - Boton 'Marcar en curso' (accion start del backend) en las acciones rapidas de la vista de lista y tarjetas moviles, entre Llegada y Completar. - Mini-checklist del flujo en el tooltip de la cuadricula (solo lectura; click abre el detalle con el checklist completo interactivo). --- frontend/src/components/ui/Badge.tsx | 28 ++++++++----- frontend/src/lib/badges.ts | 8 ++++ frontend/src/pages/Agenda.tsx | 61 ++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/ui/Badge.tsx b/frontend/src/components/ui/Badge.tsx index 9277acc..35f0bfb 100644 --- a/frontend/src/components/ui/Badge.tsx +++ b/frontend/src/components/ui/Badge.tsx @@ -13,7 +13,9 @@ export type BadgeVariant = | 'warning' | 'danger' | 'success' - | 'primary'; + | 'primary' + | 'arrived' + | 'progress'; interface BadgeProps { children: ReactNode; @@ -21,19 +23,24 @@ interface BadgeProps { className?: string; } +// Colores de estado fuertes y distinguibles entre sí (petición de la agenda): +// pendiente=ámbar, confirmada=esmeralda, llegó=cielo, en curso=violeta, +// completada=gris neutro, cancelada/no-show=rosa. const variants: Record = { - confirmed: 'bg-theme-success text-theme-success-text', - pending: 'bg-theme-accent-bg text-theme-heading', - done: 'bg-theme-lilac text-theme-heading', - cancelled: 'bg-rose-100 text-rose-700', - paid: 'bg-theme-success text-theme-success-text', - unpaid: 'bg-rose-100 text-rose-700', + confirmed: 'bg-emerald-200 text-emerald-900', + pending: 'bg-amber-100 text-amber-900', + done: 'bg-slate-200 text-slate-700', + cancelled: 'bg-rose-200 text-rose-900', + paid: 'bg-emerald-200 text-emerald-900', + unpaid: 'bg-rose-200 text-rose-900', info: 'bg-theme-sky text-theme-heading', default: 'bg-theme-accent-bg text-theme-muted', primary: 'bg-theme-accent text-theme-inverse', - warning: 'bg-theme-warning text-theme-warning-text', - danger: 'bg-rose-100 text-rose-700', - success: 'bg-theme-success text-theme-success-text', + warning: 'bg-amber-200 text-amber-900', + danger: 'bg-rose-200 text-rose-900', + success: 'bg-emerald-200 text-emerald-900', + arrived: 'bg-sky-200 text-sky-900', + progress: 'bg-violet-300 text-violet-950', }; const normalizeVariant = (variant: BadgeVariant): BadgeVariant => { @@ -41,6 +48,7 @@ const normalizeVariant = (variant: BadgeVariant): BadgeVariant => { if (variant === 'pending' || variant === 'warning') return variant; if (variant === 'done' || variant === 'info') return variant; if (variant === 'cancelled' || variant === 'danger' || variant === 'unpaid') return variant; + if (variant === 'arrived' || variant === 'progress') return variant; return 'default'; }; diff --git a/frontend/src/lib/badges.ts b/frontend/src/lib/badges.ts index d02a06b..927c6f7 100644 --- a/frontend/src/lib/badges.ts +++ b/frontend/src/lib/badges.ts @@ -4,11 +4,19 @@ export const badgeForAppointmentState = (state: string): BadgeVariant => { switch (state) { case 'confirmed': return 'confirmed'; + case 'arrived': + return 'arrived'; + case 'in_progress': + return 'progress'; case 'done': case 'completed': return 'done'; case 'cancelled': return 'cancelled'; + case 'no_show': + return 'danger'; + case 'waitlist': + return 'info'; default: return 'pending'; } diff --git a/frontend/src/pages/Agenda.tsx b/frontend/src/pages/Agenda.tsx index d02d978..00bf7a9 100644 --- a/frontend/src/pages/Agenda.tsx +++ b/frontend/src/pages/Agenda.tsx @@ -1,6 +1,6 @@ import type { FC } from 'react'; import { useEffect, useState, useCallback, useRef, useMemo } from 'react'; -import { Clock, CheckCircle, XCircle, CheckCheck, UserCheck, UserX, Plus, PackageCheck, Sparkles, RotateCcw, LayoutGrid, List, Rows3, CalendarRange, CalendarClock, ChevronLeft, ChevronRight, Ban, Phone, Cake, CreditCard, Pencil, AlertTriangle, Printer, PhoneCall, Wallet, ChevronDown, CalendarOff, Users } from 'lucide-react'; +import { Clock, CheckCircle, XCircle, CheckCheck, UserCheck, UserX, Plus, PackageCheck, Sparkles, RotateCcw, LayoutGrid, List, Rows3, CalendarRange, CalendarClock, ChevronLeft, ChevronRight, Ban, Phone, Cake, CreditCard, Pencil, AlertTriangle, Printer, PhoneCall, Wallet, ChevronDown, CalendarOff, Users, Play, Check } from 'lucide-react'; import Layout from '../components/Layout'; import { usePatientDrawer } from '../components/PatientDrawer'; import AgendaPrint from '../components/AgendaPrint'; @@ -9,7 +9,7 @@ import RecargarSaldoModal from '../components/RecargarSaldoModal'; import ReciboPrint from '../components/ReciboPrint'; import BloqueosModal, { quickCloseOptions, type BloqueoQuickClose } from '../components/agenda/BloqueosModal'; import { ListaEsperaPanel, ListaEsperaModal, whatsappLink } from '../components/agenda/ListaEspera'; -import { EstadoChecklist } from '../components/agenda/EstadoChecklist'; +import { EstadoChecklist, CHECKLIST_STEPS, stepIndex } from '../components/agenda/EstadoChecklist'; import { Card, Button, @@ -625,12 +625,13 @@ const Agenda: FC = () => { // Colores por estado siguiendo la paleta de la marca (coral/mint/sky/lilac). // El color se lleva en el fondo; la barra lateral izquierda indica la categoría del servicio. const gridStateClass: Record = { - pending: 'bg-theme-accent-bg text-theme-heading', - confirmed: 'bg-brand-mint text-theme-heading', - arrived: 'bg-brand-sky text-theme-heading', - in_progress: 'bg-brand-lilac text-theme-heading', - done: 'bg-theme-bg text-theme-muted', - no_show: 'bg-rose-50 text-rose-700', + pending: 'bg-amber-100 text-amber-900', + confirmed: 'bg-emerald-200 text-emerald-900', + arrived: 'bg-sky-200 text-sky-900', + in_progress: 'bg-violet-300 text-violet-950', + done: 'bg-slate-200 text-slate-600', + no_show: 'bg-rose-200 text-rose-900', + cancelled: 'bg-rose-100 text-rose-700 line-through', }; // Barra lateral por categoría del servicio (service_category ya viene del API) @@ -667,11 +668,11 @@ const Agenda: FC = () => { }; const gridStateLegend: { state: string; label: string; dot: string }[] = [ - { state: 'pending', label: 'Pendiente', dot: 'bg-brand-coral' }, - { state: 'confirmed', label: 'Confirmada', dot: 'bg-brand-mint border border-emerald-700' }, - { state: 'arrived', label: 'Llegó', dot: 'bg-brand-sky border border-sky-700' }, - { state: 'in_progress', label: 'En curso', dot: 'bg-brand-lilac border border-violet-600' }, - { state: 'done', label: 'Completada', dot: 'bg-theme-border-strong' }, + { state: 'pending', label: 'Pendiente', dot: 'bg-amber-300' }, + { state: 'confirmed', label: 'Confirmada', dot: 'bg-emerald-400' }, + { state: 'arrived', label: 'Llegó', dot: 'bg-sky-400' }, + { state: 'in_progress', label: 'En curso', dot: 'bg-violet-500' }, + { state: 'done', label: 'Completada', dot: 'bg-slate-400' }, ]; const firstName = (full: string) => (full || '').trim().split(' ')[0] || '-'; @@ -1607,6 +1608,17 @@ const Agenda: FC = () => { )} + {apt.state === 'arrived' && ( + + )} {apt.state !== 'done' && apt.state !== 'cancelled' && (