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 }"
@@ -52,10 +58,11 @@
<Board
ref="boardRef"
:active-department="activeDepartment"
:departments="departments"
:labels="labels"
:columns="columns"
:departments="store.departments"
:labels="store.labels"
:columns="store.columns"
:cards="cards"
:done-column-id="store.doneColumnId"
@stats-updated="stats = $event"
@open-task="openTaskPanel"
@create-task="openNewTaskPanel"
@@ -68,9 +75,10 @@
:show="panelOpen"
:card="editingCard"
:column-id="editingColumnId"
:departments="departments"
:labels="labels"
:users="users"
:done-column-id="store.doneColumnId"
:departments="store.departments"
:labels="store.labels"
:users="store.users"
@close="closePanel"
@save="handleSaveTask"
@delete="handleDeleteTask"
@@ -85,14 +93,34 @@ import Sidebar from '../components/Sidebar.vue'
import Header from '../components/Header.vue'
import Board from '../components/Board.vue'
import TaskPanel from '../components/TaskPanel.vue'
import { departmentsApi, labelsApi, columnsApi, cardsApi, usersApi } from '../api'
import ProjectSelector from '../components/ProjectSelector.vue'
import { useProjectsStore } from '../stores/projects'
import { cardsApi } from '../api'
// Активный фильтр по отделу (null = все)
// Восстанавливаем из localStorage
// ==================== STORE ====================
const store = useProjectsStore()
// ==================== КАРТОЧКИ ====================
const cards = ref([])
// Загрузка карточек текущего проекта
const fetchCards = async () => {
if (!store.currentProjectId) return
const result = await cardsApi.getAll(store.currentProjectId)
if (result.success) cards.value = result.data
}
// При смене проекта — перезагружаем карточки
const onProjectChange = async () => {
activeDepartment.value = null
await fetchCards()
}
// ==================== ФИЛЬТР ПО ОТДЕЛАМ ====================
const savedDepartment = localStorage.getItem('activeDepartment')
const activeDepartment = ref(savedDepartment ? parseInt(savedDepartment) : null)
// Сохраняем в localStorage при изменении
watch(activeDepartment, (newVal) => {
if (newVal === null) {
localStorage.removeItem('activeDepartment')
@@ -100,91 +128,60 @@ watch(activeDepartment, (newVal) => {
localStorage.setItem('activeDepartment', newVal.toString())
}
})
// Статистика для шапки
// ==================== СТАТИСТИКА ====================
const stats = ref({ total: 0, inProgress: 0, done: 0 })
// Данные из API
const departments = ref([])
const labels = ref([])
const columns = ref([])
const cards = ref([])
const users = ref([])
// Загрузка всех данных из API параллельно
const fetchData = async () => {
try {
const [departmentsData, labelsData, columnsData, cardsData, usersData] = await Promise.all([
departmentsApi.getAll(),
labelsApi.getAll(),
columnsApi.getAll(),
cardsApi.getAll(),
usersApi.getAll()
])
if (departmentsData.success) departments.value = departmentsData.data
if (labelsData.success) labels.value = labelsData.data
if (columnsData.success) columns.value = columnsData.data
if (cardsData.success) cards.value = cardsData.data
if (usersData.success) users.value = usersData.data
} catch (error) {
console.error('Ошибка загрузки данных:', error)
}
}
// Выход из системы
// Ссылка на компонент Board для вызова его методов
// ==================== ПАНЕЛЬ РЕДАКТИРОВАНИЯ ====================
const boardRef = ref(null)
// Состояние панели редактирования
const panelOpen = ref(false)
// Редактируемая карточка (null = создание новой)
const editingCard = ref(null)
// ID колонки для новой/редактируемой карточки
const editingColumnId = ref(null)
// Открыть панель для редактирования существующей задачи
const openTaskPanel = ({ card, columnId }) => {
editingCard.value = card
editingColumnId.value = columnId
panelOpen.value = true
}
// Открыть панель для создания новой задачи
const openNewTaskPanel = (columnId) => {
editingCard.value = null
editingColumnId.value = columnId
panelOpen.value = true
}
// Закрыть панель и сбросить состояние
const closePanel = () => {
panelOpen.value = false
editingCard.value = null
editingColumnId.value = null
}
// Сохранить задачу через Board компонент
const handleSaveTask = async (taskData) => {
if (!taskData.id && store.currentProjectId) {
taskData.id_project = store.currentProjectId
}
await boardRef.value?.saveTask(taskData, editingColumnId.value)
closePanel()
}
// Удалить задачу через Board компонент
const handleDeleteTask = async (cardId) => {
await boardRef.value?.deleteTask(cardId, editingColumnId.value)
closePanel()
}
// Архивировать задачу через Board компонент
const handleArchiveTask = async (cardId) => {
await boardRef.value?.archiveTask(cardId)
closePanel()
}
// Инициализация при монтировании
onMounted(() => {
fetchData()
if (window.lucide) {
window.lucide.createIcons()
}
// ==================== ИНИЦИАЛИЗАЦИЯ ====================
onMounted(async () => {
// Инициализируем store (загрузит проекты, departments, labels, users)
await store.init()
// Загружаем карточки
await fetchCards()
if (window.lucide) window.lucide.createIcons()
})
</script>
@@ -195,7 +192,6 @@ onMounted(() => {
min-height: 100vh;
}
/* Основная область контента */
.main-wrapper {
flex: 1;
@@ -213,6 +209,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;