Employees-Index: Create new User.

This commit is contained in:
Sockenklaus
2021-11-17 03:35:49 +01:00
parent 8071e8ef91
commit 6f237ff8fa
12 changed files with 408 additions and 347 deletions

View File

@@ -0,0 +1,307 @@
<template>
<EmployeeFormControls
class="mb-5"
:isActive="editEmployee || createUser"
@save="submitForm"
@toggleEdit="toggleEdit"
/>
<form class="text-start" @keyup.enter="submitForm">
<div class="row mb-5">
<div class="col pe-5">
<h4 class="">Persönliche Informationen</h4>
<label for="first-name" class="form-label">Vorname:</label>
<input
type="text"
v-model.trim="employee.firstName"
id="first-name"
class="form-control"
:class="classIsInvalid(v$.firstName)"
:disabled="!editEmployee"
>
<div
v-for="(error) in v$.firstName.$errors"
class="invalid-feedback"
id="firstNameFeedback">
{{error.$message}}
</div>
<label for="last-name" class="form-label">Nachname:</label>
<input type="text" v-model.trim="employee.lastName" id="last-name" class="form-control" :disabled="!editEmployee">
<label for="shorthand" class="form-label">Kürzel:</label>
<input
type="text"
v-model.trim="employee.shorthand"
id="shorthand"
class="form-control"
:class="classIsInvalid(v$.shorthand)"
:disabled="!editEmployee"
>
<div v-for="(error) in v$.shorthand.$errors" class="invalid-feedback" id="shorthandFeedback">
{{ error.$message }}
</div>
</div>
<div class="col ps-5 border-start">
<h4 class="">Kontaktdaten</h4>
<label for="phone" class="form-label">Telefonnummer:</label>
<MaskInput
type="tel"
id="phone"
v-model="employee.phone"
:mask="'000[00]{ / }0000 [0000]'"
class="form-control"
:disabled="!editEmployee"
placeholder="_____ / ____ ____"
/>
<label for="mobile" class="form-label">Handynummer:</label>
<MaskInput
type="tel"
v-model="employee.mobile"
:mask="'000[00]{ / }[0000] [0000]'"
id="mobile"
class="form-control"
:disabled="!editEmployee"
placeholder="_____ / ____ ____"
/>
<label for="email" class="form-label">E-Mail-Adresse:</label>
<input
type="email"
v-model.trim="employee.email"
id="email"
class="form-control"
:class="classIsInvalid(v$.email)"
:disabled="!editEmployee"
>
<div v-for="(error) in v$.email.$errors" class="invalid-feedback" id="emailFeedback">
{{error.$message}}
</div>
</div>
</div>
<div class="row">
<div class="col pe-5">
<h4 class="">Vertragsinformationen:</h4>
<label for="contract-hours" min="0" max="40" class="form-label">Wochenstunden:</label>
<MaskInput
v-model:typed="employee.contractHours"
v-model="strContractHours"
:mask="Number"
:signed="false"
@click="$event.target.select()"
id="contract-hours"
class="form-control"
:class="classIsInvalid(v$.contractHours)"
:disabled="!editEmployee || !userStore.isAdmin"
/>
<div v-for="(error) in v$.contractHours.$errors" class="invalid-feedback" id="contractHoursFeedback">
{{error.$message}}
</div>
</div>
<div class="col ps-5 border-start">
<div class="form-check form-switch">
<input
type="checkbox"
role="switch"
class="form-check-input"
id="userEnabledSwitch"
:checked="createUser || userEnabled"
@click="toggleCreateUser"
:disabled="userEnabled"
>
<label for="userEnabledSwitch" class="form-check-label h5">{{ labelUserEnabled }}</label>
</div>
<template v-if="userEnabled || createUser">
<label for="username" class="form-label">Benutzername:</label>
<input
type="text"
v-model.trim="employee.username"
id="username"
class="form-control"
:class="classIsInvalid(v$.username)"
:disabled="!createUser"
>
<div v-for="(error) in v$.username.$errors" class="invalid-feedback" id="usernameFeedback">
{{ error.$message }}
</div>
<label for="password" class="form-label">Neues Passwort:</label>
<input
type="password"
v-model="employee.password"
id="password"
class="form-control"
:class="classIsInvalid(v$.password)"
:disabled="!editEmployee && !createUser"
>
<div v-for="(error) in v$.password.$errors" id="passwordFeedback" class="invalid-feedback">
{{error.$message}}
</div>
<label for="password-repeat" class="form-label">Neues Passwort wiederholen:</label>
<input
type="password"
v-model="employee.passwordConfirm"
id="password-repeat"
class="form-control mb-3"
:class="classIsInvalid(v$.passwordConfirm)"
:disabled="!editEmployee && !createUser"
>
<div v-for="(error) in v$.passwordConfirm.$errors" class="invalid-feedback" id="passwordRepeatFeedback">
{{error.$message}}
</div>
</template>
</div>
</div>
</form>
<EmployeeFormControls
class="mt-5"
:isActive="editEmployee || createUser"
@save="submitForm"
@toggleEdit="toggleEdit"
/>
</template>
<script setup lang="ts">
import { toRefs, ref, computed, onMounted } from 'vue'
import { useVuelidate } from '@vuelidate/core'
import { required, email, between, decimal, sameAs, requiredIf, helpers } from '@vuelidate/validators'
import { storeToRefs } from 'pinia'
import { useUser } from '@/stores/user'
import { useEmployee } from '@/stores/employee'
import EmployeeFormControls from '@/components/Employees/EmployeeFormControls.vue'
import { IMaskComponent as MaskInput } from 'vue-imask'
/**
* Props
*/
const props = defineProps<{
id?: string | string[]
}>()
/**
* Stores
*/
const userStore = useUser()
const employeeStore = useEmployee()
const { employee, userEnabled } = storeToRefs(employeeStore)
/**
* Local Refs
*/
const createUser = ref(false)
const strContractHours = ref('')
const editEmployee = ref(props.id ? false : true)
/**
* Vuelidate Validator
*/
function validateApiErrors(field: string, rule: string) {
const apiErrors = employeeStore.apiValidationErrors
const error = apiErrors.find((element) => {
return element.field === field && element.rule === rule
})
if(error === undefined){
return true
}
else return helpers.withMessage(error.message, () => false)
}
const rules = computed(() => ({
firstName: {
required: required
},
shorthand: {
required: required,
validateApiErrors: validateApiErrors("shorthand", "unique")
},
email: {
email: email
},
contractHours: {
decimal,
betweenValue: between(0, 40)
},
username: {
requiredIf: requiredIf(() => createUser.value),
unique: validateApiErrors('username', 'unique')
},
password: {
requiredIf: requiredIf(() => createUser.value)
},
passwordConfirm: {
sameAs: sameAs(employee.value.password)
}
}))
const v$ = useVuelidate(rules, employee)
/**
* Getters for dynamic classes and labels
*/
function classIsInvalid(validator: any) : string {
return validator.$dirty && validator.$invalid ? 'is-invalid' : ''
}
const labelUserEnabled = computed(() => {
return userEnabled ? 'Benutzerinformationen' : 'Kein Benutzer vorhanden'
})
/**
* Actions
*/
function toggleCreateUser() {
createUser.value = !createUser.value
}
function toggleEdit() {
if(createUser.value) {
editEmployee.value = false
createUser.value = false
}
else editEmployee.value = !editEmployee.value
v$.value.$reset()
employeeStore.reset()
}
async function submitForm(){
if(await v$.value.$validate()) {
if(employee.value.id){
employeeStore.patchEmployee()
// werte apiValidation aus!!!
toggleEdit()
}
else {
employeeStore.postEmployee()
// werte apiValidation aus!!!
}
}
}
/**
* Initialize the Component
*/
onMounted(() => {
if(props.id !== undefined) {
employeeStore.fetchFromApi(props.id)
}
else {
employeeStore.$reset()
}
})
</script>
<script lang="scss">
</script>

View File

@@ -3,7 +3,7 @@
AddEmployeeModal(
:searchData="store.state.rows"
:searchFields="['first_name', 'last_name']"
:searchFields="['firstName', 'lastName']"
:searchRow="addEmployeeRow"
:modalId="modalId"
@emitResult="addEmployee($event)"

View File

@@ -2,6 +2,7 @@
<nav class="nav justify-content-center border-bottom mb-4 pb-2 d-flex">
<router-link class="nav-link" :to="{name: 'Home'}">Home</router-link>
<router-link v-if="userStore.isAdmin" :to="{name: 'Employees/Index'}" class="nav-link">Mitarbeiter</router-link>
<router-link v-if="userStore.isAdmin" :to="{name: 'Employees/New'}" class="nav-link">Neuer Mitarbeiter</router-link>
<div class="ms-auto"></div>
<router-link
v-if="userStore.isLoggedIn"