278 lines
5.4 KiB
Vue
278 lines
5.4 KiB
Vue
<script setup>
|
|
import { inject, reactive, ref } from 'vue';
|
|
|
|
import Password from '#/components/form/password.vue';
|
|
import Ellipsis from '#/components/loading/ellipsis.vue';
|
|
|
|
// import Checkbox from '#/components/form/checkbox.vue';
|
|
|
|
import { patch, post } from '#/src/api.js';
|
|
|
|
const pageContext = inject('pageContext');
|
|
const { user } = pageContext;
|
|
|
|
const credentials = reactive({
|
|
email: null,
|
|
password: null,
|
|
});
|
|
|
|
const currentPassword = ref(null);
|
|
const saving = ref(false);
|
|
const submitted = ref(false);
|
|
const verifying = ref(false);
|
|
const verified = ref(false);
|
|
|
|
function getFeedback() {
|
|
if (credentials.email && Object.entries(credentials).some(([key, value]) => key !== 'email' && value !== null)) {
|
|
return 'Account updated, please check your inbox to change e-mail.';
|
|
}
|
|
|
|
if (credentials.email) {
|
|
return 'Please check your inbox to change e-mail.';
|
|
}
|
|
|
|
return 'Account updated.';
|
|
}
|
|
|
|
async function updateAccount() {
|
|
saving.value = true;
|
|
|
|
try {
|
|
await patch('/me', {
|
|
credentials,
|
|
password: currentPassword.value,
|
|
}, {
|
|
successFeedback: getFeedback(),
|
|
errorFeedback: 'Failed to update account',
|
|
appendErrorMessage: true,
|
|
});
|
|
|
|
submitted.value = true;
|
|
}
|
|
finally {
|
|
saving.value = false;
|
|
}
|
|
}
|
|
|
|
async function verifyEmail() {
|
|
verifying.value = true;
|
|
|
|
try {
|
|
await post('/me/email_verification', null, {
|
|
successFeedback: 'E-mail verification sent, please check your inbox',
|
|
errorFeedback: 'Failed to request e-mail verification',
|
|
appendErrorMessage: true,
|
|
});
|
|
|
|
verified.value = true;
|
|
}
|
|
finally {
|
|
verifying.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<form
|
|
class="profile-section"
|
|
@submit.prevent="updateAccount"
|
|
>
|
|
<h3 class="heading settings-heading">Alerts</h3>
|
|
|
|
<label class="setting">
|
|
<span class="setting-label">
|
|
<strong class="setting-title">E-mail address</strong>
|
|
<span class="setting-description">Primarily used for alert notifications and password recovery</span>
|
|
</span>
|
|
|
|
<span class="setting-value">
|
|
<span class="setting-group">
|
|
<VDropdown v-if="!user.isEmailVerified">
|
|
<Icon
|
|
icon="warning2"
|
|
class="unverified"
|
|
/>
|
|
|
|
<template #popper>
|
|
<div class="unverified-tooltip">
|
|
Your e-mail address is unverified
|
|
|
|
<Ellipsis v-if="verifying" />
|
|
|
|
<strong
|
|
v-else-if="verified"
|
|
class="success"
|
|
>Verification e-mail sent</strong>
|
|
|
|
<button
|
|
v-else
|
|
type="button"
|
|
class="button button-primary"
|
|
@click="verifyEmail"
|
|
>Verify now</button>
|
|
</div>
|
|
</template>
|
|
</VDropdown>
|
|
|
|
<input
|
|
:value="user.email"
|
|
type="email"
|
|
class="input"
|
|
disabled
|
|
>
|
|
</span>
|
|
|
|
<input
|
|
v-model="credentials.email"
|
|
type="email"
|
|
placeholder="New e-mail"
|
|
class="input"
|
|
>
|
|
</span>
|
|
</label>
|
|
|
|
<label class="setting">
|
|
<span class="setting-label">
|
|
<strong class="setting-title">New password</strong>
|
|
<span class="setting-description">Change the password you use for signing in</span>
|
|
</span>
|
|
|
|
<span class="setting-value">
|
|
<Password
|
|
:password="credentials.password"
|
|
placeholder="New password"
|
|
autocomplete="new-password"
|
|
@input="(password) => credentials.password = password"
|
|
/>
|
|
</span>
|
|
</label>
|
|
|
|
<label class="setting">
|
|
<span class="setting-label">
|
|
<strong class="setting-title">Current password</strong>
|
|
<span class="setting-description">Enter your current password to save your changes</span>
|
|
</span>
|
|
|
|
<span class="setting-value">
|
|
<Password
|
|
:password="currentPassword"
|
|
placeholder="Current password"
|
|
@input="(password) => currentPassword = password"
|
|
/>
|
|
</span>
|
|
</label>
|
|
|
|
<div class="settings-actions">
|
|
<Ellipsis v-if="saving" />
|
|
|
|
<strong
|
|
v-else-if="submitted"
|
|
class="success"
|
|
>{{ getFeedback() }}</strong>
|
|
|
|
<button
|
|
v-else
|
|
v-tooltip="(credentials.email || credentials.password) && currentPassword ? null : 'Please supply your new credentials and current password'"
|
|
class="button button-primary"
|
|
:disabled="!currentPassword"
|
|
>Save</button>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.input {
|
|
flex-shrink: 0;
|
|
flex-basis: auto;
|
|
background: var(--background);
|
|
|
|
&:disabled {
|
|
color: var(--glass);
|
|
background: none;
|
|
}
|
|
}
|
|
|
|
.profile-section .heading {
|
|
margin: .5rem 1rem 0 1rem;
|
|
}
|
|
|
|
.setting {
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
padding: .75rem 1rem;
|
|
border-bottom: solid 1px var(--glass-weak-30);
|
|
|
|
&:hover {
|
|
border-color: var(--glass-weak-20);
|
|
}
|
|
}
|
|
|
|
.setting-label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.setting-title {
|
|
color: var(--glass-strong-20);
|
|
margin-bottom: .25rem;
|
|
}
|
|
|
|
.setting-value {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
flex-direction: column;
|
|
gap: .5rem;
|
|
}
|
|
|
|
.setting-group {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.setting-description {
|
|
color: var(--glass);
|
|
font-size: .9rem;
|
|
}
|
|
|
|
.settings-actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
padding: 1rem;
|
|
|
|
.button {
|
|
flex-basis: 0;
|
|
font-size: 1.1rem;
|
|
padding: .5rem 1rem;
|
|
}
|
|
}
|
|
|
|
.success {
|
|
color: var(--success);
|
|
margin-top: 1rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.unverified {
|
|
fill: var(--error);
|
|
padding: .5rem 1rem;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.unverified-tooltip {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.load-container {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
</style>
|