init
This commit is contained in:
165
people/people.js
Normal file
165
people/people.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import server from "/people/@server/index.js"
|
||||
import "./PeopleList.js"
|
||||
|
||||
class People extends Shadow {
|
||||
searchText = ""
|
||||
filterOnline = false
|
||||
listEl = null
|
||||
|
||||
get people() { return this._people }
|
||||
set people(val) {
|
||||
this._people = val
|
||||
global.currentNetwork.data.members = val
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this._people = (global.currentNetwork.data.members || []).map(p => ({ ...p, _online: this.isOnline(p) }))
|
||||
}
|
||||
|
||||
isOnline(member) {
|
||||
return global.socket.connectedUsers.includes(member.email)
|
||||
}
|
||||
|
||||
get filtered() {
|
||||
let list = this.people
|
||||
if (this.filterOnline) list = list.filter(p => p._online)
|
||||
if (this.searchText) {
|
||||
const q = this.searchText.toLowerCase()
|
||||
list = list.filter(p =>
|
||||
[p.first_name, p.last_name, p.email]
|
||||
.some(v => v?.toLowerCase().includes(q))
|
||||
)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
get onlineCount() {
|
||||
return this.people.filter(p => p._online).length
|
||||
}
|
||||
|
||||
render() {
|
||||
VStack(() => {
|
||||
// ── Header ────────────────────────────────────────────────
|
||||
VStack(() => {
|
||||
HStack(() => {
|
||||
VStack(() => {
|
||||
|
||||
HStack(() => {
|
||||
p(`${this.people.length} total`)
|
||||
.margin(0)
|
||||
.fontSize(0.72, em)
|
||||
.color("var(--headertext)")
|
||||
.opacity(0.4)
|
||||
|
||||
if (this.onlineCount > 0) {
|
||||
HStack(() => {
|
||||
VStack(() => {})
|
||||
.width(6, px)
|
||||
.height(6, px)
|
||||
.borderRadius(50, pct)
|
||||
.background("#10b981")
|
||||
.flexShrink(0)
|
||||
p(`${this.onlineCount} online`)
|
||||
.margin(0)
|
||||
.fontSize(0.72, em)
|
||||
.color("#10b981")
|
||||
.fontWeight("600")
|
||||
})
|
||||
.gap(0.3, em)
|
||||
.alignItems("center")
|
||||
}
|
||||
})
|
||||
.gap(0.65, em)
|
||||
.alignItems("center")
|
||||
.marginTop(0.2, em)
|
||||
})
|
||||
.gap(0)
|
||||
.flex(1)
|
||||
|
||||
// Online filter pill
|
||||
if (this.people.length > 0) {
|
||||
HStack(() => {
|
||||
VStack(() => {})
|
||||
.width(7, px)
|
||||
.height(7, px)
|
||||
.borderRadius(50, pct)
|
||||
.background(this.filterOnline ? "#10b981" : "var(--headertext)")
|
||||
.opacity(this.filterOnline ? 1 : 0.3)
|
||||
.flexShrink(0)
|
||||
p("Online")
|
||||
.margin(0)
|
||||
.fontSize(0.75, em)
|
||||
.fontWeight(this.filterOnline ? "600" : "400")
|
||||
.color("var(--headertext)")
|
||||
.opacity(this.filterOnline ? 1 : 0.45)
|
||||
})
|
||||
.gap(0.35, em)
|
||||
.alignItems("center")
|
||||
.paddingHorizontal(0.75, em)
|
||||
.paddingVertical(0.35, em)
|
||||
.background(this.filterOnline ? "rgba(16,185,129,0.12)" : "var(--darkaccent)")
|
||||
.border(`1px solid ${this.filterOnline ? "rgba(16,185,129,0.4)" : "var(--divider)"}`)
|
||||
.borderRadius(100, px)
|
||||
.cursor("pointer")
|
||||
.onTap(() => { this.filterOnline = !this.filterOnline; this.rerender() })
|
||||
}
|
||||
})
|
||||
.alignItems("flex-start")
|
||||
.marginBottom(0.75, em)
|
||||
|
||||
// Search bar
|
||||
HStack(() => {
|
||||
p("🔍")
|
||||
.margin(0)
|
||||
.fontSize(0.75, em)
|
||||
.opacity(0.4)
|
||||
.flexShrink(0)
|
||||
input("Search members…", "100%")
|
||||
.border("none")
|
||||
.background("transparent")
|
||||
.color("var(--headertext)")
|
||||
.fontSize(0.88, em)
|
||||
.outline("none")
|
||||
.flex(1)
|
||||
.attr({ value: this.searchText })
|
||||
.onInput(e => {
|
||||
this.searchText = e.target.value
|
||||
this.listEl._members = this.filtered
|
||||
this.listEl.rerender()
|
||||
})
|
||||
})
|
||||
.gap(0.5, em)
|
||||
.paddingHorizontal(0.75, em)
|
||||
.paddingVertical(0.55, em)
|
||||
.background("var(--darkaccent)")
|
||||
.border("1px solid var(--divider)")
|
||||
.borderRadius(0.55, em)
|
||||
.alignItems("center")
|
||||
})
|
||||
.paddingHorizontal(1, em)
|
||||
.paddingTop(1.25, em)
|
||||
.paddingBottom(0.85, em)
|
||||
.flexShrink(0)
|
||||
|
||||
// ── Divider ───────────────────────────────────────────────
|
||||
VStack(() => {}).height(1, px).background("var(--divider)").flexShrink(0)
|
||||
|
||||
// ── List ──────────────────────────────────────────────────
|
||||
this.listEl = PeopleList(this.filtered, global.appRefreshing || this.people.length === 0)
|
||||
})
|
||||
.height(100, pct)
|
||||
.width(100, pct)
|
||||
.boxSizing("border-box")
|
||||
.overflow("hidden")
|
||||
.onAppear(async () => {
|
||||
const res = await server.getPeople(global.currentNetwork.id)
|
||||
if (!res.error && res.length > 0 && this.people.length !== res.length) {
|
||||
this.people = res.map(p => ({ ...p, _online: this.isOnline(p) }))
|
||||
this.rerender()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
register(People)
|
||||
Reference in New Issue
Block a user