added input masks to EmployeeDetails, started implementing Employees/Index. Updated to Vue 3.2.21
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
|
||||
<VProfileControls class="mb-5" :isActive="editEmployee || createUser" @save="onUpdateEmployee" @toggleEdit="onToggleEdit" />
|
||||
<form class="text-start">
|
||||
<VProfileControls class="mb-5" :isActive="editEmployee || createUser" @save="onUpdateEmployee" @toggleEdit="onToggleEdit" />
|
||||
|
||||
<form @keydown.enter="onEnter" class="text-start">
|
||||
<div class="row mb-5">
|
||||
<div class="col pe-5">
|
||||
<h4 class="">Persönliche Informationen</h4>
|
||||
@@ -10,7 +10,7 @@
|
||||
<label for="first-name" class="form-label">Vorname:</label>
|
||||
<input
|
||||
type="text"
|
||||
v-model.trim="state.employee.firstName"
|
||||
v-model.trim="employee.firstName"
|
||||
id="first-name"
|
||||
class="form-control"
|
||||
:class="classIsInvalid(v$.firstName)"
|
||||
@@ -24,31 +24,49 @@
|
||||
</div>
|
||||
|
||||
<label for="last-name" class="form-label">Nachname:</label>
|
||||
<input type="text" v-model.trim="state.employee.lastName" id="last-name" class="form-control" :disabled="!editEmployee">
|
||||
<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="state.employee.shorthand"
|
||||
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>
|
||||
<input type="phone" v-model.trim="state.employee.phone" id="phone" class="form-control" :disabled="!editEmployee">
|
||||
<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>
|
||||
<input type="mobile" v-model.trim="state.employee.mobile" id="mobile" class="form-control" :disabled="!editEmployee">
|
||||
<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="state.employee.email"
|
||||
v-model.trim="employee.email"
|
||||
id="email"
|
||||
class="form-control"
|
||||
:class="classIsInvalid(v$.email)"
|
||||
@@ -63,15 +81,21 @@
|
||||
<div class="row">
|
||||
<div class="col pe-5">
|
||||
<h4 class="">Vertragsinformationen:</h4>
|
||||
<label for="contract-hours" class="form-label">Wochenstunden:</label>
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="state.employee.contractHours"
|
||||
<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"
|
||||
>
|
||||
/>
|
||||
|
||||
<div v-for="(error) in v$.contractHours.$errors" class="invalid-feedback" id="contractHoursFeedback">
|
||||
{{error.$message}}
|
||||
</div>
|
||||
@@ -93,7 +117,7 @@
|
||||
<label for="username" class="form-label">Benutzername:</label>
|
||||
<input
|
||||
type="text"
|
||||
v-model.trim="state.employee.username"
|
||||
v-model.trim="employee.username"
|
||||
id="username"
|
||||
class="form-control"
|
||||
:class="classIsInvalid(v$.username)"
|
||||
@@ -105,7 +129,7 @@
|
||||
<label for="password" class="form-label">Neues Passwort:</label>
|
||||
<input
|
||||
type="password"
|
||||
v-model="state.employee.password"
|
||||
v-model="employee.password"
|
||||
id="password"
|
||||
class="form-control"
|
||||
:class="classIsInvalid(v$.password)"
|
||||
@@ -117,7 +141,7 @@
|
||||
<label for="password-repeat" class="form-label">Neues Passwort wiederholen:</label>
|
||||
<input
|
||||
type="password"
|
||||
v-model="state.employee.passwordConfirm"
|
||||
v-model="employee.passwordConfirm"
|
||||
id="password-repeat"
|
||||
class="form-control mb-3"
|
||||
:class="classIsInvalid(v$.passwordConfirm)"
|
||||
@@ -130,10 +154,9 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VProfileControls class="mt-5" :isActive="editEmployee || createUser" @save="onUpdateEmployee" @toggleEdit="onToggleEdit" />
|
||||
</form>
|
||||
|
||||
<VProfileControls class="mt-5" :isActive="editEmployee || createUser" @save="onUpdateEmployee" @toggleEdit="onToggleEdit" />
|
||||
|
||||
</template>
|
||||
|
||||
@@ -143,13 +166,18 @@ import VProfileControls from '@/components/VProfileControls.vue';
|
||||
import { onMounted, computed, ref, watch } from 'vue'
|
||||
import { useEmployee } from '@/stores/employee'
|
||||
import { useRoute } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import useVuelidate from '@vuelidate/core'
|
||||
import { required, email, between, decimal, sameAs, helpers, requiredIf } from '@vuelidate/validators'
|
||||
import { required, email, between, decimal, sameAs, requiredIf } from '@vuelidate/validators'
|
||||
import { IMaskComponent as MaskInput } from 'vue-imask'
|
||||
|
||||
const route = useRoute()
|
||||
const state = useEmployee()
|
||||
|
||||
const { employee } = storeToRefs(state)
|
||||
|
||||
const editEmployee = ref(false)
|
||||
const strContractHours = ref('')
|
||||
|
||||
const rules = computed(() => ({
|
||||
firstName: {
|
||||
@@ -172,12 +200,12 @@ const rules = computed(() => ({
|
||||
requiredIf: requiredIf(() => createUser.value)
|
||||
},
|
||||
passwordConfirm: {
|
||||
sameAs: sameAs(state.employee.password)
|
||||
sameAs: sameAs(employee.value.password)
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
const v$ = useVuelidate(rules, state.employee)
|
||||
const v$ = useVuelidate(rules, employee)
|
||||
|
||||
const createUser = ref(false)
|
||||
|
||||
@@ -186,11 +214,7 @@ async function onUpdateEmployee() {
|
||||
await state.persist()
|
||||
onToggleEdit()
|
||||
}
|
||||
}
|
||||
|
||||
function onEnter() {
|
||||
onUpdateEmployee
|
||||
}
|
||||
}
|
||||
|
||||
function onToggleCreateUser() {
|
||||
createUser.value = !createUser.value
|
||||
@@ -219,7 +243,7 @@ function classIsInvalid(object : any) : string {
|
||||
return object.$dirty && object.$invalid ? 'is-invalid' : ''
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(() => {
|
||||
state.fetchFromApi(route.params.id)
|
||||
})
|
||||
|
||||
84
src/views/Employees/Index.vue
Normal file
84
src/views/Employees/Index.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
v-for="col in columns"
|
||||
@click="onSortBy(col)"
|
||||
>
|
||||
{{col}}
|
||||
<i :style="{visibility: colIsSelected(col) ? 'visible' : 'hidden'}" class="bi" :class="iconSort"></i>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="employee in rows" @click="router.push({name: 'Employees/Details', params: {id: employee.id}})">
|
||||
<td v-for="col in columns">
|
||||
{{ employee[col] }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import { onMounted, reactive, watch, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmployees } from '@/stores/employees'
|
||||
|
||||
const store = useEmployees()
|
||||
const router = useRouter()
|
||||
const { rows, meta, columns } = storeToRefs(store)
|
||||
|
||||
const sort_by = reactive({
|
||||
asc: true,
|
||||
column: 'id'
|
||||
})
|
||||
|
||||
watch(sort_by, () => {
|
||||
store.fetchFromApi(undefined, undefined, (sort_by.asc ? "asc(" : "desc(")+sort_by.column+")")
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
store.fetchFromApi(undefined, undefined, (sort_by.asc ? "asc(" : "desc(")+sort_by.column+")")
|
||||
})
|
||||
|
||||
function colIsSelected(col : string) {
|
||||
return col === sort_by.column
|
||||
}
|
||||
|
||||
function onSortBy(col : string) {
|
||||
if(col !== sort_by.column) sort_by.asc = true
|
||||
else sort_by.asc = !sort_by.asc
|
||||
|
||||
sort_by.column = col
|
||||
}
|
||||
|
||||
const iconSort = computed(() => {
|
||||
return 'bi-sort-' + (sort_by.asc ? 'down' : 'up')+'-alt'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
table th {
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user