Added ability for user to change their bio
This commit is contained in:
10
db/user.go
10
db/user.go
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
117
view/component/account/changebio.templ
Normal file
117
view/component/account/changebio.templ
Normal 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>
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ package account
|
|||||||
templ AccountGeneral() {
|
templ AccountGeneral() {
|
||||||
<div>
|
<div>
|
||||||
@ChangeUsername("", "")
|
@ChangeUsername("", "")
|
||||||
|
@ChangeBio("", "")
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user