/* ============================================================= KASDAP ONE — UI KIT (icons, money, image, toast, modal) ============================================================= */ const { useState: useStateUI } = React; /* ---------- icon set (24x24, stroke = currentColor) ---------- */ const ICONS = { search: 'M11 4a7 7 0 105.2 11.7L21 20M11 4a7 7 0 015.2 11.7A7 7 0 0111 4z', cart: 'M3 4h2l2.4 12.2a1 1 0 001 .8h9.2a1 1 0 001-.8L21 8H6M9 21a1 1 0 100-2 1 1 0 000 2zm9 0a1 1 0 100-2 1 1 0 000 2z', plus: 'M12 5v14M5 12h14', minus: 'M5 12h14', trash: 'M4 7h16M9 7V5a1 1 0 011-1h4a1 1 0 011 1v2M6 7l1 13a1 1 0 001 1h8a1 1 0 001-1l1-13', check: 'M5 12l5 5L20 6', x: 'M6 6l12 12M18 6L6 18', bell: 'M6 9a6 6 0 1112 0c0 5 2 6 2 6H4s2-1 2-6M10 21a2 2 0 004 0', sun: 'M12 3v2M12 19v2M5 5l1.5 1.5M17.5 17.5L19 19M3 12h2M19 12h2M5 19l1.5-1.5M17.5 6.5L19 5M12 8a4 4 0 100 8 4 4 0 000-8z', moon: 'M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z', user: 'M12 12a4 4 0 100-8 4 4 0 000 8zM4 21a8 8 0 0116 0', box: 'M3 8l9-5 9 5v8l-9 5-9-5V8zM3 8l9 5 9-5M12 13v8', layers: 'M12 3l9 5-9 5-9-5 9-5zM3 13l9 5 9-5M3 17l9 5 9-5', chart: 'M4 20V10M10 20V4M16 20v-7M22 20H2', settings: 'M12 9a3 3 0 100 6 3 3 0 000-6zM19 12a7 7 0 00-.1-1.3l2-1.6-2-3.4-2.4 1a7 7 0 00-2.2-1.3L14 1h-4l-.3 2.4a7 7 0 00-2.2 1.3l-2.4-1-2 3.4 2 1.6A7 7 0 005 12c0 .4 0 .9.1 1.3l-2 1.6 2 3.4 2.4-1a7 7 0 002.2 1.3L10 23h4l.3-2.4a7 7 0 002.2-1.3l2.4 1 2-3.4-2-1.6c.1-.4.1-.9.1-1.3z', truck: 'M3 6h11v9H3zM14 9h4l3 3v3h-7M7 19a2 2 0 100-4 2 2 0 000 4zm11 0a2 2 0 100-4 2 2 0 000 4z', clock: 'M12 7v5l3 2M12 3a9 9 0 100 18 9 9 0 000-18z', shield: 'M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z', shieldCheck: 'M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3zM8.5 12l2.5 2.5L15.5 10', heart: 'M12 20s-7-4.3-9.2-8.5C1.3 8.6 2.8 5.5 6 5.5c2 0 3.2 1.2 4 2.3.8-1.1 2-2.3 4-2.3 3.2 0 4.7 3.1 3.2 6C19 15.7 12 20 12 20z', brain: 'M9 4a3 3 0 00-3 3 3 3 0 00-1 5.8A3 3 0 009 18a2 2 0 003-1.7M9 4a2 2 0 013 1.8M9 4v14M15 4a3 3 0 013 3 3 3 0 011 5.8A3 3 0 0115 18a2 2 0 01-3-1.7M15 4a2 2 0 00-3 1.8M15 4v14', droplet: 'M12 3s6 5.5 6 10a6 6 0 01-12 0c0-4.5 6-10 6-10z', bone: 'M7 7a2.2 2.2 0 10-2 3l4 4 3-3-4-4a2.2 2.2 0 00-1-0zM17 17a2.2 2.2 0 102-3l-4-4-3 3 4 4a2.2 2.2 0 001 0z', lungs: 'M12 4v8M9 12c0-2-3-2-4 1s-1 6 0 7 3 0 4-2v-6zM15 12c0-2 3-2 4 1s1 6 0 7-3 0-4-2v-6z', stomach: 'M9 4v5a4 4 0 004 4h2a3 3 0 013 3v1a3 3 0 01-3 3h-1a5 5 0 01-5-5V8a4 4 0 00-4-1', spark: 'M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8L12 3z', venus: 'M12 4a4.5 4.5 0 100 9 4.5 4.5 0 000-9zM12 13v7M9 17h6', filter: 'M3 5h18l-7 8v6l-4-2v-4L3 5z', sort: 'M7 4v16M7 20l-3-3M7 4l3 3M17 20V4M17 4l-3 3M17 20l3-3', upload: 'M12 16V4M8 8l4-4 4 4M4 20h16', download: 'M12 4v12M8 12l4 4 4-4M4 20h16', arrow: 'M5 12h14M13 6l6 6-6 6', back: 'M19 12H5M11 18l-6-6 6-6', chevron: 'M9 6l6 6-6 6', chevronD: 'M6 9l6 6 6-6', store: 'M4 9l1-5h14l1 5M4 9v10a1 1 0 001 1h14a1 1 0 001-1V9M4 9h16M9 20v-6h6v6', building: 'M4 21V5a1 1 0 011-1h7a1 1 0 011 1v16M13 21V9h6a1 1 0 011 1v11M7 8h3M7 12h3M7 16h3M16 13h1M16 17h1M2 21h20', grid: 'M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z', list: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01', tag: 'M3 11l8-8 9 1 1 9-8 8-10-10zM15 8h.01', star: 'M12 3l2.6 6.3L21 10l-5 4.3L17.5 21 12 17.3 6.5 21 8 14.3 3 10l6.4-.7L12 3z', lock: 'M6 11V8a6 6 0 1112 0v3M5 11h14a1 1 0 011 1v8a1 1 0 01-1 1H5a1 1 0 01-1-1v-8a1 1 0 011-1z', mail: 'M3 6h18v12H3zM3 7l9 6 9-6', logout: 'M14 7V5a1 1 0 00-1-1H5a1 1 0 00-1 1v14a1 1 0 001 1h8a1 1 0 001-1v-2M9 12h12M18 9l3 3-3 3', menu: 'M4 6h16M4 12h16M4 18h16', sparkles: 'M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 14l.7 2.3L22 17l-2.3.7L19 20l-.7-2.3L16 17l2.3-.7L19 14z', pill: 'M10.5 13.5l3-3M8 16a4 4 0 010-5.7l2.3-2.3a4 4 0 015.7 5.7l-2.3 2.3A4 4 0 018 16z', flask: 'M9 3h6M10 3v6l-5 9a2 2 0 002 3h10a2 2 0 002-3l-5-9V3M7 15h10', receipt: 'M5 3v18l2-1 2 1 2-1 2 1 2-1 2 1V3l-2 1-2-1-2 1-2-1-2 1-2-1zM8 8h8M8 12h8M8 16h5', users: 'M9 11a3.5 3.5 0 100-7 3.5 3.5 0 000 7zM2 20a7 7 0 0114 0M17 11a3 3 0 100-6M16 20h6a5 5 0 00-3-4.6', map: 'M9 4L3 6v14l6-2 6 2 6-2V4l-6 2-6-2zM9 4v14M15 6v14', bolt: 'M13 3L4 14h7l-1 7 9-11h-7l1-7z', globe: 'M12 3a9 9 0 100 18 9 9 0 000-18zM3 12h18M12 3c2.5 2.5 2.5 15 0 18M12 3C9.5 5.5 9.5 18.5 12 21', copy: 'M9 9h11v11H9zM5 15H4V4h11v1', edit: 'M4 20h4L18 10l-4-4L4 16v4zM14 6l4 4', eye: 'M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7zM12 15a3 3 0 100-6 3 3 0 000 6z', plusBox: 'M4 4h16v16H4zM12 8v8M8 12h8', whatsapp: 'M12 3a9 9 0 00-7.7 13.6L3 21l4.5-1.2A9 9 0 1012 3zM8.5 8.5c.2-.5.4-.5.7-.5h.5c.2 0 .4 0 .6.5l.7 1.6c.1.2 0 .4-.1.6l-.5.6c-.1.1-.2.3-.1.5.3.6 1.4 1.9 2.6 2.3.2.1.4 0 .5-.1l.6-.7c.2-.2.4-.2.6-.1l1.5.8c.3.1.4.3.4.5 0 .6-.4 1.4-1.2 1.6-1.5.4-3.6-.9-4.9-2.1-1-1-1.9-2.4-2-3.8 0-.8.3-1.4.6-1.6z', }; function Icon({ name, size = 18, fill = false, style, className = '' }) { const d = ICONS[name] || ICONS.spark; return React.createElement('svg', { width: size, height: size, viewBox: '0 0 24 24', fill: fill ? 'currentColor' : 'none', stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round', strokeLinejoin: 'round', style, className, 'aria-hidden': true, }, React.createElement('path', { d })); } /* ---------- money ---------- */ const fmt = (n) => '₹' + Number(n || 0).toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 2 }); const fmt2 = (n) => '₹' + Number(n || 0).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); function Money({ value, cents, className = '', style }) { return React.createElement('span', { className: 'mono ' + className, style }, (cents ? fmt2 : fmt)(value)); } /* ---------- product image with fallback ---------- */ const CAT_HUE = { 'Cardio-Diabetic': 0, 'CNS & Neuro': 262, 'Renal & Urology': 200, 'Pain, Ortho & Rheumatology': 28, 'Respiratory & Allergy': 175, 'Gastro & Nutritional': 48, 'Specialty & Advanced': 300, 'Anti-Infective': 145, "Women's & Hormonal": 330 }; function ProductImage({ p, style, className = '', radius }) { const [err, setErr] = useStateUI(false); const hue = CAT_HUE[p.category] != null ? CAT_HUE[p.category] : 220; const init = (p.name || '?').replace(/[^A-Za-z0-9 ]/g,'').split(' ').slice(0,2).map(w=>w[0]).join('').toUpperCase(); return React.createElement('div', { className: 'pimg ' + className, style: { borderRadius: radius != null ? radius : 12, background: err ? `linear-gradient(150deg, hsl(${hue} 55% 22% / .5), hsl(${hue} 55% 12% / .35))` : 'var(--surface-2)', ...style }, }, !err && p.image ? React.createElement('img', { src: p.image, alt: p.name, loading: 'lazy', onError: () => setErr(true) }) : React.createElement('div', { className: 'ph' }, React.createElement(Icon, { name: p.icon || 'pill', size: 22, style: { color: `hsl(${hue} 60% 60%)`, marginBottom: 4 } }), React.createElement('span', { style: { fontSize: '.72rem', letterSpacing: '.04em', color: `hsl(${hue} 40% 72%)` } }, init) ) ); } /* ---------- stars ---------- */ function Stars({ value, size = 12 }) { const v = parseFloat(value); return React.createElement('span', { style: { display: 'inline-flex', gap: 1, color: 'var(--amber)' } }, [0,1,2,3,4].map(i => React.createElement(Icon, { key: i, name: 'star', size, fill: i < Math.round(v), style: { opacity: i < Math.round(v) ? 1 : .28 } })) ); } /* ---------- toasts renderer ---------- */ function Toasts() { const { toasts } = useStore(); const ic = { ok: 'check', info: 'bolt', warn: 'bell', err: 'x' }; return React.createElement('div', { className: 'toast-stack' }, toasts.map(t => React.createElement('div', { key: t.id, className: 'toast ' + t.kind }, React.createElement('span', { className: 'ti' }, React.createElement(Icon, { name: ic[t.kind] || 'bolt', size: 15 })), React.createElement('span', null, t.msg) )) ); } /* ---------- modal ---------- */ function Modal({ title, children, onClose, foot, wide }) { return React.createElement('div', { className: 'modal-overlay', onClick: onClose }, React.createElement('div', { className: 'modal', style: wide ? { maxWidth: 720 } : null, onClick: e => e.stopPropagation() }, React.createElement('div', { className: 'modal-h' }, React.createElement('h3', null, title), React.createElement('button', { className: 'iconbtn sm', onClick: onClose }, React.createElement(Icon, { name: 'x', size: 15 })) ), React.createElement('div', { className: 'modal-body' }, children), foot && React.createElement('div', { className: 'modal-foot' }, foot) ) ); } Object.assign(window, { Icon, Money, fmt, fmt2, ProductImage, Stars, Toasts, Modal }); /* resolve cross-app links for BOTH standalone files and the server package */ window.pageHref = function (which) { const f = (location.pathname.split('/').pop() || '').toLowerCase(); const nice = f === '' || f === 'index.html' || f === 'admin.html'; if (which === 'admin') return nice ? 'admin.html' : 'Kasdap Admin.html'; return nice ? 'index.html' : 'Kasdap ONE.html'; };