@nano133/nanoterra 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +51 -7
- package/ai/SPEC.md +2 -1
- package/dist/admin/panel/dom.d.ts +11 -0
- package/dist/admin/panel/dom.js +33 -0
- package/dist/admin/panel/gameCard.d.ts +5 -2
- package/dist/admin/panel/gameCard.js +8 -4
- package/dist/admin/panel/icons.d.ts +121 -0
- package/dist/admin/panel/icons.js +41 -0
- package/dist/admin/panel/index.d.ts +11 -2
- package/dist/admin/panel/index.js +6 -1
- package/dist/admin/panel/mount.js +101 -67
- package/dist/admin/panel/orders.d.ts +23 -0
- package/dist/admin/panel/orders.js +130 -0
- package/dist/admin/panel/overview.d.ts +22 -0
- package/dist/admin/panel/overview.js +75 -0
- package/dist/admin/panel/players.d.ts +7 -0
- package/dist/admin/panel/players.js +61 -0
- package/dist/admin/panel/shelf.d.ts +15 -3
- package/dist/admin/panel/shelf.js +385 -84
- package/dist/admin/panel/shelfData.js +1 -1
- package/dist/admin/panel/tabs.d.ts +23 -0
- package/dist/admin/panel/tabs.js +68 -0
- package/dist/looks/change.d.ts +5 -5
- package/dist/looks/change.js +12 -7
- package/dist/looks/index.d.ts +2 -2
- package/dist/looks/index.js +1 -1
- package/dist/looks/json.d.ts +3 -2
- package/dist/looks/json.js +16 -9
- package/dist/looks/look.d.ts +26 -6
- package/dist/looks/look.js +37 -12
- package/package.json +1 -1
- package/src/admin/panel/dom.ts +34 -0
- package/src/admin/panel/gameCard.ts +8 -4
- package/src/admin/panel/icons.ts +46 -0
- package/src/admin/panel/index.ts +11 -2
- package/src/admin/panel/mount.ts +120 -101
- package/src/admin/panel/orders.ts +172 -0
- package/src/admin/panel/overview.ts +134 -0
- package/src/admin/panel/players.ts +79 -0
- package/src/admin/panel/shelf.ts +549 -121
- package/src/admin/panel/shelfData.ts +1 -1
- package/src/admin/panel/style.css +1775 -270
- package/src/admin/panel/tabs.ts +94 -0
- package/src/looks/change.ts +12 -9
- package/src/looks/index.ts +2 -2
- package/src/looks/json.ts +12 -7
- package/src/looks/look.ts +47 -9
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// The Players tab of /admin: each player who owns a look that a paid order gave them, with the looks as chips, and a search (an address or a look). It shows
|
|
2
|
+
// only what the summary gives: the player's address and their looks.
|
|
3
|
+
|
|
4
|
+
import type { AdminPlayer, AdminSummary } from "../store.js";
|
|
5
|
+
import { copyKey, h, plural, shortAddress } from "./dom.js";
|
|
6
|
+
import { icon } from "./icons.js";
|
|
7
|
+
|
|
8
|
+
/** Whether a player matches a search: their address or the name or id of a look they own. Pure. */
|
|
9
|
+
export function playerMatches(p: AdminPlayer, query: string): boolean {
|
|
10
|
+
const q = query.trim().toLowerCase();
|
|
11
|
+
if (!q) return true;
|
|
12
|
+
return p.player.toLowerCase().includes(q) || p.looks.some((l) => l.name.toLowerCase().includes(q) || l.id.toLowerCase().includes(q));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A colour for a player's round mark, from their address: the same address always has the same colour. */
|
|
16
|
+
function hueOf(address: string): number {
|
|
17
|
+
let n = 0;
|
|
18
|
+
for (const ch of address.slice(5)) n = (n * 31 + ch.charCodeAt(0)) % 360;
|
|
19
|
+
return n;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function playersView(colourOf: (lookId: string) => string | null): { el: HTMLElement; update(s: AdminSummary): void } {
|
|
23
|
+
let s: AdminSummary | null = null;
|
|
24
|
+
let query = "";
|
|
25
|
+
const search = h("input", { class: "input search-input", type: "search", placeholder: "Address or look", "aria-label": "Search the players", autocomplete: "off", spellcheck: false });
|
|
26
|
+
search.addEventListener("input", () => {
|
|
27
|
+
query = search.value;
|
|
28
|
+
draw();
|
|
29
|
+
});
|
|
30
|
+
const sub = h("p", { class: "fine card-sub" });
|
|
31
|
+
const list = h("div", { class: "players" });
|
|
32
|
+
const tools = h("div", { class: "toolbar" }, h("label", { class: "search" }, icon("search", 18), search));
|
|
33
|
+
const el = h("section", { class: "admin-card players-card" }, h("div", { class: "card-head" }, h("div", { class: "card-title" }, h("h2", {}, "Players who own a look"), sub)), tools, list);
|
|
34
|
+
|
|
35
|
+
function draw() {
|
|
36
|
+
if (!s) return;
|
|
37
|
+
const owned = s.players.reduce((n, p) => n + p.looks.length, 0);
|
|
38
|
+
sub.textContent = s.players.length ? `${plural(s.players.length, "player")} own ${plural(owned, "look")} that a paid order gave them.` : "A player shows here when a paid order gives them a look.";
|
|
39
|
+
tools.hidden = s.players.length < 2;
|
|
40
|
+
const rows = s.players.filter((p) => playerMatches(p, query));
|
|
41
|
+
list.replaceChildren(
|
|
42
|
+
...rows.map((p) => {
|
|
43
|
+
const mark = h("span", { class: "player-mark", "aria-hidden": "true" });
|
|
44
|
+
mark.style.setProperty("--hue", String(hueOf(p.player)));
|
|
45
|
+
return h(
|
|
46
|
+
"article",
|
|
47
|
+
{ class: "player" },
|
|
48
|
+
mark,
|
|
49
|
+
h(
|
|
50
|
+
"div",
|
|
51
|
+
{ class: "player-main" },
|
|
52
|
+
h("div", { class: "player-id" }, h("code", { title: p.player }, shortAddress(p.player)), copyKey(p.player, "Copy the player's address", icon("copy", 14))),
|
|
53
|
+
h(
|
|
54
|
+
"ul",
|
|
55
|
+
{ class: "look-chips", "aria-label": "Looks they own" },
|
|
56
|
+
...p.looks.map((l) => {
|
|
57
|
+
const dot = h("span", { class: "look-dot", "aria-hidden": "true" });
|
|
58
|
+
const c = colourOf(l.id);
|
|
59
|
+
if (c) dot.style.setProperty("--swatch", c);
|
|
60
|
+
return h("li", { class: "look-chip" }, dot, l.name);
|
|
61
|
+
}),
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
h("span", { class: "player-count" }, plural(p.looks.length, "look")),
|
|
65
|
+
);
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
if (!s.players.length) list.append(h("p", { class: "empty" }, "Nobody owns a paid look yet."));
|
|
69
|
+
else if (!rows.length) list.append(h("p", { class: "empty" }, "No player matches your search."));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
el,
|
|
74
|
+
update(next) {
|
|
75
|
+
s = next;
|
|
76
|
+
draw();
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|