Ship K-design admin with multi-channel support and polish.
continuous-integration/drone/push Build is passing
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:
1 parent
1890b50e0d
commit
da85370936
102 files changed
+20282
-2153
No files matched your search
@@ -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
@@ -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");
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user