// Mockups localizados — KLEO · INGRID · BoXtore · ZUBEHÖRE // Todos los textos visibles cambian con el selector de idioma. (function () { const head = '"Poppins", system-ui, sans-serif'; const body = '"Inter", system-ui, sans-serif'; const mono = '"JetBrains Mono", ui-monospace, monospace'; const NAVY = '#0D1B2A'; const G = '#1F8A5B'; const A = '#E07B39'; // ── useLang helper ──────────────────────────────────────────── function useLang() { const [, rerender] = React.useState(0); React.useEffect(() => { const h = () => rerender(n => n + 1); window.addEventListener('langchange', h); return () => window.removeEventListener('langchange', h); }, []); } // Mock text data is loaded from mock-data.js → window.BX_MOCK / window.getMk() // ── Phone frame ─────────────────────────────────────────────── const Phone = ({ accent, children, screen = '#fff' }) => (
9:41BRITXIA
{children}
); // ── KLEO ───────────────────────────────────────────────────── function KLEO({ accent }) { useLang(); const P = accent; const { useState, useEffect } = React; const [activeTab, setActiveTab] = useState(0); const [scrollIdx, setScrollIdx] = useState(0); const mk = window.getMk().kleo; useEffect(() => { const t = setInterval(() => setActiveTab(n => (n + 1) % 4), 3600); return () => clearInterval(t); }, []); useEffect(() => { const t = setInterval(() => setScrollIdx(n => n + 1), 2200); return () => clearInterval(t); }, []); const resolveColor = (cl) => cl === 'P' ? P : cl; const visibleTasks = [0,1,2,3].map(i => mk.tasks[(scrollIdx + i) % mk.tasks.length]); return (
KLEO
{mk.date}
{mk.stat_labels.map(([v, l, c]) => (
{v}
{l}
))}
{mk.tabs.map((t, i) => (
{t}
))}
{mk.pending}
{visibleTasks.map((task, i) => (
{task.ic}
{task.t}
{task.s}
{task.tag && {task.tag}}
))}
{mk.habits_label}
{mk.habits.map(([t, v, pct]) => (
{t}{v}
))}
{mk.stats_row.map(([v, l, c]) => (
{v}
{l}
))}
); } // ── INGRID ─────────────────────────────────────────────────── function INGRID({ accent }) { useLang(); const { useState, useEffect } = React; const [visible, setVisible] = useState(2); const [typing, setTyping] = useState(false); const mk = window.getMk().ingrid; useEffect(() => { const cycle = () => { setTyping(true); setTimeout(() => { setTyping(false); setVisible(v => v < mk.messages.length ? v + 1 : 2); }, 1400); }; const t = setInterval(cycle, 3200); return () => clearInterval(t); }, [mk.messages.length]); const In = ({ children }) => (
{children}
); const Out = ({ children }) => (
{children}
); return (
I
INGRID
{mk.status}
{mk.messages.slice(0, visible).map(([isOut, text], i) => isOut ? {text} : {text} )} {typing && (
{[0,1,2].map(i => )}
)}
); } // ── BoXtore ────────────────────────────────────────────────── function BoXtore({ accent }) { useLang(); const { useState, useEffect } = React; const B = '#0F1C2B', PAN = '#162436', S = '#1E3048'; const T = '#E8EFF8', DIM = 'rgba(232,239,248,0.5)'; const GG = '#1F8A5B', AA = '#E07B39'; const [activeNav, setActiveNav] = useState(0); const [activeBar, setActiveBar] = useState(4); const mk = window.getMk().bx; // Status color map const statusColor = { 'Completado': GG, 'Concluído': GG, 'Completed': GG, 'Complété': GG, 'En camino': accent, 'On the way': accent, 'En route': accent, 'A caminho': accent, 'Pendiente': AA, 'Pending': AA, 'En attente': AA, 'Pendente': AA }; function sc(s) { return statusColor[s] || accent; } useEffect(() => { const t1 = setInterval(() => setActiveBar(b => (b + 1) % 7), 700); const t2 = setInterval(() => setActiveNav(n => (n + 1) % mk.nav.length), 3000); return () => { clearInterval(t1); clearInterval(t2); }; }, [mk.nav.length]); const bars = [38, 55, 42, 68, 85, 52, 76]; const views = { 0: () => ( <>
{mk.stats.map(([l,v,d]) => (
{l}
{v}
{d &&
{d}
}
))}
{mk.sales7}
{bars.map((h,i) =>
)}
{['L','M','X','J','V','S','D'].map(d =>
{d}
)}
{mk.recent}
{mk.orders.slice(0,3).map(([id,n,s,a]) => (
{id} {n} {s} {a}
))}
), 1: () => (
{mk.all_orders}
{mk.orders.map(([id,n,s,a,d]) => (
{id} {n} {s} {d} {a}
))}
), 2: () => (
{mk.clients_title}
{mk.clients.map(([ini,n,tel,p]) => (
{ini}
{n}
{tel}
{p}
))}
), 3: () => (
{mk.catalog.map(([n,p,s]) => (
{n}
{p}
{s}
))}
), 4: () => (
{mk.pos_ticket}
{mk.pos_items.map(([n,q,p]) => (
{n} {q} {p}
))}
{mk.pos_total} $1,500
{mk.pos_charge}
{mk.pos_cash}
{mk.pos_card}
{mk.pos_transfer}
), 5: () => (
{mk.monthly}
{mk.monthly_stats.map(([l,v]) => (
{v}
{l}
))}
{[42,58,35,70,85,62,78,55,90,72,68,80].map((h,i) => (
))}
{mk.months.map(m => (
{m}
))}
), 6: () => (
{mk.config_title}
{mk.config_fields.map(([l,v]) => (
{l} {v}
))}
), }; const ViewComponent = views[activeNav] || views[0]; return (
{['#FF5F57','#FEBC2E','#28C840'].map(c =>
)}
boxtore.britxia.tech
BoXtore
{mk.nav.map(([ic,label], i) => (
{ic} {label}
))}
{mk.nav[activeNav][1]}
{mk.date}
{mk.new_btn}
); } // ── ZUBEHÖRE ───────────────────────────────────────────────── function ZUBEHORE({ accent }) { useLang(); const { useState, useEffect } = React; const E = accent, EL = '#C7A06A', B = '#0F1A24', PAN = '#152030', S = '#1C2E3D'; const T = '#EDE8E0', DIM = 'rgba(237,232,224,0.5)'; const GG = '#1F8A5B', AA = '#E07B39'; const [activeNav, setActiveNav] = useState(0); const [progPct, setProgPct] = useState([0,0,0]); const mk = window.getMk().zu; const statusColor = { 'En proceso': GG, 'En cours': GG, 'In progress': GG, 'Em andamento': GG, 'Agendado': EL, 'Scheduled': EL, 'Planifié': EL, 'Pendiente': AA, 'Pending': AA, 'En attente': AA, 'Pendente': AA }; function sc(s) { return statusColor[s] || E; } useEffect(() => { setTimeout(() => setProgPct([72,35,15]), 400); const t = setInterval(() => setActiveNav(n => (n+1) % mk.nav.length), 3000); return () => clearInterval(t); }, [mk.nav.length]); const views = { 0: () => ( <>
{mk.stats.map(([l,v]) => (
{l}
{v}
))}
{mk.active}
{mk.projects.map(([n,tp,st],i) => (
{n} {mk.sc[st]||st}
))}
{mk.today}
{mk.schedule.slice(0,3).map(([t,l,c]) => (
{t}
{l}
))}
), 1: () => (
{mk.nav[1][1]}
{mk.projects_all.map(([n,tp,st,pct]) => (
{n}
{tp}
{mk.sc[st]||st} {pct}
))}
), 2: () => (
{mk.nav[2][1]}
{mk.quotes.map(([id,n,m,s]) => (
{id} {n} {m} {mk.quote_sc[s]||s}
))}
), 3: () => (
{mk.nav[3][1]}
{mk.clients.map(([ini,n,tel,p]) => (
{ini}
{n}
{tel}
{p}
))}
), 4: () => (
{mk.days.map((d,i) =>
{d}
)} {[16,17,18,19,20,21,22].map(d => (
{d}
))}
{mk.schedule_title}
{mk.schedule.map(([t,l,tp],i) => (
{t}
{l} {tp}
))}
), 5: () => (
{mk.finance_title}
{mk.finance_stats.map(([l,v]) => (
{v}
{l}
))}
{mk.finance_items.map(([n,m,s]) => (
{n} {m} {mk.finance_sc[s]||s}
))}
), 6: () => (
{mk.config_title}
{mk.config_fields.map(([l,v]) => (
{l} {v}
))}
), }; const ViewComponent = views[activeNav] || views[0]; return (
{['#FF5F57','#FEBC2E','#28C840'].map(c =>
)}
zubehore.britxia.tech
ZUBEHÖRE
{mk.nav.map(([ic,l],i) => (
{ic} {l}
))}
{mk.nav[activeNav][1]}
{mk.date}
{mk.new_btn}
{/* Mini phone overlay */}
ZUBEHÖRE
{mk.mini_title}
{mk.mini_proj.map(([n,s,c]) => (
{n}
{mk.sc[s]||s}
))}
); } window.Mockups = { KLEO, INGRID, BoXtore, 'ZUBEHÖRE': ZUBEHORE }; })();