forked from swablab/website
133 lines
4.1 KiB
Text
133 lines
4.1 KiB
Text
---
|
|
import Base from "../layouts/Base.astro"
|
|
|
|
const statuses = [
|
|
{ id: "not_started", title: "Nicht gestartet" },
|
|
{ id: "in_progress", title: "In Arbeit" },
|
|
{ id: "hold", title: "Wartend" },
|
|
]
|
|
---
|
|
|
|
<Base title="Todo">
|
|
<div x-data="kanban" x-cloak>
|
|
<div class="navbar glass">
|
|
<div class="navbar-start">
|
|
<a class="btn btn-ghost text-xl">todo</a>
|
|
</div>
|
|
<div class="navbar-end">
|
|
<a class="btn btn-primary btn-square" href="/todo-edit">
|
|
<span class="icon-[ph--plus] w-6 h-6"></span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div x-show="error" class="p-4 flex flex-col space-y-4">
|
|
<div
|
|
x-show="!error.includes('permission to access collection')"
|
|
class="alert alert-error"
|
|
>
|
|
<span x-text="error"></span>
|
|
</div>
|
|
<a
|
|
x-show="error.includes('permission to access collection')"
|
|
class="btn btn-primary"
|
|
href="https://directus.swablab.de/auth/login/zitadel?redirect=https://swablab.de/todo"
|
|
>
|
|
Klicke hier, um dich anzumelden
|
|
</a>
|
|
</div>
|
|
|
|
<div class="p-4 flex flex-col space-y-2" x-show="!error">
|
|
<div class="join">
|
|
<input
|
|
class="input input-primary w-full join-item"
|
|
placeholder="Suchen nach Titel oder Mitglied..."
|
|
x-model="search"
|
|
/>
|
|
<button
|
|
class="btn btn-primary join-item"
|
|
x-on:click="search = `id:${me}`"
|
|
>
|
|
Nur meine Aufgaben
|
|
</button>
|
|
</div>
|
|
<ul class="menu grid lg:grid-cols-3 w-full bg-base-200 rounded-box">
|
|
{
|
|
statuses.map((status) => (
|
|
<li x-data={"tasklist('" + status.id + "')"} class="flex-auto">
|
|
<a class="pointer-events-none">{status.title}</a>
|
|
<ul>
|
|
<template x-for="task in sortedTasks()">
|
|
<li>
|
|
<a x-bind:href="`/todo-edit?${task.id}`">
|
|
<span
|
|
x-show="task.responsibles.find(x => x.directus_users_id.id == me)"
|
|
class="badge badge-xs badge-info"
|
|
/>
|
|
<span
|
|
x-bind:class="{'text-secondary': task.priority == 'high','text-neutral-500': task.priority == 'low'}"
|
|
x-text="task.title"
|
|
/>
|
|
<span
|
|
class="badge badge-xs"
|
|
x-bind:class="new Date(task.date_due ?? 0) < new Date() ? `badge-error`: `badge-ghost`"
|
|
x-show="task.date_due != null"
|
|
x-text="formatDate(task.date_due, `short`)"
|
|
/>
|
|
</a>
|
|
</li>
|
|
</template>
|
|
</ul>
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</Base>
|
|
|
|
<script>
|
|
import Alpine from "alpinejs"
|
|
import { directus, formatDate, Task } from "../helper"
|
|
|
|
Alpine.data("kanban", () => ({
|
|
me: "",
|
|
search: "",
|
|
error: "",
|
|
init() {
|
|
directus<{ id: string }>("users/me?fields=id")
|
|
.then((res) => (this.me = res.id))
|
|
.catch((err) => (this.error = err))
|
|
},
|
|
}))
|
|
Alpine.data("tasklist", (status: string) => ({
|
|
tasks: [],
|
|
formatDate: formatDate,
|
|
init() {
|
|
directus<Task[]>(
|
|
`items/tasks_general?filter[status][_eq]=${status}&fields=*,responsibles.directus_users_id.id,responsibles.directus_users_id.first_name`,
|
|
)
|
|
.then((res) => (this.tasks = res))
|
|
.catch((err) => (this.error = err))
|
|
},
|
|
sortedTasks() {
|
|
return (this.tasks as Task[])
|
|
.filter(
|
|
(a) =>
|
|
a.title.toLowerCase().includes(this.search.toLowerCase()) ||
|
|
a.responsibles
|
|
.map(
|
|
(x) =>
|
|
`${x.directus_users_id.first_name}|id:${x.directus_users_id.id}`,
|
|
)
|
|
.join("|")
|
|
.toLowerCase()
|
|
.includes(this.search.toLowerCase()),
|
|
)
|
|
.sort((a, b) => a.title.localeCompare(b.title))
|
|
.sort((a, b) => (a.date_due ?? "z").localeCompare(b.date_due ?? "z"))
|
|
},
|
|
}))
|
|
|
|
Alpine.start()
|
|
</script>
|