Employees-Index: Create new User.
This commit is contained in:
307
src/components/Employees/EmployeeForm.vue
Normal file
307
src/components/Employees/EmployeeForm.vue
Normal 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>
|
||||
@@ -3,7 +3,7 @@
|
||||
AddEmployeeModal(
|
||||
|
||||
:searchData="store.state.rows"
|
||||
:searchFields="['first_name', 'last_name']"
|
||||
:searchFields="['firstName', 'lastName']"
|
||||
:searchRow="addEmployeeRow"
|
||||
:modalId="modalId"
|
||||
@emitResult="addEmployee($event)"
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user