diff --git a/features/profile/handlers.go b/features/profile/handlers.go index 9f2300f..9623e3e 100644 --- a/features/profile/handlers.go +++ b/features/profile/handlers.go @@ -195,14 +195,14 @@ func (h *Handlers) renderLocalProfileEdit(w http.ResponseWriter, r *http.Request // Fetch user data from users table var displayName, handle, email, bio, location, worksAt, contactMethod string - var hiring, looking, hideFromLeaderboard, hideBadges bool + var hiring, looking, hideFromLeaderboard, hideBadges, followUp bool var interestsJSON, linksJSON string err := h.DB.QueryRowContext(ctx, ` SELECT display_name, handle, email, bio, location, works_at, contact_method, - hiring, "looking", hide_from_leaderboard, hide_badges, interests, links + hiring, "looking", hide_from_leaderboard, hide_badges, interests, links, follow_up FROM users WHERE did = ? `, localID).Scan(&displayName, &handle, &email, &bio, &location, &worksAt, &contactMethod, - &hiring, &looking, &hideFromLeaderboard, &hideBadges, &interestsJSON, &linksJSON) + &hiring, &looking, &hideFromLeaderboard, &hideBadges, &interestsJSON, &linksJSON, &followUp) if err != nil { slog.Error("local profile edit: fetch user", "err", err) http.Error(w, "user not found", http.StatusNotFound) @@ -215,6 +215,7 @@ func (h *Handlers) renderLocalProfileEdit(w http.ResponseWriter, r *http.Request IsLocal: true, DisplayName: displayName, Email: email, + FollowUp: followUp, DisplayNameDisabled: false, // local users can edit their display name AvatarDisabled: true, // no avatar support for local accounts AvatarURL: "", @@ -432,6 +433,7 @@ func (h *Handlers) saveLocalProfile(w http.ResponseWriter, r *http.Request, loca hiring := r.FormValue("hiring") == "1" looking := r.FormValue("looking") == "1" hideBadges := r.FormValue("hide_badges") == "1" + followUp := r.FormValue("follow_up") == "1" // Parse interests into JSON interests := parseInterests(interestsStr) @@ -451,9 +453,9 @@ func (h *Handlers) saveLocalProfile(w http.ResponseWriter, r *http.Request, loca // Update users table _, err := h.DB.ExecContext(ctx, ` UPDATE users SET display_name = ?, email = ?, bio = ?, location = ?, works_at = ?, contact_method = ?, - hiring = ?, "looking" = ?, hide_badges = ?, interests = ?, links = ? + hiring = ?, "looking" = ?, hide_badges = ?, follow_up = ?, interests = ?, links = ? WHERE did = ? - `, displayName, email, bio, location, worksAt, contactMethod, hiring, looking, hideBadges, string(interestsJSON), string(linksJSON), localID) + `, displayName, email, bio, location, worksAt, contactMethod, hiring, looking, hideBadges, followUp, string(interestsJSON), string(linksJSON), localID) if err != nil { slog.Error("save local profile", "err", err) http.Error(w, "failed to save", http.StatusInternalServerError) diff --git a/features/profile/pages/profile_edit.templ b/features/profile/pages/profile_edit.templ index e16f1f3..9b9d003 100644 --- a/features/profile/pages/profile_edit.templ +++ b/features/profile/pages/profile_edit.templ @@ -31,6 +31,7 @@ type ProfileEditView struct { // (standard checkbox semantics) — so a plain bool here is fine. Hiring bool Looking bool + FollowUp bool // DisplayNameDisabled is true when the session lacks the // repo:app.bsky.actor.profile scope. DisplayNameDisabled bool @@ -97,6 +98,9 @@ templ ProfileEdit(v ProfileEditView) {
+ if !v.IsLocal { +

These fields are shared with your bluesky profile.

+ }
if v.AvatarURL != "" { { @@ -111,48 +115,69 @@ templ ProfileEdit(v ProfileEditView) {

Link your ATmosphere account to upload a profile picture

} } else { - +
+ + if v.AvatarURL != "" { + + + } +
- if v.AvatarURL != "" { - - } }
-
- -
- +
+
+ +
+ +
+ if v.DisplayNameDisabled { +
sign out and sign back in to edit your display name
+ }
- if v.DisplayNameDisabled { -
sign out and sign back in to edit your display name
+ + if v.IsLocal { +
+ +
+ +
+
}
if v.IsLocal { -
- -
- -
-
used for event follow-up. never shared publicly.
-
+ }
diff --git a/features/profile/pages/profile_edit_templ.go b/features/profile/pages/profile_edit_templ.go index a2433a6..2a9f9de 100644 --- a/features/profile/pages/profile_edit_templ.go +++ b/features/profile/pages/profile_edit_templ.go @@ -37,8 +37,9 @@ type ProfileEditView struct { // underlying record uses *bool so we can distinguish "unset" from // "explicitly false", but the form only ever submits "true" or absent // (standard checkbox semantics) — so a plain bool here is fine. - Hiring bool - Looking bool + Hiring bool + Looking bool + FollowUp bool // DisplayNameDisabled is true when the session lacks the // repo:app.bsky.actor.profile scope. DisplayNameDisabled bool @@ -129,7 +130,7 @@ func ProfileEdit(v ProfileEditView) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs("@") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 84, Col: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 85, Col: 56} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -145,353 +146,387 @@ func ProfileEdit(v ProfileEditView) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !v.IsLocal { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "

These fields are shared with your bluesky profile.

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.AvatarURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"")") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" loading=\"lazy\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
?
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
?
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.AvatarDisabled { if v.MissingScope { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

sign out and sign back in to change your avatar

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "

sign out and sign back in to change your avatar

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

Link your ATmosphere account to upload a profile picture

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "

Link your ATmosphere account to upload a profile picture

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.AvatarURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " placeholder=\"your name\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.DisplayNameDisabled { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
sign out and sign back in to edit your display name
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
sign out and sign back in to edit your display name
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.IsLocal { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
used for event follow-up. never shared publicly.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" maxlength=\"320\" placeholder=\"you@example.com\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if v.IsLocal { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.Error != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
error: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
error: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(v.Error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 161, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 186, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.BlueskyBio != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "leave blank to fall back to your bluesky bio:
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "leave blank to fall back to your bluesky bio:
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(v.BlueskyBio) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 180, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 205, Col: 42} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "tell people what you're about. up to 256 characters.") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "tell people what you're about. up to 256 characters.") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
where you spend your weekdays. up to 120 characters.
where you spend your weekdays. up to 120 characters.
city, region, or vibe. up to 120 characters.
city, region, or vibe. up to 120 characters.
how people should reach out after a connect. up to 200 characters.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\" maxlength=\"200\" placeholder=\"DM on bsky · email me · signal: …\">
how people should reach out after a connect. up to 200 characters.
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, t := range v.Interests { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(t) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 246, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/profile/pages/profile_edit.templ`, Line: 271, Col: 42} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\" data-tag-remove>×") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, s := range suggestedInterests { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "
pick from suggestions or add your own. up to 30, 64 characters each.
status
status
shown as pills above your bio. toggle off to hide.
links (up to 5) ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "> ● looking for work
shown as pills above your bio. toggle off to hide.
links (up to 5) ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -501,7 +536,7 @@ func ProfileEdit(v ProfileEditView) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
pinned links shown on your profile. label + URL. http(s) only.
cancel
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "
pinned links shown on your profile. label + URL. http(s) only.
cancel
atmo.quest
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -541,98 +576,98 @@ func profileLinkRow(idx int, l ProfileLink) templ.Component { templ_7745c5c3_Var20 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "