Add pending apps and frontend components
- apps/captain-mobile: Mobile API service - apps/flow-ui: Flow UI application - apps/mindlink: Mindlink application - apps/storage: Storage API and workers - apps/tzzr-cli: TZZR CLI tool - deck-frontend/backups: Historical TypeScript versions - hst-frontend: Standalone HST frontend Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
68
hst-frontend/js/ui.js
Normal file
68
hst-frontend/js/ui.js
Normal file
@@ -0,0 +1,68 @@
|
||||
// === UI RENDER FUNCTIONS ===
|
||||
|
||||
function renderGroups() {
|
||||
const el = document.getElementById("groups-bar");
|
||||
|
||||
// Count tags per group
|
||||
const gm = new Map();
|
||||
state.tags.forEach(t => {
|
||||
if (t.set_hst) {
|
||||
if (!gm.has(t.set_hst)) gm.set(t.set_hst, 0);
|
||||
gm.set(t.set_hst, gm.get(t.set_hst) + 1);
|
||||
}
|
||||
});
|
||||
|
||||
const groups = [...gm.entries()].sort((a,b) => b[1] - a[1]);
|
||||
|
||||
el.innerHTML = `<button class="group-btn ${state.group === "all" ? "active" : ""}" data-group="all">Todos (${state.tags.length})</button>` +
|
||||
groups.slice(0, 20).map(([mrf, cnt]) => {
|
||||
const info = state.groups.find(g => g.mrf === mrf);
|
||||
const name = info ? (info.name_es || info.ref) : mrf.slice(0, 6);
|
||||
return `<button class="group-btn ${state.group === mrf ? "active" : ""}" data-group="${mrf}">${name} (${cnt})</button>`;
|
||||
}).join("");
|
||||
|
||||
el.querySelectorAll(".group-btn").forEach(b => {
|
||||
b.onclick = () => {
|
||||
state.group = b.dataset.group;
|
||||
renderGroups();
|
||||
renderView();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function renderLibraries() {
|
||||
const el = document.getElementById("left-panel");
|
||||
|
||||
el.innerHTML = `<div class="lib-icon ${state.library === "all" ? "active" : ""}" data-lib="all"><span>ALL</span></div>` +
|
||||
state.libraries.map(lib => {
|
||||
const icon = lib.img_thumb_url || lib.icon_url || "";
|
||||
const name = lib.name || lib.name_es || lib.ref || lib.mrf.slice(0, 6);
|
||||
return `<div class="lib-icon ${state.library === lib.mrf ? "active" : ""}" data-lib="${lib.mrf}" title="${name}">
|
||||
${icon ? `<img src="${icon}" alt="">` : ""}
|
||||
<span>${name.slice(0, 8)}</span>
|
||||
</div>`;
|
||||
}).join("");
|
||||
|
||||
el.querySelectorAll(".lib-icon").forEach(i => {
|
||||
i.onclick = async () => {
|
||||
state.library = i.dataset.lib;
|
||||
state.libraryMembers = state.library !== "all"
|
||||
? new Set(await fetchLibraryMembers(state.library))
|
||||
: new Set();
|
||||
renderLibraries();
|
||||
renderView();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function renderView() {
|
||||
// Toggle view visibility
|
||||
document.getElementById("grid-view").style.display = state.view === "grid" ? "flex" : "none";
|
||||
document.getElementById("tree-view").style.display = state.view === "tree" ? "block" : "none";
|
||||
document.getElementById("graph-view").style.display = state.view === "graph" ? "block" : "none";
|
||||
|
||||
// Render active view
|
||||
if (state.view === "grid") renderGrid();
|
||||
else if (state.view === "tree") renderTree();
|
||||
else if (state.view === "graph") initGraph();
|
||||
}
|
||||
Reference in New Issue
Block a user