Added ability for user to change their bio

This commit is contained in:
2025-02-16 10:44:04 +11:00
parent 42ea74fd63
commit 07453b0f02
6 changed files with 170 additions and 8 deletions

View File

@@ -48,3 +48,13 @@ func (user *User) ChangeUsername(conn *sql.DB, newUsername string) error {
} }
return nil return nil
} }
// Change the user's bio
func (user *User) ChangeBio(conn *sql.DB, newBio string) error {
query := `UPDATE users SET bio = ? WHERE id = ?`
_, err := conn.Exec(query, newBio, user.ID)
if err != nil {
return errors.Wrap(err, "conn.Exec")
}
return nil
}

View File

@@ -49,7 +49,8 @@ func HandleChangeUsername(
return return
} }
if !unique { if !unique {
account.ChangeUsername("Usename is taken", newUsername).Render(r.Context(), w) account.ChangeUsername("Username is taken", newUsername).
Render(r.Context(), w)
return return
} }
user := contexts.GetUser(r.Context()) user := contexts.GetUser(r.Context())
@@ -59,7 +60,34 @@ func HandleChangeUsername(
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
w.Header().Set("HX-Redirect", "/account") w.Header().Set("HX-Refresh", "true")
},
)
}
// Handles a request to change the users bio
func HandleChangeBio(
logger *zerolog.Logger,
conn *sql.DB,
) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
newBio := r.FormValue("bio")
leng := len([]rune(newBio))
if leng > 128 {
account.ChangeBio("Bio limited to 128 characters", newBio).
Render(r.Context(), w)
return
}
user := contexts.GetUser(r.Context())
err := user.ChangeBio(conn, newBio)
if err != nil {
logger.Error().Err(err).Msg("Error updating bio")
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("HX-Refresh", "true")
}, },
) )
} }

View File

@@ -60,6 +60,12 @@ func addRoutes(
// Logout // Logout
mux.Handle("POST /logout", handlers.HandleLogout(config, logger, conn)) mux.Handle("POST /logout", handlers.HandleLogout(config, logger, conn))
// Reauthentication request
mux.Handle("POST /reauthenticate",
middleware.RequiresLogin(
handlers.HandleReauthenticate(logger, config, conn),
))
// Profile page // Profile page
mux.Handle("GET /profile", mux.Handle("GET /profile",
middleware.RequiresLogin( middleware.RequiresLogin(
@@ -81,8 +87,8 @@ func addRoutes(
handlers.HandleChangeUsername(logger, conn), handlers.HandleChangeUsername(logger, conn),
), ),
)) ))
mux.Handle("POST /reauthenticate", mux.Handle("POST /change-bio",
middleware.RequiresLogin( middleware.RequiresLogin(
handlers.HandleReauthenticate(logger, config, conn), handlers.HandleChangeBio(logger, conn),
)) ))
} }

View File

@@ -0,0 +1,117 @@
package account
import "projectreshoot/contexts"
templ ChangeBio(err string, bio string) {
{{
user := contexts.GetUser(ctx)
if bio == "" {
bio = user.Bio
}
}}
<form
hx-post="/change-bio"
hx-swap="outerHTML"
class="w-[90%] mx-auto mt-5"
x-data={ templ.JSFuncCall("bioComponent", bio, user.Bio, err).CallInline }
>
<div
class="flex flex-col"
>
<div
class="flex flex-col sm:flex-row sm:items-center relative"
>
<label
for="bio"
class="text-lg w-20"
>Bio</label>
<div
class="relative sm:ml-5 ml-0 w-fit"
>
<textarea
type="text"
id="bio"
name="bio"
class="py-1 px-4 rounded-lg text-md
bg-surface0 border border-surface2 w-60
disabled:opacity-50 disabled:pointer-events-none"
required
aria-describedby="bio-error"
x-model="bio"
x-ref="bio"
@input="updateTextArea()"
maxlength="128"
></textarea>
<span
class="absolute right-0 pr-2 bottom-0 pb-2"
x-text="bioLenText"
></span>
</div>
</div>
<div class="mt-2 sm:ml-25">
<button
class="rounded-lg bg-blue py-1 px-2 text-mantle
hover:cursor-pointer hover:bg-blue/75 transition"
x-cloak
x-show="bio !== initialBio"
x-transition.opacity.duration.500ms
>
Update
</button>
<button
class="rounded-lg bg-overlay0 py-1 px-2 text-mantle
hover:cursor-pointer hover:bg-surface2 transition"
type="button"
href="#"
x-cloak
x-show="bio !== initialBio"
x-transition.opacity.duration.500ms
@click="resetBio()"
>
Cancel
</button>
</div>
</div>
<p
class="block text-red sm:ml-26 mt-1 transition"
x-cloak
x-show="err"
x-text="err"
></p>
<script>
function bioComponent(newBio, oldBio, err) {
return {
bio: newBio,
initialBio: oldBio,
err: err,
bioLenText: '',
updateTextArea() {
this.$nextTick(() => {
if (this.$refs.bio) {
this.$refs.bio.style.height = 'auto';
this.$refs.bio.style.height = `
${this.$refs.bio.scrollHeight+20}px`;
};
this.bioLenText = `${this.bio.length}/128`;
});
},
resetBio() {
this.bio = this.initialBio;
this.err = "",
this.updateTextArea();
},
init() {
this.$nextTick(() => {
// this timeout makes sure the textarea resizes on
// page render correctly. seems 20ms is the sweet
// spot between a noticable delay and not working
setTimeout(() => {
this.updateTextArea();
}, 20);
});
}
};
}
</script>
</form>
}

View File

@@ -24,7 +24,7 @@ templ ChangeUsername(err string, username string) {
> >
<label <label
for="username" for="username"
class="text-lg" class="text-lg w-20"
>Username</label> >Username</label>
<input <input
type="text" type="text"
@@ -38,8 +38,8 @@ templ ChangeUsername(err string, username string) {
x-model="username" x-model="username"
/> />
<div <div
class="absolute inset-y-0 sm:start-66 start-43 pt-9 class="absolute inset-y-0 sm:start-68 start-43 pt-9
pointer-events-none sm:pe-3 sm:pt-2" pointer-events-none sm:pt-2"
x-show="err" x-show="err"
x-cloak x-cloak
> >
@@ -85,7 +85,7 @@ templ ChangeUsername(err string, username string) {
</div> </div>
</div> </div>
<p <p
class="block text-red sm:ml-24 mt-1 transition" class="block text-red sm:ml-26 mt-1 transition"
x-cloak x-cloak
x-show="err" x-show="err"
x-text="err" x-text="err"

View File

@@ -3,5 +3,6 @@ package account
templ AccountGeneral() { templ AccountGeneral() {
<div> <div>
@ChangeUsername("", "") @ChangeUsername("", "")
@ChangeBio("", "")
</div> </div>
} }