Full Vue 3 + Vite + TypeScript + Tailwind SPA replacing the vanilla JS static frontend. Includes router, Pinia stores (auth/tasks/calendar/devops), axios API client with all endpoints, UI components (Button/Card/Dialog/Badge/Input/etc), calendar grid with lane-packing algorithm and DnD support, SSE live feed, and all 11 views. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
1.8 KiB
Vue
75 lines
1.8 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import type { Task } from '@/types'
|
|
import TaskCard from './TaskCard.vue'
|
|
|
|
const props = defineProps<{
|
|
tasks: Task[]
|
|
loading?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
edit: [task: Task]
|
|
complete: [task: Task]
|
|
delete: [task: Task]
|
|
}>()
|
|
|
|
const grouped = computed(() => {
|
|
const groups: Record<string, Task[]> = {
|
|
doing: [],
|
|
todo: [],
|
|
done: [],
|
|
cancelled: [],
|
|
}
|
|
for (const task of props.tasks) {
|
|
groups[task.status]?.push(task)
|
|
}
|
|
return groups
|
|
})
|
|
|
|
const statusLabels: Record<string, string> = {
|
|
doing: 'In Progress',
|
|
todo: 'To Do',
|
|
done: 'Done',
|
|
cancelled: 'Cancelled',
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="space-y-6">
|
|
<div v-if="loading" class="text-sm text-muted-foreground py-4 text-center">Loading tasks...</div>
|
|
<template v-else>
|
|
<div
|
|
v-for="(group, status) in grouped"
|
|
:key="status"
|
|
v-show="group.length > 0"
|
|
>
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<h3 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
{{ statusLabels[status] }}
|
|
</h3>
|
|
<span class="text-xs text-muted-foreground bg-muted px-1.5 py-0.5 rounded-full">
|
|
{{ group.length }}
|
|
</span>
|
|
</div>
|
|
<div class="space-y-2">
|
|
<TaskCard
|
|
v-for="task in group"
|
|
:key="task.id"
|
|
:task="task"
|
|
draggable
|
|
@edit="emit('edit', task)"
|
|
@complete="emit('complete', task)"
|
|
@delete="emit('delete', task)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="!props.tasks.length"
|
|
class="text-sm text-muted-foreground text-center py-8"
|
|
>
|
|
No tasks found
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|