Restructured Project Rep
This commit is contained in:
97
pages/profiles/create.vue
Normal file
97
pages/profiles/create.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<script setup>
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const dataStore = useDataStore()
|
||||
|
||||
const itemInfo = ref({})
|
||||
|
||||
const createProfile = async () => {
|
||||
let data = {
|
||||
fullName: `${itemInfo.value.firstName} ${itemInfo.value.lastName}`,
|
||||
...itemInfo.value
|
||||
}
|
||||
|
||||
await dataStore.createNewItem("profiles", data)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar title="Mitarbeiter erstellen">
|
||||
<template #right>
|
||||
<UButton
|
||||
color="rose"
|
||||
@click="router.push(`/profiles`)"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="createProfile"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UForm
|
||||
class="p-5"
|
||||
>
|
||||
<UFormGroup
|
||||
label="Anrede"
|
||||
>
|
||||
<UInput
|
||||
required
|
||||
v-model="itemInfo.salutation"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Vorname"
|
||||
>
|
||||
<UInput
|
||||
required
|
||||
v-model="itemInfo.firstName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Nachname"
|
||||
>
|
||||
<UInput
|
||||
required
|
||||
v-model="itemInfo.lastName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Mitarbeiter Nummer"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.employeeNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="E-Mail"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.email"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Handynummer"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.mobileTel"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Festnetznummer"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.fixedTel"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</UForm>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
48
pages/profiles/index.vue
Normal file
48
pages/profiles/index.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup>
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: 'employeeNumber',
|
||||
label: "MA-Nummer:",
|
||||
sortable: true
|
||||
},{
|
||||
key: 'fullName',
|
||||
label: "Name:",
|
||||
sortable: true
|
||||
},{
|
||||
key: "email",
|
||||
label: "E-Mail:",
|
||||
sortable: true
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar title="Benutzer Einstellungen">
|
||||
<template #right>
|
||||
<UButton
|
||||
@click="router.push(`/profiles/create`)"
|
||||
>
|
||||
+ Mitarbeiter
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UTable
|
||||
:rows="dataStore.profiles"
|
||||
@select="(item) => router.push(`/profiles/show/${item.id}`)"
|
||||
:columns="columns"
|
||||
>
|
||||
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
335
pages/profiles/show/[id].vue
Normal file
335
pages/profiles/show/[id].vue
Normal file
@@ -0,0 +1,335 @@
|
||||
<script setup>
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
import dayjs from "dayjs";
|
||||
import customParseFormat from "dayjs/plugin/customParseFormat";
|
||||
import isoWeek from "dayjs/plugin/isoWeek"
|
||||
import isBetween from "dayjs/plugin/isBetween"
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(isoWeek)
|
||||
dayjs.extend(isBetween)
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const route = useRoute()
|
||||
|
||||
const itemInfo = ref({})
|
||||
|
||||
const setupPage = () => {
|
||||
if(route.params.id) itemInfo.value = dataStore.getProfileById(route.params.id)
|
||||
}
|
||||
|
||||
const selectedPresetRange = ref("Dieser Monat")
|
||||
const selectedStartDay = ref("")
|
||||
const selectedEndDay = ref("")
|
||||
|
||||
const changeRange = () => {
|
||||
let selector = "w"
|
||||
let subtract = 0
|
||||
|
||||
if(selectedPresetRange.value === "Diese Woche") {
|
||||
selector = "isoWeek"
|
||||
subtract = 0
|
||||
|
||||
} else if(selectedPresetRange.value === "Dieser Monat") {
|
||||
selector = "M"
|
||||
subtract = 0
|
||||
|
||||
} else if(selectedPresetRange.value === "Dieses Jahr") {
|
||||
selector = "y"
|
||||
subtract = 0
|
||||
} else if(selectedPresetRange.value === "Letzte Woche") {
|
||||
selector = "isoWeek"
|
||||
subtract = 1
|
||||
} else if(selectedPresetRange.value === "Letzter Monat") {
|
||||
selector = "M"
|
||||
subtract = 1
|
||||
} else if(selectedPresetRange.value === "Letztes Jahr") {
|
||||
selector = "y"
|
||||
subtract = 1
|
||||
}
|
||||
|
||||
selectedStartDay.value = dayjs().subtract(subtract,selector === "isoWeek" ? "week" : selector).startOf(selector).format("YYYY-MM-DD")
|
||||
selectedEndDay.value = dayjs().subtract(subtract,selector === "isoWeek" ? "week" : selector).endOf(selector).format("YYYY-MM-DD")
|
||||
|
||||
}
|
||||
|
||||
|
||||
const workingTimeInfo = computed(() => {
|
||||
|
||||
let times = dataStore.getWorkingTimesByProfileId(itemInfo.value.id)
|
||||
|
||||
times = times.filter(i => dayjs(i.date).isBetween(dayjs(selectedStartDay.value).subtract(1,"days"),selectedEndDay.value,'day') && i.end)
|
||||
|
||||
|
||||
|
||||
let weekFactor = 4.33
|
||||
let monthlyWorkingHours = itemInfo.value.weeklyWorkingHours * weekFactor
|
||||
|
||||
|
||||
//Eingreicht
|
||||
let sumWorkingMinutesEingereicht = 0
|
||||
times.filter(i => !i.approved).forEach(time => {
|
||||
const minutes = dayjs(time.end, "HH:mm:ss").diff(dayjs(time.start, "HH:mm:ss"),'minutes')
|
||||
sumWorkingMinutesEingereicht = sumWorkingMinutesEingereicht + minutes
|
||||
})
|
||||
|
||||
//Bestätigt
|
||||
let sumWorkingMinutesApproved = 0
|
||||
times.filter(i => i.approved).forEach(time => {
|
||||
const minutes = dayjs(time.end, "HH:mm:ss").diff(dayjs(time.start, "HH:mm:ss"),'minutes')
|
||||
sumWorkingMinutesApproved = sumWorkingMinutesApproved + minutes
|
||||
})
|
||||
//console.log(times.filter(i => i.approved).length)
|
||||
//console.log(sumWorkingMinutesApproved)
|
||||
|
||||
|
||||
//Saldo
|
||||
let saldo = (sumWorkingMinutesApproved / 60).toFixed(2) - monthlyWorkingHours
|
||||
let saldoInOfficial = ((sumWorkingMinutesApproved + sumWorkingMinutesEingereicht) / 60).toFixed(2) - monthlyWorkingHours
|
||||
|
||||
return {
|
||||
monthlyWorkingHours,
|
||||
sumWorkingMinutesEingereicht,
|
||||
sumWorkingMinutesApproved,
|
||||
saldo,
|
||||
saldoInOfficial
|
||||
}
|
||||
})
|
||||
|
||||
const getDuration = (time) => {
|
||||
const minutes = Math.floor(dayjs(time.end, "HH:mm:ss").diff(dayjs(time.start, "HH:mm:ss"),'minutes',true))
|
||||
const hours = Math.floor(minutes/60)
|
||||
return {
|
||||
//dezimal: dez,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
composed: `${hours}:${String(minutes % 60).padStart(2,"0")} h`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
setupPage()
|
||||
changeRange()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar
|
||||
:title="itemInfo.fullName"
|
||||
>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UTabs
|
||||
class="p-5"
|
||||
:items="[
|
||||
{
|
||||
label: 'Informationen'
|
||||
},{
|
||||
label: 'Logbuch'
|
||||
},{
|
||||
label: 'Zeiterfassung'
|
||||
},{
|
||||
label: 'Vertragsdaten'
|
||||
},{
|
||||
label: 'Dokumente'
|
||||
}
|
||||
]"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<UCard class="mt-5">
|
||||
<div v-if="item.label === 'Informationen'">
|
||||
<Toolbar>
|
||||
<UButton
|
||||
@click="dataStore.updateItem('profiles',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
</Toolbar>
|
||||
<InputGroup class="w-full">
|
||||
<UFormGroup
|
||||
label="Anrede"
|
||||
class="w-60"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.salutation"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Vorname"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.firstName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Nachname"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.lastName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
<InputGroup class="w-full">
|
||||
<UFormGroup
|
||||
label="Mitarbeiternummer"
|
||||
class="w-60"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.employeeNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="E-Mail"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.email"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div v-if="item.label === 'Logbuch'">
|
||||
<HistoryDisplay
|
||||
type="profile"
|
||||
v-if="itemInfo"
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="item.label === 'Zeiterfassung'">
|
||||
<Toolbar>
|
||||
<UFormGroup
|
||||
label="Vorlage:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="['Diese Woche', 'Dieser Monat', 'Dieses Jahr', 'Letzte Woche', 'Letzter Monat', 'Letztes Jahr']"
|
||||
v-model="selectedPresetRange"
|
||||
@change="changeRange"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Start:" >
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="selectedStartDay ? dayjs(selectedStartDay).format('DD.MM.YYYY') : 'Datum auswählen'"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="selectedStartDay" @close="changeRange" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Ende:">
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="selectedEndDay ? dayjs(selectedEndDay).format('DD.MM.YYYY') : 'Datum auswählen'"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="selectedEndDay" @close="changeRange" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
</Toolbar>
|
||||
<div class="truncate">
|
||||
<p>Eingreicht: {{Math.floor(workingTimeInfo.sumWorkingMinutesEingereicht/60)}}:{{String(workingTimeInfo.sumWorkingMinutesEingereicht % 60).padStart(2,"0")}} h</p>
|
||||
<p>Bestätigt: {{Math.floor(workingTimeInfo.sumWorkingMinutesApproved/60)}}:{{String(workingTimeInfo.sumWorkingMinutesApproved % 60).padStart(2,"0")}} h</p>
|
||||
<p>Soll Stunden: {{workingTimeInfo.monthlyWorkingHours}} h</p>
|
||||
<p>Abwesend: </p>
|
||||
<p>Ausgleich:</p>
|
||||
<p>Inoffizielles Saldo: {{workingTimeInfo.saldoInOfficial}} h</p>
|
||||
<p>Saldo: {{workingTimeInfo.saldo}} h</p>
|
||||
</div>
|
||||
|
||||
<UDivider class="my-3"/>
|
||||
|
||||
<UTable
|
||||
:rows="dataStore.getWorkingTimesByProfileId(itemInfo.id)"
|
||||
class="h-80"
|
||||
:columns="[
|
||||
{
|
||||
key: 'state',
|
||||
label: 'Status'
|
||||
}, {
|
||||
key: 'date',
|
||||
label: 'Datum'
|
||||
}, {
|
||||
key: 'start',
|
||||
label: 'Start'
|
||||
}, {
|
||||
key: 'end',
|
||||
label: 'Ende'
|
||||
}, {
|
||||
key: 'duration',
|
||||
label: 'Dauer'
|
||||
}, {
|
||||
key: 'notes',
|
||||
label: 'Notizen'
|
||||
}
|
||||
]"
|
||||
>
|
||||
<template #profile-data="{row}">
|
||||
{{dataStore.profiles.find(profile => profile.id === row.profile) ? dataStore.profiles.find(profile => profile.id === row.profile).fullName : row.profile }}
|
||||
</template>
|
||||
<template #date-data="{row}">
|
||||
{{dayjs(row.date).format("DD.MM.YYYY")}}
|
||||
</template>
|
||||
|
||||
<template #start-data="{row}">
|
||||
{{dayjs(row.start, "HH:mm:ss").format("HH:mm")}} Uhr
|
||||
</template>
|
||||
<template #end-data="{row}">
|
||||
{{dayjs(row.end, "HH:mm:ss").format("HH:mm")}} Uhr
|
||||
</template>
|
||||
<template #duration-data="{row}">
|
||||
{{getDuration(row).composed}}
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-if="item.label === 'Vertragsdaten'">
|
||||
<Toolbar>
|
||||
<UButton
|
||||
@click="dataStore.updateItem('profiles',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
</Toolbar>
|
||||
<InputGroup class="w-full">
|
||||
<UFormGroup
|
||||
label="Wöchentliche Arbeitszeit"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.weeklyWorkingHours"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Durchschnittliche Arbeitstage pro Woche"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.weeklyWorkingDays"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Urlaubstage"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.annualPaidLeaveDays"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</UCard>
|
||||
</template>
|
||||
</UTabs>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user