// ============================================
// SECTIONS 1 — Industries, Live Dashboard, Depreciation Slider, ROI Calculator
// ============================================
const { useState: useS1, useEffect: useE1, useRef: useR1, useMemo: useM1 } = React;
// ---------- INDUSTRIES ----------
function Industries() {
const items = [
{ id: '001', name: 'Manufactura', desc: 'Líneas de producción, OEE y maquinaria industrial', c: 'var(--lime)' },
{ id: '002', name: 'Ingeniería', desc: 'Instrumentación, calibraciones y trazabilidad metrológica', c: 'var(--violet)' },
{ id: '003', name: 'Contabilidad', desc: 'Causaciones, cuentas contables y estados financieros', c: 'var(--magenta)' },
{ id: '004', name: 'Logística', desc: 'Flota vehicular, traslados entre sedes y rutas', c: 'var(--cyan)' },
{ id: '005', name: 'Salud', desc: 'Equipo médico, calibración y hoja de vida clínica', c: 'var(--red)' },
{ id: '006', name: 'Sector Público', desc: 'Bienes del estado, depreciación fiscal y auditorías', c: 'var(--amber)' },
];
return (
INDUSTRIAS · MULTI-SECTOR
Hecho para tu sector
Una plataforma adaptada a la realidad de cada industria, con módulos específicos
para cada caso de uso. Reportes automáticos, multi-empresa, multi-sede y con
API abierta para integraciones.
{['Reportes contables automáticos', 'Multi-empresa y multi-sede', 'Integración con software contable', 'API abierta para integraciones'].map(c => (
))}
Hablar con un asesor →
{items.map(it => (
{it.id}
{it.name}
{it.desc}
))}
);
}
function IndIcon({name, color}) {
const paths = {
'Manufactura': ,
'Ingeniería': ,
'Contabilidad': ,
'Logística': ,
'Salud': ,
'Sector Público': ,
};
return (
{paths[name] || }
);
}
// ---------- LIVE DASHBOARD (sticky-build) ----------
function LiveDashboard() {
const [kpis, setKpis] = useS1({
total: 248, value: 4.23, maint: 12, alerts: 5, util: 87.3,
});
const [pulses, setPulses] = useS1([]);
const [eventFeed, setEventFeed] = useS1([
{ t: '14:22:01', m: 'ACT-2024-091 asignado a Sede Norte', c: 'cyan' },
{ t: '14:21:47', m: 'Mantenimiento preventivo completado · Compresor A-12', c: 'lime' },
{ t: '14:21:15', m: 'Alerta: garantía por vencer (7 días)', c: 'amber' },
]);
useE1(() => {
const id = setInterval(() => {
setKpis(k => ({
total: k.total + (Math.random() > 0.5 ? 1 : 0),
value: +(k.value + (Math.random() - 0.4) * 0.04).toFixed(2),
maint: Math.max(5, Math.min(20, k.maint + (Math.random() > 0.5 ? 1 : -1))),
alerts: Math.max(0, Math.min(12, k.alerts + (Math.random() > 0.7 ? 1 : -1))),
util: Math.max(75, Math.min(98, +(k.util + (Math.random() - 0.5) * 1.5).toFixed(1))),
}));
// event feed
const events = [
{ m: 'QR escaneado · Servidor R-740 · Sede Principal', c: 'cyan' },
{ m: 'Depreciación mensual calculada · $12.4M', c: 'lime' },
{ m: 'Nuevo activo registrado · Impresora HP LaserJet', c: 'cyan' },
{ m: 'Carga masiva Excel · 142 activos importados', c: 'amber' },
{ m: 'Consumible asignado · 2 resmas papel carta', c: 'violet' },
{ m: 'Mantenimiento programado · En 3 días', c: 'amber' },
{ m: 'Alerta: stock bajo · Tóner impresora', c: 'magenta' },
{ m: 'Usuario confirmó recibido · Lapiceros BIC', c: 'lime' },
];
const ev = events[Math.floor(Math.random() * events.length)];
const now = new Date();
const tstr = `${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`;
setEventFeed(f => [{ t: tstr, ...ev }, ...f].slice(0, 6));
}, 1600);
return () => clearInterval(id);
}, []);
return (
EL SISTEMA · LIVE
Todo lo que pasa en tu operación, en vivo
Dashboards que se actualizan en tiempo real, alertas inteligentes y reportes
automáticos para tomar decisiones con datos.
● LIVE
OPERATION DASHBOARD · v4.2.1
{/* KPI column */}
{[
{ l: 'ACTIVOS TOTALES', v: kpis.total, s: '+3 hoy', c: 'cyan' },
{ l: 'VALOR EN LIBROS', v: `$${kpis.value.toFixed(2)}B`, s: 'COP', c: 'lime' },
{ l: 'EN MANTENIMIENTO', v: kpis.maint, s: 'equipos', c: 'amber' },
{ l: 'ALERTAS ACTIVAS', v: kpis.alerts, s: 'req. atención', c: 'magenta' },
{ l: 'UTILIZACIÓN', v: `${kpis.util}%`, s: 'flota', c: 'violet' },
].map(k => (
))}
{/* Center - multi chart */}
DEPRECIACIÓN ACUMULADA · 12M
Lineal
Saldo Dec.
DISTRIBUCIÓN DE FLOTA
{[
{ n: 'Maquinaria', v: 34, c: 'var(--amber)' },
{ n: 'Vehículos', v: 28, c: 'var(--cyan)' },
{ n: 'Equipos TI', v: 42, c: 'var(--violet)' },
{ n: 'Edificios', v: 8, c: 'var(--lime)' },
].map(f => (
))}
{/* Right — event feed */}
EVENT STREAM
● {eventFeed.length} events
{eventFeed.map((e, i) => (
{e.t}
{e.m}
●
))}
);
}
function LiveClock() {
const [t, setT] = useS1(new Date());
useE1(() => {
const id = setInterval(() => setT(new Date()), 1000);
return () => clearInterval(id);
}, []);
const pad = n => String(n).padStart(2, '0');
return SYS TIME · {pad(t.getHours())}:{pad(t.getMinutes())}:{pad(t.getSeconds())} · BOGOTÁ ;
}
function LiveAreaChart() {
const [pts, setPts] = useS1(() => {
return Array.from({length: 36}, (_, i) => ({
a: 25 + Math.sin(i*0.35)*10 + Math.random()*6,
b: 18 + Math.cos(i*0.28)*8 + Math.random()*5,
}));
});
useE1(() => {
const id = setInterval(() => {
setPts(p => {
const n = [...p.slice(1)];
const last = p[p.length-1];
n.push({
a: Math.max(10, Math.min(55, last.a + (Math.random()-0.5)*5)),
b: Math.max(8, Math.min(45, last.b + (Math.random()-0.5)*4)),
});
return n;
});
}, 1200);
return () => clearInterval(id);
}, []);
const W = 520, H = 160;
const sx = W / (pts.length-1);
const pathA = pts.map((p,i) => `${i===0?'M':'L'} ${i*sx} ${H-p.a*2.4}`).join(' ');
const pathB = pts.map((p,i) => `${i===0?'M':'L'} ${i*sx} ${H-p.b*2.4}`).join(' ');
const fillA = `${pathA} L ${W} ${H} L 0 ${H} Z`;
return (
{[0,1,2,3].map(i => )}
{pts.map((p,i) => i===pts.length-1 && (
))}
);
}
function DonutChart() {
const data = [
{ n: 'Activos', v: 166, c: 'var(--cyan)' },
{ n: 'Mantenim.', v: 57, c: 'var(--amber)' },
{ n: 'Baja temp.', v: 19, c: 'var(--violet)' },
{ n: 'Dado de baja', v: 6, c: 'var(--red)' },
];
const total = data.reduce((s,d) => s+d.v, 0);
let offset = 0;
const C = 2 * Math.PI * 34;
return (
{data.map(d => {
const len = (d.v/total) * C;
const el = ;
offset += len;
return el;
})}
{total}
TOTAL
{data.map(d => (
{d.n} {d.v}
))}
);
}
function SiteMap() {
const sites = [
{ x: 35, y: 55, n: 'Bogotá', val: 86, active: true },
{ x: 28, y: 40, n: 'Medellín', val: 52 },
{ x: 22, y: 72, n: 'Cali', val: 38 },
{ x: 40, y: 30, n: 'Bucaramanga', val: 28 },
{ x: 20, y: 18, n: 'Barranquilla', val: 44 },
];
return (
{/* Rough Colombia silhouette */}
{sites.map(s => (
{s.n} · {s.val}
))}
);
}
// ---------- DEPRECIATION SLIDER ----------
function DepreciationLab() {
const [years, setYears] = useS1(6);
const [method, setMethod] = useS1('linea');
const [cost, setCost] = useS1(500);
const useful = 10;
const salvage = 50;
const series = useM1(() => {
const pts = [];
for (let y = 0; y <= useful; y++) {
let val;
if (method === 'linea') {
val = cost - ((cost - salvage) / useful) * y;
} else if (method === 'saldo') {
const rate = 0.2;
val = cost * Math.pow(1 - rate, y);
} else {
// sum of digits
const n = useful;
const sum = n * (n+1) / 2;
let acc = cost;
for (let i = 1; i <= y; i++) {
acc -= ((cost - salvage) * (n - i + 1)) / sum;
}
val = acc;
}
pts.push(Math.max(salvage, val));
}
return pts;
}, [method, cost]);
const current = series[years] || salvage;
const accumulated = cost - current;
const pct = ((cost - current) / (cost - salvage)) * 100;
return (
LAB · DEPRECIACIÓN
Calcula cualquier método en segundos
Arrastra el slider y mira cómo cambia el valor en libros. El sistema hace esto
automáticamente para miles de activos y por cualquier método.
VALOR EN LIBROS
${current.toFixed(0)}M
DEPRECIACIÓN ACUM.
${accumulated.toFixed(0)}M
% VIDA ÚTIL
{pct.toFixed(0)}%
);
}
function DepChart({ series, currentYear }) {
const W = 600, H = 240, pad = 30;
const maxV = Math.max(...series);
const minV = Math.min(...series);
const sx = (W - pad*2) / (series.length-1);
const sy = v => H - pad - ((v - minV) / (maxV - minV || 1)) * (H - pad*2);
const path = series.map((v, i) => `${i===0?'M':'L'} ${pad + i*sx} ${sy(v)}`).join(' ');
const fill = `${path} L ${pad + (series.length-1)*sx} ${H-pad} L ${pad} ${H-pad} Z`;
return (
{/* Grid */}
{[0,1,2,3,4].map(i => (
))}
{series.map((_, i) => (
))}
{/* Current year indicator */}
{series.map((v, i) => i % 2 === 0 && (
Año {i}
))}
);
}
// ---------- ROI CALCULATOR ----------
function ROICalc() {
const [assets, setAssets] = useS1(300);
const [hoursPerMonth, setHoursPerMonth] = useS1(40);
const [hourlyRate, setHourlyRate] = useS1(35000);
const monthlySaving = hoursPerMonth * hourlyRate * 0.7; // 70% time saved
const annualSaving = monthlySaving * 12;
const assetLosses = assets * 12000 * 0.68; // 68% reduction in lost assets ($12K avg)
const totalAnnual = annualSaving + assetLosses;
const roi = Math.round(totalAnnual / 1000);
const fmt = n => new Intl.NumberFormat('es-CO').format(Math.round(n));
return (
CALCULADORA · ROI
¿Cuánto ahorrás al mes?
Ajustá los valores y calculá tu retorno real. Basado en datos de clientes:
reducción del 68% en activos perdidos y 70% menos tiempo en gestión manual.
AHORRO ANUAL ESTIMADO
$
COP · ESTIMACIÓN
TIEMPO AHORRADO (ANUAL)
${fmt(annualSaving)}
REDUCCIÓN PÉRDIDAS (ANUAL)
${fmt(assetLosses)}
ROI ESTIMADO
×{Math.round(totalAnnual / (assets * 24000))}
Agendar demo personalizada
);
}
function ROIField({label, value, onChange, min, max, step, display}) {
return (
);
}
function CountUp({ value }) {
const [displayed, setDisplayed] = useS1(value);
const prev = useR1(value);
useE1(() => {
const start = prev.current;
const diff = value - start;
const dur = 800;
const t0 = performance.now();
let raf;
const tick = (t) => {
const p = Math.min(1, (t - t0) / dur);
const eased = 1 - Math.pow(1-p, 3);
setDisplayed(Math.round(start + diff * eased));
if (p < 1) raf = requestAnimationFrame(tick);
else prev.current = value;
};
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [value]);
return {new Intl.NumberFormat('es-CO').format(displayed)} ;
}
window.Industries = Industries;
window.LiveDashboard = LiveDashboard;
window.DepreciationLab = DepreciationLab;
window.ROICalc = ROICalc;