diff --git a/apps/finance/services/api/main/handler.go b/apps/finance/services/api/main/handler.go index 8d64a9d..082788c 100644 --- a/apps/finance/services/api/main/handler.go +++ b/apps/finance/services/api/main/handler.go @@ -118,6 +118,19 @@ func parseTmpl(files ...string) *template.Template { return "var(--bg3); color:var(--text3)" } }, + "avatarEmojis": func() []string { + return []string{ + "👥", "🚀", "⚡", "🎯", "🏆", "💡", "🔥", "🌊", "🎨", "🛠️", + "📊", "🎪", "🌿", "🦋", "🏄", "🎸", "🔬", "📡", "🏗️", "🎭", + "🌍", "🦁", "🐉", "🦅", "🐋", "🌙", "⭐", "🍀", "🔮", "🎲", + } + }, + "teamAvatar": func(t OrgTeam) string { + if t.Avatar != "" { + return t.Avatar + } + return "👥" + }, "varColor": func(planned, actual int64) string { if planned == 0 { return "var(--text2)" diff --git a/apps/finance/services/api/main/handler_org.go b/apps/finance/services/api/main/handler_org.go index 4a138d7..14118a7 100644 --- a/apps/finance/services/api/main/handler_org.go +++ b/apps/finance/services/api/main/handler_org.go @@ -229,11 +229,16 @@ func (h *Handler) OrgTeamCreate(w http.ResponseWriter, r *http.Request) { http.Error(w, "name required", http.StatusBadRequest) return } + avatar := r.FormValue("avatar") + if avatar == "" { + avatar = "👥" + } team := &OrgTeam{ ID: bson.NewObjectID().Hex(), OrgID: org.ID, Name: name, Type: teamType, + Avatar: avatar, CreatedAt: time.Now(), } if err := h.store.createTeam(ctx, team); err != nil { diff --git a/apps/finance/services/api/main/models_org.go b/apps/finance/services/api/main/models_org.go index 21daf46..d321898 100644 --- a/apps/finance/services/api/main/models_org.go +++ b/apps/finance/services/api/main/models_org.go @@ -35,6 +35,7 @@ type OrgTeam struct { OrgID string `bson:"org_id" json:"org_id"` Name string `bson:"name" json:"name"` Type TeamType `bson:"type" json:"type"` + Avatar string `bson:"avatar" json:"avatar"` // single emoji CreatedAt time.Time `bson:"created_at" json:"created_at"` } diff --git a/apps/finance/services/api/main/templates/base.html b/apps/finance/services/api/main/templates/base.html index 85d0eff..e8ecec2 100644 --- a/apps/finance/services/api/main/templates/base.html +++ b/apps/finance/services/api/main/templates/base.html @@ -396,11 +396,67 @@ cursor: pointer; font-family: inherit; } + /* Global catch-all: any bare input/select/textarea gets dark theme. + .form-group and .form-input rules above still win for their elements + due to specificity; this only fixes uncovered stragglers. */ + input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=reset]):not([type=hidden]):not([type=color]), + select, + textarea { + background: var(--bg2); + color: var(--text); + border-color: var(--border2); + font-family: inherit; + } + input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=reset]):not([type=hidden]):not([type=color]):focus, + select:focus, + textarea:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-glow); + } + input::placeholder, textarea::placeholder { color: var(--text3); opacity: 0.7; } + select option { background: var(--bg2); color: var(--text); } input[type="color"] { padding: 4px; height: 38px; cursor: pointer; } - select option, .form-input option { background: var(--bg2); color: var(--text); } textarea.form-input { resize: vertical; min-height: 72px; line-height: 1.5; } + /* Team / org avatars */ + .team-avatar { + display: inline-flex; align-items: center; justify-content: center; + width: 32px; height: 32px; + border-radius: 8px; + font-size: 17px; + line-height: 1; + flex-shrink: 0; + background: var(--bg3); + border: 1px solid var(--border2); + user-select: none; + } + .team-avatar-sm { + width: 22px; height: 22px; + border-radius: 5px; + font-size: 12px; + } + .team-avatar-lg { + width: 48px; height: 48px; + border-radius: 12px; + font-size: 26px; + } + /* Emoji picker row */ + .emoji-picker { display: flex; flex-wrap: wrap; gap: 6px; } + .emoji-opt { + width: 36px; height: 36px; + border-radius: 8px; + border: 2px solid transparent; + background: var(--bg3); + font-size: 18px; + cursor: pointer; + display: flex; align-items: center; justify-content: center; + transition: border-color 0.12s, background 0.12s; + } + .emoji-opt:hover { background: var(--surface2); } + .emoji-opt.selected { border-color: var(--accent); background: var(--accent-glow); } + /* ── Badges ──────────────────────────────────────────────────────── */ .badge { display: inline-flex; align-items: center; gap: 5px; diff --git a/apps/finance/services/api/main/templates/org_event_detail.html b/apps/finance/services/api/main/templates/org_event_detail.html index a1de7bd..6366987 100644 --- a/apps/finance/services/api/main/templates/org_event_detail.html +++ b/apps/finance/services/api/main/templates/org_event_detail.html @@ -118,7 +118,7 @@
| Name | +Team | Type | Members | {{if eq $d.MyRole "admin"}}{{end}} @@ -30,7 +30,12 @@ {{$count := 0}} {{range $d.Members}}{{range .TeamIDs}}{{if eq . $t.ID}}{{$count = add $count 1}}{{end}}{{end}}{{end}} |
|---|---|---|---|---|
| {{$t.Name}} | +
+
+ {{if $t.Avatar}}{{$t.Avatar}}{{else}}👥{{end}}
+ {{$t.Name}}
+
+ |
{{if eq (print $t.Type) "guest"}} guest @@ -64,13 +69,27 @@ {{end}} {{if eq $d.MyRole "admin"}} - |