Files
arnefandCopilot 8b10386c91 Add account management page
Add a new /web/account page, reachable by clicking the username in
the nav, with two forms: updating display name/email, and changing
the password (requires the current password, min 8 chars, confirm
match). Add db.SetProfile to persist display name/email.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-21 06:32:18 +02:00

80 lines
3.8 KiB
Templ

package templates
// AccountData is everything the account page needs to render the
// current user's profile and password forms.
type AccountData struct {
Username string
DisplayName string
Email string
ProfileMsg string // success/error message shown above the profile form, "" for none
ProfileErr bool // true if ProfileMsg is an error (red) rather than a success (green)
PasswordMsg string // success/error message shown above the password form, "" for none
PasswordErr bool
}
templ Account(data AccountData) {
@Layout("Account", data.Username) {
<h1 class="text-2xl font-semibold mb-6">Account</h1>
<div class="bg-white rounded-lg border border-gray-200 p-6 mb-6 max-w-lg">
<h2 class="text-lg font-medium mb-4">Profile</h2>
if data.ProfileMsg != "" {
<p class={ "mb-4 text-sm rounded px-3 py-2 border", templ.KV("text-red-600 bg-red-50 border-red-200", data.ProfileErr), templ.KV("text-green-700 bg-green-50 border-green-200", !data.ProfileErr) }>
{ data.ProfileMsg }
</p>
}
<form method="POST" action="/web/account/profile" class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700">Username</label>
<input type="text" value={ data.Username } disabled
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 bg-gray-50 text-gray-500 shadow-sm"/>
</div>
<div>
<label for="display_name" class="block text-sm font-medium text-gray-700">Display name</label>
<input id="display_name" name="display_name" type="text" value={ data.DisplayName }
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"/>
</div>
<div>
<label for="email" class="block text-sm font-medium text-gray-700">Email</label>
<input id="email" name="email" type="email" value={ data.Email }
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"/>
</div>
<button type="submit"
class="bg-indigo-600 text-white rounded-md px-4 py-2 text-sm font-medium hover:bg-indigo-700">
Save profile
</button>
</form>
</div>
<div class="bg-white rounded-lg border border-gray-200 p-6 max-w-lg">
<h2 class="text-lg font-medium mb-4">Change password</h2>
if data.PasswordMsg != "" {
<p class={ "mb-4 text-sm rounded px-3 py-2 border", templ.KV("text-red-600 bg-red-50 border-red-200", data.PasswordErr), templ.KV("text-green-700 bg-green-50 border-green-200", !data.PasswordErr) }>
{ data.PasswordMsg }
</p>
}
<form method="POST" action="/web/account/password" class="space-y-4">
<div>
<label for="current_password" class="block text-sm font-medium text-gray-700">Current password</label>
<input id="current_password" name="current_password" type="password" required
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"/>
</div>
<div>
<label for="new_password" class="block text-sm font-medium text-gray-700">New password</label>
<input id="new_password" name="new_password" type="password" required minlength="8"
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"/>
</div>
<div>
<label for="confirm_password" class="block text-sm font-medium text-gray-700">Confirm new password</label>
<input id="confirm_password" name="confirm_password" type="password" required minlength="8"
class="mt-1 block w-full rounded-md border-gray-300 border px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"/>
</div>
<button type="submit"
class="bg-indigo-600 text-white rounded-md px-4 py-2 text-sm font-medium hover:bg-indigo-700">
Change password
</button>
</form>
</div>
}
}