import { defineStore } from 'pinia'; import { AppwriteIds, databases, ID } from 'src/boot/appwrite'; import type { Models } from 'appwrite'; export const TASKSTATUS = ['ready', 'complete', 'waiting', 'archived']; export interface Task extends Partial { title: string; description: string; /* Array of Appwrite Document IDs */ required_skills: string[]; /* Array of Appwrite Document IDs */ tags: string[]; due_date: string; duration: number; /* Array of Appwrite Document IDs */ volunteers: string[]; volunteers_required: number; status: string; /* Array of Appwrite Document IDs */ depends_on: string[]; /* Appwrite ID of a Boat resource */ boat?: string[]; } export interface TaskTag extends Models.Document { name: string; description: string; colour: string; } export interface SkillTag extends Models.Document { name: string; description: string; tagColour: string; } export const useTaskStore = defineStore('tasks', { state: () => ({ tasks: [] as Task[], taskTags: [] as TaskTag[], skillTags: [] as SkillTag[], }), actions: { async fetchTasks() { try { await this.fetchTaskTags(); await this.fetchSkillTags(); const response = await databases.listDocuments( AppwriteIds.databaseId, AppwriteIds.collection.task ); this.tasks = response.documents as Task[]; } catch (error) { console.error('Failed to fetch tasks', error); } }, async fetchTaskTags() { // This is fine for a small number of tags, but more than a few hundred tags, we'd need to optimize try { const response = await databases.listDocuments( AppwriteIds.databaseId, AppwriteIds.collection.taskTags ); this.taskTags = response.documents as TaskTag[]; } catch (error) { console.error('Failed to fetch task tags', error); } }, async fetchSkillTags() { // This is fine for a small number of tags, but more than a few hundred tags, we'd need to optimize try { const response = await databases.listDocuments( AppwriteIds.databaseId, AppwriteIds.collection.skillTags ); this.skillTags = response.documents as SkillTag[]; } catch (error) { console.error('Failed to fetch skill tags', error); } }, async deleteTask(task: Task | string) { const docId = typeof task === 'string' ? task : task.$id; if (docId === undefined) { console.error('No document ID provided to deleteTask!'); return; } try { const response = await databases.deleteDocument( AppwriteIds.databaseId, AppwriteIds.collection.task, docId ); this.tasks = this.tasks.filter((task) => docId !== task.$id); } catch (error) { // Need some better error handling, here. console.error('Failed to delete task:', error); } }, async addTask(task: Task) { const newTask = { ...task }; try { const response = await databases.createDocument( AppwriteIds.databaseId, AppwriteIds.collection.task, ID.unique(), newTask ); this.tasks.push(response as Task); } catch (error) { console.error('Failed to add task:', error); } }, async updateTask(task: Task) { const newTask = >{ ...task, id: undefined, $databaseId: undefined, $collectionId: undefined, }; if (!task.$id) { console.error('No Task ID!'); return; } try { const response = await databases.updateDocument( AppwriteIds.databaseId, AppwriteIds.collection.task, task.$id, newTask ); this.tasks.push(response as Task); } catch (error) { console.error('Failed to update task:', error); } }, // TODO: Enhance this store to include offline caching, and subscription notification when items change on the server. }, // Add more actions as needed (e.g., updateTask, deleteTask) getters: { getTaskById: (state) => (id: string) => { return state.tasks.find((task) => task.$id === id) || null; }, getTaskTagById: (state) => (id: string) => { return state.taskTags.find((tag) => tag.$id === id) || null; }, getSkillById: (state) => (id: string) => { return state.skillTags.find((tag) => tag.$id === id) || null; }, filterTasksByTitle: (state) => (searchQuery: string) => { const result = state.tasks.filter((task) => task.title.toLowerCase().includes(searchQuery.toLowerCase()) ); console.log(result); return result; }, }, });