1
0

Добавление проектов

Добавили возможность создавания разных проектов.
This commit is contained in:
2026-01-14 10:46:38 +07:00
parent 04e88cb7fa
commit 719aecd09e
22 changed files with 996 additions and 233 deletions

View File

@@ -9,6 +9,12 @@
<Header title="Архив задач">
<template #filters>
<div class="filters">
<!-- Выбор проекта -->
<ProjectSelector @change="onProjectChange" />
<div class="filter-divider"></div>
<!-- Фильтр по отделам -->
<button
class="filter-tag"
:class="{ active: activeDepartment === null }"
@@ -17,7 +23,7 @@
Все
</button>
<button
v-for="dept in departments"
v-for="dept in store.departments"
:key="dept.id"
class="filter-tag"
:class="{ active: activeDepartment === dept.id }"
@@ -44,8 +50,8 @@
v-for="card in filteredCards"
:key="card.id"
:card="card"
:departments="departments"
:labels="labels"
:departments="store.departments"
:labels="store.labels"
@click="openTaskPanel(card)"
@restore="handleRestore"
@delete="confirmDelete"
@@ -73,9 +79,9 @@
:card="editingCard"
:column-id="null"
:is-archived="true"
:departments="departments"
:labels="labels"
:users="users"
:departments="store.departments"
:labels="store.labels"
:users="store.users"
@close="closePanel"
@save="handleSaveTask"
@delete="handleDeleteTask"
@@ -101,26 +107,15 @@ import Header from '../components/Header.vue'
import ArchiveCard from '../components/ArchiveCard.vue'
import TaskPanel from '../components/TaskPanel.vue'
import ConfirmDialog from '../components/ConfirmDialog.vue'
import { departmentsApi, labelsApi, cardsApi, usersApi } from '../api'
import ProjectSelector from '../components/ProjectSelector.vue'
import { useProjectsStore } from '../stores/projects'
import { cardsApi } from '../api'
// Активный фильтр по отделу (синхронизация с основной доской)
const savedDepartment = localStorage.getItem('activeDepartment')
const activeDepartment = ref(savedDepartment ? parseInt(savedDepartment) : null)
// ==================== STORE ====================
const store = useProjectsStore()
// Сохраняем в localStorage при изменении
watch(activeDepartment, (newVal) => {
if (newVal === null) {
localStorage.removeItem('activeDepartment')
} else {
localStorage.setItem('activeDepartment', newVal.toString())
}
})
// Данные
const departments = ref([])
const labels = ref([])
// ==================== КАРТОЧКИ ====================
const cards = ref([])
const users = ref([])
const loading = ref(true)
// Отфильтрованные карточки (сортируем по дате завершения, новые сверху)
@@ -130,30 +125,24 @@ const filteredCards = computed(() => {
result = result.filter(card => card.departmentId === activeDepartment.value)
}
return result.sort((a, b) => {
// Сортировка по дате завершения (новые сверху)
const dateA = a.dateClosed ? new Date(a.dateClosed).getTime() : 0
const dateB = b.dateClosed ? new Date(b.dateClosed).getTime() : 0
return dateB - dateA
})
})
// Загрузка данных
const fetchData = async () => {
// Загрузка архивных карточек
const fetchCards = async () => {
if (!store.currentProjectId) {
loading.value = false
return
}
loading.value = true
try {
const [departmentsData, labelsData, cardsData, usersData] = await Promise.all([
departmentsApi.getAll(),
labelsApi.getAll(),
cardsApi.getAll(1), // archive = 1
usersApi.getAll()
])
if (departmentsData.success) departments.value = departmentsData.data
if (labelsData.success) labels.value = labelsData.data
if (usersData.success) users.value = usersData.data
if (cardsData.success) {
cards.value = cardsData.data.map(card => ({
const result = await cardsApi.getAll(store.currentProjectId, 1) // archive = 1
if (result.success) {
cards.value = result.data.map(card => ({
id: card.id,
title: card.title,
description: card.descript,
@@ -175,14 +164,30 @@ const fetchData = async () => {
}))
}))
}
} catch (error) {
console.error('Ошибка загрузки данных:', error)
} finally {
loading.value = false
}
}
// Панель редактирования
// При смене проекта
const onProjectChange = async () => {
activeDepartment.value = null
await fetchCards()
}
// ==================== ФИЛЬТР ПО ОТДЕЛАМ ====================
const savedDepartment = localStorage.getItem('activeDepartment')
const activeDepartment = ref(savedDepartment ? parseInt(savedDepartment) : null)
watch(activeDepartment, (newVal) => {
if (newVal === null) {
localStorage.removeItem('activeDepartment')
} else {
localStorage.setItem('activeDepartment', newVal.toString())
}
})
// ==================== ПАНЕЛЬ РЕДАКТИРОВАНИЯ ====================
const panelOpen = ref(false)
const editingCard = ref(null)
@@ -196,10 +201,8 @@ const closePanel = () => {
editingCard.value = null
}
// Сохранение задачи
const handleSaveTask = async (taskData) => {
if (taskData.id) {
// Обновляем на сервере
await cardsApi.update({
id: taskData.id,
id_department: taskData.departmentId,
@@ -211,7 +214,6 @@ const handleSaveTask = async (taskData) => {
descript_full: taskData.details
})
// Обновляем локально
const card = cards.value.find(c => c.id === taskData.id)
if (card) {
card.title = taskData.title
@@ -228,7 +230,6 @@ const handleSaveTask = async (taskData) => {
closePanel()
}
// Удаление через панель
const handleDeleteTask = async (cardId) => {
const result = await cardsApi.delete(cardId)
if (result.success) {
@@ -237,7 +238,7 @@ const handleDeleteTask = async (cardId) => {
closePanel()
}
// Диалог подтверждения удаления
// ==================== УДАЛЕНИЕ С ПОДТВЕРЖДЕНИЕМ ====================
const confirmDialogOpen = ref(false)
const cardToDelete = ref(null)
@@ -257,7 +258,7 @@ const handleConfirmDelete = async () => {
cardToDelete.value = null
}
// Восстановление из архива
// ==================== ВОССТАНОВЛЕНИЕ ====================
const handleRestore = async (cardId) => {
const result = await cardsApi.setArchive(cardId, 0)
if (result.success) {
@@ -265,18 +266,17 @@ const handleRestore = async (cardId) => {
}
}
// Восстановление через панель редактирования
const handleRestoreFromPanel = async (cardId) => {
await handleRestore(cardId)
closePanel()
}
// Инициализация
onMounted(() => {
fetchData()
if (window.lucide) {
window.lucide.createIcons()
}
// ==================== ИНИЦИАЛИЗАЦИЯ ====================
onMounted(async () => {
await store.init()
await fetchCards()
if (window.lucide) window.lucide.createIcons()
})
</script>
@@ -304,6 +304,14 @@ onMounted(() => {
flex-wrap: wrap;
}
/* Разделитель между проектом и отделами */
.filter-divider {
width: 1px;
height: 24px;
background: rgba(255, 255, 255, 0.1);
margin: 0 8px;
}
/* Кнопка фильтра */
.filter-tag {
padding: 6px 12px;