init
This commit is contained in:
100
people/desktop/DesktopPeopleToolbar.js
Normal file
100
people/desktop/DesktopPeopleToolbar.js
Normal file
@@ -0,0 +1,100 @@
|
||||
class DesktopPeopleToolbar extends Shadow {
|
||||
constructor(people, searchText, filterRole, filterTier, onSearch, onFilterRole, onFilterTier) {
|
||||
super()
|
||||
this.people = people
|
||||
this.searchText = searchText
|
||||
this.filterRole = filterRole
|
||||
this.filterTier = filterTier
|
||||
this.onSearch = onSearch
|
||||
this.onFilterRole = onFilterRole
|
||||
this.onFilterTier = onFilterTier
|
||||
}
|
||||
|
||||
get allRoles() {
|
||||
const roles = new Set();
|
||||
this.people.forEach(p => (p.roles || []).forEach(r => roles.add(r)));
|
||||
return [...roles].sort();
|
||||
}
|
||||
|
||||
render() {
|
||||
const online = this.people.filter(p => p._online).length;
|
||||
const total = this.people.length;
|
||||
|
||||
HStack(() => {
|
||||
// Counts
|
||||
HStack(() => {
|
||||
p(`${total} member${total !== 1 ? "s" : ""}`)
|
||||
.margin(0)
|
||||
.fontSize(0.88, em)
|
||||
.fontWeight("600")
|
||||
.color("var(--headertext)")
|
||||
|
||||
if (online > 0) {
|
||||
HStack(() => {
|
||||
VStack(() => {})
|
||||
.width(0.42, em).height(0.42, em).borderRadius(50, pct)
|
||||
.background("#22c55e").flexShrink(0)
|
||||
p(`${online} online`)
|
||||
.margin(0).fontSize(0.78, em).color("#22c55e").fontWeight("500")
|
||||
})
|
||||
.gap(0.3, em).alignItems("center")
|
||||
.paddingHorizontal(0.6, em).paddingVertical(0.18, em)
|
||||
.background("rgba(34,197,94,0.08)")
|
||||
.border("1px solid rgba(34,197,94,0.2)")
|
||||
.borderRadius(100, px)
|
||||
}
|
||||
})
|
||||
.marginTop(20, px)
|
||||
.gap(0.75, em).alignItems("center").flex(1)
|
||||
|
||||
// Search
|
||||
HStack(() => {
|
||||
p("🔍")
|
||||
.margin(0).fontSize(0.8, em).opacity(0.38).flexShrink(0)
|
||||
input("", "200px")
|
||||
.attr({ type: "text", placeholder: "Search members…", value: this.searchText })
|
||||
.border("none").outline("none").background("transparent")
|
||||
.color("var(--headertext)").fontSize(0.85, em)
|
||||
.onInput((e) => this.onSearch(e.target.value))
|
||||
})
|
||||
.gap(0.5, em).paddingHorizontal(0.8, em)
|
||||
.background("var(--darkaccent)").border("1px solid var(--divider)")
|
||||
.borderRadius(0.5, em).alignItems("center")
|
||||
|
||||
// Role filter
|
||||
this.filterSelect(
|
||||
[{ label: "All Roles", value: "" }, ...this.allRoles.map(r => ({ label: this.capitalize(r), value: r }))],
|
||||
this.filterRole, this.onFilterRole
|
||||
)
|
||||
|
||||
// Tier filter
|
||||
this.filterSelect(
|
||||
[{ label: "All Tiers", value: "" }, { label: "Regular", value: "1" }, { label: "Patron", value: "2" }],
|
||||
this.filterTier, this.onFilterTier
|
||||
)
|
||||
})
|
||||
.gap(0.65, em).paddingHorizontal(1.5, em).paddingVertical(0.85, em)
|
||||
.borderBottom("1px solid var(--divider)")
|
||||
.alignItems("center").width(100, pct).boxSizing("border-box").flexShrink(0)
|
||||
}
|
||||
|
||||
filterSelect(options, value, onChange) {
|
||||
select(() => {
|
||||
options.forEach(opt => {
|
||||
option(opt.label)
|
||||
.attr({ value: opt.value, ...(opt.value === value ? { selected: "" } : {}) })
|
||||
})
|
||||
})
|
||||
.paddingVertical(0.52, em).paddingHorizontal(0.75, em)
|
||||
.background("var(--darkaccent)").border("1px solid var(--divider)")
|
||||
.borderRadius(0.5, em).color("var(--headertext)").fontSize(0.85, em)
|
||||
.outline("none").cursor("pointer").flexShrink(0)
|
||||
.onChange((e) => onChange(e.target.value))
|
||||
}
|
||||
|
||||
capitalize(s) {
|
||||
return s ? s[0].toUpperCase() + s.slice(1) : s;
|
||||
}
|
||||
}
|
||||
|
||||
register(DesktopPeopleToolbar)
|
||||
Reference in New Issue
Block a user