Compare commits
5 Commits
0141a243ce
...
bbb893dd6c
| Author | SHA1 | Date | |
|---|---|---|---|
| bbb893dd6c | |||
| 724f152d70 | |||
| 27be8241bf | |||
| d27e437ba6 | |||
| f5253b29f4 |
@@ -142,13 +142,6 @@ function getAssigneeLabel(task) {
|
|||||||
return assigneeOptions.value.find((option) => option.value === assigneeId)?.label || "-"
|
return assigneeOptions.value.find((option) => option.value === assigneeId)?.label || "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusBadgeColor(status) {
|
|
||||||
const normalized = normalizeStatus(status)
|
|
||||||
if (normalized === "Offen") return "gray"
|
|
||||||
if (normalized === "In Bearbeitung") return "amber"
|
|
||||||
return "green"
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadTasks() {
|
async function loadTasks() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
@@ -368,7 +361,6 @@ onMounted(async () => {
|
|||||||
/>
|
/>
|
||||||
<UButton
|
<UButton
|
||||||
icon="i-heroicons-arrow-path"
|
icon="i-heroicons-arrow-path"
|
||||||
color="gray"
|
|
||||||
variant="soft"
|
variant="soft"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@click="loadTasks"
|
@click="loadTasks"
|
||||||
@@ -391,15 +383,15 @@ onMounted(async () => {
|
|||||||
v-model="showOnlyMine"
|
v-model="showOnlyMine"
|
||||||
label="Nur meine Aufgaben"
|
label="Nur meine Aufgaben"
|
||||||
/>
|
/>
|
||||||
<span v-else class="text-sm text-gray-500">Ansicht: Nur eigene Aufgaben</span>
|
<span v-else class="text-sm">Ansicht: Nur eigene Aufgaben</span>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<div class="flex items-center gap-1 rounded-lg border border-gray-200 p-1 dark:border-gray-700">
|
<div class="view-toggle">
|
||||||
<UButton
|
<UButton
|
||||||
size="xs"
|
size="xs"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
icon="i-heroicons-view-columns"
|
icon="i-heroicons-view-columns"
|
||||||
:color="viewMode === 'kanban' ? 'primary' : 'gray'"
|
:variant="viewMode === 'kanban' ? 'solid' : 'ghost'"
|
||||||
@click="viewMode = 'kanban'"
|
@click="viewMode = 'kanban'"
|
||||||
>
|
>
|
||||||
Kanban
|
Kanban
|
||||||
@@ -408,7 +400,7 @@ onMounted(async () => {
|
|||||||
size="xs"
|
size="xs"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
icon="i-heroicons-list-bullet"
|
icon="i-heroicons-list-bullet"
|
||||||
:color="viewMode === 'list' ? 'primary' : 'gray'"
|
:variant="viewMode === 'list' ? 'solid' : 'ghost'"
|
||||||
@click="viewMode = 'list'"
|
@click="viewMode = 'list'"
|
||||||
>
|
>
|
||||||
Liste
|
Liste
|
||||||
@@ -429,7 +421,7 @@ onMounted(async () => {
|
|||||||
>
|
>
|
||||||
<header class="kanban-column-header">
|
<header class="kanban-column-header">
|
||||||
<h3>{{ status }}</h3>
|
<h3>{{ status }}</h3>
|
||||||
<UBadge color="gray" variant="subtle">{{ groupedTasks[status]?.length || 0 }}</UBadge>
|
<UBadge variant="subtle">{{ groupedTasks[status]?.length || 0 }}</UBadge>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div :class="['kanban-dropzone', droppingOn === status ? 'kanban-dropzone-active' : '']">
|
<div :class="['kanban-dropzone', droppingOn === status ? 'kanban-dropzone-active' : '']">
|
||||||
@@ -445,13 +437,13 @@ onMounted(async () => {
|
|||||||
<p v-if="task.description" class="kanban-card-description">{{ task.description }}</p>
|
<p v-if="task.description" class="kanban-card-description">{{ task.description }}</p>
|
||||||
|
|
||||||
<div class="kanban-card-meta">
|
<div class="kanban-card-meta">
|
||||||
<UBadge v-if="getEntityLabel(projectOptions, task.project?.id || task.project)" color="primary" variant="soft">
|
<UBadge v-if="getEntityLabel(projectOptions, task.project?.id || task.project)" variant="soft">
|
||||||
{{ getEntityLabel(projectOptions, task.project?.id || task.project) }}
|
{{ getEntityLabel(projectOptions, task.project?.id || task.project) }}
|
||||||
</UBadge>
|
</UBadge>
|
||||||
<UBadge v-if="getEntityLabel(customerOptions, task.customer?.id || task.customer)" color="gray" variant="soft">
|
<UBadge v-if="getEntityLabel(customerOptions, task.customer?.id || task.customer)" variant="soft">
|
||||||
{{ getEntityLabel(customerOptions, task.customer?.id || task.customer) }}
|
{{ getEntityLabel(customerOptions, task.customer?.id || task.customer) }}
|
||||||
</UBadge>
|
</UBadge>
|
||||||
<UBadge v-if="getEntityLabel(plantOptions, task.plant?.id || task.plant)" color="gray" variant="soft">
|
<UBadge v-if="getEntityLabel(plantOptions, task.plant?.id || task.plant)" variant="soft">
|
||||||
{{ getEntityLabel(plantOptions, task.plant?.id || task.plant) }}
|
{{ getEntityLabel(plantOptions, task.plant?.id || task.plant) }}
|
||||||
</UBadge>
|
</UBadge>
|
||||||
</div>
|
</div>
|
||||||
@@ -464,17 +456,15 @@ onMounted(async () => {
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<UTable
|
<UTable
|
||||||
v-else
|
v-else-if="filteredTasks.length"
|
||||||
:rows="filteredTasks"
|
:rows="filteredTasks"
|
||||||
:columns="listColumns"
|
:columns="listColumns"
|
||||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Aufgaben anzuzeigen' }"
|
|
||||||
@select="(task) => openTaskViaRoute(task)"
|
@select="(task) => openTaskViaRoute(task)"
|
||||||
>
|
>
|
||||||
<template #actions-data="{ row }">
|
<template #actions-data="{ row }">
|
||||||
<UButton
|
<UButton
|
||||||
v-if="normalizeStatus(row.categorie) !== 'Abgeschlossen' && canCreate"
|
v-if="normalizeStatus(row.categorie) !== 'Abgeschlossen' && canCreate"
|
||||||
size="xs"
|
size="xs"
|
||||||
color="green"
|
|
||||||
variant="soft"
|
variant="soft"
|
||||||
icon="i-heroicons-check"
|
icon="i-heroicons-check"
|
||||||
:loading="quickCompleteLoadingId === row.id"
|
:loading="quickCompleteLoadingId === row.id"
|
||||||
@@ -484,9 +474,7 @@ onMounted(async () => {
|
|||||||
</UButton>
|
</UButton>
|
||||||
</template>
|
</template>
|
||||||
<template #categorie-data="{ row }">
|
<template #categorie-data="{ row }">
|
||||||
<UBadge :color="getStatusBadgeColor(row.categorie)" variant="soft">
|
<UBadge variant="soft">{{ normalizeStatus(row.categorie) }}</UBadge>
|
||||||
{{ normalizeStatus(row.categorie) }}
|
|
||||||
</UBadge>
|
|
||||||
</template>
|
</template>
|
||||||
<template #assignee-data="{ row }">
|
<template #assignee-data="{ row }">
|
||||||
{{ getAssigneeLabel(row) }}
|
{{ getAssigneeLabel(row) }}
|
||||||
@@ -501,6 +489,12 @@ onMounted(async () => {
|
|||||||
{{ getEntityLabel(plantOptions, row.plant?.id || row.plant) || "-" }}
|
{{ getEntityLabel(plantOptions, row.plant?.id || row.plant) || "-" }}
|
||||||
</template>
|
</template>
|
||||||
</UTable>
|
</UTable>
|
||||||
|
<UAlert
|
||||||
|
v-else
|
||||||
|
icon="i-heroicons-circle-stack-20-solid"
|
||||||
|
title="Keine Aufgaben anzuzeigen"
|
||||||
|
variant="subtle"
|
||||||
|
/>
|
||||||
</UDashboardPanelContent>
|
</UDashboardPanelContent>
|
||||||
|
|
||||||
<UModal v-model="isModalOpen" :prevent-close="saving || deleting">
|
<UModal v-model="isModalOpen" :prevent-close="saving || deleting">
|
||||||
@@ -508,7 +502,7 @@ onMounted(async () => {
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h3 class="font-semibold">{{ modalTitle }}</h3>
|
<h3 class="font-semibold">{{ modalTitle }}</h3>
|
||||||
<UBadge color="gray" variant="subtle">{{ taskForm.id ? `#${taskForm.id}` : "Neu" }}</UBadge>
|
<UBadge variant="subtle">{{ taskForm.id ? `#${taskForm.id}` : "Neu" }}</UBadge>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -595,7 +589,6 @@ onMounted(async () => {
|
|||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<UButton
|
<UButton
|
||||||
v-if="taskForm.id && canCreate"
|
v-if="taskForm.id && canCreate"
|
||||||
color="red"
|
|
||||||
variant="soft"
|
variant="soft"
|
||||||
:loading="deleting"
|
:loading="deleting"
|
||||||
@click="archiveTask"
|
@click="archiveTask"
|
||||||
@@ -605,10 +598,9 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<UButton color="gray" variant="ghost" @click="closeModal">Schließen</UButton>
|
<UButton variant="ghost" @click="closeModal">Schließen</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
v-if="modalMode === 'show' && canCreate"
|
v-if="modalMode === 'show' && canCreate"
|
||||||
color="gray"
|
|
||||||
variant="soft"
|
variant="soft"
|
||||||
@click="modalMode = 'edit'"
|
@click="modalMode = 'edit'"
|
||||||
>
|
>
|
||||||
@@ -632,7 +624,8 @@ onMounted(async () => {
|
|||||||
.kanban-grid {
|
.kanban-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 1rem;
|
gap: 1.25rem;
|
||||||
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
@@ -642,38 +635,56 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column {
|
.kanban-column {
|
||||||
border: 1px solid rgb(229 231 235);
|
border: 1px solid var(--ui-border);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: rgb(249 250 251);
|
background: var(--ui-bg);
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 1px 2px color-mix(in oklab, var(--ui-text) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.kanban-column:not(:first-child)::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: -0.7rem;
|
||||||
|
top: 0.75rem;
|
||||||
|
bottom: 0.75rem;
|
||||||
|
width: 1px;
|
||||||
|
background: var(--ui-border);
|
||||||
|
opacity: 0.9;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column-header {
|
.kanban-column-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0.75rem 0.9rem;
|
padding: 0.85rem 1rem;
|
||||||
border-bottom: 1px solid rgb(229 231 235);
|
border-bottom: 1px solid var(--ui-border);
|
||||||
|
background: var(--ui-bg-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-dropzone {
|
.kanban-dropzone {
|
||||||
padding: 0.75rem;
|
padding: 0.9rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.75rem;
|
gap: 0.85rem;
|
||||||
transition: background-color 0.2s ease;
|
transition: background-color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-dropzone-active {
|
.kanban-dropzone-active {
|
||||||
background: rgb(239 246 255);
|
background: var(--ui-bg-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-card {
|
.kanban-card {
|
||||||
border: 1px solid rgb(229 231 235);
|
border: 1px solid var(--ui-border);
|
||||||
background: white;
|
background: var(--ui-bg-elevated);
|
||||||
border-radius: 0.6rem;
|
border-radius: 0.6rem;
|
||||||
padding: 0.7rem;
|
padding: 0.7rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -686,7 +697,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
.kanban-card-description {
|
.kanban-card-description {
|
||||||
margin-top: 0.4rem;
|
margin-top: 0.4rem;
|
||||||
color: rgb(107 114 128);
|
color: var(--ui-text-dimmed);
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 1.15rem;
|
line-height: 1.15rem;
|
||||||
}
|
}
|
||||||
@@ -699,8 +710,8 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-empty {
|
.kanban-empty {
|
||||||
border: 1px dashed rgb(209 213 219);
|
border: 1px dashed var(--ui-border);
|
||||||
color: rgb(156 163 175);
|
color: var(--ui-text-dimmed);
|
||||||
border-radius: 0.6rem;
|
border-radius: 0.6rem;
|
||||||
padding: 0.7rem;
|
padding: 0.7rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
@@ -711,36 +722,15 @@ onMounted(async () => {
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 0.35rem;
|
margin-bottom: 0.35rem;
|
||||||
|
color: var(--ui-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .kanban-column {
|
.view-toggle {
|
||||||
border-color: rgb(55 65 81);
|
display: flex;
|
||||||
background: rgb(17 24 39);
|
align-items: center;
|
||||||
}
|
gap: 0.25rem;
|
||||||
|
border: 1px solid var(--ui-border);
|
||||||
:global(.dark) .kanban-column-header {
|
border-radius: 0.5rem;
|
||||||
border-bottom-color: rgb(55 65 81);
|
padding: 0.25rem;
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .kanban-dropzone-active {
|
|
||||||
background: rgb(30 41 59);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .kanban-card {
|
|
||||||
border-color: rgb(75 85 99);
|
|
||||||
background: rgb(31 41 55);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .kanban-card-description {
|
|
||||||
color: rgb(209 213 219);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .kanban-empty {
|
|
||||||
border-color: rgb(75 85 99);
|
|
||||||
color: rgb(156 163 175);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .form-label {
|
|
||||||
color: rgb(229 231 235);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user