Files
FEDEO/pages/profiles/show/[id].vue
flfeders f69b30b5ba Added Notifications
Added Mentions in HistoryItems
2024-11-08 20:17:56 +01:00

569 lines
16 KiB
Vue

<script setup>
import axios from "axios"
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 router = useRouter()
const supabase = useSupabaseClient()
const toast = useToast()
const itemInfo = ref({
weeklyRegularWorkingHours: {}
})
const oldItemInfo = ref({})
const setupPage = () => {
if(route.params.id) itemInfo.value = dataStore.getProfileById(route.params.id)
if(itemInfo.value.id) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
}
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()
const emailSignature = ref(dataStore.activeProfile.emailSignature)
const tiptapLoaded = ref(false)
const contentSaved = ref(true)
const contentChanged = async (content) => {
console.log(tiptapLoaded)
emailSignature.value = content.html
if(tiptapLoaded.value === true) {
contentSaved.value = false
} else {
tiptapLoaded.value = true
}
}
const saveSignature = async () => {
const {data,error} = await supabase.from("profiles").update({emailSignature: emailSignature.value}).eq("id", dataStore.activeProfile.id)
if(error) {
toast.add({title: "Fehler beim Speichern der Signatur", color:"rose"})
}
else {
contentSaved.value = true
}
}
const addToNewsletter = async () => {
const {data,error} = await axios({
url: "https://newsletter.fedeo.io/api/public/subscription",
method: "post",
data: {
email: dataStore.activeProfile.email,
name: dataStore.activeProfile.name,
list_uuids: ["b97453fd-14b2-4b25-8f9b-b83847317ea3"],
}
})
console.log(data)
}
const calcWeeklyWorkingHours = () => {
itemInfo.value.weeklyWorkingHours =
itemInfo.value.weeklyRegularWorkingHours[1] +
itemInfo.value.weeklyRegularWorkingHours[2] +
itemInfo.value.weeklyRegularWorkingHours[3] +
itemInfo.value.weeklyRegularWorkingHours[4] +
itemInfo.value.weeklyRegularWorkingHours[5] +
itemInfo.value.weeklyRegularWorkingHours[6] +
itemInfo.value.weeklyRegularWorkingHours[7]
}
const colorMode = useColorMode()
const isLight = computed({
get() {
return colorMode.value !== 'dark'
},
set() {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
})
</script>
<template>
<UDashboardNavbar
:title="itemInfo.fullName"
>
<template #left>
<UButton
icon="i-heroicons-chevron-left"
variant="outline"
@click="router.push(`/profiles`)"
>
Mitarbeiter
</UButton>
</template>
<template #center>
<h1
v-if="itemInfo"
:class="['text-xl','font-medium'/*, ... true ? ['text-primary'] : ['text-rose-500']*/]"
>{{itemInfo ? `Mitarbeiter: ${itemInfo.fullName}` : ''}}</h1>
</template>
</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, fullName: itemInfo.firstName + ' ' + itemInfo.lastName},oldItemInfo)"
>
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>
<UFormGroup
label="Benutzername"
class="flex-auto"
>
<UInput
v-model="itemInfo.username"
/>
</UFormGroup>
</InputGroup>
<InputGroup class="w-full">
<UFormGroup
label="Kleidergröße Oberteil"
class="w-60"
>
<UInput
v-model="itemInfo.clothingSizeTop"
/>
</UFormGroup>
<UFormGroup
label="Kleidergröße Hose"
class="w-60"
>
<UInput
v-model="itemInfo.clothingSizeBottom"
/>
</UFormGroup>
</InputGroup>
<UDivider class="my-5">
Helligkeitseinstellung
</UDivider>
<UButton
:icon="!isLight ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
color="white"
variant="outline"
aria-label="Theme"
@click="isLight = !isLight"
>
{{!isLight ? "Hell" : "Dunkel"}}
</UButton>
<UDivider class="my-5">
E-Mail Signatur
</UDivider>
<UButton
variant="outline"
v-if="!contentSaved"
@click="saveSignature"
>
Speichern
</UButton>
<Tiptap
@updateContent="contentChanged"
:preloadedContent="emailSignature"
/>
<UDivider>Newsletter</UDivider>
<!-- <UButton
@click="addToNewsletter"
variant="outline"
>
In Newsletter eintragen
</UButton>-->
</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"
type="number"
/>
</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>
<UDivider class="my-3">Regelarbeitszeiten</UDivider>
<InputGroup class="w-full">
<UFormGroup
label="Montag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[1]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup><UFormGroup
label="Dienstag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[2]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
<UFormGroup
label="Mittwoch"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[3]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
<UFormGroup
label="Donnerstag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[4]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
<UFormGroup
label="Freitag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[5]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
<UFormGroup
label="Samstag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[6]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
<UFormGroup
label="Sonntag"
class="flex-auto"
>
<UInput
v-model="itemInfo.weeklyRegularWorkingHours[7]"
type="number"
@change="calcWeeklyWorkingHours"
/>
</UFormGroup>
</InputGroup>
</div>
</UCard>
</template>
</UTabs>
</template>
<style scoped>
</style>