Client - update password update in user account
This commit is contained in:
parent
a4d7dc24da
commit
7d78bcc302
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="password-input">
|
<div class="password-input">
|
||||||
<input
|
<input
|
||||||
|
id="password"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:required="required"
|
:required="required"
|
||||||
@ -18,13 +19,21 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="checkStrength" class="form-info">
|
||||||
|
<i class="fa fa-info-circle" aria-hidden="true" />
|
||||||
|
{{ $t('user.PASSWORD_INFO') }}
|
||||||
|
</div>
|
||||||
|
<PasswordStrength v-if="checkStrength" :password="passwordValue" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, ref, toRefs, watch, withDefaults } from 'vue'
|
import { Ref, ref, toRefs, watch, withDefaults } from 'vue'
|
||||||
|
|
||||||
|
import PasswordStrength from '@/components/Common/PasswordStength.vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
checkStrength?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
password?: string
|
password?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
@ -32,10 +41,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
checkStrength: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
password: '',
|
||||||
required: false,
|
required: false,
|
||||||
})
|
})
|
||||||
const { disabled, password, placeholder, required } = toRefs(props)
|
const { checkStrength, disabled, password, placeholder, required } =
|
||||||
|
toRefs(props)
|
||||||
|
|
||||||
const showPassword: Ref<boolean> = ref(false)
|
const showPassword: Ref<boolean> = ref(false)
|
||||||
const passwordValue: Ref<string> = ref('')
|
const passwordValue: Ref<string> = ref('')
|
||||||
|
@ -38,14 +38,13 @@
|
|||||||
watch,
|
watch,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
|
||||||
import { ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { getPasswordStrength, setZxcvbnOptions } from '@/utils/password'
|
import { getPasswordStrength, setZxcvbnOptions } from '@/utils/password'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const { password } = toRefs(props)
|
const { password } = toRefs(props)
|
||||||
|
|
||||||
@ -53,6 +52,9 @@
|
|||||||
const language: ComputedRef<string> = computed(
|
const language: ComputedRef<string> = computed(
|
||||||
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||||
)
|
)
|
||||||
|
const isSuccess: ComputedRef<boolean> = computed(
|
||||||
|
() => store.getters[AUTH_USER_STORE.GETTERS.IS_SUCCESS]
|
||||||
|
)
|
||||||
const passwordScore: Ref<number> = ref(0)
|
const passwordScore: Ref<number> = ref(0)
|
||||||
const passwordStrength: Ref<string> = ref('')
|
const passwordStrength: Ref<string> = ref('')
|
||||||
const passwordSuggestions: Ref<string[]> = ref([])
|
const passwordSuggestions: Ref<string[]> = ref([])
|
||||||
@ -77,7 +79,11 @@
|
|||||||
watch(
|
watch(
|
||||||
() => password.value,
|
() => password.value,
|
||||||
async (newPassword) => {
|
async (newPassword) => {
|
||||||
calculatePasswordStrength(newPassword)
|
if (isSuccess.value) {
|
||||||
|
passwordStrength.value = ''
|
||||||
|
} else {
|
||||||
|
calculatePasswordStrength(newPassword)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
<template>
|
||||||
|
<div id="user-infos-edition">
|
||||||
|
<Modal
|
||||||
|
v-if="displayModal"
|
||||||
|
:title="$t('common.CONFIRMATION')"
|
||||||
|
:message="$t('user.CONFIRM_ACCOUNT_DELETION')"
|
||||||
|
@confirmAction="deleteAccount(user.username)"
|
||||||
|
@cancelAction="updateDisplayModal(false)"
|
||||||
|
/>
|
||||||
|
<div class="profile-form form-box">
|
||||||
|
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
||||||
|
<div class="info-box success-message" v-if="isSuccess">
|
||||||
|
{{ $t('user.PROFILE.SUCCESSFUL_UPDATE') }}
|
||||||
|
</div>
|
||||||
|
<form :class="{ errors: formErrors }" @submit.prevent="updateProfile">
|
||||||
|
<label class="form-items" for="email">
|
||||||
|
{{ $t('user.EMAIL') }}
|
||||||
|
<input id="email" :value="user.email" disabled />
|
||||||
|
</label>
|
||||||
|
<label class="form-items" for="password-field">
|
||||||
|
{{ $t('user.PASSWORD') }}
|
||||||
|
<PasswordInput
|
||||||
|
id="password-field"
|
||||||
|
:disabled="loading"
|
||||||
|
:checkStrength="true"
|
||||||
|
:password="userForm.password"
|
||||||
|
:isSuccess="false"
|
||||||
|
:required="true"
|
||||||
|
@updatePassword="updatePassword"
|
||||||
|
@passwordError="invalidateForm"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<div class="form-buttons">
|
||||||
|
<button class="confirm" type="submit">
|
||||||
|
{{ $t('buttons.SUBMIT') }}
|
||||||
|
</button>
|
||||||
|
<button class="cancel" @click.prevent="$router.push('/profile')">
|
||||||
|
{{ $t('buttons.CANCEL') }}
|
||||||
|
</button>
|
||||||
|
<button class="danger" @click.prevent="updateDisplayModal(true)">
|
||||||
|
{{ $t('buttons.DELETE_MY_ACCOUNT') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
ComputedRef,
|
||||||
|
Ref,
|
||||||
|
computed,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
toRefs,
|
||||||
|
onMounted,
|
||||||
|
watch,
|
||||||
|
onUnmounted,
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
|
import PasswordInput from '@/components/Common/PasswordInput.vue'
|
||||||
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
|
import { IUserProfile, IUserAccountPayload } from '@/types/user'
|
||||||
|
import { useStore } from '@/use/useStore'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
user: IUserProfile
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
const { user } = toRefs(props)
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
const userForm: IUserAccountPayload = reactive({
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
})
|
||||||
|
const loading = computed(
|
||||||
|
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
||||||
|
)
|
||||||
|
const isSuccess: ComputedRef<boolean> = computed(
|
||||||
|
() => store.getters[AUTH_USER_STORE.GETTERS.IS_SUCCESS]
|
||||||
|
)
|
||||||
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
|
)
|
||||||
|
const formErrors = ref(false)
|
||||||
|
const displayModal: Ref<boolean> = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.user) {
|
||||||
|
updateUserForm(props.user)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function invalidateForm() {
|
||||||
|
formErrors.value = true
|
||||||
|
}
|
||||||
|
function updateUserForm(user: IUserProfile) {
|
||||||
|
userForm.email = user.email
|
||||||
|
}
|
||||||
|
function updatePassword(password: string) {
|
||||||
|
userForm.password = password
|
||||||
|
}
|
||||||
|
function updateProfile() {
|
||||||
|
store.dispatch(AUTH_USER_STORE.ACTIONS.UPDATE_USER_ACCOUNT, {
|
||||||
|
password: userForm.password,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function updateDisplayModal(value: boolean) {
|
||||||
|
displayModal.value = value
|
||||||
|
}
|
||||||
|
function deleteAccount(username: string) {
|
||||||
|
store.dispatch(AUTH_USER_STORE.ACTIONS.DELETE_ACCOUNT, { username })
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() =>
|
||||||
|
store.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => isSuccess.value,
|
||||||
|
async (isSuccessValue) => {
|
||||||
|
if (isSuccessValue) {
|
||||||
|
updatePassword('')
|
||||||
|
formErrors.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/scss/vars.scss';
|
||||||
|
|
||||||
|
.form-items {
|
||||||
|
.password-input {
|
||||||
|
::v-deep(.show-password) {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-top: -4px;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
::v-deep(.form-info) {
|
||||||
|
font-weight: normal;
|
||||||
|
padding-left: $default-padding;
|
||||||
|
}
|
||||||
|
::v-deep(.password-strength-details) {
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-buttons {
|
||||||
|
flex-direction: row;
|
||||||
|
@media screen and (max-width: $x-small-limit) {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-message {
|
||||||
|
margin: $default-margin * 2 0;
|
||||||
|
background-color: var(--success-background-color);
|
||||||
|
color: var(--success-color);
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,32 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="user-infos-edition">
|
<div id="user-infos-edition">
|
||||||
<Modal
|
|
||||||
v-if="displayModal"
|
|
||||||
:title="$t('common.CONFIRMATION')"
|
|
||||||
:message="$t('user.CONFIRM_ACCOUNT_DELETION')"
|
|
||||||
@confirmAction="deleteAccount(user.username)"
|
|
||||||
@cancelAction="updateDisplayModal(false)"
|
|
||||||
/>
|
|
||||||
<div class="profile-form form-box">
|
<div class="profile-form form-box">
|
||||||
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
||||||
<form @submit.prevent="updateProfile">
|
<form @submit.prevent="updateProfile">
|
||||||
<label class="form-items" for="email">
|
|
||||||
{{ $t('user.EMAIL') }}
|
|
||||||
<input id="email" :value="user.email" disabled />
|
|
||||||
</label>
|
|
||||||
<label class="form-items" for="registrationDate">
|
<label class="form-items" for="registrationDate">
|
||||||
{{ $t('user.PROFILE.REGISTRATION_DATE') }}
|
{{ $t('user.PROFILE.REGISTRATION_DATE') }}
|
||||||
<input id="registrationDate" :value="registrationDate" disabled />
|
<input id="registrationDate" :value="registrationDate" disabled />
|
||||||
</label>
|
</label>
|
||||||
<label class="form-items" for="password">
|
|
||||||
{{ $t('user.PASSWORD') }}
|
|
||||||
<PasswordInput
|
|
||||||
id="password"
|
|
||||||
:disabled="loading"
|
|
||||||
@updatePassword="updatePassword"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<hr />
|
|
||||||
<label class="form-items" for="first_name">
|
<label class="form-items" for="first_name">
|
||||||
{{ $t('user.PROFILE.FIRST_NAME') }}
|
{{ $t('user.PROFILE.FIRST_NAME') }}
|
||||||
<input
|
<input
|
||||||
@ -74,9 +54,6 @@
|
|||||||
<button class="cancel" @click.prevent="$router.push('/profile')">
|
<button class="cancel" @click.prevent="$router.push('/profile')">
|
||||||
{{ $t('buttons.CANCEL') }}
|
{{ $t('buttons.CANCEL') }}
|
||||||
</button>
|
</button>
|
||||||
<button class="danger" @click.prevent="updateDisplayModal(true)">
|
|
||||||
{{ $t('buttons.DELETE_MY_ACCOUNT') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -85,17 +62,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { format } from 'date-fns'
|
import { format } from 'date-fns'
|
||||||
import {
|
import { ComputedRef, computed, reactive, onMounted } from 'vue'
|
||||||
ComputedRef,
|
|
||||||
Ref,
|
|
||||||
computed,
|
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
toRefs,
|
|
||||||
onMounted,
|
|
||||||
} from 'vue'
|
|
||||||
|
|
||||||
import PasswordInput from '@/components/Common/PasswordInput.vue'
|
|
||||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { IUserProfile, IUserPayload } from '@/types/user'
|
import { IUserProfile, IUserPayload } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
@ -107,9 +75,7 @@
|
|||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const { user } = toRefs(props)
|
|
||||||
const userForm: IUserPayload = reactive({
|
const userForm: IUserPayload = reactive({
|
||||||
password: '',
|
|
||||||
first_name: '',
|
first_name: '',
|
||||||
last_name: '',
|
last_name: '',
|
||||||
birth_date: '',
|
birth_date: '',
|
||||||
@ -127,7 +93,6 @@
|
|||||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
)
|
)
|
||||||
let displayModal: Ref<boolean> = ref(false)
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.user) {
|
if (props.user) {
|
||||||
@ -147,18 +112,9 @@
|
|||||||
function updateBio(value: string) {
|
function updateBio(value: string) {
|
||||||
userForm.bio = value
|
userForm.bio = value
|
||||||
}
|
}
|
||||||
function updatePassword(password: string) {
|
|
||||||
userForm.password = password
|
|
||||||
}
|
|
||||||
function updateProfile() {
|
function updateProfile() {
|
||||||
store.dispatch(AUTH_USER_STORE.ACTIONS.UPDATE_USER_PROFILE, userForm)
|
store.dispatch(AUTH_USER_STORE.ACTIONS.UPDATE_USER_PROFILE, userForm)
|
||||||
}
|
}
|
||||||
function updateDisplayModal(value: boolean) {
|
|
||||||
displayModal.value = value
|
|
||||||
}
|
|
||||||
function deleteAccount(username: string) {
|
|
||||||
store.dispatch(AUTH_USER_STORE.ACTIONS.DELETE_ACCOUNT, { username })
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const { user, tab } = toRefs(props)
|
const { user, tab } = toRefs(props)
|
||||||
const tabs = ['PROFILE', 'PICTURE', 'PREFERENCES', 'SPORTS']
|
const tabs = ['PROFILE', 'ACCOUNT', 'PICTURE', 'PREFERENCES', 'SPORTS']
|
||||||
const loading = computed(
|
const loading = computed(
|
||||||
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
||||||
)
|
)
|
||||||
|
@ -64,21 +64,10 @@
|
|||||||
: $t('user.PASSWORD')
|
: $t('user.PASSWORD')
|
||||||
"
|
"
|
||||||
:password="formData.password"
|
:password="formData.password"
|
||||||
|
:checkStrength="['reset', 'register'].includes(action)"
|
||||||
@updatePassword="updatePassword"
|
@updatePassword="updatePassword"
|
||||||
@passwordError="invalidateForm"
|
@passwordError="invalidateForm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="['reset', 'register'].includes(action)"
|
|
||||||
class="form-info"
|
|
||||||
>
|
|
||||||
<i class="fa fa-info-circle" aria-hidden="true" />
|
|
||||||
{{ $t('user.PASSWORD_INFO') }}
|
|
||||||
</div>
|
|
||||||
<PasswordStrength
|
|
||||||
v-if="['reset', 'register'].includes(action)"
|
|
||||||
:password="formData.password"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" :disabled="registration_disabled">
|
<button type="submit" :disabled="registration_disabled">
|
||||||
{{ $t(buttonText) }}
|
{{ $t(buttonText) }}
|
||||||
@ -118,7 +107,6 @@
|
|||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
import PasswordInput from '@/components/Common/PasswordInput.vue'
|
import PasswordInput from '@/components/Common/PasswordInput.vue'
|
||||||
import PasswordStrength from '@/components/Common/PasswordStength.vue'
|
|
||||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { TAppConfig } from '@/types/application'
|
import { TAppConfig } from '@/types/application'
|
||||||
import { ILoginRegisterFormData } from '@/types/user'
|
import { ILoginRegisterFormData } from '@/types/user'
|
||||||
@ -234,13 +222,6 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
padding: 0 $default-padding;
|
padding: 0 $default-padding;
|
||||||
}
|
}
|
||||||
.form-info {
|
|
||||||
color: var(--alert-color);
|
|
||||||
font-size: 0.8em;
|
|
||||||
margin-top: -0.2 * $default-margin;
|
|
||||||
padding: 0 $default-padding * 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin: $default-margin;
|
margin: $default-margin;
|
||||||
border: solid 1px var(--app-color);
|
border: solid 1px var(--app-color);
|
||||||
|
@ -35,8 +35,9 @@
|
|||||||
|
|
||||||
function getPath(tab: string) {
|
function getPath(tab: string) {
|
||||||
switch (tab) {
|
switch (tab) {
|
||||||
|
case 'ACCOUNT':
|
||||||
case 'PICTURE':
|
case 'PICTURE':
|
||||||
return '/profile/edit/picture'
|
return `/profile/edit/${tab.toLocaleLowerCase()}`
|
||||||
case 'PREFERENCES':
|
case 'PREFERENCES':
|
||||||
case 'SPORTS':
|
case 'SPORTS':
|
||||||
return `/profile${
|
return `/profile${
|
||||||
@ -52,7 +53,10 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~@/scss/vars.scss';
|
@import '~@/scss/vars.scss';
|
||||||
|
|
||||||
.profile-tabs {
|
.profile-tabs-checkboxes {
|
||||||
margin: $default-margin 0 $default-margin;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: $default-margin * 0.5;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
},
|
},
|
||||||
"PASSWORD_UPDATED": "Your password have been updated. Click {0} to log in.",
|
"PASSWORD_UPDATED": "Your password have been updated. Click {0} to log in.",
|
||||||
"PROFILE": {
|
"PROFILE": {
|
||||||
|
"ACCOUNT_EDITION": "Account edition",
|
||||||
"BACK_TO_PROFILE": "Back to profile",
|
"BACK_TO_PROFILE": "Back to profile",
|
||||||
"BIO": "Bio",
|
"BIO": "Bio",
|
||||||
"BIRTH_DATE": "Birth date",
|
"BIRTH_DATE": "Birth date",
|
||||||
@ -62,6 +63,7 @@
|
|||||||
"SPORTS_EDITION": "Sports preferences edition",
|
"SPORTS_EDITION": "Sports preferences edition",
|
||||||
"SUNDAY": "Sunday",
|
"SUNDAY": "Sunday",
|
||||||
"TABS": {
|
"TABS": {
|
||||||
|
"ACCOUNT": "account",
|
||||||
"PICTURE": "picture",
|
"PICTURE": "picture",
|
||||||
"PREFERENCES": "preferences",
|
"PREFERENCES": "preferences",
|
||||||
"PROFILE": "profile",
|
"PROFILE": "profile",
|
||||||
@ -75,6 +77,7 @@
|
|||||||
"LABEL": "label",
|
"LABEL": "label",
|
||||||
"STOPPED_SPEED_THRESHOLD": "stopped speed threshold"
|
"STOPPED_SPEED_THRESHOLD": "stopped speed threshold"
|
||||||
},
|
},
|
||||||
|
"SUCCESSFUL_UPDATE": "Your account has been updated successfully",
|
||||||
"UNITS": {
|
"UNITS": {
|
||||||
"LABEL": "Units for distance",
|
"LABEL": "Units for distance",
|
||||||
"IMPERIAL": "Imperial system (ft, mi)",
|
"IMPERIAL": "Imperial system (ft, mi)",
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
},
|
},
|
||||||
"PASSWORD_UPDATED": "Votre mot de passe a été mis à jour. Cliquez {0} pour vous connecter.",
|
"PASSWORD_UPDATED": "Votre mot de passe a été mis à jour. Cliquez {0} pour vous connecter.",
|
||||||
"PROFILE": {
|
"PROFILE": {
|
||||||
|
"ACCOUNT_EDITION": "Mise à jour du compte",
|
||||||
"BACK_TO_PROFILE": "Revenir au profil",
|
"BACK_TO_PROFILE": "Revenir au profil",
|
||||||
"BIO": "Bio",
|
"BIO": "Bio",
|
||||||
"BIRTH_DATE": "Date de naissance",
|
"BIRTH_DATE": "Date de naissance",
|
||||||
@ -61,6 +62,7 @@
|
|||||||
"SPORTS_EDITION": "Mise à jour des préférences des sports",
|
"SPORTS_EDITION": "Mise à jour des préférences des sports",
|
||||||
"SUNDAY": "Dimanche",
|
"SUNDAY": "Dimanche",
|
||||||
"TABS": {
|
"TABS": {
|
||||||
|
"ACCOUNT": "compte",
|
||||||
"PICTURE": "image",
|
"PICTURE": "image",
|
||||||
"PREFERENCES": "préférences",
|
"PREFERENCES": "préférences",
|
||||||
"PROFILE": "profil",
|
"PROFILE": "profil",
|
||||||
@ -79,6 +81,7 @@
|
|||||||
"LABEL": "label",
|
"LABEL": "label",
|
||||||
"STOPPED_SPEED_THRESHOLD": "seuil de vitesse arrêtée"
|
"STOPPED_SPEED_THRESHOLD": "seuil de vitesse arrêtée"
|
||||||
},
|
},
|
||||||
|
"SUCCESSFUL_UPDATE": "Votre compte a été modifié avec succès",
|
||||||
"TIMEZONE": "Fuseau horaire"
|
"TIMEZONE": "Fuseau horaire"
|
||||||
},
|
},
|
||||||
"REGISTER": "S'inscrire",
|
"REGISTER": "S'inscrire",
|
||||||
|
@ -8,6 +8,7 @@ import Profile from '@/components/User/ProfileDisplay/index.vue'
|
|||||||
import UserInfos from '@/components/User/ProfileDisplay/UserInfos.vue'
|
import UserInfos from '@/components/User/ProfileDisplay/UserInfos.vue'
|
||||||
import UserPreferences from '@/components/User/ProfileDisplay/UserPreferences.vue'
|
import UserPreferences from '@/components/User/ProfileDisplay/UserPreferences.vue'
|
||||||
import ProfileEdition from '@/components/User/ProfileEdition/index.vue'
|
import ProfileEdition from '@/components/User/ProfileEdition/index.vue'
|
||||||
|
import UserAccountEdition from '@/components/User/ProfileEdition/UserAccountEdition.vue'
|
||||||
import UserInfosEdition from '@/components/User/ProfileEdition/UserInfosEdition.vue'
|
import UserInfosEdition from '@/components/User/ProfileEdition/UserInfosEdition.vue'
|
||||||
import UserPictureEdition from '@/components/User/ProfileEdition/UserPictureEdition.vue'
|
import UserPictureEdition from '@/components/User/ProfileEdition/UserPictureEdition.vue'
|
||||||
import UserPreferencesEdition from '@/components/User/ProfileEdition/UserPreferencesEdition.vue'
|
import UserPreferencesEdition from '@/components/User/ProfileEdition/UserPreferencesEdition.vue'
|
||||||
@ -123,6 +124,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: 'UserInfosEdition',
|
name: 'UserInfosEdition',
|
||||||
component: UserInfosEdition,
|
component: UserInfosEdition,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'account',
|
||||||
|
name: 'UserAccountEdition',
|
||||||
|
component: UserAccountEdition,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'picture',
|
path: 'picture',
|
||||||
name: 'UserPictureEdition',
|
name: 'UserPictureEdition',
|
||||||
|
@ -142,6 +142,14 @@ button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-info {
|
||||||
|
color: var(--alert-color);
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-top: -0.2 * $default-margin;
|
||||||
|
padding: 0 $default-padding * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.upper {
|
.upper {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
--info-color: var(--app-color);
|
--info-color: var(--app-color);
|
||||||
--error-background-color: #ffd2d2;
|
--error-background-color: #ffd2d2;
|
||||||
--error-color: #db1924;
|
--error-color: #db1924;
|
||||||
|
--success-background-color: #d9ecd9;
|
||||||
|
--success-color: #306430;
|
||||||
|
|
||||||
--disabled-background-color: #e0e0e0;
|
--disabled-background-color: #e0e0e0;
|
||||||
--disabled-color: #a3a3a3;
|
--disabled-color: #a3a3a3;
|
||||||
|
@ -20,6 +20,7 @@ import { IRootState } from '@/store/modules/root/types'
|
|||||||
import { deleteUserAccount } from '@/store/modules/users/actions'
|
import { deleteUserAccount } from '@/store/modules/users/actions'
|
||||||
import {
|
import {
|
||||||
ILoginOrRegisterData,
|
ILoginOrRegisterData,
|
||||||
|
IUserAccountPayload,
|
||||||
IUserDeletionPayload,
|
IUserDeletionPayload,
|
||||||
IUserPasswordPayload,
|
IUserPasswordPayload,
|
||||||
IUserPasswordResetPayload,
|
IUserPasswordResetPayload,
|
||||||
@ -145,6 +146,31 @@ export const actions: ActionTree<IAuthUserState, IRootState> &
|
|||||||
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_ACCOUNT](
|
||||||
|
context: ActionContext<IAuthUserState, IRootState>,
|
||||||
|
payload: IUserAccountPayload
|
||||||
|
): void {
|
||||||
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
|
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, true)
|
||||||
|
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
||||||
|
authApi
|
||||||
|
.patch('auth/profile/edit/account', payload)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.status === 'success') {
|
||||||
|
context.commit(
|
||||||
|
AUTH_USER_STORE.MUTATIONS.UPDATE_AUTH_USER_PROFILE,
|
||||||
|
res.data.data
|
||||||
|
)
|
||||||
|
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS, true)
|
||||||
|
} else {
|
||||||
|
handleError(context, null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => handleError(context, error))
|
||||||
|
.finally(() =>
|
||||||
|
context.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING, false)
|
||||||
|
)
|
||||||
|
},
|
||||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PREFERENCES](
|
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PREFERENCES](
|
||||||
context: ActionContext<IAuthUserState, IRootState>,
|
context: ActionContext<IAuthUserState, IRootState>,
|
||||||
payload: IUserPreferencesPayload
|
payload: IUserPreferencesPayload
|
||||||
|
@ -8,6 +8,7 @@ export enum AuthUserActions {
|
|||||||
SEND_PASSWORD_RESET_REQUEST = 'SEND_PASSWORD_RESET_REQUEST',
|
SEND_PASSWORD_RESET_REQUEST = 'SEND_PASSWORD_RESET_REQUEST',
|
||||||
RESET_USER_PASSWORD = 'RESET_USER_PASSWORD',
|
RESET_USER_PASSWORD = 'RESET_USER_PASSWORD',
|
||||||
RESET_USER_SPORT_PREFERENCES = 'RESET_USER_SPORT_PREFERENCES',
|
RESET_USER_SPORT_PREFERENCES = 'RESET_USER_SPORT_PREFERENCES',
|
||||||
|
UPDATE_USER_ACCOUNT = 'UPDATE_USER_ACCOUNT',
|
||||||
UPDATE_USER_PICTURE = 'UPDATE_USER_PICTURE',
|
UPDATE_USER_PICTURE = 'UPDATE_USER_PICTURE',
|
||||||
UPDATE_USER_PROFILE = 'UPDATE_USER_PROFILE',
|
UPDATE_USER_PROFILE = 'UPDATE_USER_PROFILE',
|
||||||
UPDATE_USER_PREFERENCES = 'UPDATE_USER_PREFERENCES',
|
UPDATE_USER_PREFERENCES = 'UPDATE_USER_PREFERENCES',
|
||||||
@ -19,6 +20,7 @@ export enum AuthUserGetters {
|
|||||||
AUTH_USER_PROFILE = 'AUTH_USER_PROFILE',
|
AUTH_USER_PROFILE = 'AUTH_USER_PROFILE',
|
||||||
IS_ADMIN = 'IS_ADMIN',
|
IS_ADMIN = 'IS_ADMIN',
|
||||||
IS_AUTHENTICATED = 'IS_AUTHENTICATED',
|
IS_AUTHENTICATED = 'IS_AUTHENTICATED',
|
||||||
|
IS_SUCCESS = 'IS_SUCCESS',
|
||||||
USER_LOADING = 'USER_LOADING',
|
USER_LOADING = 'USER_LOADING',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,5 +28,6 @@ export enum AuthUserMutations {
|
|||||||
CLEAR_AUTH_USER_TOKEN = 'CLEAR_AUTH_USER_TOKEN',
|
CLEAR_AUTH_USER_TOKEN = 'CLEAR_AUTH_USER_TOKEN',
|
||||||
UPDATE_AUTH_TOKEN = 'UPDATE_AUTH_TOKEN',
|
UPDATE_AUTH_TOKEN = 'UPDATE_AUTH_TOKEN',
|
||||||
UPDATE_AUTH_USER_PROFILE = 'UPDATE_AUTH_USER_PROFILE',
|
UPDATE_AUTH_USER_PROFILE = 'UPDATE_AUTH_USER_PROFILE',
|
||||||
|
UPDATE_IS_SUCCESS = 'UPDATE_USER_IS_SUCCESS',
|
||||||
UPDATE_USER_LOADING = 'UPDATE_USER_LOADING',
|
UPDATE_USER_LOADING = 'UPDATE_USER_LOADING',
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@ export const getters: GetterTree<IAuthUserState, IRootState> &
|
|||||||
[AUTH_USER_STORE.GETTERS.IS_ADMIN]: (state: IAuthUserState) => {
|
[AUTH_USER_STORE.GETTERS.IS_ADMIN]: (state: IAuthUserState) => {
|
||||||
return state.authUserProfile && state.authUserProfile.admin
|
return state.authUserProfile && state.authUserProfile.admin
|
||||||
},
|
},
|
||||||
|
[AUTH_USER_STORE.GETTERS.IS_SUCCESS]: (state: IAuthUserState) => {
|
||||||
|
return state.isSuccess
|
||||||
|
},
|
||||||
[AUTH_USER_STORE.GETTERS.USER_LOADING]: (state: IAuthUserState) => {
|
[AUTH_USER_STORE.GETTERS.USER_LOADING]: (state: IAuthUserState) => {
|
||||||
return state.loading
|
return state.loading
|
||||||
},
|
},
|
||||||
|
@ -24,6 +24,12 @@ export const mutations: MutationTree<IAuthUserState> & TAuthUserMutations = {
|
|||||||
) {
|
) {
|
||||||
state.authUserProfile = authUserProfile
|
state.authUserProfile = authUserProfile
|
||||||
},
|
},
|
||||||
|
[AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS](
|
||||||
|
state: IAuthUserState,
|
||||||
|
isSuccess: boolean
|
||||||
|
) {
|
||||||
|
state.isSuccess = isSuccess
|
||||||
|
},
|
||||||
[AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING](
|
[AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING](
|
||||||
state: IAuthUserState,
|
state: IAuthUserState,
|
||||||
loading: boolean
|
loading: boolean
|
||||||
|
@ -4,5 +4,6 @@ import { IUserProfile } from '@/types/user'
|
|||||||
export const authUserState: IAuthUserState = {
|
export const authUserState: IAuthUserState = {
|
||||||
authToken: null,
|
authToken: null,
|
||||||
authUserProfile: <IUserProfile>{},
|
authUserProfile: <IUserProfile>{},
|
||||||
|
isSuccess: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,13 @@ import {
|
|||||||
IUserPicturePayload,
|
IUserPicturePayload,
|
||||||
IUserPreferencesPayload,
|
IUserPreferencesPayload,
|
||||||
IUserSportPreferencesPayload,
|
IUserSportPreferencesPayload,
|
||||||
|
IUserAccountPayload,
|
||||||
} from '@/types/user'
|
} from '@/types/user'
|
||||||
|
|
||||||
export interface IAuthUserState {
|
export interface IAuthUserState {
|
||||||
authToken: string | null
|
authToken: string | null
|
||||||
authUserProfile: IUserProfile
|
authUserProfile: IUserProfile
|
||||||
|
isSuccess: boolean
|
||||||
loading: boolean
|
loading: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +50,11 @@ export interface IAuthUserActions {
|
|||||||
payload: IUserPayload
|
payload: IUserPayload
|
||||||
): void
|
): void
|
||||||
|
|
||||||
|
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_ACCOUNT](
|
||||||
|
context: ActionContext<IAuthUserState, IRootState>,
|
||||||
|
payload: IUserAccountPayload
|
||||||
|
): void
|
||||||
|
|
||||||
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PREFERENCES](
|
[AUTH_USER_STORE.ACTIONS.UPDATE_USER_PREFERENCES](
|
||||||
context: ActionContext<IAuthUserState, IRootState>,
|
context: ActionContext<IAuthUserState, IRootState>,
|
||||||
payload: IUserPreferencesPayload
|
payload: IUserPreferencesPayload
|
||||||
@ -99,6 +106,8 @@ export interface IAuthUserGetters {
|
|||||||
|
|
||||||
[AUTH_USER_STORE.GETTERS.IS_AUTHENTICATED](state: IAuthUserState): boolean
|
[AUTH_USER_STORE.GETTERS.IS_AUTHENTICATED](state: IAuthUserState): boolean
|
||||||
|
|
||||||
|
[AUTH_USER_STORE.GETTERS.IS_SUCCESS](state: IAuthUserState): boolean
|
||||||
|
|
||||||
[AUTH_USER_STORE.GETTERS.USER_LOADING](state: IAuthUserState): boolean
|
[AUTH_USER_STORE.GETTERS.USER_LOADING](state: IAuthUserState): boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +121,10 @@ export type TAuthUserMutations<S = IAuthUserState> = {
|
|||||||
state: S,
|
state: S,
|
||||||
authUserProfile: IUserProfile
|
authUserProfile: IUserProfile
|
||||||
): void
|
): void
|
||||||
|
[AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS](
|
||||||
|
state: S,
|
||||||
|
isSuccess: boolean
|
||||||
|
): void
|
||||||
[AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING](
|
[AUTH_USER_STORE.MUTATIONS.UPDATE_USER_LOADING](
|
||||||
state: S,
|
state: S,
|
||||||
loading: boolean
|
loading: boolean
|
||||||
|
@ -31,6 +31,10 @@ export interface IUserPayload {
|
|||||||
first_name: string
|
first_name: string
|
||||||
last_name: string
|
last_name: string
|
||||||
location: string
|
location: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUserAccountPayload {
|
||||||
|
email?: string
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user