Cleared Deprecated Folder
This commit is contained in:
@@ -1,209 +0,0 @@
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const profileStore = useProfileStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const id = ref(route.params.id ? route.params.id : null )
|
||||
|
||||
|
||||
//Working
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({
|
||||
approved: "Offen"
|
||||
})
|
||||
const states = ["Offen","Genehmigt", "Abgelehnt"]
|
||||
|
||||
const absenceReasons = [
|
||||
"Elternzeit",
|
||||
"Kind krank - Kinderbetreuung",
|
||||
"Krankheit",
|
||||
"Krankheit 1 Tag (mit Attest)",
|
||||
"Krankheit ab 2. Tag (mit Attest)",
|
||||
"Mutterschutz",
|
||||
"Sonderurlaub (bezahlt)",
|
||||
"Überstundenausgleich",
|
||||
"Unbezahlter Urlaub",
|
||||
"Urlaub"
|
||||
]
|
||||
|
||||
//Functions
|
||||
const setupPage = () => {
|
||||
if(mode.value === "show" || mode.value === "edit"){
|
||||
itemInfo.value = dataStore.getAbsenceRequestById(Number(useRoute().params.id))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const editItem = async () => {
|
||||
router.push(`/absenceRequests/edit/${itemInfo.value.id}`)
|
||||
setupPage()
|
||||
}
|
||||
|
||||
const cancelEditorCreate = () => {
|
||||
if(itemInfo.value) {
|
||||
router.push(`/absenceRequests/show/${itemInfo.value.id}`)
|
||||
} else {
|
||||
router.push(`/absenceRequests/`)
|
||||
}
|
||||
}
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar :title="itemInfo ? itemInfo.name : (mode === 'create' ? 'Abwesenheit erstellen' : 'Abwesenheit bearbeiten')">
|
||||
<template #right>
|
||||
<UButton
|
||||
v-if="mode === 'edit'"
|
||||
@click="dataStore.updateItem('absencerequests',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('absencerequests',itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="cancelEditorCreate"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
v-if="mode === 'edit' || mode === 'create'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click="editItem"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
<template #badge v-if="itemInfo">
|
||||
<UBadge
|
||||
v-if="itemInfo.approved === 'Offen'"
|
||||
color="blue"
|
||||
>{{itemInfo.approved}}</UBadge>
|
||||
<UBadge
|
||||
v-else-if="itemInfo.approved === 'Genehmigt'"
|
||||
color="primary"
|
||||
>{{itemInfo.approved}}</UBadge>
|
||||
<UBadge
|
||||
v-else-if="itemInfo.approved === 'Abgelehnt'"
|
||||
color="rose"
|
||||
>{{itemInfo.approved}}</UBadge>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<UTabs
|
||||
:items="[{label: 'Informationen'}, {label: 'Logbuch'}]"
|
||||
v-if="itemInfo && mode == 'show'"
|
||||
class="p-5"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<UCard class="mt-5">
|
||||
<div v-if="item.label === 'Informationen'">
|
||||
<div class="truncate">
|
||||
<p>Mitarbeiter: {{profileStore.profiles.find(item => item.id === itemInfo.user) ? profileStore.profiles.find(item => item.id === itemInfo.user).fullName : ""}}</p>
|
||||
<p>Start: {{dayjs(itemInfo.start).format("DD.MM.YYYY")}}</p>
|
||||
<p>Ende: {{dayjs(itemInfo.end).format("DD.MM.YYYY")}}</p>
|
||||
<p>Grund: {{itemInfo.reason}}</p>
|
||||
<p>Notizen: {{itemInfo.notes}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Logbuch'">
|
||||
<HistoryDisplay
|
||||
type="absencerequest"
|
||||
v-if="itemInfo"
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</div>
|
||||
</UCard>
|
||||
</template>
|
||||
</UTabs>
|
||||
<UForm v-else-if="mode == 'edit' || mode == 'create'" class="p-5" >
|
||||
<UFormGroup
|
||||
label="Status:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.approved"
|
||||
:options="states"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Grund:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.reason"
|
||||
:options="absenceReasons"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Mitarbeiter:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.user"
|
||||
:options="profileStore.profiles"
|
||||
option-attribute="fullName"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['fullName']"
|
||||
>
|
||||
<template #label>
|
||||
{{profileStore.getProfileById(itemInfo.user) ? profileStore.getProfileById(itemInfo.user).fullName : "Mitarbeiter auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Start:">
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="itemInfo.start ? dayjs(itemInfo.start).format('DD.MM.YYYY') : 'Datum auswählen'"
|
||||
variant="outline"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="itemInfo.start" @close="close" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Ende:">
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
variant="outline"
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="itemInfo.end ? dayjs(itemInfo.end).format('DD.MM.YYYY') : 'Datum auswählen'"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="itemInfo.end" @close="close" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Notizen:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.note"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
</UForm>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,141 +0,0 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Abwesenheiten" :badge="filteredRows ? filteredRows.length : null">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/absenceRequests/create`)">+ Abwesenheit</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/absenceRequests/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Abwesenheiten anzuzeigen' }"
|
||||
>
|
||||
<template #approved-data="{row}">
|
||||
<span v-if="!row.approved">
|
||||
Genehmigung offen
|
||||
</span>
|
||||
<span
|
||||
v-else-if="row.approved"
|
||||
class="text-primary"
|
||||
>
|
||||
Genemigt
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="text-rose"
|
||||
>
|
||||
Abgelehnt
|
||||
</span>
|
||||
</template>
|
||||
<template #user-data="{row}">
|
||||
{{profileStore.profiles.find(profile => profile.id === row.user) ? profileStore.profiles.find(profile => profile.id === row.user).fullName : ""}}
|
||||
</template>
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/absenceRequests/create")
|
||||
}
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const profileStore = useProfileStore()
|
||||
const router = useRouter()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: "approved",
|
||||
label: "Genehmigt",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "user",
|
||||
label: "Mitarbeiter",
|
||||
sortable: true
|
||||
},{
|
||||
key: "reason",
|
||||
label: "Grund",
|
||||
sortable: true
|
||||
},{
|
||||
key: "start",
|
||||
label: "Start",
|
||||
sortable: true
|
||||
},{
|
||||
key: "end",
|
||||
label: "Ende",
|
||||
sortable: true
|
||||
},{
|
||||
key: "note",
|
||||
label: "Notizen",
|
||||
sortable: true
|
||||
}
|
||||
]
|
||||
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
const searchString = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
let items = dataStore.absencerequests
|
||||
|
||||
if(!searchString.value) {
|
||||
return items
|
||||
}
|
||||
|
||||
return items.filter(item => {
|
||||
return Object.values(item).some((value) => {
|
||||
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,337 +0,0 @@
|
||||
<script setup>
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
import dayjs from "dayjs";
|
||||
import {useSupabaseSelectSingle} from "~/composables/useSupabase.js";
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'backspace': () => {
|
||||
router.push("/checks")
|
||||
},
|
||||
'arrowleft': () => {
|
||||
if(openTab.value > 0){
|
||||
openTab.value -= 1
|
||||
}
|
||||
},
|
||||
'arrowright': () => {
|
||||
if(openTab.value < 3) {
|
||||
openTab.value += 1
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const id = ref(route.params.id ? route.params.id : null )
|
||||
const openTab = ref(0)
|
||||
|
||||
const vehicles = ref([])
|
||||
const profiles = ref([])
|
||||
const inventoryitems = ref([])
|
||||
|
||||
|
||||
//Working
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({
|
||||
name: "",
|
||||
vehicle: null,
|
||||
inventoryitem: null,
|
||||
profile: null,
|
||||
distance: 1,
|
||||
distanceUnit: "days"
|
||||
})
|
||||
|
||||
//Functions
|
||||
const setupPage = async () => {
|
||||
|
||||
profiles.value = await useSupabaseSelect("profiles")
|
||||
vehicles.value = await useSupabaseSelect("vehicles")
|
||||
inventoryitems.value = await useSupabaseSelect("inventoryitems")
|
||||
|
||||
if(mode.value === "show" ){
|
||||
itemInfo.value = await useSupabaseSelectSingle("checks", route.params.id, "*, checkexecutions(*, executed_by(fullName)), vehicle(*), profile(*), inventoryitem(*)")
|
||||
} else if (mode.value === "edit"){
|
||||
itemInfo.value = await useSupabaseSelectSingle("checks", route.params.id, "*")
|
||||
}
|
||||
|
||||
if(mode.value === "create") {
|
||||
let query = route.query
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const cancelEditorCreate = () => {
|
||||
if(itemInfo.value) {
|
||||
router.push(`/checks/show/${itemInfo.value.id}`)
|
||||
} else {
|
||||
router.push(`/checks/`)
|
||||
}
|
||||
}
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar>
|
||||
<template #left>
|
||||
<UButton
|
||||
icon="i-heroicons-chevron-left"
|
||||
variant="outline"
|
||||
@click="router.push(`/checks`)"
|
||||
>
|
||||
Überprüfungen
|
||||
</UButton>
|
||||
</template>
|
||||
<template #center>
|
||||
<h1
|
||||
v-if="itemInfo"
|
||||
:class="['text-xl','font-medium']"
|
||||
>{{itemInfo ? `Überprüfung: ${itemInfo.name}` : (mode === 'create' ? 'Überprüfung erstellen' : 'Überprüfung bearbeiten')}}</h1>
|
||||
</template>
|
||||
<template #right>
|
||||
<UButton
|
||||
v-if="mode === 'edit'"
|
||||
@click="dataStore.updateItem('checks',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('checks',itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="cancelEditorCreate"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
v-if="mode === 'edit' || mode === 'create'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click="router.push(`/checks/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<UDashboardPanelContent>
|
||||
<UTabs
|
||||
v-if="itemInfo.id && mode === 'show'"
|
||||
:items="[{label: 'Informationen'}, {label: 'Dokumente'}, {label: 'Ausführungen'}]"
|
||||
class="p-5"
|
||||
v-model="openTab"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<div v-if="item.label === 'Informationen'" class="flex mt-5">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UCard>
|
||||
<div class="text-wrap">
|
||||
<table class="mb-3 w-full">
|
||||
<tr>
|
||||
<td>Name:</td>
|
||||
<td>{{itemInfo.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rhythmus:</td>
|
||||
<td>
|
||||
{{itemInfo.distance}}
|
||||
<span v-if="itemInfo.distanceUnit === 'dayjs'">Tage</span>
|
||||
<span v-if="itemInfo.distanceUnit === 'years'">Jahre</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.vehicle">
|
||||
<td>Fahrzeug:</td>
|
||||
<td>{{itemInfo.vehicle.licensePlate}}</td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.profile">
|
||||
<td>Person:</td>
|
||||
<td>{{itemInfo.profile.fullName}}</td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.inventoryitem">
|
||||
<td>Inventarartikel:</td>
|
||||
<td>{{itemInfo.inventoryitem.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Beschreibung:</td>
|
||||
<td>{{itemInfo.description}}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UCard class="h-full">
|
||||
<HistoryDisplay
|
||||
type="check"
|
||||
v-if="itemInfo"
|
||||
:element-id="itemInfo.id"
|
||||
:render-headline="true"
|
||||
/>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Dokumente'">
|
||||
<UCard class="mt-5">
|
||||
<Toolbar>
|
||||
<DocumentUpload
|
||||
type="check"
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</Toolbar>
|
||||
<DocumentList
|
||||
:documents="dataStore.getDocumentsByContractId(itemInfo.id)"
|
||||
/>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Ausführungen'">
|
||||
<UCard class="mt-5">
|
||||
<UTable
|
||||
:rows="itemInfo.checkexecutions"
|
||||
:columns="[{key:'created_at',label:'Ersellt am:'},{key:'executed_at',label:'Ausgeführt am:'},{key:'executed_by',label:'Ausgeführt von:'},{key:'description',label:'Beschreibung:'}]"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Ausführungen anzuzeigen' }"
|
||||
>
|
||||
<template #created_at-data="{row}">
|
||||
{{dayjs(row.created_at).format("DD.MM.YYYY HH:mm")}}
|
||||
</template>
|
||||
<template #executed_at-data="{row}">
|
||||
{{dayjs(row.executed_at).format("DD.MM.YYYY HH:mm")}}
|
||||
</template>
|
||||
<template #executed_by-data="{row}">
|
||||
{{row.executed_by.fullName}}
|
||||
</template>
|
||||
</UTable>
|
||||
</UCard>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
</UTabs>
|
||||
<UForm v-else-if="mode === 'edit' || mode === 'create'" class="p-5" >
|
||||
<div class="mx-auto w-4/5">
|
||||
<div class="flex flex-row justify-around">
|
||||
<div class="w-1/2">
|
||||
<UDivider>Allgemeines</UDivider>
|
||||
<UFormGroup
|
||||
label="Name:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.name"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.type"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Rhythmus"
|
||||
class="w-full"
|
||||
>
|
||||
<InputGroup class="w-full">
|
||||
<UInput
|
||||
v-model="itemInfo.distance"
|
||||
type="number"
|
||||
class="flex-auto"
|
||||
></UInput>
|
||||
<USelectMenu
|
||||
:options="[{key: 'days', label: 'Tage'},{key:'years',label:'Jahre'}]"
|
||||
option-attribute="label"
|
||||
value-attribute="key"
|
||||
v-model="itemInfo.distanceUnit"
|
||||
class="w-40"
|
||||
></USelectMenu>
|
||||
</InputGroup>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
</div>
|
||||
<div class=" ml-5 w-1/2">
|
||||
<UDivider>Verknüpftes Element</UDivider>
|
||||
<UFormGroup
|
||||
label="Fahrzeug:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="vehicles"
|
||||
option-attribute="licensePlate"
|
||||
value-attribute="id"
|
||||
v-model="itemInfo.vehicle"
|
||||
:disabled="itemInfo.inventoryitem || itemInfo.profile"
|
||||
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Person:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="profiles"
|
||||
option-attribute="fullName"
|
||||
value-attribute="id"
|
||||
v-model="itemInfo.profile"
|
||||
:disabled="itemInfo.vehicle || itemInfo.inventoryitem"
|
||||
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Inventarartikel:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="inventoryitems"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
v-model="itemInfo.inventoryitem"
|
||||
:disabled="itemInfo.vehicle || itemInfo.profile"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<UFormGroup
|
||||
label="Beschreibung:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.description"
|
||||
rows="6"
|
||||
maxrows="12"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</UForm>
|
||||
</UDashboardPanelContent>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
td {
|
||||
border-bottom: 1px solid lightgrey;
|
||||
vertical-align: top;
|
||||
padding-bottom: 0.15em;
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,148 +0,0 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Überprüfungen" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/checks/create`)">+ Überprüfung</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/checks/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Überprüfungen anzuzeigen' }"
|
||||
>
|
||||
<template #name-data="{row}">
|
||||
<span v-if="row === filteredRows[selectedItem]" class="text-primary-500 font-bold">{{row.name}}</span>
|
||||
<span v-else>{{row.name}}</span>
|
||||
</template>
|
||||
<template #vehicle-data="{row}">
|
||||
<span v-if="row.vehicle">{{row.vehicle.licensePlate}}</span>
|
||||
</template>
|
||||
<template #profile-data="{row}">
|
||||
<span v-if="row.profile">{{row.profile.fullName}}</span>
|
||||
</template>
|
||||
<template #inventoryitem-data="{row}">
|
||||
<span v-if="row.inventoryitem">{{row.inventoryitem.name}}</span>
|
||||
</template>
|
||||
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/checks/create")
|
||||
},
|
||||
'Enter': {
|
||||
usingInput: true,
|
||||
handler: () => {
|
||||
router.push(`/checks/show/${filteredRows.value[selectedItem.value].id}`)
|
||||
}
|
||||
},
|
||||
'arrowdown': () => {
|
||||
if(selectedItem.value < filteredRows.value.length - 1) {
|
||||
selectedItem.value += 1
|
||||
} else {
|
||||
selectedItem.value = 0
|
||||
}
|
||||
},
|
||||
'arrowup': () => {
|
||||
if(selectedItem.value === 0) {
|
||||
selectedItem.value = filteredRows.value.length - 1
|
||||
} else {
|
||||
selectedItem.value -= 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
|
||||
const items = ref([])
|
||||
const selectedItem = ref(0)
|
||||
|
||||
const setupPage = async () => {
|
||||
items.value = await useSupabaseSelect("checks","*, vehicle(licensePlate), profile(fullName), inventoryitem(name)")
|
||||
}
|
||||
|
||||
setupPage()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: "name",
|
||||
label: "Name",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "vehicle",
|
||||
label: "Fahrzeug"
|
||||
},
|
||||
{
|
||||
key: "profile",
|
||||
label: "Person"
|
||||
},
|
||||
{
|
||||
key: "inventoryitem",
|
||||
label: "Inventarartikel"
|
||||
},
|
||||
{
|
||||
key: "notes",
|
||||
label: "Notizen"
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
|
||||
const searchString = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
return useSearch(searchString.value, items.value)
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,580 +0,0 @@
|
||||
<script setup>
|
||||
import axios from 'axios'
|
||||
import {sub} from 'date-fns'
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const accounts = ref([])
|
||||
|
||||
//accounts.value = dataStore.emailAccounts.map(i => { return { label: i.emailAddress, emailEngingeId: i.emailEngineId }})
|
||||
|
||||
const mailboxes = ref({})
|
||||
const messages = ref([])
|
||||
const selectedMailbox = ref("INBOX")
|
||||
const selectedAccount = ref(null)
|
||||
const selectedMessage = ref(null)
|
||||
const setup = async () => {
|
||||
accounts.value = dataStore.emailAccounts.map((i,index) => {
|
||||
let item = { label: i.emailAddress, emailEngineId: i.emailEngineId }
|
||||
if(index === 0) {
|
||||
item.defaultOpen = true
|
||||
}
|
||||
return item
|
||||
|
||||
})
|
||||
|
||||
for await (const account of accounts.value) {
|
||||
console.log(account.emailEngineId)
|
||||
const {data,error} = await axios.get(`http://157.90.231.142:3000/v1/account/${account.emailEngineId}/mailboxes`, {headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'}})
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
mailboxes.value[account.emailEngineId] = data.mailboxes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const selectMailbox = async (account, mailbox) => {
|
||||
selectedMailbox.value = mailbox
|
||||
const {data,error} = await axios.get(`http://157.90.231.142:3000/v1/account/${account}/messages?path=${ mailbox.path}`, {headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'}})
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
messages.value = data.messages
|
||||
selectedAccount.value = account
|
||||
}
|
||||
const messageHTML = ref(null)
|
||||
const messageText = ref(null)
|
||||
const selectMessage = async (account, message) => {
|
||||
console.log(message)
|
||||
selectedMessage.value = message
|
||||
const {data,error} = await axios.get(`http://157.90.231.142:3000/v1/account/${account}/text/${message.text.id}`, {headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'}})
|
||||
messageHTML.value = data.html
|
||||
messageText.value = data.plain
|
||||
}
|
||||
|
||||
const addFlags = async (account, message, flags) => {
|
||||
console.log(flags)
|
||||
const {data,error} = await axios({
|
||||
method: "PUT",
|
||||
url: `http://157.90.231.142:3000/v1/account/${account}/message/${message.id}`,
|
||||
headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'},
|
||||
data: {
|
||||
flags: {
|
||||
add: flags
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
const removeFlags = async (account, message, flags) => {
|
||||
console.log(flags)
|
||||
const {data,error} = await axios({
|
||||
method: "PUT",
|
||||
url: `http://157.90.231.142:3000/v1/account/${account}/message/${message.id}`,
|
||||
headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'},
|
||||
data: {
|
||||
flags: {
|
||||
delete: flags
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
const setSeen = async (seen,message) => {
|
||||
if(seen) {
|
||||
await addFlags(selectedAccount.value,message, ["\\Seen"])
|
||||
await selectMailbox(selectedAccount.value, selectedMailbox.value)
|
||||
} else {
|
||||
await removeFlags(selectedAccount.value,message, ["\\Seen"])
|
||||
await selectMailbox(selectedAccount.value, selectedMailbox.value)
|
||||
}
|
||||
}
|
||||
|
||||
const moveTo = async (destinationPath) => {
|
||||
const {data,error} = await axios({
|
||||
method: "PUT",
|
||||
url: `http://157.90.231.142:3000/v1/account/${selectedAccount.value}/message/${selectedMessage.value.id}/move`,
|
||||
headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'},
|
||||
data: {
|
||||
path: destinationPath
|
||||
}
|
||||
})
|
||||
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
selectedMessage.value = null
|
||||
messageHTML.value = null
|
||||
messageText.value = null
|
||||
selectMailbox(selectedAccount.value, selectedMailbox.value)
|
||||
}
|
||||
|
||||
const downloadAttachment = async (attachment) => {
|
||||
const {data,error} = await axios({
|
||||
method: "GET",
|
||||
url: `http://157.90.231.142:3000/v1/account/${selectedAccount.value}/attachment/${attachment.id}`,
|
||||
headers: { 'Authorization': 'Bearer dadb572465fba648590f31557f68028a750b47b278d87c1773e8fd09670eec59'},
|
||||
responseType: "blob"
|
||||
})
|
||||
|
||||
const downloadURL = URL.createObjectURL(new Blob([data]))
|
||||
const link = document.createElement('a')
|
||||
link.href = downloadURL
|
||||
link.setAttribute('download', attachment.filename)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
|
||||
setup()
|
||||
|
||||
const selectedTab = ref(0)
|
||||
|
||||
const mails = ref([{
|
||||
id: 1,
|
||||
from: {
|
||||
name: 'Alex Smith',
|
||||
email: 'alex.smith@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=1'
|
||||
}
|
||||
},
|
||||
subject: 'Meeting Schedule',
|
||||
body: 'Hi there, just a quick reminder about our meeting scheduled for 10 AM tomorrow. We\'ll be discussing the new marketing strategies and I would really appreciate your input on the matter. Looking forward to a productive session.',
|
||||
date: new Date().toISOString()
|
||||
}, {
|
||||
id: 2,
|
||||
unread: true,
|
||||
from: {
|
||||
name: 'Jordan Brown',
|
||||
email: 'jordan.brown@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=2'
|
||||
}
|
||||
},
|
||||
subject: 'Project Update',
|
||||
body: 'I wanted to provide you with the latest update on the project. We\'ve made significant progress on the development front and I\'ve attached a detailed report for your review. Please let me know your thoughts and any areas for improvement.',
|
||||
date: sub(new Date(), { minutes: 7 }).toISOString()
|
||||
}, {
|
||||
id: 3,
|
||||
unread: true,
|
||||
from: {
|
||||
name: 'Taylor Green',
|
||||
email: 'taylor.green@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=3'
|
||||
}
|
||||
},
|
||||
subject: 'Lunch Plans',
|
||||
body: 'Hey! I was wondering if you would like to grab lunch this Friday. I know a great spot downtown that serves the best Mexican cuisine. It would be a great opportunity for us to catch up and discuss the upcoming team event.',
|
||||
date: sub(new Date(), { hours: 3 }).toISOString()
|
||||
}, {
|
||||
id: 4,
|
||||
from: {
|
||||
name: 'Morgan White',
|
||||
email: 'morgan.white@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=4'
|
||||
}
|
||||
},
|
||||
subject: 'New Proposal',
|
||||
body: 'I\'ve attached the new proposal for our next project. It outlines all the objectives, timelines, and resource allocations. I\'m particularly excited about the innovative approach we\'re taking this time. Please have a look and let me know your thoughts.',
|
||||
date: sub(new Date(), { days: 1 }).toISOString()
|
||||
}, {
|
||||
id: 5,
|
||||
from: {
|
||||
name: 'Casey Gray',
|
||||
email: 'casey.gray@example.com'
|
||||
},
|
||||
subject: 'Travel Itinerary',
|
||||
body: 'Your travel itinerary for the upcoming business trip is ready. I\'ve included all flight details, hotel reservations, and meeting schedules. Please review and let me know if there are any changes you would like to make or any additional arrangements needed.',
|
||||
date: sub(new Date(), { days: 1 }).toISOString()
|
||||
}, {
|
||||
id: 6,
|
||||
from: {
|
||||
name: 'Jamie Johnson',
|
||||
email: 'jamie.johnson@example.com'
|
||||
},
|
||||
subject: 'Budget Report',
|
||||
body: 'I\'ve completed the budget report for this quarter. It includes a detailed analysis of our expenditures and revenue, along with projections for the next quarter. I believe there are some areas where we can optimize our spending. Let\'s discuss this in our next finance meeting.',
|
||||
date: sub(new Date(), { days: 2 }).toISOString()
|
||||
}, {
|
||||
id: 7,
|
||||
from: {
|
||||
name: 'Riley Davis',
|
||||
email: 'riley.davis@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=7'
|
||||
}
|
||||
},
|
||||
subject: 'Training Session',
|
||||
body: 'Just a reminder about the training session scheduled for next week. We\'ll be covering new software tools that are crucial for our workflow. It\'s important that everyone attends as this will greatly enhance our team\'s efficiency. Please confirm your availability.',
|
||||
date: sub(new Date(), { days: 2 }).toISOString()
|
||||
}, {
|
||||
id: 8,
|
||||
unread: true,
|
||||
from: {
|
||||
name: 'Kelly Wilson',
|
||||
email: 'kelly.wilson@example.com',
|
||||
avatar: {
|
||||
src: 'https://i.pravatar.cc/128?u=8'
|
||||
}
|
||||
},
|
||||
subject: 'Happy Birthday!',
|
||||
body: 'Happy Birthday! Wishing you a fantastic day filled with joy and laughter. Your dedication and hard work throughout the year have been invaluable to our team. Enjoy your day to the fullest!',
|
||||
date: sub(new Date(), { days: 2 }).toISOString()
|
||||
}, {
|
||||
id: 9,
|
||||
from: {
|
||||
name: 'Drew Moore',
|
||||
email: 'drew.moore@example.com'
|
||||
},
|
||||
subject: 'Website Feedback',
|
||||
body: 'We are in the process of revamping our company website and I would greatly appreciate your feedback on the new design. Your perspective is always insightful and could help us enhance the user experience significantly. Please let me know a convenient time for you to discuss this.',
|
||||
date: sub(new Date(), { days: 5 }).toISOString()
|
||||
}, {
|
||||
id: 10,
|
||||
from: {
|
||||
name: 'Jordan Taylor',
|
||||
email: 'jordan.taylor@example.com'
|
||||
},
|
||||
subject: 'Gym Membership',
|
||||
body: 'This is a friendly reminder that your gym membership is due for renewal at the end of this month. We\'ve added several new classes and facilities that I think you\'ll really enjoy. Let me know if you would like a tour of the new facilities.',
|
||||
date: sub(new Date(), { days: 5 }).toISOString()
|
||||
}, {
|
||||
id: 11,
|
||||
unread: true,
|
||||
from: {
|
||||
name: 'Morgan Anderson',
|
||||
email: 'morgan.anderson@example.com'
|
||||
},
|
||||
subject: 'Insurance Policy',
|
||||
body: 'I\'m writing to inform you that your insurance policy details have been updated. The new document outlines the changes in coverage and premium rates. It\'s important to review these changes to ensure they meet your needs. Please don\'t hesitate to contact me if you have any questions.',
|
||||
date: sub(new Date(), { days: 12 }).toISOString()
|
||||
}, {
|
||||
id: 12,
|
||||
from: {
|
||||
name: 'Casey Thomas',
|
||||
email: 'casey.thomas@example.com'
|
||||
},
|
||||
subject: 'Book Club Meeting',
|
||||
body: 'I\'m excited to remind you about our next book club meeting scheduled for next Thursday. We\'ll be discussing \'The Great Gatsby,\' and I\'m looking forward to hearing everyone\'s perspectives. Also, we will be choosing our next book, so bring your suggestions!',
|
||||
date: sub(new Date(), { months: 1 }).toISOString()
|
||||
}, {
|
||||
id: 13,
|
||||
from: {
|
||||
name: 'Jamie Jackson',
|
||||
email: 'jamie.jackson@example.com'
|
||||
},
|
||||
subject: 'Recipe Exchange',
|
||||
body: 'Don\'t forget to send in your favorite recipe for our upcoming recipe exchange. It\'s a great opportunity to share and discover new and delicious meals. I\'m particularly excited to try out new dishes and add some variety to my cooking.',
|
||||
date: sub(new Date(), { months: 1 }).toISOString()
|
||||
}, {
|
||||
id: 14,
|
||||
from: {
|
||||
name: 'Riley White',
|
||||
email: 'riley.white@example.com'
|
||||
},
|
||||
subject: 'Yoga Class Schedule',
|
||||
body: 'The new schedule for yoga classes is now available. We\'ve added some new styles and adjusted the timings to accommodate more participants. I believe these classes are a great way to relieve stress and stay healthy. Hope to see you there!',
|
||||
date: sub(new Date(), { months: 1 }).toISOString()
|
||||
}, {
|
||||
id: 15,
|
||||
from: {
|
||||
name: 'Kelly Harris',
|
||||
email: 'kelly.harris@example.com'
|
||||
},
|
||||
subject: 'Book Launch Event',
|
||||
body: 'I\'m thrilled to invite you to my book launch event next month. It\'s been a journey writing this book and I\'m eager to share it with you. The event will include a reading session, Q&A, and a signing opportunity. Your support would mean a lot to me.',
|
||||
date: sub(new Date(), { months: 1 }).toISOString()
|
||||
}, {
|
||||
id: 16,
|
||||
from: {
|
||||
name: 'Drew Martin',
|
||||
email: 'drew.martin@example.com'
|
||||
},
|
||||
subject: 'Tech Conference',
|
||||
body: 'Join us at the upcoming tech conference where we will be discussing the latest trends and innovations in technology. This is a great opportunity to network with industry leaders and learn about cutting-edge developments. Your participation would greatly contribute to our team\'s knowledge and growth.',
|
||||
date: sub(new Date(), { months: 1, days: 4 }).toISOString()
|
||||
}, {
|
||||
id: 17,
|
||||
from: {
|
||||
name: 'Alex Thompson',
|
||||
email: 'alex.thompson@example.com'
|
||||
},
|
||||
subject: 'Art Exhibition',
|
||||
body: 'I wanted to invite you to check out the new art exhibition this weekend. It features some amazing contemporary artists and their latest works. It\'s a great opportunity to immerse yourself in the local art scene and get inspired. Let me know if you\'re interested in going together.',
|
||||
date: sub(new Date(), { months: 1, days: 15 }).toISOString()
|
||||
}, {
|
||||
id: 18,
|
||||
from: {
|
||||
name: 'Jordan Garcia',
|
||||
email: 'jordan.garcia@example.com'
|
||||
},
|
||||
subject: 'Networking Event',
|
||||
body: 'I\'m looking forward to seeing you at the networking event next week. It\'s a great chance to connect with professionals from various industries and expand our professional network. There will also be guest speakers discussing key business trends. Your presence would add great value to the discussions.',
|
||||
date: sub(new Date(), { months: 1, days: 18 }).toISOString()
|
||||
}, {
|
||||
id: 19,
|
||||
from: {
|
||||
name: 'Taylor Rodriguez',
|
||||
email: 'taylor.rodriguez@example.com'
|
||||
},
|
||||
subject: 'Volunteer Opportunity',
|
||||
body: 'We\'re looking for volunteers for the upcoming community event. It\'s a great opportunity to give back and make a positive impact. There are various roles available, so you can choose something that aligns with your interests and skills. Let me know if you\'re interested and I\'ll provide more details.',
|
||||
date: sub(new Date(), { months: 1, days: 25 }).toISOString()
|
||||
}, {
|
||||
id: 20,
|
||||
from: {
|
||||
name: 'Morgan Lopez',
|
||||
email: 'morgan.lopez@example.com'
|
||||
},
|
||||
subject: 'Car Service Reminder',
|
||||
body: 'Just a reminder that your car is due for service next week. Regular maintenance is important to ensure your vehicle\'s longevity and performance. I\'ve included the details of the service center and the recommended services in this email. Feel free to contact them directly to schedule an appointment.',
|
||||
date: sub(new Date(), { months: 2 }).toISOString()
|
||||
}])
|
||||
|
||||
const dropdownItems = [[{
|
||||
label: 'Mark as unread',
|
||||
icon: 'i-heroicons-check-circle'
|
||||
}, {
|
||||
label: 'Mark as important',
|
||||
icon: 'i-heroicons-exclamation-circle'
|
||||
}], [{
|
||||
label: 'Star thread',
|
||||
icon: 'i-heroicons-star'
|
||||
}, {
|
||||
label: 'Mute thread',
|
||||
icon: 'i-heroicons-pause-circle'
|
||||
}]]
|
||||
|
||||
// Filter mails based on the selected tab
|
||||
const filteredMails = computed(() => {
|
||||
if (selectedTab.value === 1) {
|
||||
return mails.value.filter(mail => !!mail.unread)
|
||||
} else {
|
||||
return mails.value
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
const selectedMail = ref(null)
|
||||
|
||||
const isMailPanelOpen = computed({
|
||||
get () {
|
||||
return !!selectedMail.value
|
||||
},
|
||||
set (value) {
|
||||
if (!value) {
|
||||
selectedMail.value = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<!-- <div class="flex flex-row">
|
||||
<div id="mailboxlist">
|
||||
<UAccordion
|
||||
:items="accounts"
|
||||
>
|
||||
<template #default="{ item, index, open }">
|
||||
<UButton variant="soft" class="mt-3">
|
||||
|
||||
<span class="truncate">{{ item.label }}</span>
|
||||
|
||||
<template #trailing>
|
||||
<UIcon
|
||||
name="i-heroicons-chevron-right-20-solid"
|
||||
class="w-5 h-5 ms-auto transform transition-transform duration-200"
|
||||
:class="[open && 'rotate-90']"
|
||||
/>
|
||||
</template>
|
||||
</UButton>
|
||||
</template>
|
||||
<template #item="{ item }">
|
||||
<div
|
||||
v-for="mailbox in mailboxes[item.emailEngineId]"
|
||||
class="my-3"
|
||||
>
|
||||
<UButton
|
||||
@click="selectMailbox(item.emailEngineId, mailbox)"
|
||||
variant="outline"
|
||||
>
|
||||
<span v-if="mailbox.name === 'Trash'">Papierkorb</span>
|
||||
<span v-else-if="mailbox.name === 'INBOX'">Eingang</span>
|
||||
<span v-else-if="mailbox.name === 'Sent'">Gesendet</span>
|
||||
<span v-else-if="mailbox.name === 'Drafts'">Entwürfe</span>
|
||||
<span v-else-if="mailbox.name === 'spambucket'">Spam</span>
|
||||
<span v-else>{{mailbox.name}}</span>
|
||||
<UBadge v-if="mailbox.messages > 0">{{mailbox.messages}}</UBadge>
|
||||
</UButton>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
</UAccordion>
|
||||
|
||||
</div>
|
||||
<UDivider orientation="vertical" class="maiLDivider"/>
|
||||
<div id="maillist">
|
||||
<div
|
||||
v-for="message in messages"
|
||||
v-if="messages.length > 0"
|
||||
>
|
||||
<div
|
||||
:class="message === selectedMessage ? ['message','text-primary-500'] : ['message']"
|
||||
@click="selectMessage(selectedAccount, message),
|
||||
!message.flags.includes('\\Seen') ? setSeen(true,message) : null"
|
||||
>
|
||||
<UChip
|
||||
position="top-left"
|
||||
:show="!message.flags.includes('\\Seen')"
|
||||
>
|
||||
<h1>{{message.from.name ||message.from.address}}</h1>
|
||||
</UChip>
|
||||
|
||||
<h3>{{message.subject}}</h3>
|
||||
</div>
|
||||
<UDivider class="my-3"/>
|
||||
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
>
|
||||
Keine E-Mails in diesem Postfach
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<UDivider orientation="vertical" class="maiLDivider"/>
|
||||
|
||||
<div id="mailcontent" v-if="selectedMessage">
|
||||
<Toolbar>
|
||||
<!–<UButton
|
||||
@click="setup"
|
||||
>Setup</UButton>
|
||||
<UButton>+ Neu</UButton>
|
||||
<UButton>Sync</UButton>
|
||||
<UButton>Papierkorb</UButton>
|
||||
<UButton>Weiterleiten</UButton>
|
||||
<UButton>Antworten</UButton>–>
|
||||
<UButton
|
||||
@click="setSeen(false,selectedMessage)"
|
||||
>
|
||||
Als Ungelesen markieren
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="moveTo('INBOX.Trash')"
|
||||
icon="i-heroicons-trash"
|
||||
>
|
||||
|
||||
</UButton>
|
||||
</Toolbar>
|
||||
<UAlert
|
||||
v-if="selectedMessage"
|
||||
:title="attachment.filename"
|
||||
v-for="attachment in selectedMessage.attachments"
|
||||
class="my-3"
|
||||
:actions="[{label: 'Download', click:() => {downloadAttachment(attachment)}}]"
|
||||
>
|
||||
|
||||
</UAlert>
|
||||
<iframe
|
||||
v-if="messageHTML"
|
||||
style="width: 100%; height: 100%"
|
||||
:srcdoc="messageHTML">
|
||||
</iframe>
|
||||
<pre
|
||||
class="text-wrap"
|
||||
v-else-if="messageText">
|
||||
{{messageText}}
|
||||
</pre>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<UDashboardPanel id="inbox" :width="400" :resizable="{ min: 300, max: 500 }">
|
||||
<UDashboardNavbar title="Inbox" >
|
||||
<template #right>
|
||||
<UTabs v-model="selectedTab" :items="[{label: 'Alle'},{label: 'Ungelesen'}]" :ui="{ wrapper: '', list: { height: 'h-9', tab: { height: 'h-7', size: 'text-[13px]' } } }" />
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<!-- ~/components/inbox/InboxList.vue -->
|
||||
<InboxList v-model="selectedMail" :mails="filteredMails" />
|
||||
</UDashboardPanel>
|
||||
|
||||
<UDashboardPanel v-model="isMailPanelOpen" collapsible grow side="right">
|
||||
<template v-if="selectedMail">
|
||||
<UDashboardNavbar>
|
||||
<template #toggle>
|
||||
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
|
||||
|
||||
<UDivider orientation="vertical" class="mx-1.5 lg:hidden" />
|
||||
</template>
|
||||
|
||||
<template #left>
|
||||
<UTooltip text="Archive">
|
||||
<UButton icon="i-heroicons-archive-box" color="gray" variant="ghost" />
|
||||
</UTooltip>
|
||||
|
||||
<UTooltip text="Move to junk">
|
||||
<UButton icon="i-heroicons-archive-box-x-mark" color="gray" variant="ghost" />
|
||||
</UTooltip>
|
||||
|
||||
<!-- <UDivider orientation="vertical" class="mx-1.5" />-->
|
||||
|
||||
<!-- <UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<template #default="{ open }">
|
||||
<UTooltip text="Snooze" :prevent="open">
|
||||
<UButton icon="i-heroicons-clock" color="gray" variant="ghost" :class="[open && 'bg-gray-50 dark:bg-gray-800']" />
|
||||
</UTooltip>
|
||||
</template>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<DatePicker @close="close" />
|
||||
</template>
|
||||
</UPopover>-->
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<UTooltip text="Reply">
|
||||
<UButton icon="i-heroicons-arrow-uturn-left" color="gray" variant="ghost" />
|
||||
</UTooltip>
|
||||
|
||||
<UTooltip text="Forward">
|
||||
<UButton icon="i-heroicons-arrow-uturn-right" color="gray" variant="ghost" />
|
||||
</UTooltip>
|
||||
|
||||
<UDivider orientation="vertical" class="mx-1.5" />
|
||||
|
||||
<UDropdown :items="dropdownItems">
|
||||
<UButton icon="i-heroicons-ellipsis-vertical" color="gray" variant="ghost" />
|
||||
</UDropdown>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<!-- ~/components/inbox/InboxMail.vue -->
|
||||
<InboxMail :mail="selectedMail" />
|
||||
</template>
|
||||
<div v-else class="flex-1 hidden lg:flex items-center justify-center">
|
||||
<UIcon name="i-heroicons-inbox" class="w-32 h-32 text-gray-400 dark:text-gray-500" />
|
||||
</div>
|
||||
</UDashboardPanel>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,260 +0,0 @@
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const dataStore = useDataStore()
|
||||
const profileStore = useProfileStore()
|
||||
|
||||
const mode = ref(route.params.mode || "show")
|
||||
|
||||
|
||||
const itemInfo = ref({
|
||||
resources: []
|
||||
})
|
||||
const oldItemInfo = ref({})
|
||||
|
||||
const resourceToAdd = ref(profileStore.activeProfile.id)
|
||||
/*const mapResources = () => {
|
||||
console.log(itemInfo.value.resources)
|
||||
itemInfo.value.resources.map(resource => {
|
||||
console.log(resource)
|
||||
return {
|
||||
id: resource.id,
|
||||
type: resource.type
|
||||
}
|
||||
})
|
||||
}*/
|
||||
|
||||
|
||||
const setupPage = async () => {
|
||||
if(mode.value === "show"){
|
||||
itemInfo.value = await useSupabaseSelectSingle("events",route.params.id,"*, project(id,name)")
|
||||
} else if(mode.value === "edit" && route.params.id) {
|
||||
itemInfo.value = await useSupabaseSelectSingle("events",route.params.id,"*")
|
||||
|
||||
}
|
||||
|
||||
if(route.query.start) itemInfo.value.start = new Date(route.query.start.replace(" ", "+"))
|
||||
if(route.query.end) itemInfo.value.end = new Date(route.query.end.replace(" ", "+"))
|
||||
if(route.query.resources) {
|
||||
itemInfo.value.resources = JSON.parse(route.query.resources).map(resource => {
|
||||
return dataStore.getResourcesList.find(i => i.id === resource)
|
||||
})
|
||||
}
|
||||
if(route.query.project) itemInfo.value.project = route.query.project
|
||||
if(itemInfo.value.id) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar :title="mode === 'show' ? 'Termin: ' + itemInfo.title : 'Neuen Termin erstellen'">
|
||||
<template #right>
|
||||
<UButton
|
||||
color="rose"
|
||||
@click="router.push(route.params.id ? `/events/show/${route.params.id}` : `/events`)"
|
||||
v-if="mode === 'edit'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
@click="dataStore.createNewItem('events',itemInfo)"
|
||||
v-if="mode === 'edit' && !route.params.id"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="dataStore.updateItem('events',itemInfo,oldItemInfo)"
|
||||
v-else-if="mode === 'edit' && route.params.id"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click="router.push(`/events/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<!-- <UDashboardToolbar>
|
||||
|
||||
</UDashboardToolbar>-->
|
||||
<UTabs
|
||||
v-if="mode === 'show'"
|
||||
:items="[{label:'Informationen'},{label:'Logbuch'}]"
|
||||
class="p-5"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<UCard class="mt-5">
|
||||
<div v-if="item.label === 'Informationen'">
|
||||
<div class="truncate" >
|
||||
<p>Titel: {{itemInfo.title ? itemInfo.title : ''}}</p>
|
||||
<p>Typ: {{itemInfo.type? itemInfo.type : ''}}</p>
|
||||
<p>Start: {{dayjs(itemInfo.start).format("DD.MM.YY HH:mm")}}</p>
|
||||
<p>Ende: {{dayjs(itemInfo.end).format("DD.MM.YY HH:mm")}}</p>
|
||||
<p>Projekt: {{itemInfo.project ? itemInfo.project.name : ''}}</p>
|
||||
<p>Link: <a v-if="itemInfo.link" :href="itemInfo.link">{{itemInfo.link }}</a></p>
|
||||
<p>Resources: {{itemInfo.resources.map((x) => `${x.type} - ${x.title}`).join(",")}}</p>
|
||||
<p>Notizen: {{itemInfo.notes ? itemInfo.notes : ''}}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-if="item.label === 'Logbuch'">
|
||||
<HistoryDisplay
|
||||
type="event"
|
||||
v-if="itemInfo"
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</div>
|
||||
</UCard>
|
||||
</template>
|
||||
</UTabs>
|
||||
<UForm class="p-5" v-if="mode === 'edit'">
|
||||
<UFormGroup
|
||||
label="Titel:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.title"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Projekt:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.project"
|
||||
:options="dataStore.projects"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
searchable-placeholder="Suche..."
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
||||
</template>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.type"
|
||||
:options="dataStore.getEventTypes"
|
||||
option-attribute="label"
|
||||
value-attribute="label"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Link:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.link"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Notizen:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.notes"
|
||||
rows="3"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Start:"
|
||||
>
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
variant="outline"
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="itemInfo.start ? dayjs(itemInfo.start).format('DD.MM.YYYY HH:mm') : 'Datum auswählen'"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker
|
||||
v-model="itemInfo.start"
|
||||
mode="dateTime"
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Ende:"
|
||||
>
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
variant="outline"
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="itemInfo.end ? dayjs(itemInfo.end).format('DD.MM.YYYY HH:mm') : 'Datum auswählen'"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker
|
||||
v-model="itemInfo.end"
|
||||
mode="dateTime"
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Resource:"
|
||||
class="w-full"
|
||||
>
|
||||
<InputGroup class="w-full">
|
||||
<USelectMenu
|
||||
v-model="resourceToAdd"
|
||||
:options="dataStore.getResourcesList"
|
||||
option-attribute="title"
|
||||
value-attribute="id"
|
||||
class="w-full"
|
||||
></USelectMenu>
|
||||
<UButton
|
||||
@click="itemInfo.resources.push(dataStore.getResourcesList.find(i => i.id === resourceToAdd))"
|
||||
:disabled="itemInfo.resources.find(i => i.id === resourceToAdd)"
|
||||
>
|
||||
+ Hinzufügen
|
||||
</UButton>
|
||||
</InputGroup>
|
||||
</UFormGroup>
|
||||
<UTable
|
||||
v-if="itemInfo.resources.length > 0"
|
||||
:rows="itemInfo.resources"
|
||||
:columns="[
|
||||
{
|
||||
key:'type',
|
||||
label: 'Type'
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Name'
|
||||
}, {
|
||||
key: 'remove'
|
||||
}
|
||||
]"
|
||||
>
|
||||
<template #remove-data="{row}">
|
||||
<UButton
|
||||
color="rose"
|
||||
variant="outline"
|
||||
@click="itemInfo.resources = itemInfo.resources.filter(i => i.id !== row.id)"
|
||||
>
|
||||
Entfernen
|
||||
</UButton>
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
|
||||
</UForm>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Termine" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/events/edit`)">+ Termin</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/events/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Termine anzuzeigen' }"
|
||||
>
|
||||
<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 #project-data="{row}">
|
||||
{{row.project ? dataStore.getProjectById(row.project).name: ""}}
|
||||
</template>
|
||||
<template #resources-data="{row}">
|
||||
{{row.resources ? row.resources.map(i => i.title).join(", ") : ""}}
|
||||
</template>
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/events/[mode]")
|
||||
}
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: 'title',
|
||||
label: "Titel:",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "start",
|
||||
label: "Start",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "end",
|
||||
label: "Ende"
|
||||
},
|
||||
{
|
||||
key: "resources",
|
||||
label: "Resourcen"
|
||||
},
|
||||
{
|
||||
key: "project",
|
||||
label: "Projekt"
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
|
||||
const searchString = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
if(!searchString.value) {
|
||||
return dataStore.events
|
||||
}
|
||||
|
||||
return dataStore.events.filter(item => {
|
||||
return Object.values(item).some((value) => {
|
||||
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,382 +0,0 @@
|
||||
<script setup>
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
import dayjs from "dayjs";
|
||||
import {useSupabaseSelectSingle} from "~/composables/useSupabase.js";
|
||||
import DocumentUpload from "~/components/DocumentUpload.vue";
|
||||
import DocumentList from "~/components/DocumentList.vue";
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const id = ref(route.params.id ? route.params.id : null )
|
||||
|
||||
//Working
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({
|
||||
name: null,
|
||||
description: null,
|
||||
quantity: 0
|
||||
})
|
||||
|
||||
//Functions
|
||||
const setupPage = async () => {
|
||||
if(mode.value === "show"){
|
||||
itemInfo.value = await useSupabaseSelectSingle("inventoryitems", route.params.id, "*, vendor(*), checks(*)")
|
||||
} else if(mode.value === "edit") {
|
||||
itemInfo.value = await useSupabaseSelectSingle("inventoryitems", route.params.id, "*")
|
||||
}
|
||||
}
|
||||
|
||||
const cancelEditorCreate = () => {
|
||||
if(itemInfo.value) {
|
||||
router.push(`/inventoryitems/show/${itemInfo.value.id}`)
|
||||
} else {
|
||||
router.push(`/inventoryitems`)
|
||||
}
|
||||
}
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar :title="itemInfo ? itemInfo.name : (mode === 'create' ? 'Inventartikel erstellen' : 'Inventartikel bearbeiten')">
|
||||
<template #left>
|
||||
<UButton
|
||||
icon="i-heroicons-chevron-left"
|
||||
variant="outline"
|
||||
@click="router.push(`/inventoryitems`)"
|
||||
>
|
||||
Inventar
|
||||
</UButton>
|
||||
</template>
|
||||
<template #center>
|
||||
<h1
|
||||
v-if="itemInfo"
|
||||
:class="['text-xl','font-medium']"
|
||||
>{{itemInfo.id ? `Inventarartikel: ${itemInfo.name}` : (mode === 'create' ? 'Inventarartikel erstellen' : 'Inventarartikel bearbeiten')}}</h1>
|
||||
</template>
|
||||
<template #right>
|
||||
<ButtonWithConfirm
|
||||
color="rose"
|
||||
variant="outline"
|
||||
@confirmed="dataStore.updateItem('inventoryitems',{...itemInfo, archived: true})"
|
||||
v-if="mode === 'edit'"
|
||||
>
|
||||
<template #button>
|
||||
Archivieren
|
||||
</template>
|
||||
<template #header>
|
||||
<span class="text-md text-black font-bold">Archivieren bestätigen</span>
|
||||
</template>
|
||||
Möchten Sie den Inventarartikel {{itemInfo.name}} wirklich archivieren?
|
||||
</ButtonWithConfirm>
|
||||
<UButton
|
||||
v-if="mode === 'edit'"
|
||||
@click="dataStore.updateItem('inventoryitems',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('inventoryitems',itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'create'"
|
||||
class="ml-2"
|
||||
@click="dataStore.createNewItem('inventoryitems',itemInfo);
|
||||
itemInfo = {
|
||||
name: null,
|
||||
description: null,
|
||||
quantity: 0
|
||||
}"
|
||||
>
|
||||
Erstellen + Neu
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="cancelEditorCreate"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
v-if="mode === 'edit' || mode === 'create'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click=" router.push(`/inventoryitems/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<UTabs
|
||||
:items="[{label: 'Informationen'},{label: 'Dokumente'},{label: 'Überprüfungen'}]"
|
||||
v-if="itemInfo && mode === 'show'"
|
||||
class="p-5"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<div v-if="item.label === 'Informationen'" class="flex-row flex mt-5">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UCard>
|
||||
<UAlert
|
||||
v-if="itemInfo.archived"
|
||||
color="rose"
|
||||
variant="outline"
|
||||
title="Objekt archiviert"
|
||||
icon="i-heroicons-light-bulb"
|
||||
class="mb-5"
|
||||
/>
|
||||
<table class="w-full">
|
||||
<tr>
|
||||
<td>Name: </td>
|
||||
<td>{{itemInfo.name}}</td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.currentSpace">
|
||||
<td>Lagerplatz: </td>
|
||||
<td>{{dataStore.getSpaceById(itemInfo.currentSpace).spaceNumber}} - {{dataStore.getSpaceById(itemInfo.currentSpace).description}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seriennummer:</td>
|
||||
<td>{{itemInfo.serialNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Menge:</td>
|
||||
<td>{{itemInfo.quantity > 0 ? itemInfo.quantity : 'Einzelarktikel'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Artikelnummer:</td>
|
||||
<td>{{itemInfo.articleNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hersteller:</td>
|
||||
<td>{{itemInfo.manufacturer}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Herstellernummer:</td>
|
||||
<td>{{itemInfo.manufacturerNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Lieferant:</td>
|
||||
<td>{{itemInfo.vendor ? itemInfo.vendor.name : ''}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kaufdatum:</td>
|
||||
<td>{{itemInfo.purchaseDate ? dayjs(itemInfo.purchaseDate).format("DD.MM.YYYY") : ''}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Wert bei Kauf:</td>
|
||||
<td>{{itemInfo.purchasePrice ? itemInfo.purchasePrice.toFixed(2).replace(".",",") + " €" : ''}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aktueller Wert:</td>
|
||||
<td>{{itemInfo.currentValue ? itemInfo.currentValue.toFixed(2).replace(".",",") + " €" : ''}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Beschreibung:</td>
|
||||
<td>{{itemInfo.description}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UCard>
|
||||
<HistoryDisplay
|
||||
type="inventoryitem"
|
||||
v-if="itemInfo"
|
||||
render-headline
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Dokumente'">
|
||||
<UCard>
|
||||
<DocumentUpload
|
||||
type="inventoryitem"
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
|
||||
<DocumentList :documents="dataStore.getDocumentsByProfileId(itemInfo.id)"/>
|
||||
</UCard>
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Überprüfungen'">
|
||||
<UCard>
|
||||
<UTable
|
||||
:rows="itemInfo.checks"
|
||||
:columns="[{key:'name',label: 'Name'},{key:'rhythm',label: 'Rhythmus'},{key:'description',label: 'Beschreibung'}]"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/checks/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Überprüfungen anzuzeigen' }"
|
||||
>
|
||||
<template #rhythm-data="{row}">
|
||||
{{row.distance}}
|
||||
<span v-if="row.distanceUnit === 'dayjs'">Tage</span>
|
||||
<span v-if="row.distanceUnit === 'years'">Jahre</span>
|
||||
</template>
|
||||
</UTable>
|
||||
</UCard>
|
||||
</div>
|
||||
</template>
|
||||
</UTabs>
|
||||
<UForm
|
||||
v-else-if="mode == 'edit' || mode == 'create'"
|
||||
class="p-5"
|
||||
>
|
||||
<div class="flex flex-row">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UDivider>
|
||||
Allgemeines
|
||||
</UDivider>
|
||||
<UFormGroup
|
||||
label="Name:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.name"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Artikelnummer:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.articleNumber"
|
||||
placeholder="Leer lassen für automatische generierte Nummer"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Lagerplatz:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="dataStore.spaces"
|
||||
v-model="itemInfo.currentSpace"
|
||||
value-attribute="id"
|
||||
>
|
||||
<template #option="{option}">
|
||||
<span class="truncate">{{option.spaceNumber}} - {{option.description}}</span>
|
||||
</template>
|
||||
<template #label>
|
||||
<span v-if="itemInfo.currentSpace">{{dataStore.getSpaceById(itemInfo.currentSpace).spaceNumber }} - {{dataStore.getSpaceById(itemInfo.currentSpace).description}}</span>
|
||||
<span v-else>Kein Lagerplatz ausgewählt</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Seriennummer:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.serialNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Menge:"
|
||||
:help="itemInfo.serialNumber ? 'Menge deaktiviert durch Eingabe der Seriennummer' : 'Für Einzelartikel Menge gleich 0'"
|
||||
>
|
||||
<UInput
|
||||
type="number"
|
||||
v-model="itemInfo.quantity"
|
||||
:disabled="itemInfo.serialNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UDivider>
|
||||
Anschaffung
|
||||
</UDivider>
|
||||
<UFormGroup
|
||||
label="Hersteller:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.manufacturer"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Herstellernr.:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.manufacturerNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Lieferant:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="dataStore.vendors"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
v-model="itemInfo.vendor"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Kaufdatum:"
|
||||
>
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton
|
||||
icon="i-heroicons-calendar-days-20-solid"
|
||||
:label="itemInfo.purchaseDate ? dayjs(itemInfo.purchaseDate).format('DD.MM.YYYY') : 'Datum auswählen'"
|
||||
variant="outline"
|
||||
/>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="itemInfo.purchaseDate" @close="close" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Wert bei Kauf:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.purchasePrice"
|
||||
type="number"
|
||||
steps="0.01"
|
||||
>
|
||||
<template #trailing>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Aktueller Wert:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.currentValue"
|
||||
type="number"
|
||||
steps="0.01"
|
||||
>
|
||||
<template #trailing>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Beschreibung:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.description"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</UForm>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
td {
|
||||
border-bottom: 1px solid lightgrey;
|
||||
vertical-align: top;
|
||||
padding-bottom: 0.15em;
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,130 +0,0 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Inventar" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/inventoryitems/create`)">+ Inventarartikel</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/inventoryitems/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Inventarartikel anzuzeigen' }"
|
||||
v-model:sort="sortConfig"
|
||||
sort-mode="manual"
|
||||
@update:sort="setupPage"
|
||||
>
|
||||
|
||||
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {sort} from "fast-sort"
|
||||
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/tasks/create")
|
||||
}
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
const items = ref([])
|
||||
|
||||
const sortConfig = ref({
|
||||
column: "articleNumber",
|
||||
direction: "desc"
|
||||
})
|
||||
|
||||
const setupPage = async () => {
|
||||
items.value = await useSupabaseSelect("inventoryitems","*")
|
||||
}
|
||||
|
||||
setupPage()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: "articleNumber",
|
||||
label: "Artikelnummer",
|
||||
sortable: true
|
||||
},{
|
||||
key: "name",
|
||||
label: "Name",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "description",
|
||||
label: "Beschreibung",
|
||||
sortable: true
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
|
||||
|
||||
const searchString = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
|
||||
let sorted = []
|
||||
|
||||
if(sortConfig.value.direction === "asc"){
|
||||
sorted = sort(items.value).asc(i => i[sortConfig.value.column])
|
||||
} else {
|
||||
sorted = sort(items.value).desc(i => i[sortConfig.value.column])
|
||||
}
|
||||
|
||||
return useListFilter(searchString.value, sorted)
|
||||
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,321 +0,0 @@
|
||||
<script setup>
|
||||
import axios from "axios";
|
||||
import ZebraBrowserPrintWrapper from "zebra-browser-print-wrapper"
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const id = ref(route.params.id ? route.params.id : null )
|
||||
|
||||
//Working
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({
|
||||
spaceNumber: "",
|
||||
address: {
|
||||
streetNumber: "",
|
||||
city: "",
|
||||
zip:""
|
||||
}
|
||||
})
|
||||
const spaceTypes = ["Standort","Regalplatz", "Kiste", "Palettenplatz", "Sonstiges"]
|
||||
const spaceProducts = ref([])
|
||||
const spaceMovements = ref([])
|
||||
|
||||
const spaces = ref([])
|
||||
|
||||
//Functions
|
||||
const setupPage = async () => {
|
||||
if(mode.value === "show"){
|
||||
itemInfo.value = await useSupabaseSelectSingle("spaces",route.params.id,"*, parentSpace(*), inventoryitems(*)")
|
||||
|
||||
spaceMovements.value = await dataStore.getMovementsBySpace(itemInfo.value.id)
|
||||
spaceProducts.value = []
|
||||
spaceMovements.value.forEach(movement => {
|
||||
if(spaceProducts.value.filter(product => product.id === movement.productId).length === 0) spaceProducts.value.push(dataStore.getProductById(movement.productId))
|
||||
})
|
||||
|
||||
|
||||
} else if(mode.value === "edit") {
|
||||
itemInfo.value = await useSupabaseSelectSingle("spaces",route.params.id,"*")
|
||||
}
|
||||
|
||||
if(mode.value === "edit" || mode.value === "create"){
|
||||
if(itemInfo.value){
|
||||
spaces.value = (await useSupabaseSelect("spaces",'*')).filter(i => i.id !== itemInfo.value.id)
|
||||
} else {
|
||||
spaces.value = (await useSupabaseSelect("spaces",'*'))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
const cancelEditorCreate = () => {
|
||||
if(itemInfo.value) {
|
||||
router.push(`/spaces/show/${itemInfo.value.id}`)
|
||||
} else {
|
||||
router.push(`/spaces/`)
|
||||
}
|
||||
}
|
||||
|
||||
function getSpaceProductCount(productId) {
|
||||
let productMovements = spaceMovements.value.filter(movement => movement.productId === productId)
|
||||
let count = 0;
|
||||
productMovements.forEach(movement => count += movement.quantity)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
/*
|
||||
const printSpaceLabel = async () => {
|
||||
axios
|
||||
.post(`http://${profileStore.ownTenant.value.labelPrinterIp}/pstprnt`, `^XA^FO10,20^BCN,100^FD${itemInfo.value.spaceNumber}^XZ` )
|
||||
.then(console.log)
|
||||
.catch(console.log)
|
||||
}
|
||||
*/
|
||||
|
||||
const cityLoading = ref(false)
|
||||
const setCityByZip = async () => {
|
||||
cityLoading.value = true
|
||||
itemInfo.value.address.city = await useZipCheck(itemInfo.value.address.zip)
|
||||
cityLoading.value = false
|
||||
}
|
||||
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar :title="itemInfo ? itemInfo.name : (mode === 'create' ? 'Lagerplatz erstellen' : 'Lagerplatz bearbeiten')">
|
||||
<template #left>
|
||||
<UButton
|
||||
icon="i-heroicons-chevron-left"
|
||||
variant="outline"
|
||||
@click="router.push(`/spaces`)"
|
||||
>
|
||||
Lagerplätze
|
||||
</UButton>
|
||||
</template>
|
||||
<template #center>
|
||||
<h1
|
||||
v-if="itemInfo"
|
||||
:class="['text-xl','font-medium']"
|
||||
>{{itemInfo ? `Lagerplatz: ${itemInfo.spaceNumber} - ${itemInfo.description}` : (mode === 'create' ? 'Lagerplatz erstellen' : 'Lagerplatz bearbeiten')}}</h1>
|
||||
</template>
|
||||
<template #right>
|
||||
<UButton
|
||||
v-if="mode === 'edit'"
|
||||
@click="dataStore.updateItem('spaces',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('spaces',itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="cancelEditorCreate"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
v-if="mode === 'edit' || mode === 'create'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click=" router.push(`/spaces/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<UDashboardPanelContent>
|
||||
<UTabs
|
||||
:items="[{label: 'Informationen'},{label: 'Bestand'},{label: 'Inventarartikel'}]"
|
||||
v-if="itemInfo && mode === 'show'"
|
||||
class="p-5"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<div v-if="item.label === 'Informationen'" class="flex mt-5">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UCard>
|
||||
<div class="truncate">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Typ:</td>
|
||||
<td>{{itemInfo.type}}</td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.type !== 'Standort'">
|
||||
<td>Übergeordneter Lagerplatz:</td>
|
||||
<td><router-link v-if="itemInfo.parentSpace" :to="`/spaces/show/${itemInfo.parentSpace.id}`">{{itemInfo.parentSpace.spaceNumber}} - {{itemInfo.parentSpace.description}}</router-link></td>
|
||||
</tr>
|
||||
<tr v-if="itemInfo.type === 'Standort'">
|
||||
<td>Adresse:</td>
|
||||
<td>{{`${itemInfo.address.streetNumber}, ${itemInfo.address.zip} ${itemInfo.address.city}`}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Beschreibung:</td>
|
||||
<td>{{itemInfo.description}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UCard>
|
||||
<HistoryDisplay
|
||||
type="space"
|
||||
v-if="itemInfo"
|
||||
render-headline
|
||||
:element-id="itemInfo.id"
|
||||
/>
|
||||
</UCard>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Bestand'">
|
||||
<UCard>
|
||||
<div v-if="spaceProducts.length > 0">
|
||||
|
||||
<table class="w-full">
|
||||
<tr>
|
||||
<th class="text-left">Artikel in diesem Lagerplatz</th>
|
||||
<th>Anzahl</th>
|
||||
<th>Einheit</th>
|
||||
</tr>
|
||||
<tr v-for="product in spaceProducts">
|
||||
<td>{{product.name}}</td>
|
||||
<td>{{getSpaceProductCount(product.id)}}</td>
|
||||
<td>{{dataStore.units.find(unit => unit.id === product.unit).name}}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<p v-else>Es befinden sich keine Artikel in diesem Lagerplatz</p>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Inventarartikel'">
|
||||
<UAlert
|
||||
description="Hier werden alle Inventarartikel in diesem Lagerplatz aufgelistet"
|
||||
color="primary"
|
||||
variant="outline"
|
||||
/>
|
||||
<UTable
|
||||
:rows="itemInfo.inventoryitems"
|
||||
:columns="[{label:'Name',key:'name'}]"
|
||||
@select="(row) => router.push(`/inventoryitems/show/${row.id}`)"
|
||||
>
|
||||
|
||||
</UTable>
|
||||
</div>
|
||||
</template>
|
||||
</UTabs>
|
||||
<UForm
|
||||
v-else-if="mode === 'edit' || mode === 'create'"
|
||||
class="p-5"
|
||||
>
|
||||
<div class="flex flex-row">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UDivider>
|
||||
Allgemeines
|
||||
</UDivider>
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="spaceTypes"
|
||||
v-model="itemInfo.type"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Übergeordneter Lagerplatz:"
|
||||
v-if="itemInfo.type !== 'Standort'"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="spaces"
|
||||
option-attribute="spaceNumber"
|
||||
value-attribute="id"
|
||||
v-model="itemInfo.parentSpace"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
<div class="w-1/2" v-if="itemInfo.type === 'Standort'">
|
||||
<UDivider>
|
||||
Ort
|
||||
</UDivider>
|
||||
<UFormGroup
|
||||
label="Straße + Hausnummer:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.address.streetNumber"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="PLZ + Ort:"
|
||||
>
|
||||
<InputGroup class="w-full">
|
||||
<UInput
|
||||
v-model="itemInfo.address.zip"
|
||||
placeholder="PLZ"
|
||||
@focusout="setCityByZip"
|
||||
/>
|
||||
<UInput
|
||||
v-model="itemInfo.address.city"
|
||||
placeholder="Ort"
|
||||
class="flex-auto"
|
||||
:disabled="cityLoading"
|
||||
|
||||
/>
|
||||
</InputGroup>
|
||||
|
||||
</UFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Beschreibung:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.description"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</UForm>
|
||||
</UDashboardPanelContent>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
td,th {
|
||||
padding-right: 2em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
border-bottom: 1px solid lightgrey;
|
||||
vertical-align: top;
|
||||
padding-bottom: 0.15em;
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Lagerplätze" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/spaces/create`)">+ Lagerplatz</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/spaces/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Lagerplätze anzuzeigen' }"
|
||||
>
|
||||
<template #spaceNumber-data="{row}">
|
||||
<span v-if="row === filteredRows[selectedItem]" class="text-primary-500 font-bold">{{row.spaceNumber}}</span>
|
||||
<span v-else>{{row.spaceNumber}}</span>
|
||||
</template>
|
||||
<template #address-data="{row}">
|
||||
<span>{{row.address.streetNumber ? `${row.address.streetNumber}, ${row.address.zip}${row.address.city}` : ''}}</span>
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/spaces/create")
|
||||
},
|
||||
'Enter': {
|
||||
usingInput: true,
|
||||
handler: () => {
|
||||
router.push(`/spaces/show/${filteredRows.value[selectedItem.value].id}`)
|
||||
}
|
||||
},
|
||||
'arrowdown': () => {
|
||||
if(selectedItem.value < filteredRows.value.length - 1) {
|
||||
selectedItem.value += 1
|
||||
} else {
|
||||
selectedItem.value = 0
|
||||
}
|
||||
},
|
||||
'arrowup': () => {
|
||||
if(selectedItem.value === 0) {
|
||||
selectedItem.value = filteredRows.value.length - 1
|
||||
} else {
|
||||
selectedItem.value -= 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
|
||||
const items = ref([])
|
||||
const selectedItem = ref(0)
|
||||
|
||||
const setupPage = async () => {
|
||||
items.value = await useSupabaseSelect("spaces","*","spaceNumber")
|
||||
}
|
||||
|
||||
setupPage()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: 'spaceNumber',
|
||||
label: "Lagerplatznr.",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
label: "Typ",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "description",
|
||||
label: "Beschreibung",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "address",
|
||||
label: "Adresse",
|
||||
sortable: true
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
const searchString = ref('')
|
||||
const filteredRows = computed(() => {
|
||||
return useSearch(searchString.value, items.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,453 +0,0 @@
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
|
||||
//TODO: Build User Page
|
||||
|
||||
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const profileStore = useProfileStore()
|
||||
const supabase = useSupabaseClient()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const id = ref(route.params.id ? route.params.id : null )
|
||||
|
||||
let currentItem = null
|
||||
|
||||
//Working
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({})
|
||||
|
||||
const tabItems = [
|
||||
{
|
||||
label: "Informationen"
|
||||
},{
|
||||
label: "Zeiterfassung"
|
||||
},{
|
||||
label: "Rechte"
|
||||
},
|
||||
]
|
||||
|
||||
const timeSelection = ref("Heute")
|
||||
const timeColumns = [
|
||||
{
|
||||
key: "state",
|
||||
label: "Status"
|
||||
},{
|
||||
key: "user",
|
||||
label: "Benutzer"
|
||||
},{
|
||||
key: "start",
|
||||
label: "Start"
|
||||
},{
|
||||
key: "end",
|
||||
label: "Ende"
|
||||
},{
|
||||
key: "notes",
|
||||
label: "Notizen"
|
||||
},{
|
||||
key: "projectId",
|
||||
label: "Projekt"
|
||||
},{
|
||||
key: "duration",
|
||||
label: "Dauer"
|
||||
},
|
||||
]
|
||||
|
||||
const filteredTimes = computed(() => {
|
||||
let rows = dataStore.times
|
||||
rows = rows.filter(i => i.user === currentItem.id)
|
||||
|
||||
if(timeSelection.value === 'Heute') {
|
||||
rows = rows.filter(i => dayjs().isSame(i.start,'day'))
|
||||
} else if(timeSelection.value === 'Diese Woche') {
|
||||
rows = rows.filter(i => dayjs().isSame(i.start,'week'))
|
||||
} else if(timeSelection.value === 'Dieser Monat') {
|
||||
rows = rows.filter(i => dayjs().isSame(i.start,'month'))
|
||||
} else if(timeSelection.value === 'Dieses Jahr') {
|
||||
rows = rows.filter(i => dayjs().isSame(i.start,'year'))
|
||||
} else if(timeSelection.value === 'Letztes Jahr') {
|
||||
rows = rows.filter(i => dayjs().subtract(1,'year').isSame(i.start,'year'))
|
||||
}
|
||||
|
||||
return rows
|
||||
})
|
||||
|
||||
//Functions
|
||||
const setupPage = () => {
|
||||
if(mode.value === "show" || mode.value === "edit"){
|
||||
currentItem = profileStore.getProfileById(useRoute().params.id)
|
||||
}
|
||||
|
||||
itemInfo.value = currentItem
|
||||
}
|
||||
|
||||
const editItem = async () => {
|
||||
router.push(`/users/edit/${currentItem.id}`)
|
||||
setupPage()
|
||||
}
|
||||
|
||||
const cancelEditorCreate = () => {
|
||||
mode.value = "show"
|
||||
itemInfo.value = {
|
||||
id: 0,
|
||||
infoData: {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getDuration = (time) => {
|
||||
const dez = dayjs(time.end).diff(time.start,'hour',true).toFixed(2)
|
||||
const hours = Math.floor(dez)
|
||||
const minutes = Math.floor((dez - hours) * 60)
|
||||
return {
|
||||
dezimal: dez,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
composed: `${hours}:${minutes}`
|
||||
}
|
||||
}
|
||||
|
||||
const getSelectionSum = computed(() => {
|
||||
let times = filteredTimes.value
|
||||
let sum = 0
|
||||
let sumEntwurf = 0
|
||||
let sumEingereicht = 0
|
||||
let sumBestaetigt = 0
|
||||
|
||||
times.forEach(time => {
|
||||
let duration = getDuration(time)
|
||||
|
||||
sum += Number(duration.dezimal)
|
||||
|
||||
if(time.state === 'Entwurf') {
|
||||
sumEntwurf += Number(duration.dezimal)
|
||||
} else if(time.state === 'Eingereicht') {
|
||||
sumEingereicht += Number(duration.dezimal)
|
||||
} else if(time.state === 'Bestätigt') {
|
||||
sumBestaetigt += Number(duration.dezimal)
|
||||
}
|
||||
})
|
||||
|
||||
sum = sum.toFixed(2)
|
||||
sumEntwurf = sumEntwurf.toFixed(2)
|
||||
sumEingereicht = sumEingereicht.toFixed(2)
|
||||
sumBestaetigt = sumBestaetigt.toFixed(2)
|
||||
|
||||
return {
|
||||
sum,
|
||||
sumEntwurf,
|
||||
sumEingereicht,
|
||||
sumBestaetigt
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UCard v-if="currentItem && mode == 'show'" >
|
||||
<template #header>
|
||||
{{currentItem.fullName}}
|
||||
</template>
|
||||
|
||||
<UTabs :items="tabItems">
|
||||
<template #item="{item}">
|
||||
<div
|
||||
v-if="item.label === 'Informationen'"
|
||||
class="w-full"
|
||||
>
|
||||
<InputGroup class="w-full">
|
||||
<div class="w-1/2 mr-5">
|
||||
<UFormGroup
|
||||
label="Anrede"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
|
||||
<InputGroup>
|
||||
<UFormGroup
|
||||
label="Vorname:"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.firstName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Nachnahme:"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.lastName"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Geburtsdatum"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Benutzername"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.username"
|
||||
disabled
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UFormGroup
|
||||
label="E-Mail"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
|
||||
<InputGroup>
|
||||
<UFormGroup
|
||||
label="Telefonnummer:"
|
||||
class="w-1/2"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Mobilfunknummer:"
|
||||
class="w-1/2"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Straße & Hausnummer"
|
||||
>
|
||||
<UInput
|
||||
class="flex-auto"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<InputGroup>
|
||||
<UFormGroup
|
||||
label="Postleitzahl:"
|
||||
class="w-40"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Ort:"
|
||||
class="flex-auto"
|
||||
>
|
||||
<UInput/>
|
||||
</UFormGroup>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</InputGroup>
|
||||
<UButton
|
||||
class="mt-5"
|
||||
@click="dataStore.updateItem('users',itemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
|
||||
</div>
|
||||
<div v-else-if="item.label === 'Zeiterfassung'">
|
||||
<UButtonGroup>
|
||||
<UButton
|
||||
@click="timeSelection = 'Heute'"
|
||||
:variant="timeSelection === 'Heute' ? 'solid' : 'outline'"
|
||||
>
|
||||
Heute
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="timeSelection = 'Diese Woche'"
|
||||
:variant="timeSelection === 'Diese Woche' ? 'solid' : 'outline'"
|
||||
>
|
||||
Diese Woche
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="timeSelection = 'Dieser Monat'"
|
||||
:variant="timeSelection === 'Dieser Monat' ? 'solid' : 'outline'"
|
||||
>
|
||||
Dieser Monat
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="timeSelection = 'Dieses Jahr'"
|
||||
:variant="timeSelection === 'Dieses Jahr' ? 'solid' : 'outline'"
|
||||
>
|
||||
Dieses Jahr
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="timeSelection = 'Letztes Jahr'"
|
||||
:variant="timeSelection === 'Letztes Jahr' ? 'solid' : 'outline'"
|
||||
color="rose"
|
||||
>
|
||||
Letztes Jahr
|
||||
</UButton>
|
||||
</UButtonGroup>
|
||||
<UButton
|
||||
class="ml-3"
|
||||
to="/employees/timetracking"
|
||||
>
|
||||
Zur Zeiterfassung
|
||||
</UButton>
|
||||
|
||||
<InputGroup class="w-full">
|
||||
<div>
|
||||
Summe: {{getSelectionSum.sum}}<br>
|
||||
Summe Entwurf: {{getSelectionSum.sumEntwurf}}<br>
|
||||
Summe Eingereicht: {{getSelectionSum.sumEingereicht}}<br>
|
||||
Summe Bestätigt: {{getSelectionSum.sumBestaetigt}}<br>
|
||||
</div>
|
||||
</InputGroup>
|
||||
|
||||
<UTable
|
||||
:rows="filteredTimes"
|
||||
:columns="timeColumns"
|
||||
>
|
||||
<template #state-data="{row}">
|
||||
<span
|
||||
v-if="row.state === 'Entwurf'"
|
||||
class="text-rose-500"
|
||||
>{{row.state}}</span>
|
||||
<span
|
||||
v-if="row.state === 'Eingereicht'"
|
||||
class="text-cyan-500"
|
||||
>{{row.state}}</span>
|
||||
<span
|
||||
v-if="row.state === 'Bestätigt'"
|
||||
class="text-primary-500"
|
||||
>{{row.state}}</span>
|
||||
</template>
|
||||
<template #start-data="{row}">
|
||||
<div class="text-right">{{dayjs(row.start).format("DD.MM.YY HH:mm")}}</div>
|
||||
</template>
|
||||
<template #end-data="{row}">
|
||||
<div class="text-right">{{dayjs(row.end).format("HH:mm")}}</div>
|
||||
</template>
|
||||
<template #user-data="{row}">
|
||||
{{profileStore.getProfileById(row.user) ? profileStore.getProfileById(row.user).fullName : ""}}
|
||||
</template>
|
||||
<template #duration-data="{row}">
|
||||
<div class="text-right">{{ getDuration(row).composed}} Std</div>
|
||||
</template>
|
||||
<template #projectId-data="{row}">
|
||||
{{dataStore.getProjectById(row.projectId) ? dataStore.getProjectById(row.projectId).name : ""}}
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</UTabs>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
v-if="mode == 'show' && currentItem.id"
|
||||
@click="editItem"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
</UCard>
|
||||
<UCard v-else-if="mode == 'edit' || mode == 'create'" >
|
||||
<template #header>
|
||||
{{itemInfo.title}}
|
||||
</template>
|
||||
|
||||
<UFormGroup
|
||||
label="Titel:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.title"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Status:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.state"
|
||||
:options="states"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Kundennummer:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.customer"
|
||||
:options="dataStore.customers"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.customers.find(customer => customer.id === itemInfo.customer) ? dataStore.customers.find(customer => customer.id === itemInfo.customer).name : "Kunde auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Beschreibung:"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="itemInfo.description"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
v-if="mode == 'edit'"
|
||||
@click="dataStore.updateItem('users',{...itemInfo, fullName: `${itemInfo.firstName} ${itemInfo.lastName}`})"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<!-- <UButton
|
||||
v-else-if="mode == 'create'"
|
||||
@click="dataStore.createItem()"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>-->
|
||||
<UButton
|
||||
@click="cancelEditorCreate"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
</UCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,43 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
const dataStore = useDataStore()
|
||||
const router = useRouter()
|
||||
|
||||
const columns = [
|
||||
{
|
||||
key:"fullName",
|
||||
label: "Name",
|
||||
},/*
|
||||
{
|
||||
key: "username",
|
||||
label: "Benutzername"
|
||||
},*/
|
||||
{
|
||||
key: "role",
|
||||
label: "Rolle"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<UTable
|
||||
:rows="dataStore.profiles"
|
||||
:columns="columns"
|
||||
@select="(item) => router.push(`/users/show/${item.id}`)"
|
||||
>
|
||||
|
||||
</UTable>
|
||||
|
||||
<DevOnly>
|
||||
{{dataStore.profiles}}
|
||||
</DevOnly>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user