fase 1 productizacion: capa de configuracion (glosario multi-giro, sucursales y categorias configurables, ajustes de clinica por instancia, colores de marca, horarios, URLs de pago dinamicas) + script de provisioning de instancia nueva con datos demo + frontend consumiendo la config

This commit is contained in:
2026-10-11 05:50:18 +00:00
parent 28118ce732
commit f92018f88e
50 changed files with 4314 additions and 210 deletions

View File

@@ -51,8 +51,9 @@ import { odooApi, type DashboardStats, type Appointment, type Service, type Char
import { usePatientDrawer } from '../components/PatientDrawer';
import { useTheme } from '../lib/theme';
import { useAuth } from '../lib/auth';
import { useGlosario } from '../lib/glosario';
import { waLink } from '../lib/whatsapp';
import { APT_STATE_LABELS } from './Agenda';
import { aptStateLabel } from './Agenda';
const formatCurrency = (value: number) =>
new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN', maximumFractionDigits: 0 }).format(value);
@@ -161,6 +162,7 @@ const TodayTile: FC<TodayTileProps> = ({ label, icon, onClick, children, classNa
const Dashboard: FC = () => {
const { theme } = useTheme();
const { user } = useAuth();
const { term } = useGlosario();
const navigate = useNavigate();
const isHomeNest = theme === 'homenest';
const [stats, setStats] = useState<DashboardStats | null>(null);
@@ -436,7 +438,7 @@ const Dashboard: FC = () => {
</div>
<div className="flex flex-wrap gap-3 shrink-0">
<Button variant="primary" size="md" onClick={() => navigate('/agenda')}>
<Calendar size={16} className="mr-2" /> Nueva cita
<Calendar size={16} className="mr-2" /> Nueva {term('appointment_singular').toLowerCase()}
</Button>
<Button variant="outline" size="md" onClick={() => navigate('/reportes')}>
<TrendingUp size={16} className="mr-2" /> Ver reportes
@@ -706,7 +708,7 @@ const Dashboard: FC = () => {
<p className="text-sm font-medium text-theme-heading truncate">{apt.patient}</p>
<p className="text-xs text-theme-muted truncate">{apt.service} • {apt.time}</p>
</div>
<Badge variant={badgeForAppointmentState(apt.state)}>{APT_STATE_LABELS[apt.state] || apt.state}</Badge>
<Badge variant={badgeForAppointmentState(apt.state)}>{aptStateLabel(apt.state, term)}</Badge>
</div>
))}
</div>