Cleared Deprecated Folder

This commit is contained in:
2024-12-28 14:33:36 +01:00
parent d3c865a10f
commit 8cfa5eaa43
13 changed files with 0 additions and 3270 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
&lt;!&ndash;<UButton
@click="setup"
>Setup</UButton>
<UButton>+ Neu</UButton>
<UButton>Sync</UButton>
<UButton>Papierkorb</UButton>
<UButton>Weiterleiten</UButton>
<UButton>Antworten</UButton>&ndash;&gt;
<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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>