233 lines
No EOL
6.7 KiB
Vue
233 lines
No EOL
6.7 KiB
Vue
<script setup lang="ts">
|
|
import {useAuthStore} from '@/stores/auth.store.ts';
|
|
import {storeToRefs} from 'pinia';
|
|
import {onBeforeMount, ref, reactive} from 'vue';
|
|
import {useRouter} from "vue-router";
|
|
import axios from "axios";
|
|
|
|
const router = useRouter();
|
|
const authStore = useAuthStore();
|
|
const {userData} = storeToRefs(authStore);
|
|
|
|
const localUserData = reactive({...userData.value});
|
|
|
|
const emit = defineEmits([
|
|
'userProfilePage'
|
|
]);
|
|
|
|
let timezones = ref<string[]>([]);
|
|
let roleList = ref<string[]>([]);
|
|
|
|
const form = ref<HTMLFormElement | null>(null);
|
|
const passwordForm = ref<HTMLFormElement | null>(null);
|
|
|
|
const dialog = ref(false);
|
|
const passwordData = reactive({
|
|
oldPassword: '',
|
|
newPassword: '',
|
|
confirmPassword: '',
|
|
});
|
|
|
|
const formRules = {
|
|
'emailRules': [(v: string) => !v || /.+@.+\..+/.test(v) || 'E-mail must be a valid format'],
|
|
'cellphoneRules': [(v: string) => !v || /^[0-9-()]*$/.test(v) || 'Cellphone must be a valid number'],
|
|
'passwordConfirmationRule': [
|
|
(v: string) => !!v || 'Password confirmation is required',
|
|
(v: string) => v === passwordData.newPassword || 'Passwords do not match'
|
|
],
|
|
'requiredRule': [(v: string) => !!v || 'This field is required'],
|
|
}
|
|
|
|
const saveUser = async () => {
|
|
if (!form.value) return
|
|
|
|
const {valid} = await form.value.validate();
|
|
if (!valid) return
|
|
|
|
authStore.userData = {...localUserData};
|
|
await authStore.updateUser();
|
|
};
|
|
|
|
const goBack = () => {
|
|
router.go(-1);
|
|
}
|
|
|
|
const openPasswordDialog = () => {
|
|
dialog.value = true;
|
|
};
|
|
|
|
const closePasswordDialog = () => {
|
|
dialog.value = false;
|
|
passwordForm.value?.reset();
|
|
passwordForm.value?.resetValidation();
|
|
};
|
|
|
|
const resetPassword = async () => {
|
|
console.log('aaaa')
|
|
try {
|
|
await axios.put('/api/user/password', passwordData)
|
|
console.log('Password changed');
|
|
closePasswordDialog()
|
|
return
|
|
} catch (e) {
|
|
const errorMessage = e.response?.data?.error || 'An unexpected error occurred.';
|
|
console.error('Error changing password:' + errorMessage);
|
|
return
|
|
}
|
|
};
|
|
|
|
onBeforeMount(async () => {
|
|
await axios.get('/timezoneList').then(response => {
|
|
timezones.value = response?.data
|
|
})
|
|
if (userData.value.role === 'admin') {
|
|
await axios.get('/roleList').then(response => {
|
|
roleList.value = response?.data
|
|
})
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<v-form ref="form">
|
|
<v-container>
|
|
<v-row>
|
|
<v-col cols="12" md="6">
|
|
<v-text-field
|
|
v-model="localUserData.login"
|
|
label="Login"
|
|
required
|
|
hint="Your public username."
|
|
persistent-hint
|
|
></v-text-field>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-text-field
|
|
v-model="localUserData.email"
|
|
:rules="formRules.emailRules"
|
|
label="Email Address"
|
|
hint="Used for notifications and account recovery."
|
|
persistent-hint
|
|
></v-text-field>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-text-field
|
|
v-model="localUserData.firstName"
|
|
label="First Name"
|
|
required
|
|
></v-text-field>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-text-field
|
|
v-model="localUserData.lastName"
|
|
label="Last Name"
|
|
required
|
|
></v-text-field>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-text-field
|
|
v-model="localUserData.cellPhone"
|
|
:rules="formRules.cellphoneRules"
|
|
label="Cell Phone"
|
|
></v-text-field>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-autocomplete
|
|
v-model="localUserData.timezone"
|
|
:items="timezones"
|
|
label="Timezone"
|
|
hint="Sets the time for all events and schedules."
|
|
persistent-hint
|
|
></v-autocomplete>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-select
|
|
v-model="localUserData.role"
|
|
:items="roleList"
|
|
label="Ruolo"
|
|
:disabled="userData.role !== 'admin'"
|
|
></v-select>
|
|
</v-col>
|
|
|
|
</v-row>
|
|
<v-row>
|
|
<v-col class="d-flex justify-end">
|
|
<v-btn color="secondary" @click="goBack" class="mr-4">
|
|
Back
|
|
</v-btn>
|
|
<v-btn color="primary" @click="saveUser">
|
|
Save Changes
|
|
</v-btn>
|
|
<v-btn color="error" @click="openPasswordDialog">
|
|
Reset Password
|
|
</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</v-form>
|
|
<v-dialog v-model="dialog" persistent max-width="600px">
|
|
|
|
<v-card>
|
|
<v-card-title>
|
|
<span class="text-h5">Reset Your Password</span>
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<p class="text-subtitle-1 mb-4">
|
|
Please be sure about the new password you are choosing. Password recovery via email is not implemented yet,
|
|
so
|
|
a forgotten password cannot be recovered.
|
|
</p>
|
|
</v-card-text>
|
|
<v-form ref="passwordForm" @submit.prevent="resetPassword">
|
|
<v-container>
|
|
<v-row>
|
|
<v-col cols="12">
|
|
<v-text-field
|
|
v-model="passwordData.oldPassword"
|
|
label="Old Password"
|
|
type="password"
|
|
:rules="formRules.requiredRule"
|
|
required
|
|
></v-text-field>
|
|
</v-col>
|
|
<v-col cols="12">
|
|
<v-text-field
|
|
v-model="passwordData.newPassword"
|
|
label="New Password"
|
|
type="password"
|
|
:rules="formRules.requiredRule"
|
|
required
|
|
></v-text-field>
|
|
</v-col>
|
|
<v-col cols="12">
|
|
<v-text-field
|
|
v-model="passwordData.confirmPassword"
|
|
label="Confirm New Password"
|
|
type="password"
|
|
:rules="formRules.passwordConfirmationRule"
|
|
required
|
|
></v-text-field>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn color="blue-darken-1" variant="text" @click="closePasswordDialog">
|
|
Cancel
|
|
</v-btn>
|
|
<v-btn type="submit" color="blue-darken-1" variant="tonal">
|
|
Confirm
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-form>
|
|
</v-card>
|
|
</v-dialog>
|
|
</div>
|
|
</template> |