1
0
Files
TaskBoard/front_vue/src/stores/projects.js
Falknat c46fd3952e PWA модуль
Теперь проект может быть установлен как приложение на телефон
2026-01-16 16:12:34 +07:00

260 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { projectsApi, usersApi, cardsApi } from '../api'
import { getCachedUser } from '../router'
export const useProjectsStore = defineStore('projects', () => {
// ==================== СОСТОЯНИЕ ====================
const projects = ref([])
const departments = ref([])
const labels = ref([])
const columns = ref([])
const users = ref([])
const cards = ref([]) // Активные карточки текущего проекта
const archivedCards = ref([]) // Архивные карточки текущего проекта
const cardsLoading = ref(false) // Загрузка карточек
const loading = ref(false)
const initialized = ref(false)
const currentUser = ref(null) // Текущий авторизованный пользователь
// Текущий проект (из localStorage)
const savedProjectId = localStorage.getItem('currentProjectId')
const savedProjectName = localStorage.getItem('currentProjectName')
const currentProjectId = ref(savedProjectId ? parseInt(savedProjectId) : null)
// ==================== ГЕТТЕРЫ ====================
// Текущий проект (объект)
const currentProject = computed(() =>
projects.value.find(p => p.id === currentProjectId.value) ||
(savedProjectName && currentProjectId.value ? { id: currentProjectId.value, name: savedProjectName } : null)
)
// ID колонки "Готово" текущего проекта
const doneColumnId = computed(() => {
const project = projects.value.find(p => p.id === currentProjectId.value)
return project ? Number(project.id_ready) : null
})
// ID текущего пользователя
const currentUserId = computed(() => currentUser.value?.id || null)
// Имя текущего пользователя
const currentUserName = computed(() => currentUser.value?.name || '')
// Аватар текущего пользователя
const currentUserAvatar = computed(() => currentUser.value?.avatar_url || '')
// Является ли текущий пользователь админом проекта
// Сервер возвращает id_admin: true только если текущий пользователь — админ
const isProjectAdmin = computed(() => {
const project = projects.value.find(p => p.id === currentProjectId.value)
return project?.id_admin === true
})
// ==================== ДЕЙСТВИЯ ====================
// Инициализация (загрузка проектов + данных активного)
const init = async () => {
// Если уже инициализировано И есть данные — пропускаем
if (initialized.value && projects.value.length > 0) return
loading.value = true
try {
// Загружаем проекты и данные активного одним запросом
const result = await projectsApi.getAll(currentProjectId.value || undefined)
if (result.success) {
if (result.data.projects) {
projects.value = result.data.projects
// Применяем данные активного проекта
if (result.data.active) {
columns.value = result.data.active.columns
departments.value = result.data.active.departments
labels.value = result.data.active.labels
}
} else {
projects.value = result.data
}
// Если нет выбранного проекта — выбираем первый
if (!currentProjectId.value || !projects.value.find(p => p.id === currentProjectId.value)) {
if (projects.value.length > 0) {
await selectProject(projects.value[0].id, true) // Загружаем данные проекта
}
} else if (!columns.value.length) {
// Есть проект но нет данных — загружаем
await fetchProjectData()
} else {
// Обновляем название в localStorage
const project = projects.value.find(p => p.id === currentProjectId.value)
if (project) localStorage.setItem('currentProjectName', project.name)
}
}
// Загружаем пользователей
const usersData = await usersApi.getAll()
if (usersData.success) users.value = usersData.data
// Получаем текущего пользователя из кэша роутера (без повторного запроса)
if (!currentUser.value) {
const cachedUser = getCachedUser()
if (cachedUser) {
// Находим полные данные пользователя (с id) из списка users
const fullUser = users.value.find(u => u.username === cachedUser.username)
currentUser.value = fullUser || cachedUser
}
}
initialized.value = true
} catch (error) {
console.error('Ошибка инициализации:', error)
} finally {
loading.value = false
}
}
// Выбор проекта
const selectProject = async (projectId, fetchData = true) => {
currentProjectId.value = projectId
localStorage.setItem('currentProjectId', projectId.toString())
// Сохраняем название
const project = projects.value.find(p => p.id === projectId)
if (project) localStorage.setItem('currentProjectName', project.name)
// Загружаем данные проекта
if (fetchData) {
await fetchProjectData()
}
}
// Загрузка данных текущего проекта
const fetchProjectData = async () => {
if (!currentProjectId.value) return
try {
const projectData = await projectsApi.getData(currentProjectId.value)
if (projectData.success) {
columns.value = projectData.data.columns
departments.value = projectData.data.departments
labels.value = projectData.data.labels
// Обновляем id_admin в списке проектов (сервер возвращает true если текущий пользователь админ)
const project = projects.value.find(p => p.id === currentProjectId.value)
if (project && projectData.data.project?.id_admin === true) {
project.id_admin = true
}
}
} catch (error) {
console.error('Ошибка загрузки данных проекта:', error)
}
}
// ==================== КАРТОЧКИ ====================
// Загрузка активных карточек (silent = тихое обновление без loading)
const fetchCards = async (silent = false) => {
if (!currentProjectId.value) {
cardsLoading.value = false
return
}
if (!silent) cardsLoading.value = true
try {
const result = await cardsApi.getAll(currentProjectId.value)
if (result.success) cards.value = result.data
} finally {
if (!silent) cardsLoading.value = false
}
}
// Загрузка архивных карточек
const fetchArchivedCards = async () => {
if (!currentProjectId.value) return
cardsLoading.value = true
try {
const result = await cardsApi.getAll(currentProjectId.value, 1) // archive = 1
if (result.success) {
archivedCards.value = result.data.map(card => ({
id: card.id,
title: card.title,
description: card.descript,
details: card.descript_full,
departmentId: card.id_department,
labelId: card.id_label,
accountId: card.id_account,
assignee: card.avatar_img,
dueDate: card.date,
dateCreate: card.date_create,
dateClosed: card.date_closed,
columnId: card.column_id,
order: card.order ?? 0,
comments_count: card.comments_count || 0,
files: card.files || (card.file_img || []).map(f => ({
name: f.name,
url: f.url,
size: f.size,
preview: f.url
}))
}))
}
} finally {
cardsLoading.value = false
}
}
// Очистка карточек при смене проекта
const clearCards = () => {
cards.value = []
archivedCards.value = []
}
// Сброс при выходе
const reset = () => {
projects.value = []
departments.value = []
labels.value = []
columns.value = []
users.value = []
cards.value = []
archivedCards.value = []
currentProjectId.value = null
currentUser.value = null
initialized.value = false
localStorage.removeItem('currentProjectId')
localStorage.removeItem('currentProjectName')
}
return {
// Состояние
projects,
departments,
labels,
columns,
users,
cards,
archivedCards,
cardsLoading,
loading,
initialized,
currentProjectId,
currentUser,
// Геттеры
currentProject,
doneColumnId,
currentUserId,
currentUserName,
currentUserAvatar,
isProjectAdmin,
// Действия
init,
selectProject,
fetchProjectData,
fetchCards,
fetchArchivedCards,
clearCards,
reset
}
})