feat: task system
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m55s

This commit is contained in:
domrichardson
2026-03-27 16:33:11 +00:00
parent d793b5ccf2
commit 1b336299ee
15 changed files with 3876 additions and 17 deletions

View File

@@ -13,9 +13,12 @@ export const useSpaceStore = defineStore("space", () => {
const notesLoading = ref(false);
const categories = ref([]);
const categoryTree = ref([]);
const tasks = ref([]);
const taskStatuses = ref([]);
const noteLinkedTasks = ref([]);
const refreshSpaceData = async (spaceId) => {
await Promise.all([fetchCategories(spaceId), fetchNotes(spaceId)]);
await Promise.all([fetchCategories(spaceId), fetchNotes(spaceId), fetchTaskStatuses(spaceId), fetchTasks(spaceId)]);
};
const fetchSpaces = async () => {
@@ -208,6 +211,130 @@ export const useSpaceStore = defineStore("space", () => {
searchResults.value = [];
};
const fetchTaskStatuses = async (spaceId) => {
if (!spaceId) {
taskStatuses.value = [];
return [];
}
try {
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/task-statuses`);
taskStatuses.value = response.data || [];
return taskStatuses.value;
} catch (error) {
console.error("Error fetching task statuses:", error);
taskStatuses.value = [];
return [];
}
};
const createTaskStatus = async (spaceId, payload) => {
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/task-statuses`, payload);
await fetchTaskStatuses(spaceId);
return response.data;
};
const updateTaskStatus = async (spaceId, statusId, payload) => {
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/task-statuses/${statusId}`, payload);
await fetchTaskStatuses(spaceId);
return response.data;
};
const deleteTaskStatus = async (spaceId, statusId) => {
await apiClient.delete(`/api/v1/spaces/${spaceId}/task-statuses/${statusId}`);
await fetchTaskStatuses(spaceId);
};
const reorderTaskStatuses = async (spaceId, orderedStatusIds) => {
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/task-statuses/reorder`, {
ordered_status_ids: orderedStatusIds,
});
taskStatuses.value = response.data || [];
return taskStatuses.value;
};
const fetchTasks = async (spaceId, filters = {}) => {
if (!spaceId) {
tasks.value = [];
return [];
}
const params = {};
if (filters.categoryId) {
params.categoryId = filters.categoryId;
}
if (filters.statusId) {
params.statusId = filters.statusId;
}
if (typeof filters.parentTaskId === "string") {
params.parentTaskId = filters.parentTaskId;
}
try {
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks`, { params });
tasks.value = response.data || [];
return tasks.value;
} catch (error) {
console.error("Error fetching tasks:", error);
tasks.value = [];
return [];
}
};
const searchTasks = async (spaceId, query) => {
if (!spaceId || !query?.trim()) {
return [];
}
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks/search`, { params: { q: query } });
return response.data || [];
};
const getTask = async (spaceId, taskId) => {
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks/${taskId}`);
return response.data;
};
const createTask = async (spaceId, payload) => {
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks`, payload);
await fetchTasks(spaceId);
return response.data;
};
const updateTask = async (spaceId, taskId, payload) => {
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/tasks/${taskId}`, payload);
await fetchTasks(spaceId);
return response.data;
};
const deleteTask = async (spaceId, taskId) => {
await apiClient.delete(`/api/v1/spaces/${spaceId}/tasks/${taskId}`);
await fetchTasks(spaceId);
};
const transitionTask = async (spaceId, taskId, direction) => {
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks/${taskId}/transition`, { direction });
await fetchTasks(spaceId);
return response.data;
};
const fetchTasksForNote = async (spaceId, noteId) => {
if (!spaceId || !noteId) {
noteLinkedTasks.value = [];
return [];
}
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/notes/${noteId}/tasks`);
noteLinkedTasks.value = response.data || [];
return noteLinkedTasks.value;
};
const linkTaskToNote = async (spaceId, taskId, noteId) => {
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks/${taskId}/notes`, { note_id: noteId });
return response.data;
};
const unlinkTaskFromNote = async (spaceId, taskId, noteId) => {
const response = await apiClient.delete(`/api/v1/spaces/${spaceId}/tasks/${taskId}/notes/${noteId}`);
return response.data;
};
return {
spaces,
currentSpace,
@@ -217,6 +344,9 @@ export const useSpaceStore = defineStore("space", () => {
notesLoading,
categories,
categoryTree,
tasks,
taskStatuses,
noteLinkedTasks,
fetchSpaces,
selectSpace,
fetchNotes,
@@ -232,5 +362,20 @@ export const useSpaceStore = defineStore("space", () => {
deleteNote,
searchNotes,
clearSearchResults,
fetchTaskStatuses,
createTaskStatus,
updateTaskStatus,
deleteTaskStatus,
reorderTaskStatuses,
fetchTasks,
searchTasks,
getTask,
createTask,
updateTask,
deleteTask,
transitionTask,
fetchTasksForNote,
linkTaskToNote,
unlinkTaskFromNote,
};
});