Added Bankimport, BankAccounts, BankStatements Some Visual Changes Added Contacts Changes in VendorInvoices Added layouts with default an one for Login PAge Added Input Group Component
407 lines
9.6 KiB
Vue
407 lines
9.6 KiB
Vue
<script setup>
|
|
import * as dayjs from "dayjs";
|
|
import VueDatePicker from '@vuepic/vue-datepicker'
|
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
|
|
|
|
definePageMeta({
|
|
middleware: "auth"
|
|
})
|
|
|
|
const supabase = useSupabaseClient()
|
|
const user = useSupabaseUser()
|
|
const toast = useToast()
|
|
|
|
const {times, projects, profiles, jobs} = storeToRefs(useDataStore())
|
|
const {fetchTimes, getTimeTypes} = useDataStore()
|
|
const timeTypes = getTimeTypes
|
|
const timeInfo = ref({
|
|
user: "",
|
|
start: "",
|
|
end: null,
|
|
notes: null,
|
|
projectId: null,
|
|
type: null
|
|
})
|
|
|
|
const filteredRows = computed(() => {
|
|
|
|
if(user.value && times.value) {
|
|
return times.value.filter(time => time.user === user.value.id)
|
|
} else {
|
|
return []
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const createTimeInfo = ref({
|
|
user: "",
|
|
start: new Date(),
|
|
end: "",
|
|
notes: null,
|
|
projectId: null,
|
|
type: null
|
|
})
|
|
|
|
|
|
const columns = [
|
|
{
|
|
key: "user",
|
|
label: "Benutzer"
|
|
},
|
|
{
|
|
key:"start",
|
|
label:"Start"
|
|
},
|
|
{
|
|
key:"type",
|
|
label:"Typ"
|
|
},
|
|
{
|
|
key: "end",
|
|
label: "Ende"
|
|
},
|
|
{
|
|
key: "duration",
|
|
label: "Dauer"
|
|
},
|
|
{
|
|
key: "projectId",
|
|
label: "Projekt"
|
|
},
|
|
{
|
|
key: "job",
|
|
label: "Job"
|
|
},
|
|
{
|
|
key: "notes",
|
|
label: "Notizen"
|
|
}
|
|
]
|
|
|
|
const runningTimeInfo = ref({})
|
|
const showAddTimeModal = ref(false)
|
|
|
|
|
|
|
|
const startTime = async () => {
|
|
console.log("started")
|
|
timeInfo.value.user = user.value.id
|
|
timeInfo.value.start = new Date().toISOString()
|
|
|
|
const {data,error} = await supabase
|
|
.from("times")
|
|
.insert([timeInfo.value])
|
|
.select()
|
|
|
|
if(error) {
|
|
console.log(error)
|
|
} else if(data) {
|
|
timeInfo.value = data[0]
|
|
await fetchTimes()
|
|
runningTimeInfo.value = times.value.find(time => time.user == user.value.id && !time.end)
|
|
}
|
|
|
|
}
|
|
|
|
const stopStartedTime = async () => {
|
|
console.log(runningTimeInfo.value)
|
|
|
|
runningTimeInfo.value.end = new Date().toISOString()
|
|
|
|
const mapNumRange = (num, inMin, inMax, outMin, outMax) =>
|
|
((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
|
|
|
runningTimeInfo.value.duration = Math.round(mapNumRange(Math.abs(new Date(runningTimeInfo.value.end) - new Date(runningTimeInfo.value.start))/1000/60,0,60,0,1)*100)/100
|
|
|
|
const {data,error} = await supabase
|
|
.from("times")
|
|
.update(runningTimeInfo.value)
|
|
.eq('id',runningTimeInfo.value.id)
|
|
.select()
|
|
console.log(data)
|
|
|
|
if(error) {
|
|
console.log(error)
|
|
} else {
|
|
toast.add({title: "Zeit erfolgreich gestoppt"})
|
|
runningTimeInfo.value = {}
|
|
fetchTimes()
|
|
}
|
|
}
|
|
|
|
if(times.value.find(time => time.user == user.value.id && !time.end)) {
|
|
runningTimeInfo.value = times.value.find(time => time.user == user.value.id && !time.end)
|
|
}
|
|
|
|
|
|
const createTime = async () => {
|
|
const {data,error} = await supabase
|
|
.from("times")
|
|
.insert([createTimeInfo.value])
|
|
.select()
|
|
|
|
if(error) {
|
|
console.log(error)
|
|
} else if(data) {
|
|
createTimeInfo.value = {}
|
|
toast.add({title: "Zeit erfolgreich erstellt"})
|
|
showAddTimeModal.value = false
|
|
await fetchTimes()
|
|
|
|
}
|
|
}
|
|
|
|
const format = (date) => {
|
|
let dateFormat = dayjs(date).format("DD.MM.YY HH:mm")
|
|
|
|
return `${dateFormat}`;
|
|
}
|
|
|
|
const selectStartedTime = () => {
|
|
runningTimeInfo.value = times.value.find(time => time.user == user.value.id && !time.end)
|
|
}
|
|
|
|
|
|
|
|
|
|
//selectStartedTime()
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-center gap-1">
|
|
<UButton
|
|
class="controlButton"
|
|
@click="startTime"
|
|
:disabled="runningTimeInfo.id"
|
|
>
|
|
Start
|
|
</UButton>
|
|
<UButton
|
|
class="controlButton"
|
|
@click="stopStartedTime"
|
|
:disabled="!runningTimeInfo.id"
|
|
>
|
|
Stop
|
|
</UButton>
|
|
<UButton
|
|
class="controlButton"
|
|
@click="showAddTimeModal = true"
|
|
>
|
|
Erstellen
|
|
</UButton>
|
|
</div>
|
|
|
|
<div v-if="runningTimeInfo.id" class="mt-3">
|
|
|
|
Start: {{dayjs(runningTimeInfo.start).format("DD.MM.YY HH:mm")}}
|
|
|
|
<UFormGroup
|
|
label="Notizen:"
|
|
>
|
|
<UTextarea
|
|
v-model="runningTimeInfo.notes"
|
|
/>
|
|
</UFormGroup>
|
|
|
|
<UFormGroup
|
|
label="Projekt:"
|
|
>
|
|
<USelectMenu
|
|
:options="projects"
|
|
option-attribute="name"
|
|
value-attribute="id"
|
|
v-model="runningTimeInfo.projectId"
|
|
>
|
|
<template #label>
|
|
{{ projects.find(project => project.id === runningTimeInfo.projectId) ? projects.find(project => project.id === runningTimeInfo.projectId).name : "Projekt auswählen" }}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
|
|
<UFormGroup
|
|
label="Job:"
|
|
>
|
|
<USelectMenu
|
|
:options="jobs"
|
|
option-attribute="title"
|
|
value-attribute="id"
|
|
v-model="runningTimeInfo.job"
|
|
>
|
|
<template #label>
|
|
{{ jobs.find(job => job.id === runningTimeInfo.job) ? jobs.find(job => job.id === runningTimeInfo.job).title : "Job auswählen" }}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
|
|
<UFormGroup
|
|
label="Kategorie:"
|
|
>
|
|
<USelectMenu
|
|
v-model="runningTimeInfo.type"
|
|
:options="timeTypes"
|
|
option-attribute="label"
|
|
value-attribute="label"
|
|
>
|
|
<template #label>
|
|
{{runningTimeInfo.type ? runningTimeInfo.type : "Kategorie auswählen"}}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
</div>
|
|
|
|
<UModal
|
|
v-model="showAddTimeModal"
|
|
>
|
|
<UCard>
|
|
<template #header>
|
|
Zeiteintrag erstellen
|
|
</template>
|
|
|
|
<UFormGroup
|
|
label="Start:"
|
|
>
|
|
<VueDatePicker
|
|
v-model="createTimeInfo.start"
|
|
locale="de"
|
|
cancel-text="Abbrechen"
|
|
select-text="Auswählen"
|
|
now-button-label="Jetzt"
|
|
text-input="MM.dd.yyyy HH:mm"
|
|
:dark="useColorMode().value !== 'light'"
|
|
:format="format"
|
|
:preview-format="format"
|
|
/>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Ende:"
|
|
>
|
|
<VueDatePicker
|
|
v-model="createTimeInfo.end"
|
|
locale="de"
|
|
cancel-text="Abbrechen"
|
|
select-text="Auswählen"
|
|
now-button-label="Jetzt"
|
|
text-input="MM.dd.yyyy HH:mm"
|
|
:dark="useColorMode().value !== 'light'"
|
|
:format="format"
|
|
:preview-format="format"
|
|
/>
|
|
</UFormGroup>
|
|
<!-- <UFormGroup
|
|
label="Dauer:"
|
|
>
|
|
<UInput
|
|
|
|
/>
|
|
</UFormGroup>-->
|
|
<UFormGroup
|
|
label="Benutzer:"
|
|
>
|
|
<USelectMenu
|
|
:options="profiles"
|
|
v-model="createTimeInfo.user"
|
|
option-attribute="firstName"
|
|
value-attribute="id"
|
|
>
|
|
<template #label>
|
|
{{profiles.find(profile => profile.id === createTimeInfo.user) ? profiles.find(profile => profile.id === createTimeInfo.user).firstName : "Benutzer auswählen"}}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Projekt:"
|
|
>
|
|
<USelectMenu
|
|
:options="projects"
|
|
v-model="createTimeInfo.projectId"
|
|
option-attribute="name"
|
|
value-attribute="id"
|
|
>
|
|
<template #label>
|
|
{{projects.find(project => project.id === createTimeInfo.projectId) ? projects.find(project => project.id === createTimeInfo.projectId).name : "Projekt auswählen"}}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Job:"
|
|
>
|
|
<USelectMenu
|
|
:options="jobs"
|
|
option-attribute="title"
|
|
value-attribute="id"
|
|
v-model="createTimeInfo.job"
|
|
>
|
|
<template #label>
|
|
{{ jobs.find(job => job.id === runningTimeInfo.job) ? jobs.find(job => job.id === runningTimeInfo.job).title : "Job auswählen" }}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Typ:"
|
|
>
|
|
<USelectMenu
|
|
v-model="runningTimeInfo.type"
|
|
:options="timeTypes"
|
|
option-attribute="label"
|
|
value-attribute="label"
|
|
>
|
|
<template #label>
|
|
{{runningTimeInfo.type ? runningTimeInfo.type : "Kategorie auswählen"}}
|
|
</template>
|
|
</USelectMenu>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Notizen:"
|
|
>
|
|
<UTextarea
|
|
v-model="createTimeInfo.notes"
|
|
/>
|
|
</UFormGroup>
|
|
|
|
|
|
<template #footer>
|
|
<UButton
|
|
@click="createTime"
|
|
>
|
|
Erstellen
|
|
</UButton>
|
|
</template>
|
|
</UCard>
|
|
</UModal>
|
|
|
|
<UDivider class="mt-3"/>
|
|
|
|
<UTable
|
|
class="mt-3"
|
|
:columns="columns"
|
|
:rows="filteredRows"
|
|
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Noch keine Einträge' }"
|
|
>
|
|
<template #user-data="{row}">
|
|
{{profiles.find(profile => profile.id === row.user) ? profiles.find(profile => profile.id === row.user).firstName + " " + profiles.find(profile => profile.id === row.user).lastName : row.user }}
|
|
</template>
|
|
|
|
<template #start-data="{row}">
|
|
{{dayjs(row.start).format("DD.MM.YY HH:mm")}}
|
|
</template>
|
|
<template #end-data="{row}">
|
|
{{dayjs(row.end).format("DD.MM.YY HH:mm")}}
|
|
</template>
|
|
<template #projectId-data="{row}">
|
|
{{projects.find(project => project.id === row.projectId) ? projects.find(project => project.id === row.projectId).name : ""}}
|
|
</template>
|
|
<template #job-data="{row}">
|
|
{{jobs.find(job => job.id === row.job) ? jobs.find(job => job.id === row.job).title : ""}}
|
|
</template>
|
|
</UTable>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.controlButton {
|
|
margin-right: 1em;
|
|
}
|
|
</style> |