Refactored employee-Details to fit store and fetch / persist logic into pinia store. Added a clean state to reset to.
This commit is contained in:
123
src/stores/employee.ts
Normal file
123
src/stores/employee.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||||
|
import axios from '@/axios'
|
||||||
|
import { useUser } from './user'
|
||||||
|
import { useNotifications } from './notifications'
|
||||||
|
|
||||||
|
type ResultData = {
|
||||||
|
employee: {
|
||||||
|
id: number,
|
||||||
|
firstName: string,
|
||||||
|
lastName: string,
|
||||||
|
shorthand: string,
|
||||||
|
phone: string,
|
||||||
|
mobile: string,
|
||||||
|
email: string,
|
||||||
|
contractHours: number,
|
||||||
|
hasUser: boolean,
|
||||||
|
},
|
||||||
|
user?: {
|
||||||
|
id?: number,
|
||||||
|
username?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = useUser()
|
||||||
|
const notifications = useNotifications()
|
||||||
|
|
||||||
|
export const useEmployee = defineStore({
|
||||||
|
id: 'employee',
|
||||||
|
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
clean: {
|
||||||
|
employee: {
|
||||||
|
id: NaN,
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
shorthand: '',
|
||||||
|
phone: '',
|
||||||
|
mobile: '',
|
||||||
|
email: '',
|
||||||
|
contractHours: NaN,
|
||||||
|
hasUser: false
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: NaN,
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
passwordConfirm: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
employee: {
|
||||||
|
id: NaN,
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
shorthand: '',
|
||||||
|
phone: '',
|
||||||
|
mobile: '',
|
||||||
|
email: '',
|
||||||
|
contractHours: NaN,
|
||||||
|
hasUser: false
|
||||||
|
},
|
||||||
|
|
||||||
|
user: {
|
||||||
|
id: NaN,
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
passwordConfirm: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
async fetchFromApi(id: string | string[]) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data : ResultData = await <ResultData>(await axios.get('employees/'+id, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer '+user.token
|
||||||
|
}
|
||||||
|
})).data
|
||||||
|
|
||||||
|
Object.assign(this.clean.employee, data.employee)
|
||||||
|
Object.assign(this.clean.user, data.user)
|
||||||
|
Object.assign(this.employee, data.employee),
|
||||||
|
Object.assign(this.user, data.user)
|
||||||
|
}
|
||||||
|
catch(err){
|
||||||
|
if(err instanceof Error) notifications.add('danger', err.message, -1)
|
||||||
|
else console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
Object.assign(this.user, this.clean.user)
|
||||||
|
Object.assign(this.employee, this.clean.employee)
|
||||||
|
},
|
||||||
|
|
||||||
|
/** TODO: #23 Persist user if password is changed */
|
||||||
|
async persist() {
|
||||||
|
try {
|
||||||
|
const result = await axios.patch('employees/'+this.employee.id, this.employee,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer '+user.token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Object.assign(this.clean.employee, this.employee)
|
||||||
|
Object.assign(this.clean.user, this.user)
|
||||||
|
notifications.add('success', result.statusText)
|
||||||
|
}
|
||||||
|
catch(error) {
|
||||||
|
if(error instanceof Error) notifications.add('danger', error.message, -1)
|
||||||
|
else console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useEmployee, import.meta.hot))
|
||||||
|
}
|
||||||
@@ -69,8 +69,8 @@
|
|||||||
{{}}
|
{{}}
|
||||||
</div>
|
</div>
|
||||||
<label for="password-repeat" class="form-label">Neues Passwort wiederholen:</label>
|
<label for="password-repeat" class="form-label">Neues Passwort wiederholen:</label>
|
||||||
<input type="password" v-model="state.user.passwordRepeat" id="password-repeat" class="form-control mb-3" :class="{'is-invalid': classIsInvalid('user', 'passwordRepeat')}" :disabled="!editEmployee" >
|
<input type="password" v-model="state.user.passwordConfirm" id="password-repeat" class="form-control mb-3" :class="{'is-invalid': classIsInvalid('user', 'passwordConfirm')}" :disabled="!editEmployee" >
|
||||||
<div v-for="(error) in v$.user.passwordRepeat.$errors" class="invalid-feedback" id="passwordRepeatFeedback">
|
<div v-for="(error) in v$.user.passwordConfirm.$errors" class="invalid-feedback" id="passwordRepeatFeedback">
|
||||||
{{error.$message}}
|
{{error.$message}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -99,59 +99,18 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
type ResultData = {
|
|
||||||
employee: {
|
|
||||||
id: number,
|
|
||||||
firstName: string,
|
|
||||||
lastName: string,
|
|
||||||
shorthand: string,
|
|
||||||
phone: string,
|
|
||||||
mobile: string,
|
|
||||||
email: string,
|
|
||||||
contractHours: number,
|
|
||||||
hasUser: Boolean,
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
id?: number,
|
|
||||||
username?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import VProfileControls from '@/components/VProfileControls.vue';
|
import VProfileControls from '@/components/VProfileControls.vue';
|
||||||
import { reactive, onMounted, computed, ref, watch } from 'vue'
|
import { onMounted, computed, ref, watch } from 'vue'
|
||||||
import { useUser } from '@/stores/user';
|
import { useEmployee } from '@/stores/employee'
|
||||||
import axios from '@/axios'
|
|
||||||
import { useNotifications } from '@/stores/notifications';
|
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import useVuelidate from '@vuelidate/core'
|
import useVuelidate from '@vuelidate/core'
|
||||||
import { required, email, between, decimal, sameAs, helpers } from '@vuelidate/validators'
|
import { required, email, between, decimal, sameAs, helpers } from '@vuelidate/validators'
|
||||||
|
|
||||||
const userStore = useUser()
|
|
||||||
const useNotification = useNotifications()
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const state = useEmployee()
|
||||||
|
|
||||||
const editEmployee = ref(false)
|
const editEmployee = ref(false)
|
||||||
|
|
||||||
let state = reactive({
|
|
||||||
employee: {
|
|
||||||
id: NaN,
|
|
||||||
firstName: '',
|
|
||||||
lastName: '',
|
|
||||||
shorthand: '',
|
|
||||||
phone: '',
|
|
||||||
mobile: '',
|
|
||||||
email: '',
|
|
||||||
contractHours: '',
|
|
||||||
hasUser: false
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
id: NaN,
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
passwordRepeat: ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const rules = computed(() => ({
|
const rules = computed(() => ({
|
||||||
employee: {
|
employee: {
|
||||||
firstName: {
|
firstName: {
|
||||||
@@ -166,35 +125,26 @@ const rules = computed(() => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
passwordRepeat: {
|
passwordConfirm: {
|
||||||
sameAs: helpers.withMessage('Die eingebebenen Passwörter müssen übereinstimmen', sameAs(state.user.password))
|
sameAs: helpers.withMessage('Die eingebebenen Passwörter müssen übereinstimmen', sameAs(state.user.password))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const v$ = useVuelidate(rules, state)
|
|
||||||
|
const v$ = useVuelidate(rules,
|
||||||
|
{
|
||||||
|
employee: state.employee,
|
||||||
|
user: state.user
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const createUser = ref(false)
|
const createUser = ref(false)
|
||||||
|
|
||||||
async function onUpdateEmployee() {
|
async function onUpdateEmployee() {
|
||||||
if(await v$.value.$validate()){
|
if(await v$.value.$validate()){
|
||||||
if(state.user.password !== undefined && state.user.password.length > 0){
|
await state.persist()
|
||||||
// push user
|
onToggleEdit()
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = await axios.patch('employees/'+state.employee.id, state.employee,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer '+userStore.token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
onToggleEdit()
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
if(error instanceof Error) useNotification.add('danger', error.message)
|
|
||||||
else console.log(error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,19 +155,19 @@ function onEnter() {
|
|||||||
function onToggleEdit() {
|
function onToggleEdit() {
|
||||||
editEmployee.value = !editEmployee.value
|
editEmployee.value = !editEmployee.value
|
||||||
v$.value.$reset()
|
v$.value.$reset()
|
||||||
getEmployee()
|
state.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => [route.params, route.name], ([newParam, newName], [oldParam, oldName]) => {
|
watch(() => [route.params, route.name], ([newParam, newName], [oldParam, oldName]) => {
|
||||||
if(newName === oldName && newParam !== oldParam) {
|
if(newName === oldName && newParam !== oldParam) {
|
||||||
getEmployee()
|
state.fetchFromApi(route.params.id)
|
||||||
createUser.value = false
|
createUser.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function classIsInvalid<E extends 'user' | 'employee'>(entity: E, field: E extends 'user' ? 'passwordRepeat' : 'firstName' | 'email' | 'contractHours') : boolean {
|
function classIsInvalid<E extends 'user' | 'employee'>(entity: E, field: E extends 'user' ? 'passwordConfirm' : 'firstName' | 'email' | 'contractHours') : boolean {
|
||||||
if(entity === 'user'){
|
if(entity === 'user'){
|
||||||
let fU = field as 'passwordRepeat'
|
let fU = field as 'passwordConfirm'
|
||||||
return v$.value.user[fU].$dirty && v$.value.user[fU].$invalid
|
return v$.value.user[fU].$dirty && v$.value.user[fU].$invalid
|
||||||
}
|
}
|
||||||
else if (entity === 'employee') {
|
else if (entity === 'employee') {
|
||||||
@@ -227,23 +177,8 @@ function classIsInvalid<E extends 'user' | 'employee'>(entity: E, field: E exten
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getEmployee() {
|
|
||||||
try {
|
|
||||||
const data : ResultData = await <ResultData>(await axios.get('employees/'+route.params.id, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer '+userStore.token
|
|
||||||
}
|
|
||||||
})).data
|
|
||||||
|
|
||||||
Object.assign(state, data)
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
if(err instanceof Error) useNotification.add('danger', err.message, -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
getEmployee()
|
state.fetchFromApi(route.params.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user