133 lines
4.6 KiB
JavaScript
133 lines
4.6 KiB
JavaScript
class PeopleCard extends Shadow {
|
|
constructor(person) {
|
|
super()
|
|
this.person = person
|
|
}
|
|
|
|
render() {
|
|
const p_ = this.person
|
|
const initials = ((p_.first_name?.[0] ?? "") + (p_.last_name?.[0] ?? "")).toUpperCase()
|
|
const roles = Array.isArray(p_.roles) ? p_.roles : []
|
|
const isOnline = p_._online
|
|
|
|
HStack(() => {
|
|
// Avatar + online dot
|
|
ZStack(() => {
|
|
VStack(() => {
|
|
if (p_.image_path) {
|
|
img(`${config.SERVER}${p_.image_path}`, "2.75em", "2.75em")
|
|
.borderRadius(50, pct)
|
|
.objectFit("cover")
|
|
} else {
|
|
p(initials)
|
|
.margin(0)
|
|
.fontSize(0.78, em)
|
|
.fontWeight("700")
|
|
.color("white")
|
|
}
|
|
})
|
|
.width(2.75, em)
|
|
.height(2.75, em)
|
|
.borderRadius(50, pct)
|
|
.background(p_.image_path ? "transparent" : this.avatarColor(p_.email || p_.first_name))
|
|
.justifyContent("center")
|
|
.alignItems("center")
|
|
.overflow("hidden")
|
|
.flexShrink(0)
|
|
|
|
// Online indicator
|
|
if (isOnline) {
|
|
VStack(() => {})
|
|
.width(0.68, em)
|
|
.height(0.68, em)
|
|
.borderRadius(50, pct)
|
|
.background("#10b981")
|
|
.boxSizing("border-box")
|
|
.position("absolute")
|
|
.bottom(0).right(0)
|
|
}
|
|
})
|
|
.position("relative")
|
|
.width(2.75, em)
|
|
.height(2.75, em)
|
|
.flexShrink(0)
|
|
|
|
// Info
|
|
VStack(() => {
|
|
HStack(() => {
|
|
p(`${p_.first_name} ${p_.last_name}`)
|
|
.margin(0)
|
|
.fontSize(0.92, em)
|
|
.fontWeight("600")
|
|
.color("var(--headertext)")
|
|
.flex(1)
|
|
.minWidth(0)
|
|
.overflow("hidden")
|
|
.whiteSpace("nowrap")
|
|
.textOverflow("ellipsis")
|
|
|
|
if (isOnline) {
|
|
p("online")
|
|
.margin(0)
|
|
.fontSize(0.65, em)
|
|
.fontWeight("600")
|
|
.color("#10b981")
|
|
.flexShrink(0)
|
|
}
|
|
})
|
|
.alignItems("center")
|
|
.gap(0.5, em)
|
|
|
|
HStack(() => {
|
|
p(p_.email ?? "")
|
|
.margin(0)
|
|
.fontSize(0.72, em)
|
|
.color("var(--headertext)")
|
|
.opacity(0.42)
|
|
.overflow("hidden")
|
|
.whiteSpace("nowrap")
|
|
.textOverflow("ellipsis")
|
|
.flex(1)
|
|
.minWidth(0)
|
|
|
|
roles.slice(0, 2).forEach(role => {
|
|
p(role)
|
|
.margin(0)
|
|
.fontSize(0.62, em)
|
|
.fontWeight("600")
|
|
.color("var(--quillred)")
|
|
.background("rgba(159,28,41,0.1)")
|
|
.paddingHorizontal(0.45, em)
|
|
.paddingVertical(0.12, em)
|
|
.borderRadius(100, px)
|
|
.whiteSpace("nowrap")
|
|
.flexShrink(0)
|
|
})
|
|
})
|
|
.gap(0.35, em)
|
|
.alignItems("center")
|
|
.marginTop(0.2, em)
|
|
})
|
|
.flex(1)
|
|
.minWidth(0)
|
|
.gap(0)
|
|
})
|
|
.gap(0.75, em)
|
|
.paddingHorizontal(1, em)
|
|
.paddingVertical(0.85, em)
|
|
.alignItems("center")
|
|
.width(100, pct)
|
|
.boxSizing("border-box")
|
|
}
|
|
|
|
avatarColor(seed) {
|
|
const colors = ["#3b82f6", "#9E1C29", "#10b981", "#f59e0b", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16"]
|
|
if (!seed) return colors[0]
|
|
let hash = 0
|
|
for (let i = 0; i < seed.length; i++) hash = seed.charCodeAt(i) + ((hash << 5) - hash)
|
|
return colors[Math.abs(hash) % colors.length]
|
|
}
|
|
}
|
|
|
|
register(PeopleCard)
|