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.

189 lines
5.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. <script lang="ts">
  2. import stuffLogClient from "../clients/stufflog";
  3. import DateRangeSelect from "../components/DateRangeSelect.svelte";
  4. import EmptyList from "../components/EmptyList.svelte";
  5. import EmptyParentEntry from "../components/EmptyParentEntry.svelte";
  6. import EveryMinute from "../components/EveryMinute.svelte";
  7. import GoalEntry from "../components/GoalEntry.svelte";
  8. import ItemProgress from "../components/ItemProgress.svelte";
  9. import LogEntry from "../components/LogEntry.svelte";
  10. import ParentEntry from "../components/ParentEntry.svelte";
  11. import ProjectEntry from "../components/ProjectEntry.svelte";
  12. import RefreshSelection from "../components/RefreshSelection.svelte";
  13. import type { ProjectResult } from "../models/project";
  14. import { fpGoalStore } from "../stores/goal";
  15. import { fpLogStore } from "../stores/logs";
  16. import { fpProjectStore, fpProjectStore2 } from "../stores/project";
  17. import { fpTaskStore } from "../stores/tasks";
  18. import { RelativeDateRange } from "../utils/date-range";
  19. import { endOfDay, startOfDay } from "../utils/time";
  20. let fakeMap: {[projectId: string]: boolean} = {}
  21. let fakeProjects: ProjectResult[]
  22. let sortedProjects: ProjectResult[]
  23. let now = new Date();
  24. $: {
  25. if ($fpGoalStore.stale && !$fpGoalStore.loading) {
  26. const [minTime, maxTime] = (new RelativeDateRange(3, "day")).calculate(now);
  27. fpGoalStore.load({minTime, maxTime});
  28. }
  29. }
  30. $: {
  31. if ($fpTaskStore.stale && !$fpTaskStore.loading) {
  32. fpTaskStore.load({
  33. active: true,
  34. expiring: true,
  35. sort: ["status"],
  36. })
  37. }
  38. }
  39. $: {
  40. if ($fpProjectStore.stale && !$fpProjectStore.loading) {
  41. fpProjectStore.load({
  42. active: true,
  43. expiring: true,
  44. includeSemiActive: true,
  45. });
  46. }
  47. }
  48. $: {
  49. if ($fpProjectStore2.stale && !$fpProjectStore2.loading) {
  50. fpProjectStore2.load({
  51. favorite: true,
  52. });
  53. }
  54. }
  55. $: {
  56. if ($fpLogStore.stale && !$fpLogStore.loading) {
  57. fpLogStore.load({
  58. maxTime: endOfDay(now),
  59. minTime: startOfDay(now),
  60. })
  61. }
  62. }
  63. $: {
  64. const individualTasks = $fpTaskStore.tasks
  65. .filter(t => $fpProjectStore.projects.find(p => p.id === t.projectId) == null)
  66. .sort((a,b) => Date.parse(a.endTime) - Date.parse(b.endTime));
  67. fakeProjects = [];
  68. fakeMap = {};
  69. console.log(individualTasks, $fpTaskStore.tasks);
  70. for (let task of individualTasks) {
  71. if (!task.project.active) {
  72. continue;
  73. }
  74. let fakeProject = fakeProjects.find(p => p.id === task.projectId);
  75. if (fakeProject == null) {
  76. fakeMap[task.projectId] = true;
  77. fakeProjects.push({
  78. ...task.project,
  79. tasks: [task],
  80. subtractions: [],
  81. });
  82. } else {
  83. fakeProject.tasks.push(task);
  84. }
  85. }
  86. for (const fakeProject of fakeProjects) {
  87. fakeProject.createdTime = fakeProject.tasks.map(t => t.createdTime).sort()[0];
  88. fakeProject.endTime = fakeProject.tasks[0].endTime;
  89. }
  90. }
  91. $: {
  92. sortedProjects = [...fakeProjects, ...$fpProjectStore.projects]
  93. .sort((a,b) => Date.parse(a.endTime) - Date.parse(b.endTime));
  94. }
  95. </script>
  96. <div class="page">
  97. <EveryMinute bind:now={now} />
  98. <div class="left">
  99. {#if !$fpGoalStore.loading || $fpGoalStore.goals.length > 0}
  100. <h1>Active Goals</h1>
  101. {/if}
  102. {#each $fpGoalStore.goals as goal (goal.id)}
  103. <GoalEntry goal={goal} />
  104. {/each}
  105. {#if !$fpGoalStore.loading && $fpGoalStore.goals.length === 0}
  106. <EmptyList icon="list" text="No goals." />
  107. {/if}
  108. {#if $fpLogStore.logs.length > 0}
  109. <h1>Today's Logs</h1>
  110. <ItemProgress logs={$fpLogStore.logs} centered />
  111. <EmptyParentEntry icon="list">
  112. {#each $fpLogStore.logs as log (log.id)}
  113. <LogEntry log={log} />
  114. {/each}
  115. </EmptyParentEntry>
  116. {/if}
  117. </div>
  118. <div class="right">
  119. {#if $fpProjectStore.projects.length > 0}
  120. <h1>Upcoming Deadlines</h1>
  121. {#each sortedProjects as project (project.id)}
  122. <ProjectEntry isFake={fakeMap[project.id]} hideInactive project={project} />
  123. {/each}
  124. {/if}
  125. {#if $fpProjectStore2.projects.length > 0}
  126. <h1>Starred Projects</h1>
  127. {#each $fpProjectStore2.projects as project (project.id)}
  128. <ProjectEntry hideInactive project={project} />
  129. {/each}
  130. {/if}
  131. </div>
  132. </div>
  133. <RefreshSelection />
  134. <style>
  135. div.page {
  136. display: flex;
  137. flex-direction: row;
  138. max-width: 100%;
  139. padding: 0 1ch;
  140. margin: 0;
  141. width: 1020px;
  142. box-sizing: border-box;
  143. margin: 1em auto;
  144. }
  145. div.left, div.right {
  146. width: 50%;
  147. padding: 0 1ch;
  148. margin: 0;
  149. box-sizing: border-box;
  150. }
  151. h1 {
  152. font-size: 1.5em;
  153. font-weight: 100;
  154. text-align: center;
  155. }
  156. @media screen and (max-width: 900px) {
  157. div.page {
  158. display: block;
  159. }
  160. div.left, div.right {
  161. padding-left: 0;
  162. padding-right: 0;
  163. padding-bottom: 2em;
  164. max-width: 100%;
  165. width: 640px;
  166. margin: auto;
  167. }
  168. }
  169. </style>