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.

146 lines
5.3 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <script lang="ts">
  2. import stuffLogClient from "../clients/stufflog";
  3. import Modal from "../components/Modal.svelte";
  4. import modalStore from "../stores/modal";
  5. import type { GoalResult } from "../models/goal";
  6. import { nextMonth } from "../utils/time";
  7. import GroupSelect from "../components/GroupSelect.svelte";
  8. import markStale from "../stores/markStale";
  9. import Checkbox from "../components/Checkbox.svelte";
  10. import GroupItemSelect from "../components/GroupItemSelect.svelte";
  11. import groupStore from "../stores/group";
  12. import type { GroupResult } from "../models/group";
  13. import DateRangeSelect from "../components/DateRangeSelect.svelte";
  14. import { allOffsets, rangeFromDates } from "../utils/date-range";
  15. export let deletion = false;
  16. export let creation = false;
  17. const md = $modalStore;
  18. let goal: GoalResult = {
  19. id: "",
  20. groupId: "",
  21. startTime: nextMonth(new Date()).toISOString(),
  22. endTime: new Date(nextMonth(nextMonth(new Date())).getTime() - 1).toISOString(),
  23. amount: 1,
  24. name: "",
  25. description: "",
  26. completedAmount: 0,
  27. unweighted: false,
  28. compositionMode: "item",
  29. itemId: null,
  30. group: {id: "", name: "", icon: "question", description: ""},
  31. items: [],
  32. logs: [],
  33. };
  34. let verb = "Add";
  35. if (md.name === "goal.edit" || md.name === "goal.delete") {
  36. goal = md.goal;
  37. verb = (md.name === "goal.edit") ? "Edit" : "Delete";
  38. } else if (md.name !== "goal.add") {
  39. throw new Error("Wrong form")
  40. }
  41. let name = goal.name;
  42. let description = goal.description;
  43. let groupId = goal.groupId;
  44. let amount = goal.amount;
  45. let unweighted = goal.unweighted;
  46. let itemId = goal.itemId || "";
  47. let compositionMode = goal.compositionMode;
  48. let range = rangeFromDates(new Date(goal.startTime), new Date(goal.endTime), allOffsets);
  49. let taskFilter = goal.taskFilter || "";
  50. let itemFilter = goal.itemFilter || "";
  51. let error = null;
  52. let loading = false;
  53. let selectedGroup: GroupResult = null;
  54. function onSubmit() {
  55. loading = true;
  56. const [startTime, endTime] = range.calculate(new Date());
  57. if (creation) {
  58. stuffLogClient.createGoal({
  59. startTime, endTime,
  60. itemId: itemId || null,
  61. taskFilter: taskFilter.toLowerCase() || null,
  62. itemFilter: itemFilter.toLowerCase() || null,
  63. groupId, name, description, amount, unweighted, compositionMode
  64. }).then(() => {
  65. markStale("goal");
  66. modalStore.close();
  67. }).catch(err => {
  68. error = err.message ? err.message : err.toString();
  69. }).finally(() => {
  70. loading = false;
  71. })
  72. } else if (deletion) {
  73. stuffLogClient.deleteGoal(goal.id).then(() => {
  74. markStale("goal");
  75. modalStore.close();
  76. }).catch(err => {
  77. error = err.message ? err.message : err.toString();
  78. }).finally(() => {
  79. loading = false;
  80. })
  81. } else {
  82. stuffLogClient.updateGoal(goal.id, {
  83. startTime, endTime,
  84. itemId: itemId || null,
  85. clearItemId: itemId === "",
  86. taskFilter: taskFilter.toLowerCase() || null,
  87. clearTaskFilter: taskFilter === "",
  88. itemFilter: itemFilter.toLowerCase() || null,
  89. clearItemFilter: itemFilter === "",
  90. name, description, amount, compositionMode, unweighted,
  91. }).then(() => {
  92. markStale("goal");
  93. modalStore.close();
  94. }).catch(err => {
  95. error = err.message ? err.message : err.toString();
  96. }).finally(() => {
  97. loading = false;
  98. })
  99. }
  100. error = null;
  101. }
  102. function onClose() {
  103. modalStore.close();
  104. }
  105. $: selectedGroup = $groupStore.groups.find(g => g.id === groupId);
  106. </script>
  107. <Modal show title="{verb} Goal" error={error} closable on:close={onClose}>
  108. <form on:submit|preventDefault={onSubmit}>
  109. <label for="name">Name</label>
  110. <input disabled={deletion} name="name" type="text" bind:value={name} />
  111. <label for="description">Description</label>
  112. <textarea disabled={deletion} name="description" bind:value={description} />
  113. <label for="groupId">Group</label>
  114. <GroupSelect disabled={!creation} name="groupId" bind:value={groupId}/>
  115. <label for="groupId">Specific Item</label>
  116. <GroupItemSelect disabled={deletion} optional optionalLabel="Whole Group" group={selectedGroup} name="itemId" bind:value={itemId}/>
  117. <label for="amount">Amount</label>
  118. <input disabled={deletion} name="amount" type="number" bind:value={amount} />
  119. <label for="compositionMode">Composition Mode</label>
  120. <select name="compositionMode" bind:value={compositionMode} disabled={deletion}>
  121. <option value="item" selected={"item" === compositionMode}>Item</option>
  122. <option value="task" selected={"task" === compositionMode}>Task</option>
  123. <option value="project" selected={"project" === compositionMode}>Project</option>
  124. </select>
  125. <DateRangeSelect disabled={deletion} bind:value={range} />
  126. <label for="taskFilter">Task Filter (Optional)</label>
  127. <input disabled={deletion} name="taskFilter" type="text" bind:value={taskFilter} />
  128. <label for="itemFilter">Item Filter (Optional)</label>
  129. <input disabled={deletion} name="itemFilter" type="text" bind:value={itemFilter} />
  130. <Checkbox bind:checked={unweighted} label="Unweighted (All items count as 1)" />
  131. <hr />
  132. <button disabled={loading} type="submit">{verb} Goal</button>
  133. </form>
  134. </Modal>