Files
FEDEO/pages/staff/time/[id]/evaluate.vue
2025-11-11 08:56:52 +01:00

236 lines
7.9 KiB
Vue

<script setup lang="ts">
const { $dayjs } = useNuxtApp()
const router = useRouter()
const route = useRoute()
const auth = useAuthStore()
// 🔹 State
const workingtimes = ref([])
const absencerequests = ref([])
const workingTimeInfo = ref(null)
const selectedPresetRange = ref("Dieser Monat bis heute")
const selectedStartDay = ref("")
const selectedEndDay = ref("")
const openTab = ref(0)
const showDocument = ref(false)
const uri = ref("")
const itemInfo = ref({})
function formatMinutesToHHMM(minutes = 0) {
const h = Math.floor(minutes / 60)
const m = Math.floor(minutes % 60)
return `${h}:${String(m).padStart(2, "0")} h`
}
// 📅 Zeitraumumschaltung
function changeRange() {
const rangeMap = {
"Diese Woche": { selector: "isoWeek", subtract: 0 },
"Dieser Monat": { selector: "M", subtract: 0 },
"Dieser Monat bis heute": { selector: "M", subtract: 0 },
"Dieses Jahr": { selector: "y", subtract: 0 },
"Letzte Woche": { selector: "isoWeek", subtract: 1 },
"Letzter Monat": { selector: "M", subtract: 1 },
"Letztes Jahr": { selector: "y", subtract: 1 }
}
const { selector, subtract } = rangeMap[selectedPresetRange.value] || { selector: "M", subtract: 0 }
selectedStartDay.value = $dayjs()
.subtract(subtract, selector === "isoWeek" ? "week" : selector)
.startOf(selector)
.format("YYYY-MM-DD")
selectedEndDay.value =
selectedPresetRange.value === "Dieser Monat bis heute"
? $dayjs().format("YYYY-MM-DD")
: $dayjs()
.subtract(subtract, selector === "isoWeek" ? "week" : selector)
.endOf(selector)
.format("YYYY-MM-DD")
loadWorkingTimeInfo()
}
const profile = ref(null)
// 📊 Daten laden
async function setupPage() {
await changeRange()
profile.value = (await useNuxtApp().$api("/api/tenant/profiles")).data.find(i => i.user_id === route.params.id)
console.log(profile.value)
}
async function loadWorkingTimeInfo() {
workingTimeInfo.value = await useFunctions().getWorkingTimesEvaluationData(
route.params.id,
selectedStartDay.value,
selectedEndDay.value
)
openTab.value = 0
}
// 📄 PDF generieren
async function generateDocument() {
const path = (await useEntities("letterheads").select("*"))[0].path // TODO SELECT
uri.value = await useFunctions().useCreatePDF({
full_name: profile.value.full_name,
...workingTimeInfo.value}, path, "timesheet")
showDocument.value = true
}
async function onTabChange(index: number) {
if (index === 1) await generateDocument()
}
// Initialisierung
await setupPage()
changeRange()
</script>
<template>
<UDashboardNavbar :ui="{ center: 'flex items-stretch gap-1.5 min-w-0' }">
<template #left>
<UButton
icon="i-heroicons-chevron-left"
variant="outline"
@click="router.push('/staff/time')"
>
Anwesenheiten
</UButton>
</template>
<template #center>
<h1 class="text-xl font-medium truncate">
Auswertung Anwesenheiten: {{ profile?.full_name || '' }}
</h1>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #left>
<UFormGroup label="Zeitraum:">
<USelectMenu
:options="[
'Dieser Monat bis heute',
'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 wählen'"
/>
<template #panel="{ close }">
<LazyDatePicker v-model="selectedStartDay" @close="loadWorkingTimeInfo" />
</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 wählen'"
/>
<template #panel="{ close }">
<LazyDatePicker v-model="selectedEndDay" @close="loadWorkingTimeInfo" />
</template>
</UPopover>
</UFormGroup>
</template>
</UDashboardToolbar>
<UDashboardPanelContent>
<UTabs
:items="[{ label: 'Information' }, { label: 'Bericht' }]"
v-model="openTab"
@change="onTabChange"
>
<template #item="{ item }">
<div v-if="item.label === 'Information'">
<UCard v-if="workingTimeInfo" class="my-5">
<template #header>
<h3 class="text-base font-semibold">Zusammenfassung</h3>
</template>
<div class="grid grid-cols-2 gap-3 text-sm">
<p>Eingereicht: <b>{{ formatMinutesToHHMM(workingTimeInfo.sumWorkingMinutesEingereicht) }}</b></p>
<p>Genehmigt: <b>{{ formatMinutesToHHMM(workingTimeInfo.sumWorkingMinutesApproved) }}</b></p>
<p>Feiertagsausgleich: <b>{{ formatMinutesToHHMM(workingTimeInfo.sumWorkingMinutesRecreationDays) }}</b> / {{ workingTimeInfo.sumRecreationDays }} Tage</p>
<p>Urlaubs-/Berufsschulausgleich: <b>{{ formatMinutesToHHMM(workingTimeInfo.sumWorkingMinutesVacationDays) }}</b> / {{ workingTimeInfo.sumVacationDays }} Tage</p>
<p>Krankheitsausgleich: <b>{{ formatMinutesToHHMM(workingTimeInfo.sumWorkingMinutesSickDays) }}</b> / {{ workingTimeInfo.sumSickDays }} Tage</p>
<p>Soll-Stunden: <b>{{ formatMinutesToHHMM(workingTimeInfo.timeSpanWorkingMinutes) }}</b></p>
<p class="col-span-2">
Inoffizielles Saldo: <b>{{ (workingTimeInfo.saldoInOfficial >= 0 ? '+' : '-') + formatMinutesToHHMM(Math.abs(workingTimeInfo.saldoInOfficial)) }}</b>
</p>
<p class="col-span-2">
Saldo: <b>{{ (workingTimeInfo.saldo >= 0 ? '+' : '-') + formatMinutesToHHMM(Math.abs(workingTimeInfo.saldo)) }}</b>
</p>
</div>
</UCard>
<UDashboardPanel>
<UTable
v-if="workingTimeInfo"
:rows="workingTimeInfo.times"
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Anwesenheiten' }"
:columns="[
{ key: 'state', label: 'Status' },
{ key: 'start', label: 'Start' },
{ key: 'end', label: 'Ende' },
{ key: 'duration', label: 'Dauer' },
{ key: 'description', label: 'Beschreibung' }
]"
@select="(row) => router.push(`/workingtimes/edit/${row.id}`)"
>
<template #state-data="{row}">
<span v-if="row.state === 'approved'" class="text-primary-500">Genehmigt</span>
<span v-else-if="row.state === 'submitted'" class="text-cyan-500">Eingereicht</span>
<span v-else-if="row.state === 'draft'" class="text-red-500">Entwurf</span>
</template>
<template #start-data="{ row }">
{{ $dayjs(row.started_at).format('HH:mm DD.MM.YY') }} Uhr
</template>
<template #end-data="{ row }">
{{ $dayjs(row.stopped_at).format('HH:mm DD.MM.YY') }} Uhr
</template>
<template #duration-data="{ row }">
{{ useFormatDuration(row.duration_minutes) }}
</template>
</UTable>
</UDashboardPanel>
</div>
<div v-else-if="item.label === 'Bericht'">
<PDFViewer
v-if="showDocument"
:uri="uri"
location="show_time_evaluation"
/>
</div>
</template>
</UTabs>
</UDashboardPanelContent>
</template>