From 914b322805ab39901e9bafe2d021605f5c2be634 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Mon, 7 Sep 2026 19:32:28 +0200 Subject: [PATCH] KI-AGENT: Projekttermine in der Plantafel darstellen --- frontend/pages/organisation/plantafel.vue | 43 +++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/frontend/pages/organisation/plantafel.vue b/frontend/pages/organisation/plantafel.vue index 4864768..339d13a 100644 --- a/frontend/pages/organisation/plantafel.vue +++ b/frontend/pages/organisation/plantafel.vue @@ -36,6 +36,7 @@ const resources = ref([]) const events = ref([]) const profiles = ref([]) const inventoryitems = ref([]) +const projects = ref([]) const isDraftModeActive = ref(false) const isFinalizeDraftsModalOpen = ref(false) const finalizingDrafts = ref(false) @@ -123,7 +124,8 @@ const resourceTypeOptions = [ { label: "Alle Ressourcen", value: "all" }, { label: "Teams", value: "Team" }, { label: "Profile", value: "Profile" }, - { label: "Inventarartikel", value: "Inventarartikel" } + { label: "Inventarartikel", value: "Inventarartikel" }, + { label: "Projekte", value: "Projekte" } ] const calendarViewOptions = [ @@ -407,10 +409,17 @@ function resolveEventColor(eventType) { function resolveEventTitle(event, projectsById) { if (event.name) return event.name - if (event.project && projectsById.has(event.project)) return projectsById.get(event.project).name + const projectId = getEventProjectId(event) + if (projectId && projectsById.has(projectId)) return projectsById.get(projectId).name return event.quick ? activeQuickEntryConfig.value.name : "Planung" } +function getEventProjectId(event) { + return event?.project && typeof event.project === "object" + ? event.project.id + : event?.project +} + function resolveRenderedEventColor(event) { if (event?.quick) return event?.color || activeQuickEntryConfig.value.color return resolveEventColor(event.eventtype) @@ -470,7 +479,7 @@ function normalizeSelectedResourceIds(resourceId) { return [resourceId] } -function buildResources({ profiles, inventoryitems }) { +function buildResources({ profiles, inventoryitems, projects }) { const branchResources = [] const teamResources = [] const profileResources = [] @@ -541,18 +550,28 @@ function buildResources({ profiles, inventoryitems }) { title: item.name })) - return [...branchResources, ...teamResources, ...profileResources, ...inventoryResources] + const projectResources = projects + .filter((project) => !project.archived) + .map((project) => ({ + id: `PRJ-${project.id}`, + type: "Projekte", + title: project.name + })) + + return [...branchResources, ...teamResources, ...profileResources, ...inventoryResources, ...projectResources] } function buildEvents({ rawEvents, projectsById }) { const mappedEvents = rawEvents .filter((event) => !event.archived) .flatMap((event) => { + const projectId = getEventProjectId(event) const resourceIds = [ ...(profiles.value .filter((profile) => (event.profiles || []).includes(profile.id)) .flatMap((profile) => getProfileResourceIds(profile))), - ...(event.inventoryitems || []).map((itemId) => `I-${itemId}`) + ...(event.inventoryitems || []).map((itemId) => `I-${itemId}`), + ...(projectId ? [`PRJ-${projectId}`] : []) ] return expandRecurringEvent( @@ -807,7 +826,9 @@ async function createQuickEvent(info) { vehicles: [], notes: "", link: "", - project: null, + project: resourceIds + .filter((resourceId) => resourceId.startsWith("PRJ-")) + .map((resourceId) => Number(resourceId.replace("PRJ-", "")))[0] || null, customer: null, vendor: null, } @@ -938,7 +959,7 @@ async function loadPlanningBoard() { loading.value = true try { - const [rawEvents, projects, profileResponse, inventoryItemRows] = await Promise.all([ + const [rawEvents, projectRows, profileResponse, inventoryItemRows] = await Promise.all([ useEntities("events").select(), useEntities("projects").select(), useNuxtApp().$api("/api/tenant/profiles"), @@ -960,9 +981,10 @@ async function loadPlanningBoard() { })) ) - const projectsById = new Map((projects || []).map((project) => [project.id, project])) + const projectsById = new Map((projectRows || []).map((project) => [project.id, project])) profiles.value = profileRows || [] inventoryitems.value = inventoryItemRows || [] + projects.value = projectRows || [] if (!absenceForm.userId) { absenceForm.userId = profileOptions.value[0]?.value || "" @@ -970,7 +992,8 @@ async function loadPlanningBoard() { resources.value = buildResources({ profiles: profiles.value, - inventoryitems: inventoryitems.value + inventoryitems: inventoryitems.value, + projects: projects.value }) events.value = buildEvents({ @@ -1109,7 +1132,7 @@ onMounted(() => { v-else-if="visibleResources.length === 0" icon="i-heroicons-calendar-days" title="Keine planbaren Ressourcen vorhanden" - description="Lege Profile an oder aktiviere die Plantafel-Nutzung bei Inventarartikeln, damit hier Ressourcen erscheinen." + description="Lege Profile oder Projekte an oder aktiviere die Plantafel-Nutzung bei Inventarartikeln, damit hier Ressourcen erscheinen." />