import { writable, derived } from "svelte/store"; import slApi from "../api/stufflog"; import Activity, { ActivityUpdate } from "../models/activity"; import Period, { PeriodUpdate } from "../models/period"; const UNKNOWN_GOAL = Object.freeze({name: "(Unknown)", subGoals: []}); const NO_SUB_GOAL = Object.freeze({name: "(None)"}); const UNKNOWN_SUB_GOAL = Object.freeze({name: "(Unknown)"}); const UNKNOWN_ACTIVITY = Object.freeze({name: "(Unknown)", subActivities: []}); const UNKNOWN_SUB_ACTIVITY = Object.freeze({name: "(Unknown)", unitName: "unit"}); function calculateTotalScore(period) { return period.goals.reduce((o, g) => o = ({...o, [g.id]: ( period.logs.filter(l => l.goalId === g.id) .map(l => l.score.total) .reduce((n, m) => n + m, 0) )}), {}) } function replaceActivity(d, activity) { const data = { ...d, activities: [ ...d.activities.filter(a => a.id !== activity.id), activity, ].sort((a,b) => a.name.localeCompare(b.name)), }; data.periods = data.periods.map(p => ({ ...p, scores: calculateTotalScore(p), })); return data; } function replacePeriod(d, period) { return { ...d, periods: [ ...d.periods.filter(a => a.id !== period.id), { ...period, scores: calculateTotalScore(period), }, ].sort((a,b) => b.from - a.from), }; } function deleteActivity(d, id) { return { ...d, activities: d.activities.filter(a => a.id !== id), }; } function deletePeriod(d, id) { return { ...d, periods: d.periods.filter(a => a.id !== id), }; } function createStufflogStore() { /** @type {{activities: Activity[], periods: Period[], logTables: {}}} */ const initialData = {activities: [], periods: [], logTables: {}}; const {set, update, subscribe} = writable(initialData); return { subscribe, async listActivities() { const activities = await slApi.listActivities(); update(d => ({ ...d, activities: activities.sort((a,b) => a.name.localeCompare(b.name)), periods: d.periods.map(p => ({ ...p, scores: calculateTotalScore(p), })), })); }, async loadActivity(id) { const activity = await slApi.findActivity(id); update(d => replaceActivity(d, activity)); }, async listPeriods() { const periods = await slApi.listPeriods(); update(d => ({ ...d, periods: periods.sort((a,b) => b.from - a.from).map(p => ({ ...p, scores: calculateTotalScore(p), })), })); }, async loadPeriods(id) { const period = await slApi.findPeriod(id); update(d => replacePeriod(d, period)); }, /** * Create period * * @param {Period} input */ async createPeriod(input) { const period = await slApi.postPeriod(input); update(d => replacePeriod(d, period)); }, /** * Create an activity * * @param {Activity} input */ async createActivity(input) { const activity = await slApi.postActivity(input); update(d => replaceActivity(d, activity)) }, /** * Update activities * * @param {string} id * @param {...ActivityUpdate} updates */ async updateActivity(id, ...updates) { const activity = await slApi.patchActivity(id, ...updates); update(d => replaceActivity(d, activity)); }, /** * Update periods * * @param {string} id * @param {...PeriodUpdate} updates */ async updatePeriod(id, ...updates) { const period = await slApi.patchPeriod(id, ...updates); update(d => replacePeriod(d, period)); }, /** * Delete an activity * * @param {string} id */ async deleteActivity(id) { const activity = await slApi.deleteActivity(id); update(d => deleteActivity(d, activity.id)); }, /** * Delete a period * * @param {string} id */ async deletePeriod(id) { const period = await slApi.deletePeriod(id); update(d => deletePeriod(d, period.id)); }, /** * Clear all data. This does not do any API call. */ clearAll() { set({activities: [], periods: []}); }, } }; const stufflog = createStufflogStore(); export default stufflog;