/
Codename-Nik
/
WebApp
Обзор
Документация
Войти
/
Codename-Nik
/
WebApp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
frontend/src/components/TaskList.vue
183 строки
5 KB
Nikolay Pokhodnya
first commit
03 ноя 2025, 19:47
03 ноя 2025, 19:47
a9fbdee
Код
Авторство
О чём код?
<template> <div> <div v-if="loading" class="text-center py-8"> <v-progress-circular indeterminate size="64" width="4"></v-progress-circular> <div class="text-body-1 mt-4 text-grey">Загрузка задач...</div> </div> <div v-else-if="tasks.length === 0" class="text-center py-12"> <v-icon size="80" color="grey-lighten-2" class="mb-4">mdi-format-list-checks</v-icon> <div class="text-h6 text-grey mb-2">Задачи отсутствуют</div> <div class="text-body-2 text-grey mb-4">Создайте первую задачу чтобы начать работу</div> <v-btn color="primary" prepend-icon="mdi-plus" @click="$emit('create-task')"> Создать задачу </v-btn> </div> <v-list v-else lines="three" class="bg-transparent"> <v-list-item v-for="task in tasks" :key="task.id" :to="{ name: 'task-detail', params: { id: task.id } }" class="mb-2 rounded-lg task-item" variant="outlined" > <template v-slot:prepend> <div class="d-flex flex-column align-center mr-4"> <v-chip :color="getPriorityColor(task.priority)" size="small" class="mb-1" > {{ getPriorityText(task.priority) }} </v-chip> <v-icon v-if="getCommentCount(task) > 0" size="16" color="grey" > mdi-comment-outline </v-icon> <span v-if="getCommentCount(task) > 0" class="text-caption text-grey"> {{ getCommentCount(task) }} </span> </div> </template> <v-list-item-title class="font-weight-medium text-body-1 mb-1"> {{ task.title }} </v-list-item-title> <v-list-item-subtitle class="text-body-2 mb-2"> {{ task.description || 'Без описания' }} </v-list-item-subtitle> <template v-slot:append> <div class="d-flex flex-column align-end"> <v-chip :color="getStatusColor(task.status)" size="small" class="mb-2" > {{ getStatusText(task.status) }} </v-chip> <div class="d-flex align-center text-caption text-grey"> <v-icon size="14" class="mr-1">mdi-account</v-icon> <span>{{ getAssignedToName(task) }}</span> </div> <div v-if="task.due_date" class="d-flex align-center text-caption mt-1" :class="getDueDateClass(task.due_date)"> <v-icon size="14" class="mr-1">mdi-clock-outline</v-icon> <span>{{ formatDate(task.due_date) }}</span> </div> </div> </template> </v-list-item> </v-list> </div> </template> <script setup lang="ts"> import type { Task } from '@/types/tasks' interface Props { tasks: Task[] loading?: boolean } interface Emits { (e: 'create-task'): void } defineProps<Props>() defineEmits<Emits>() const getCommentCount = (task: Task): number => { return task.comment_count || 0 } const getAssignedToName = (task: Task): string => { return task.assigned_to_name || 'Не назначена' } const getStatusColor = (status: string) => { const colors: { [key: string]: string } = { todo: 'grey', in_progress: 'warning', review: 'info', done: 'success' } return colors[status] || 'grey' } const getStatusText = (status: string) => { const texts: { [key: string]: string } = { todo: 'To Do', in_progress: 'In Progress', review: 'Review', done: 'Done' } return texts[status] || status } const getPriorityColor = (priority: string) => { const colors: { [key: string]: string } = { low: 'success', medium: 'warning', high: 'error', urgent: 'deep-purple' } return colors[priority] || 'grey' } const getPriorityText = (priority: string) => { const texts: { [key: string]: string } = { low: 'Low', medium: 'Medium', high: 'High', urgent: 'Urgent' } return texts[priority] || priority } const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', year: 'numeric' }) } const getDueDateClass = (dueDate: string) => { const now = new Date() const due = new Date(dueDate) const diffTime = due.getTime() - now.getTime() const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) if (diffDays < 0) { return 'text-error' } else if (diffDays <= 1) { return 'text-warning' } else { return 'text-grey' } } </script> <style scoped> .task-item { transition: all 0.2s ease-in-out; border: 1px solid rgba(0, 0, 0, 0.12); } .task-item:hover { border-color: rgb(var(--v-theme-primary)); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transform: translateY(-1px); } :deep(.v-list-item__prepend) { align-items: start; } </style>