diff --git a/frontend/src/views/SettingsView.vue b/frontend/src/views/SettingsView.vue
index 4f4231d..4f1f95f 100644
--- a/frontend/src/views/SettingsView.vue
+++ b/frontend/src/views/SettingsView.vue
@@ -55,9 +55,73 @@
Signed in as
{{ auth.user?.email }}
+
Sign out
+
+
+
+
Change password
+
+
+
+
(null)
+const pwSuccess = ref(false)
+
+const pwConfirmMismatch = computed(() =>
+ pwConfirm.value.length > 0 && pwConfirm.value !== pwNew.value,
+)
+
+function resetPasswordForm() {
+ pwCurrent.value = ''
+ pwNew.value = ''
+ pwConfirm.value = ''
+ pwError.value = null
+ pwSuccess.value = false
+ pwSubmitting.value = false
+}
+
+function closePasswordModal() {
+ passwordModalOpen.value = false
+ resetPasswordForm()
+}
+
+async function submitPasswordChange() {
+ if (pwConfirmMismatch.value) return
+ pwError.value = null
+ pwSuccess.value = false
+ pwSubmitting.value = true
+ try {
+ const res = await fetch('/api/user/password', {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ currentPassword: pwCurrent.value,
+ newPassword: pwNew.value,
+ }),
+ })
+ if (res.status === 204) {
+ pwSuccess.value = true
+ pwCurrent.value = ''
+ pwNew.value = ''
+ pwConfirm.value = ''
+ // Auto-close after a moment so the user sees the confirmation.
+ setTimeout(closePasswordModal, 1500)
+ return
+ }
+ const body = await res.json().catch(() => ({}))
+ pwError.value = body?.error ?? 'Could not update password.'
+ } catch {
+ pwError.value = 'Network error. Try again.'
+ } finally {
+ pwSubmitting.value = false
+ }
+}