Added Chat
Restructured Calendar Some Changes in Timetracking
This commit is contained in:
@@ -42,6 +42,11 @@ const userMenuItems = ref([
|
|||||||
label: 'Benutzer',
|
label: 'Benutzer',
|
||||||
icon: 'i-heroicons-user-group',
|
icon: 'i-heroicons-user-group',
|
||||||
to: "/users"
|
to: "/users"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Chat',
|
||||||
|
icon: 'i-heroicons-user-group',
|
||||||
|
to: "/chat"
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -138,7 +143,12 @@ const navLinks = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Plantafel",
|
label: "Plantafel",
|
||||||
to: "/planningBoard",
|
to: "/calendar/timeline",
|
||||||
|
icon: "i-heroicons-calendar-days"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kalender",
|
||||||
|
to: "/calendar/grid",
|
||||||
icon: "i-heroicons-calendar-days"
|
icon: "i-heroicons-calendar-days"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup>
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"@fullcalendar/list": "^6.1.10",
|
"@fullcalendar/list": "^6.1.10",
|
||||||
"@fullcalendar/resource": "^6.1.10",
|
"@fullcalendar/resource": "^6.1.10",
|
||||||
"@fullcalendar/resource-timeline": "^6.1.10",
|
"@fullcalendar/resource-timeline": "^6.1.10",
|
||||||
|
"@fullcalendar/timegrid": "^6.1.10",
|
||||||
"@fullcalendar/vue3": "^6.1.10",
|
"@fullcalendar/vue3": "^6.1.10",
|
||||||
"@nuxt/content": "^2.9.0",
|
"@nuxt/content": "^2.9.0",
|
||||||
"@nuxt/ui-pro": "^0.7.0",
|
"@nuxt/ui-pro": "^0.7.0",
|
||||||
|
|||||||
304
spaces/pages/calendar/[mode].vue
Normal file
304
spaces/pages/calendar/[mode].vue
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
<script setup>
|
||||||
|
import deLocale from "@fullcalendar/core/locales/de";
|
||||||
|
import listPlugin from "@fullcalendar/list";
|
||||||
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
|
import dayGridPlugin from "@fullcalendar/daygrid"
|
||||||
|
import timeGridPlugin from "@fullcalendar/timeGrid"
|
||||||
|
import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
|
||||||
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
//Config
|
||||||
|
const route = useRoute()
|
||||||
|
const mode = ref(route.params.mode || "grid")
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
|
const dataStore = useDataStore()
|
||||||
|
const resources = dataStore.getResources
|
||||||
|
const eventTypes = dataStore.getEventTypes
|
||||||
|
|
||||||
|
|
||||||
|
//Working
|
||||||
|
const newEventData = ref({
|
||||||
|
resources: [],
|
||||||
|
resourceId: "",
|
||||||
|
resourceType: "",
|
||||||
|
title: "",
|
||||||
|
type: "Umsetzung",
|
||||||
|
start: "",
|
||||||
|
end: null
|
||||||
|
})
|
||||||
|
const showNewEventModal = ref(false)
|
||||||
|
const showEventModal = ref(false)
|
||||||
|
const selectedEvent = ref({})
|
||||||
|
const selectedResources = ref([])
|
||||||
|
|
||||||
|
|
||||||
|
//Functions
|
||||||
|
const convertResourceIds = () => {
|
||||||
|
|
||||||
|
newEventData.value.resources = selectedResources.value.map(i => {
|
||||||
|
/*if(i.type !== 'Mitarbeiter') {
|
||||||
|
return {id: Number(i.id.split('-')[1]), type: i.type}
|
||||||
|
} else {
|
||||||
|
return {id: i.id, type: i.type}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if((String(i).match(/-/g) || []).length > 1) {
|
||||||
|
return {type: "Mitarbeiter", id: i}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if(i.split('-')[0] === 'I') {
|
||||||
|
return {id: Number(i.split('-')[1]), type: "Inventar"}
|
||||||
|
} else if(i.split('-')[0] === 'F') {
|
||||||
|
return {id: Number(i.split('-')[1]), type: "Fahrzeug"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const createEvent = async () => {
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("events")
|
||||||
|
.insert([newEventData.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("OK")
|
||||||
|
showNewEventModal.value = false
|
||||||
|
newEventData.value = {}
|
||||||
|
dataStore.fetchEvents()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calendar Config
|
||||||
|
const calendarOptionsGrid = reactive({
|
||||||
|
locale: deLocale,
|
||||||
|
plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin],
|
||||||
|
headerToolbar: {
|
||||||
|
left: 'prev,next today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
||||||
|
},
|
||||||
|
initialView: "dayGridMonth",
|
||||||
|
initialEvents: dataStore.getEvents,
|
||||||
|
nowIndicator: true,
|
||||||
|
height: "80vh",
|
||||||
|
selectable: true,
|
||||||
|
select: function(info) {
|
||||||
|
console.log(info)
|
||||||
|
/*newEventData.value.resourceId = info.resource.id
|
||||||
|
if(info.resource.extendedProps){
|
||||||
|
newEventData.value.resourceType = info.resource.extendedProps.type
|
||||||
|
}*/
|
||||||
|
|
||||||
|
newEventData.value.start = info.startStr
|
||||||
|
newEventData.value.end = info.endStr
|
||||||
|
showNewEventModal.value = true
|
||||||
|
},
|
||||||
|
eventClick: function (info){
|
||||||
|
selectedEvent.value = info.event
|
||||||
|
showEventModal.value = true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const calendarOptionsTimeline = reactive({
|
||||||
|
schedulerLicenseKey: "CC-Attribution-NonCommercial-NoDerivatives",
|
||||||
|
locale: deLocale,
|
||||||
|
plugins: [resourceTimelinePlugin, interactionPlugin],
|
||||||
|
initialView: "resourceTimeline3Hours",
|
||||||
|
|
||||||
|
headerToolbar: {
|
||||||
|
left: 'prev,next',
|
||||||
|
center: 'title',
|
||||||
|
right: 'resourceTimelineDay,resourceTimeline3Hours,resourceTimelineMonth'
|
||||||
|
},
|
||||||
|
initialEvents: dataStore.getEventsByResource,
|
||||||
|
selectable: true,
|
||||||
|
select: function (info) {
|
||||||
|
/*let resourceObj = {}
|
||||||
|
|
||||||
|
resourceObj.id = info.resource.id
|
||||||
|
if(info.resource.extendedProps){
|
||||||
|
resourceObj.type = info.resource.extendedProps.type
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(resourceObj)*/
|
||||||
|
|
||||||
|
selectedResources.value = [info.resource.id]
|
||||||
|
newEventData.value.start = info.startStr
|
||||||
|
newEventData.value.end = info.endStr
|
||||||
|
console.log(newEventData.value)
|
||||||
|
convertResourceIds()
|
||||||
|
showNewEventModal.value = true
|
||||||
|
},
|
||||||
|
eventClick: function (info){
|
||||||
|
selectedEvent.value = info.event
|
||||||
|
showEventModal.value = true
|
||||||
|
},
|
||||||
|
resourceGroupField: "type",
|
||||||
|
resourceOrder: "-type",
|
||||||
|
resources: resources,
|
||||||
|
nowIndicator:true,
|
||||||
|
views: {
|
||||||
|
resourceTimeline3Hours: {
|
||||||
|
type: 'resourceTimeline',
|
||||||
|
slotDuration: {hours: 3},
|
||||||
|
slotMinTime: "06:00:00",
|
||||||
|
slotMaxTime: "21:00:00",
|
||||||
|
/*duration: {days:7},*/
|
||||||
|
buttonText: "Woche",
|
||||||
|
visibleRange: function(currentDate) {
|
||||||
|
// Generate a new date for manipulating in the next step
|
||||||
|
var startDate = new Date(currentDate);
|
||||||
|
var endDate = new Date(currentDate);
|
||||||
|
|
||||||
|
// Adjust the start & end dates, respectively
|
||||||
|
startDate.setDate(startDate.getDate() - startDate.getDay() +1); // One day in the past
|
||||||
|
endDate.setDate(startDate.getDate() + 5); // Two days into the future
|
||||||
|
|
||||||
|
return { start: startDate, end: endDate };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
height: '80vh',
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- NEW EVENT MODAL -->
|
||||||
|
<UModal
|
||||||
|
v-model="showNewEventModal"
|
||||||
|
>
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
Neuen Termin erstellen
|
||||||
|
</template>
|
||||||
|
{{newEventData.resources}}
|
||||||
|
<UFormGroup
|
||||||
|
label="Resource:"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="selectedResources"
|
||||||
|
:options="resources"
|
||||||
|
option-attribute="title"
|
||||||
|
value-attribute="id"
|
||||||
|
multiple
|
||||||
|
@change="convertResourceIds"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span v-if="selectedResources.length == 0">Keine Ressourcen ausgewählt</span>
|
||||||
|
<span v-else >{{ selectedResources.length }} ausgewählt</span>
|
||||||
|
</template>
|
||||||
|
</USelectMenu>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Titel:"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="newEventData.title"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Projekt:"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="newEventData.project"
|
||||||
|
:options="dataStore.projects"
|
||||||
|
option-attribute="name"
|
||||||
|
value-attribute="id"
|
||||||
|
searchable
|
||||||
|
searchable-placeholder="Suche..."
|
||||||
|
:search-attributes="['name']"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
{{dataStore.getProjectById(newEventData.project) ? dataStore.getProjectById(newEventData.project).name : "Kein Projekt ausgewählt"}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</USelectMenu>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Typ:"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="newEventData.type"
|
||||||
|
:options="eventTypes"
|
||||||
|
option-attribute="label"
|
||||||
|
value-attribute="label"
|
||||||
|
>
|
||||||
|
|
||||||
|
</USelectMenu>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Start:"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="newEventData.start"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Ende:"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="newEventData.end"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton
|
||||||
|
@click="createEvent"
|
||||||
|
>
|
||||||
|
Erstellen
|
||||||
|
</UButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</UCard>
|
||||||
|
</UModal>
|
||||||
|
|
||||||
|
<!--SHOW EVENT MODAL -->
|
||||||
|
<UModal
|
||||||
|
v-model="showEventModal"
|
||||||
|
>
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
{{selectedEvent.title}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
Start: {{dayjs(selectedEvent.startStr).format("DD.MM.YYYY HH:mm")}}<br>
|
||||||
|
Ende: {{dayjs(selectedEvent.endStr).format("DD.MM.YYYY HH:mm")}}
|
||||||
|
|
||||||
|
<DevOnly>
|
||||||
|
<UDivider class="my-3"/>
|
||||||
|
{{selectedEvent}}
|
||||||
|
</DevOnly>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
|
||||||
|
</UModal>
|
||||||
|
|
||||||
|
<div v-if="mode === 'grid'">
|
||||||
|
<FullCalendar
|
||||||
|
:options="calendarOptionsGrid"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="mode === 'timeline'">
|
||||||
|
<FullCalendar
|
||||||
|
:options="calendarOptionsTimeline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
157
spaces/pages/chat.vue
Normal file
157
spaces/pages/chat.vue
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
layout: "default"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
|
const user = useSupabaseUser()
|
||||||
|
|
||||||
|
const dataStore = useDataStore()
|
||||||
|
const selectedChat = ref({})
|
||||||
|
const messageText = ref("")
|
||||||
|
const createMessage = async () => {
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("messages")
|
||||||
|
.insert([{
|
||||||
|
text: messageText.value,
|
||||||
|
origin: user.value.id,
|
||||||
|
destination: selectedChat.value.id
|
||||||
|
}])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
messageText.value = ""
|
||||||
|
console.log("OK")
|
||||||
|
dataStore.fetchMessages()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex h-full">
|
||||||
|
<div class="w-1/5 mr-2">
|
||||||
|
<a
|
||||||
|
v-for="chat in dataStore.chats"
|
||||||
|
@click="selectedChat = chat"
|
||||||
|
>
|
||||||
|
<UAlert
|
||||||
|
:title="chat.title ? chat.title : chat.members.map(i => { if(i !== user.id) return dataStore.getProfileById(i).fullName}).join(' ')"
|
||||||
|
:avatar="{alt: chat.members.map(i => { if(i !== user.id) return dataStore.getProfileById(i).fullName}).join(' ')}"
|
||||||
|
:color="selectedChat.id === chat.id ? 'primary' : 'white'"
|
||||||
|
variant="outline"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<!-- <UCard class="h-full" v-if="selectedChat.id">
|
||||||
|
<template #header>
|
||||||
|
<Placeholder class="h-8"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="h-full">
|
||||||
|
<UAlert
|
||||||
|
v-for="message in dataStore.getMessagesByChatId(selectedChat.id)"
|
||||||
|
:color="message.origin === user.id ? 'primary' : 'white'"
|
||||||
|
variant="outline"
|
||||||
|
:avatar="{alt: dataStore.getProfileById(message.origin).fullName}"
|
||||||
|
:title="message.text"
|
||||||
|
:description="dayjs(message.created_at).isSame(dayjs(), 'day') ? dayjs(message.created_at).format('HH:mm') : dayjs(message.created_at).format('DD.MM.YY HH:mm')"
|
||||||
|
class="mb-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="h-8">
|
||||||
|
<UButtonGroup class="w-full">
|
||||||
|
<UInput
|
||||||
|
class="flex-auto"
|
||||||
|
placeholder="Neue Nachricht"
|
||||||
|
v-model="messageText"
|
||||||
|
@keyup.enter="createMessage"
|
||||||
|
/>
|
||||||
|
<UButton
|
||||||
|
@click="createMessage"
|
||||||
|
>
|
||||||
|
Senden
|
||||||
|
</UButton>
|
||||||
|
</UButtonGroup>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</UCard>-->
|
||||||
|
|
||||||
|
<div class="w-full h-full px-5 flex flex-col justify-between" v-if="selectedChat.id">
|
||||||
|
<div class="flex flex-col mt-5">
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="message in dataStore.getMessagesByChatId(selectedChat.id)"
|
||||||
|
>
|
||||||
|
<div class="flex justify-end mb-4" v-if="message.origin === user.id">
|
||||||
|
<div
|
||||||
|
class="mr-2 py-3 px-4 bg-primary-400 rounded-bl-3xl rounded-tl-3xl rounded-tr-xl text-white"
|
||||||
|
>
|
||||||
|
{{message.text}}
|
||||||
|
</div>
|
||||||
|
<UAvatar
|
||||||
|
:alt="dataStore.getProfileById(message.origin) ? dataStore.getProfileById(message.origin).fullName : ''"
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-start mb-4" v-else>
|
||||||
|
<UAvatar
|
||||||
|
:alt="dataStore.getProfileById(message.origin) ? dataStore.getProfileById(message.origin).fullName : ''"
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="ml-2 py-3 px-4 bg-gray-400 rounded-br-3xl rounded-tr-3xl rounded-tl-xl text-white"
|
||||||
|
>
|
||||||
|
{{message.text}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="py-5">
|
||||||
|
<UButtonGroup class="w-full">
|
||||||
|
<UInput
|
||||||
|
variant="outline"
|
||||||
|
color="primary"
|
||||||
|
placeholder="Neue Nachricht"
|
||||||
|
v-model="messageText"
|
||||||
|
@keyup.enter="createMessage"
|
||||||
|
class="flex-auto"
|
||||||
|
/>
|
||||||
|
<UButton
|
||||||
|
@click="createMessage"
|
||||||
|
>
|
||||||
|
Senden
|
||||||
|
</UButton>
|
||||||
|
</UButtonGroup>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -300,6 +300,7 @@ const setState = async (newState) => {
|
|||||||
:dark="useColorMode().value !== 'light'"
|
:dark="useColorMode().value !== 'light'"
|
||||||
:format="format"
|
:format="format"
|
||||||
:preview-format="format"
|
:preview-format="format"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
@@ -315,6 +316,7 @@ const setState = async (newState) => {
|
|||||||
:dark="useColorMode().value !== 'light'"
|
:dark="useColorMode().value !== 'light'"
|
||||||
:format="format"
|
:format="format"
|
||||||
:preview-format="format"
|
:preview-format="format"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
<!-- <UFormGroup
|
<!-- <UFormGroup
|
||||||
@@ -332,6 +334,7 @@ const setState = async (newState) => {
|
|||||||
v-model="itemInfo.user"
|
v-model="itemInfo.user"
|
||||||
option-attribute="fullName"
|
option-attribute="fullName"
|
||||||
value-attribute="id"
|
value-attribute="id"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{dataStore.profiles.find(profile => profile.id === itemInfo.user) ? dataStore.profiles.find(profile => profile.id === itemInfo.user).firstName : "Benutzer auswählen"}}
|
{{dataStore.profiles.find(profile => profile.id === itemInfo.user) ? dataStore.profiles.find(profile => profile.id === itemInfo.user).firstName : "Benutzer auswählen"}}
|
||||||
@@ -349,6 +352,7 @@ const setState = async (newState) => {
|
|||||||
searchable
|
searchable
|
||||||
searchable-placeholder="Suche..."
|
searchable-placeholder="Suche..."
|
||||||
:search-attributes="['name']"
|
:search-attributes="['name']"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{dataStore.projects.find(project => project.id === itemInfo.projectId) ? dataStore.projects.find(project => project.id === itemInfo.projectId).name : "Projekt auswählen"}}
|
{{dataStore.projects.find(project => project.id === itemInfo.projectId) ? dataStore.projects.find(project => project.id === itemInfo.projectId).name : "Projekt auswählen"}}
|
||||||
@@ -363,6 +367,7 @@ const setState = async (newState) => {
|
|||||||
:options="timeTypes"
|
:options="timeTypes"
|
||||||
option-attribute="label"
|
option-attribute="label"
|
||||||
value-attribute="label"
|
value-attribute="label"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{itemInfo.type ? itemInfo.type : "Kategorie auswählen"}}
|
{{itemInfo.type ? itemInfo.type : "Kategorie auswählen"}}
|
||||||
@@ -374,11 +379,12 @@ const setState = async (newState) => {
|
|||||||
>
|
>
|
||||||
<UTextarea
|
<UTextarea
|
||||||
v-model="itemInfo.notes"
|
v-model="itemInfo.notes"
|
||||||
|
:disabled="itemInfo.state !== 'Entwurf'"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|
||||||
|
|
||||||
<template #footer>
|
<template #footer v-if="configTimeMode === 'create' || itemInfo.state === 'Entwurf'">
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<UButton
|
<UButton
|
||||||
@click="createTime"
|
@click="createTime"
|
||||||
@@ -389,11 +395,13 @@ const setState = async (newState) => {
|
|||||||
<UButton
|
<UButton
|
||||||
@click="updateTime"
|
@click="updateTime"
|
||||||
v-else-if="configTimeMode === 'edit'"
|
v-else-if="configTimeMode === 'edit'"
|
||||||
|
v-if="itemInfo.state === 'Entwurf'"
|
||||||
>
|
>
|
||||||
Speichern
|
Speichern
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
@click="setState('Eingereicht')"
|
@click="setState('Eingereicht')"
|
||||||
|
v-if="itemInfo.state === 'Entwurf'"
|
||||||
>
|
>
|
||||||
Einreichen
|
Einreichen
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ const tabItems = [
|
|||||||
key: "phases",
|
key: "phases",
|
||||||
label: "Phasen"
|
label: "Phasen"
|
||||||
},*/{
|
},*/{
|
||||||
|
key: "information",
|
||||||
|
label: "Informationen"
|
||||||
|
},{
|
||||||
key: "tasks",
|
key: "tasks",
|
||||||
label: "Aufgaben"
|
label: "Aufgaben"
|
||||||
},/*{
|
},/*{
|
||||||
@@ -31,6 +34,9 @@ const tabItems = [
|
|||||||
},{
|
},{
|
||||||
key: "timetracking",
|
key: "timetracking",
|
||||||
label: "Zeiterfassung"
|
label: "Zeiterfassung"
|
||||||
|
},{
|
||||||
|
key: "events",
|
||||||
|
label: "Termine"
|
||||||
}/*,{
|
}/*,{
|
||||||
key: "material",
|
key: "material",
|
||||||
label: "Material"
|
label: "Material"
|
||||||
@@ -421,6 +427,10 @@ setupPage()
|
|||||||
|
|
||||||
</UTable>
|
</UTable>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="item.key === 'events'" class="space-y-3">
|
||||||
|
{{dataStore.getEventsByProjectId(currentItem.id)}}
|
||||||
|
|
||||||
|
</div>
|
||||||
<!--
|
<!--
|
||||||
<div v-else-if="item.key === 'material'" class="space-y-3">
|
<div v-else-if="item.key === 'material'" class="space-y-3">
|
||||||
<p>Hier wird aktuell noch gearbeitet</p>
|
<p>Hier wird aktuell noch gearbeitet</p>
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
const accounts = ref([])
|
const accounts = ref([])
|
||||||
const taxTypes = ref([])
|
const taxTypes = ref([])
|
||||||
const plants = ref([])
|
const plants = ref([])
|
||||||
|
const inventoryItems = ref([])
|
||||||
|
const chats = ref([])
|
||||||
|
const messages = ref([])
|
||||||
|
|
||||||
async function fetchData () {
|
async function fetchData () {
|
||||||
fetchDocuments()
|
fetchDocuments()
|
||||||
@@ -82,6 +85,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
await fetchAccounts()
|
await fetchAccounts()
|
||||||
await fetchTaxTypes()
|
await fetchTaxTypes()
|
||||||
await fetchPlants()
|
await fetchPlants()
|
||||||
|
await fetchInventoryItems()
|
||||||
|
await fetchChats()
|
||||||
|
await fetchMessages()
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +122,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
accounts.value = []
|
accounts.value = []
|
||||||
taxTypes.value = []
|
taxTypes.value = []
|
||||||
plants.value = []
|
plants.value = []
|
||||||
|
inventoryItems.value = []
|
||||||
|
chats.value = []
|
||||||
|
messages.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchOwnTenant () {
|
async function fetchOwnTenant () {
|
||||||
@@ -201,6 +210,15 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
async function fetchPlants () {
|
async function fetchPlants () {
|
||||||
plants.value = (await supabase.from("plants").select()).data
|
plants.value = (await supabase.from("plants").select()).data
|
||||||
}
|
}
|
||||||
|
async function fetchInventoryItems () {
|
||||||
|
inventoryItems.value = (await supabase.from("inventoryItems").select()).data
|
||||||
|
}
|
||||||
|
async function fetchChats() {
|
||||||
|
chats.value = (await supabase.from("chats").select()).data
|
||||||
|
}
|
||||||
|
async function fetchMessages() {
|
||||||
|
messages.value = (await supabase.from("messages").select().order('created_at', {ascending:true})).data
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchDocuments () {
|
async function fetchDocuments () {
|
||||||
documents.value = (await supabase.from("documents").select()).data
|
documents.value = (await supabase.from("documents").select()).data
|
||||||
@@ -257,6 +275,10 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
return documents.value.filter(item => item.project === projectId)
|
return documents.value.filter(item => item.project === projectId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const getEventsByProjectId = computed(() => (projectId:string) => {
|
||||||
|
return events.value.filter(item => item.project === projectId)
|
||||||
|
})
|
||||||
|
|
||||||
const getTimesByProjectId = computed(() => (projectId:string) => {
|
const getTimesByProjectId = computed(() => (projectId:string) => {
|
||||||
return times.value.filter(time => time.projectId === projectId)
|
return times.value.filter(time => time.projectId === projectId)
|
||||||
})
|
})
|
||||||
@@ -281,6 +303,10 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
return movements.value.filter(movement => movement.spaceId === spaceId)
|
return movements.value.filter(movement => movement.spaceId === spaceId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const getMessagesByChatId = computed(() => (chatId:string) => {
|
||||||
|
return messages.value.filter(i => i.destination === chatId)
|
||||||
|
})
|
||||||
|
|
||||||
const getStockByProductId = computed(() => (productId:string) => {
|
const getStockByProductId = computed(() => (productId:string) => {
|
||||||
let productMovements = movements.value.filter(movement => movement.productId === productId)
|
let productMovements = movements.value.filter(movement => movement.productId === productId)
|
||||||
|
|
||||||
@@ -322,7 +348,14 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
return {
|
return {
|
||||||
type: 'Fahrzeug',
|
type: 'Fahrzeug',
|
||||||
title: vehicle.licensePlate,
|
title: vehicle.licensePlate,
|
||||||
id: vehicle.licensePlate
|
id: `F-${vehicle.id}`
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
...inventoryItems.value.filter(i=> i.usePlanning).map(item => {
|
||||||
|
return {
|
||||||
|
type: 'Inventar',
|
||||||
|
title: item.name,
|
||||||
|
id: `I-${item.id}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
@@ -333,6 +366,72 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
...events.value.map(event => {
|
...events.value.map(event => {
|
||||||
let eventColor = ownTenant.value.calendarConfig.eventTypes.find(type => type.label === event.type).color
|
let eventColor = ownTenant.value.calendarConfig.eventTypes.find(type => type.label === event.type).color
|
||||||
|
|
||||||
|
let title = ""
|
||||||
|
if(event.title) {
|
||||||
|
title = event.title
|
||||||
|
} else if(event.project) {
|
||||||
|
projects.value.find(i => i.id === event.project) ? projects.value.find(i => i.id === event.project).name : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...event,
|
||||||
|
title: title,
|
||||||
|
borderColor: eventColor,
|
||||||
|
textColor: eventColor,
|
||||||
|
backgroundColor: "black"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
...absenceRequests.value.map(absence => {
|
||||||
|
return {
|
||||||
|
resourceId: absence.user,
|
||||||
|
resourceType: "person",
|
||||||
|
title: absence.reason,
|
||||||
|
start: dayjs(absence.start).toDate(),
|
||||||
|
end: dayjs(absence.end).add(1,'day').toDate(),
|
||||||
|
allDay: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const getEventsByResource = computed(() => {
|
||||||
|
let tempEvents = []
|
||||||
|
events.value.forEach(event => {
|
||||||
|
event.resources.forEach(resource => {
|
||||||
|
let eventColor = ownTenant.value.calendarConfig.eventTypes.find(type => type.label === event.type).color
|
||||||
|
|
||||||
|
let title = ""
|
||||||
|
if(event.title) {
|
||||||
|
title = event.title
|
||||||
|
} else if(event.project) {
|
||||||
|
projects.value.find(i => i.id === event.project) ? projects.value.find(i => i.id === event.project).name : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tempEvents.push({
|
||||||
|
...event,
|
||||||
|
resourceId: resource.type !== 'Mitarbeiter' ? `${resource.type[0]}-${resource.id}`: resource.id,
|
||||||
|
resourceType: resource.type,
|
||||||
|
title: title,
|
||||||
|
borderColor: eventColor,
|
||||||
|
textColor: eventColor,
|
||||||
|
backgroundColor: "black"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
...tempEvents,
|
||||||
|
/*...events.value.map(event => {
|
||||||
|
|
||||||
|
|
||||||
|
let eventColor = ownTenant.value.calendarConfig.eventTypes.find(type => type.label === event.type).color
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
title: !event.title ? projects.value.find(i => i.id === event.project).name : event.title,
|
title: !event.title ? projects.value.find(i => i.id === event.project).name : event.title,
|
||||||
@@ -340,7 +439,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
textColor: eventColor,
|
textColor: eventColor,
|
||||||
backgroundColor: "black"
|
backgroundColor: "black"
|
||||||
}
|
}
|
||||||
}),
|
}),*/
|
||||||
...absenceRequests.value.map(absence => {
|
...absenceRequests.value.map(absence => {
|
||||||
return {
|
return {
|
||||||
resourceId: absence.user,
|
resourceId: absence.user,
|
||||||
@@ -479,6 +578,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
accounts,
|
accounts,
|
||||||
taxTypes,
|
taxTypes,
|
||||||
plants,
|
plants,
|
||||||
|
inventoryItems,
|
||||||
|
chats,
|
||||||
|
messages,
|
||||||
//Functions
|
//Functions
|
||||||
fetchData,
|
fetchData,
|
||||||
clearStore,
|
clearStore,
|
||||||
@@ -508,6 +610,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
fetchDocuments,
|
fetchDocuments,
|
||||||
fetchAbsenceRequests,
|
fetchAbsenceRequests,
|
||||||
fetchPlants,
|
fetchPlants,
|
||||||
|
fetchInventoryItems,
|
||||||
|
fetchChats,
|
||||||
|
fetchMessages,
|
||||||
addHistoryItem,
|
addHistoryItem,
|
||||||
//Getters
|
//Getters
|
||||||
getOpenTasksCount,
|
getOpenTasksCount,
|
||||||
@@ -515,11 +620,13 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
getContactsByCustomerId,
|
getContactsByCustomerId,
|
||||||
getContactsByVendorId,
|
getContactsByVendorId,
|
||||||
getDocumentsByProjectId,
|
getDocumentsByProjectId,
|
||||||
|
getEventsByProjectId,
|
||||||
getTimesByProjectId,
|
getTimesByProjectId,
|
||||||
getTasksByProjectId,
|
getTasksByProjectId,
|
||||||
getTasksByPlantId,
|
getTasksByPlantId,
|
||||||
getProjectsByPlantId,
|
getProjectsByPlantId,
|
||||||
getMovementsBySpaceId,
|
getMovementsBySpaceId,
|
||||||
|
getMessagesByChatId,
|
||||||
getStockByProductId,
|
getStockByProductId,
|
||||||
getIncomingInvoicesByVehicleId,
|
getIncomingInvoicesByVehicleId,
|
||||||
getEventTypes,
|
getEventTypes,
|
||||||
@@ -528,6 +635,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
getMeasures,
|
getMeasures,
|
||||||
getResources,
|
getResources,
|
||||||
getEvents,
|
getEvents,
|
||||||
|
getEventsByResource,
|
||||||
getCostCentresComposed,
|
getCostCentresComposed,
|
||||||
getProductById,
|
getProductById,
|
||||||
getVendorById,
|
getVendorById,
|
||||||
|
|||||||
Reference in New Issue
Block a user