Ship K-design admin with multi-channel support and polish.
continuous-integration/drone/push Build is passing

Replace placeholder admin pages with the design system, add analytics/customers/categories/inventory/settings, channel pricing and order sources, plus skeleton loaders and clean motion.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Rafał MiczekandCursor committed 2026-10-17 13:46:21 +02:00
1 parent 1890b50e0d
commit da85370936
102 files changed
+20282 -2153

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
<!-- Shared nav snippet reference (SVG icons). Active link: add class is-active -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-brand">
<span class="mark"><svg class="ico" aria-hidden="true"><use href="#i-bulb"></use></svg></span>
<span>iLED Admin</span>
</div>
<nav class="sidebar-nav" aria-label="Main">
<div class="nav-group">
<div class="nav-group-label">Ops</div>
<a class="nav-link" href="02-dashboard.html"><svg class="ico" aria-hidden="true"><use href="#i-dashboard"></use></svg> Dashboard</a>
<a class="nav-link" href="14-analytics.html"><svg class="ico" aria-hidden="true"><use href="#i-dashboard"></use></svg> Analytics</a>
<a class="nav-link" href="05-orders.html"><svg class="ico" aria-hidden="true"><use href="#i-orders"></use></svg> Orders</a>
<a class="nav-link" href="12-inventory.html"><svg class="ico" aria-hidden="true"><use href="#i-inventory"></use></svg> Inventory</a>
</div>
<div class="nav-group">
<div class="nav-group-label">Catalog</div>
<a class="nav-link" href="03-products.html"><svg class="ico" aria-hidden="true"><use href="#i-products"></use></svg> Products</a>
<a class="nav-link" href="11-categories.html"><svg class="ico" aria-hidden="true"><use href="#i-categories"></use></svg> Categories</a>
</div>
<div class="nav-group">
<div class="nav-group-label">People</div>
<a class="nav-link" href="10-customers.html"><svg class="ico" aria-hidden="true"><use href="#i-customers"></use></svg> Customers</a>
</div>
<div class="nav-group">
<div class="nav-group-label">Marketing</div>
<a class="nav-link" href="07-promotions.html"><svg class="ico" aria-hidden="true"><use href="#i-promotions"></use></svg> Promotions</a>
<a class="nav-link" href="08-newsletter.html"><svg class="ico" aria-hidden="true"><use href="#i-newsletter"></use></svg> Newsletter</a>
<a class="nav-link" href="09-reviews.html"><svg class="ico" aria-hidden="true"><use href="#i-reviews"></use></svg> Reviews</a>
</div>
<div class="nav-group">
<div class="nav-group-label">System</div>
<a class="nav-link" href="13-settings.html"><svg class="ico" aria-hidden="true"><use href="#i-settings"></use></svg> Settings</a>
</div>
</nav>
<div class="sidebar-foot">
<a class="btn btn-secondary w-full" href="01-login.html">Log out</a>
</div>
</aside>
File diff suppressed because it is too large. Load diff
+245
View File
@@ -0,0 +1,245 @@
(function () {
"use strict";
function qs(sel, root) {
return (root || document).querySelector(sel);
}
function qsa(sel, root) {
return Array.prototype.slice.call((root || document).querySelectorAll(sel));
}
/* Inject clean stroke icon sprite once */
if (!qs("#admin-icon-sprite")) {
var sprite = document.createElementNS("http://www.w3.org/2000/svg", "svg");
sprite.id = "admin-icon-sprite";
sprite.setAttribute("aria-hidden", "true");
sprite.style.cssText =
"position:absolute;width:0;height:0;overflow:hidden";
sprite.innerHTML = [
'<symbol id="i-bulb" viewBox="0 0 24 24"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 12c.6.6 1 1.5 1 2.4V18h6v-1.6c0-.9.4-1.8 1-2.4A7 7 0 0 0 12 2z"/></symbol>',
'<symbol id="i-dashboard" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></symbol>',
'<symbol id="i-orders" viewBox="0 0 24 24"><circle cx="9" cy="20" r="1"/><circle cx="17" cy="20" r="1"/><path d="M3 3h2l2.4 12.3a2 2 0 0 0 2 1.7h7.8a2 2 0 0 0 2-1.6L21 8H6"/></symbol>',
'<symbol id="i-inventory" viewBox="0 0 24 24"><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="M3.3 7 12 12l8.7-5"/><path d="M12 22V12"/></symbol>',
'<symbol id="i-products" viewBox="0 0 24 24"><path d="M16.5 9.4 7.5 4.2"/><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="M3.3 7 12 12l8.7-5"/><path d="M12 22V12"/></symbol>',
'<symbol id="i-categories" viewBox="0 0 24 24"><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h10"/></symbol>',
'<symbol id="i-customers" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>',
'<symbol id="i-promotions" viewBox="0 0 24 24"><path d="M19 5 5 19"/><circle cx="7.5" cy="7.5" r="2.5"/><circle cx="16.5" cy="16.5" r="2.5"/></symbol>',
'<symbol id="i-newsletter" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 7L2 7"/></symbol>',
'<symbol id="i-reviews" viewBox="0 0 24 24"><path d="m12 3 2.5 6.5L21 11l-5 4.2L17.5 22 12 18.5 6.5 22 8 15.2 3 11l6.5-1.5L12 3z"/></symbol>',
'<symbol id="i-settings" viewBox="0 0 24 24"><path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9c.3.6.9 1 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></symbol>',
'<symbol id="i-menu" viewBox="0 0 24 24"><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h16"/></symbol>',
'<symbol id="i-search" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></symbol>',
'<symbol id="i-pick" viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></symbol>',
'<symbol id="i-invoice" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M8 13h8"/><path d="M8 17h8"/><path d="M8 9h2"/></symbol>',
'<symbol id="i-label" viewBox="0 0 24 24"><path d="M20.6 13.1 13.1 20.6a2 2 0 0 1-2.8 0L3 13.4V4h9.4l8.2 8.2a2 2 0 0 1 0 2.9z"/><circle cx="7.5" cy="7.5" r="1.5"/></symbol>',
'<symbol id="i-team" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>',
].join("");
document.body.insertBefore(sprite, document.body.firstChild);
}
/* Mobile nav */
var menuBtn = qs("[data-menu-toggle]");
var closeBtns = qsa("[data-menu-close]");
function openNav() {
document.body.classList.add("nav-open");
}
function closeNav() {
document.body.classList.remove("nav-open");
}
if (menuBtn) {
menuBtn.addEventListener("click", openNav);
}
closeBtns.forEach(function (btn) {
btn.addEventListener("click", closeNav);
});
/* Tabs */
qsa("[data-tabs]").forEach(function (root) {
var tabs = qsa(".tab", root);
var host = root.closest("[data-tabs-host]") || root.parentElement;
var panels = qsa(".tab-panel", host);
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
var id = tab.getAttribute("data-tab");
tabs.forEach(function (t) {
t.classList.toggle("is-active", t === tab);
});
panels.forEach(function (p) {
p.classList.toggle("is-active", p.getAttribute("data-panel") === id);
});
});
});
});
/* Locale switcher */
qsa(".locale").forEach(function (group) {
qsa("button", group).forEach(function (btn) {
btn.addEventListener("click", function () {
qsa("button", group).forEach(function (b) {
b.classList.remove("is-active");
});
btn.classList.add("is-active");
});
});
});
/* Row select + bulk bar */
function updateBulkBar(scope) {
var root = scope || document;
var bars = qsa("[data-bulk-bar]", root);
bars.forEach(function (bar) {
var card = bar.closest(".card") || document;
var checked = qsa(
'tbody input[type="checkbox"]:checked',
card
).length;
bar.classList.toggle("is-visible", checked > 0);
var countEl = qs("[data-bulk-count]", bar);
if (countEl) {
countEl.textContent =
checked + (checked === 1 ? " selected" : " selected");
}
});
}
qsa("[data-select-all]").forEach(function (master) {
master.addEventListener("change", function () {
var table = master.closest("table") || master.closest(".card");
qsa('tbody input[type="checkbox"]', table).forEach(function (cb) {
cb.checked = master.checked;
var tr = cb.closest("tr");
if (tr) tr.classList.toggle("is-selected", master.checked);
});
updateBulkBar(master.closest(".card"));
});
});
qsa('table.data tbody input[type="checkbox"]').forEach(function (cb) {
cb.addEventListener("change", function () {
var tr = cb.closest("tr");
if (tr) tr.classList.toggle("is-selected", cb.checked);
updateBulkBar(cb.closest(".card"));
});
});
updateBulkBar();
/* Settings section nav */
function activateSettings(href) {
if (!href || href.charAt(0) !== "#") return;
qsa("[data-settings-nav] a").forEach(function (a) {
a.classList.toggle("is-active", a.getAttribute("href") === href);
});
qsa("[data-settings-section]").forEach(function (sec) {
sec.classList.toggle("hidden", "#" + sec.id !== href);
});
}
qsa("[data-settings-nav] a").forEach(function (link) {
link.addEventListener("click", function (e) {
var href = link.getAttribute("href");
if (!href || href.charAt(0) !== "#") return;
e.preventDefault();
activateSettings(href);
if (history.replaceState) {
history.replaceState(null, "", href);
}
});
});
if (qsa("[data-settings-nav]").length && location.hash) {
activateSettings(location.hash);
}
/* Stagger reveal on page load */
qsa(".content > *").forEach(function (el, i) {
if (el.classList.contains("reveal")) return;
el.classList.add("reveal");
if (i > 0 && i < 6) {
el.classList.add("reveal-delay-" + Math.min(i, 5));
}
});
/* Chart.js dashboard chart */
var chartCanvas = qs("#ordersChart");
if (chartCanvas && typeof Chart !== "undefined") {
new Chart(chartCanvas, {
type: "bar",
data: {
labels: [
"04", "05", "06", "07", "08", "09", "10",
"11", "12", "13", "14", "15", "16", "17",
],
datasets: [
{
label: "Orders",
data: [4, 6, 5, 8, 7, 10, 9, 5, 7, 11, 9, 13, 10, 14],
backgroundColor: "rgba(255, 188, 57, 0.85)",
hoverBackgroundColor: "rgba(240, 168, 32, 1)",
borderRadius: 6,
borderSkipped: false,
maxBarThickness: 28,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
animation: { duration: 900, easing: "easeOutQuart" },
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: "#111827",
padding: 10,
cornerRadius: 8,
displayColors: false,
},
},
scales: {
x: {
grid: { display: false },
ticks: {
color: "#9ca3af",
font: { size: 10, family: "Inter" },
},
border: { display: false },
},
y: {
beginAtZero: true,
grid: { color: "#f3f4f6" },
ticks: {
color: "#9ca3af",
font: { size: 11, family: "Inter" },
precision: 0,
},
border: { display: false },
},
},
},
});
}
/* Dashboard state demos */
if (location.search.indexOf("empty=1") !== -1) {
qsa("[data-demo-content]").forEach(function (el) {
el.classList.add("hidden");
});
qsa("[data-demo-empty]").forEach(function (el) {
el.classList.remove("hidden");
});
}
if (location.search.indexOf("loading=1") !== -1) {
qsa("[data-demo-content]").forEach(function (el) {
el.classList.add("hidden");
});
qsa("[data-demo-loading]").forEach(function (el) {
el.classList.remove("hidden");
});
}
})();