src/lib/store/tasksStore.ts (view raw)
1import { get, writable } from "svelte/store";
2import { debounce, WEEKDAYS } from "../utils";
3import { taskToThing } from "../models/task";
4import {
5 getThingAll,
6 saveSolidDatasetAt,
7 setThing,
8 removeThing,
9} from "@inrupt/solid-client";
10import { fetch } from "@inrupt/solid-client-authn-browser";
11import podInfo from "./podInfoStore";
12import { addToast } from "./toastStore";
13import { DateTime } from "luxon";
14
15const DEBOUNCE_TIME_SYNC = 2000;
16
17const taskStore = writable<Task[]>([]);
18const { update, set, subscribe } = taskStore;
19
20const addTask = (task: Omit<Task, "id">) => {
21 const podUrl = get(podInfo).podUrl;
22 update(tasks => [
23 ...tasks,
24 { ...task, id: `${podUrl}/tasks/default#${Date.now()}` },
25 ]);
26};
27
28const updateTask = (taskId: string, taskUpdate: Partial<Task>) => {
29 update(tasks =>
30 tasks.map(task => {
31 if (task.id === taskId) return { ...task, ...taskUpdate };
32 return task;
33 })
34 );
35
36 if (taskUpdate.done) {
37 const task = get(taskStore).find(item => item.id === taskId);
38 const now = DateTime.now();
39 const datetime = task?.dueDate
40 ? DateTime.fromJSDate(task.dueDate)
41 : now
42 let weekday = WEEKDAYS[task?.byDay as string];
43 let dueDate: DateTime | null = null;
44 if (task?.byDay && !task.byMonthWeek) {
45 dueDate = datetime.set({ weekday });
46 if (dueDate <= now) dueDate = dueDate.plus({ week: 1 })
47 }
48 else if (task?.byMonthDay) {
49 dueDate = datetime.set({ day: task.byMonthDay })
50 if (dueDate <= now) dueDate = dueDate.plus({ month: 1 })
51 }
52 else if (task?.byDay && task?.byMonthWeek) {
53 dueDate = datetime.set({ weekday, weekNumber: task.byMonthWeek })
54 if (dueDate <= now) dueDate = dueDate.plus({ month: 1 })
55 }
56
57 if (dueDate) {
58 console.log(`Tâche replanifiée pour le ${dueDate.toISODate()}`)
59 addTask({ ...task, dueDate: dueDate.toJSDate(), done: false, endTime: undefined });
60 }
61 }
62};
63
64const deleteTask = (taskId: string) => {
65 update(tasks => tasks.filter(task => task.id !== taskId));
66};
67
68// Sync tasks with pod data
69let init = false;
70subscribe(
71 debounce(async (tasks: Task[]) => {
72 if (!init) return (init = true);
73
74 let taskDataset = get(podInfo).tasksDataset;
75 if (!taskDataset) throw new Error("No tasks dataset. Can't write to pod.");
76
77 const currentDatasetThings = getThingAll(taskDataset);
78 const updatedDatasetThings = tasks.map(taskToThing);
79
80 // Add task things to dataset
81 for (const taskThing of updatedDatasetThings) {
82 taskDataset = setThing(taskDataset, taskThing);
83 }
84
85 // Remove deleted tasks from dataset
86 const removedThings = currentDatasetThings.filter(
87 thing => !updatedDatasetThings.find(thg => thg.url === thing.url)
88 );
89 for (const removedThing of removedThings) {
90 taskDataset = removeThing(taskDataset, removedThing);
91 }
92
93 const podUrl = get(podInfo).podUrl;
94 const savedSolidDataset = await saveSolidDatasetAt(
95 `${podUrl}/tasks/default`,
96 taskDataset,
97 { fetch: fetch }
98 );
99 podInfo.update(store => ({ ...store, tasksDataset: savedSolidDataset }));
100 addToast("Tâches enregistrées vers le pod.");
101 }, DEBOUNCE_TIME_SYNC)
102);
103
104export default { set, update, subscribe, addTask, updateTask, deleteTask };