Plan stuff. Log stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

203 lines
5.1 KiB

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 generateLogTable(activities, period) {
const newTable = [];
for (const log of period.logs) {
const goal = period.goals.find(g => g.id === log.goalId) || UNKNOWN_GOAL;
const subGoal = log.subGoalId
? goal.subGoals.find(s => s.id === log.subGoalId) || UNKNOWN_SUB_GOAL
: NO_SUB_GOAL;
const activity = activities.find(a => a.id === goal.activityId) || UNKNOWN_ACTIVITY;
const subActivity = activity.subActivities.find(s => s.id === log.subActivityId) || UNKNOWN_SUB_ACTIVITY;
newTable.push({log, goal, subGoal, activity, subActivity})
}
newTable.sort((a, b) => a.log.date - b.log.date);
return newTable;
}
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),
table: generateLogTable(data.activities, p),
}));
return data;
}
function replacePeriod(d, period) {
return {
...d,
periods: [
...d.periods.filter(a => a.id !== period.id),
{
...period,
scores: calculateTotalScore(period),
table: generateLogTable(d.activities, 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),
table: generateLogTable(activities, 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),
table: generateLogTable(d.activities, 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;