1
0
Fork 0
forked from swablab/website
website/src/pages/todo.astro
2025-02-22 16:59:06 +00:00

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>