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:
Sockenklaus
2021-11-02 00:59:55 +01:00
parent 5a65b596ee
commit a9b394bf09
2 changed files with 143 additions and 85 deletions

123
src/stores/employee.ts Normal file
View 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))
}

View File

@@ -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>