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.

179 lines
4.3 KiB

4 years ago
  1. import { writable, derived } from "svelte/store";
  2. import slApi from "../api/stufflog";
  3. import Activity, { ActivityUpdate } from "../models/activity";
  4. import Period, { PeriodUpdate } from "../models/period";
  5. const UNKNOWN_GOAL = Object.freeze({name: "(Unknown)", subGoals: []});
  6. const NO_SUB_GOAL = Object.freeze({name: "(None)"});
  7. const UNKNOWN_SUB_GOAL = Object.freeze({name: "(Unknown)"});
  8. const UNKNOWN_ACTIVITY = Object.freeze({name: "(Unknown)", subActivities: []});
  9. const UNKNOWN_SUB_ACTIVITY = Object.freeze({name: "(Unknown)", unitName: "unit"});
  10. function calculateTotalScore(period) {
  11. return period.goals.reduce((o, g) => o = ({...o, [g.id]: (
  12. period.logs.filter(l => l.goalId === g.id)
  13. .map(l => l.score.total)
  14. .reduce((n, m) => n + m, 0)
  15. )}), {})
  16. }
  17. function replaceActivity(d, activity) {
  18. const data = {
  19. ...d,
  20. activities: [
  21. ...d.activities.filter(a => a.id !== activity.id),
  22. activity,
  23. ].sort((a,b) => a.name.localeCompare(b.name)),
  24. };
  25. data.periods = data.periods.map(p => ({
  26. ...p,
  27. scores: calculateTotalScore(p),
  28. }));
  29. return data;
  30. }
  31. function replacePeriod(d, period) {
  32. return {
  33. ...d,
  34. periods: [
  35. ...d.periods.filter(a => a.id !== period.id),
  36. {
  37. ...period,
  38. scores: calculateTotalScore(period),
  39. },
  40. ].sort((a,b) => b.from - a.from),
  41. };
  42. }
  43. function deleteActivity(d, id) {
  44. return {
  45. ...d,
  46. activities: d.activities.filter(a => a.id !== id),
  47. };
  48. }
  49. function deletePeriod(d, id) {
  50. return {
  51. ...d,
  52. periods: d.periods.filter(a => a.id !== id),
  53. };
  54. }
  55. function createStufflogStore() {
  56. /** @type {{activities: Activity[], periods: Period[], logTables: {}}} */
  57. const initialData = {activities: [], periods: [], logTables: {}};
  58. const {set, update, subscribe} = writable(initialData);
  59. return {
  60. subscribe,
  61. async listActivities() {
  62. const activities = await slApi.listActivities();
  63. update(d => ({
  64. ...d,
  65. activities: activities.sort((a,b) => a.name.localeCompare(b.name)),
  66. periods: d.periods.map(p => ({
  67. ...p,
  68. scores: calculateTotalScore(p),
  69. })),
  70. }));
  71. },
  72. async loadActivity(id) {
  73. const activity = await slApi.findActivity(id);
  74. update(d => replaceActivity(d, activity));
  75. },
  76. async listPeriods() {
  77. const periods = await slApi.listPeriods();
  78. update(d => ({
  79. ...d,
  80. periods: periods.sort((a,b) => b.from - a.from).map(p => ({
  81. ...p,
  82. scores: calculateTotalScore(p),
  83. })),
  84. }));
  85. },
  86. async loadPeriods(id) {
  87. const period = await slApi.findPeriod(id);
  88. update(d => replacePeriod(d, period));
  89. },
  90. /**
  91. * Create period
  92. *
  93. * @param {Period} input
  94. */
  95. async createPeriod(input) {
  96. const period = await slApi.postPeriod(input);
  97. update(d => replacePeriod(d, period));
  98. },
  99. /**
  100. * Create an activity
  101. *
  102. * @param {Activity} input
  103. */
  104. async createActivity(input) {
  105. const activity = await slApi.postActivity(input);
  106. update(d => replaceActivity(d, activity))
  107. },
  108. /**
  109. * Update activities
  110. *
  111. * @param {string} id
  112. * @param {...ActivityUpdate} updates
  113. */
  114. async updateActivity(id, ...updates) {
  115. const activity = await slApi.patchActivity(id, ...updates);
  116. update(d => replaceActivity(d, activity));
  117. },
  118. /**
  119. * Update periods
  120. *
  121. * @param {string} id
  122. * @param {...PeriodUpdate} updates
  123. */
  124. async updatePeriod(id, ...updates) {
  125. const period = await slApi.patchPeriod(id, ...updates);
  126. update(d => replacePeriod(d, period));
  127. },
  128. /**
  129. * Delete an activity
  130. *
  131. * @param {string} id
  132. */
  133. async deleteActivity(id) {
  134. const activity = await slApi.deleteActivity(id);
  135. update(d => deleteActivity(d, activity.id));
  136. },
  137. /**
  138. * Delete a period
  139. *
  140. * @param {string} id
  141. */
  142. async deletePeriod(id) {
  143. const period = await slApi.deletePeriod(id);
  144. update(d => deletePeriod(d, period.id));
  145. },
  146. /**
  147. * Clear all data. This does not do any API call.
  148. */
  149. clearAll() {
  150. set({activities: [], periods: []});
  151. },
  152. }
  153. };
  154. const stufflog = createStufflogStore();
  155. export default stufflog;