8 changed files with 353 additions and 24 deletions
			
			
		- 
					127svelte-ui/src/components/DateRangeSelect.svelte
- 
					118svelte-ui/src/components/DeadlineSelect.svelte
- 
					2svelte-ui/src/components/ParentEntry.svelte
- 
					26svelte-ui/src/components/ProjectEntry.svelte
- 
					53svelte-ui/src/components/TaskEntry.svelte
- 
					6svelte-ui/src/forms/GoalForm.svelte
- 
					5svelte-ui/src/forms/TaskForm.svelte
- 
					40svelte-ui/src/utils/time.ts
| @ -0,0 +1,127 @@ | |||||
|  | <script lang="ts"> | ||||
|  |   import { onMount } from "svelte"; | ||||
|  |   import { endOfMonth, endOfWeek, endOfYear, formatFormTime, lastMonth, monthName, nextMonth, startOfMonth, startOfWeek, startOfYear } from "../utils/time"; | ||||
|  | import EveryMinute from "./EveryMinute.svelte"; | ||||
|  | 
 | ||||
|  |   interface DateOption { | ||||
|  |     id: string | ||||
|  |     label: string | ||||
|  |     from: Date | ||||
|  |     to: Date | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   export let fromValue: string; | ||||
|  |   export let toValue: string; | ||||
|  |   export let disabled: boolean; | ||||
|  |   export let styled: boolean; | ||||
|  | 
 | ||||
|  |   let selected: string = "custom"; | ||||
|  |   let options: DateOption[] = []; | ||||
|  |   let now: Date = new Date(); | ||||
|  | 
 | ||||
|  |   onMount(() => { | ||||
|  |     for (const option of options) { | ||||
|  |       if (formatFormTime(option.from) === fromValue && formatFormTime(option.to) === toValue) { | ||||
|  |         selected = option.id; | ||||
|  |       } | ||||
|  |     } | ||||
|  |   }); | ||||
|  | 
 | ||||
|  |   $: { | ||||
|  |     if (options.length === 0) { | ||||
|  |       let current = startOfMonth(now); | ||||
|  |       const nextWeek = new Date(Date.now() + (86400000 * 7)); | ||||
|  |       const lastWeek = new Date(Date.now() - (86400000 * 7)); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_week", | ||||
|  |         label: "This Week", | ||||
|  |         from: startOfWeek(now), | ||||
|  |         to: endOfWeek(now), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_week", | ||||
|  |         label: "Next Week", | ||||
|  |         from: startOfWeek(nextWeek), | ||||
|  |         to: endOfWeek(nextWeek), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_week", | ||||
|  |         label: "Last Week", | ||||
|  |         from: startOfWeek(lastWeek), | ||||
|  |         to: endOfWeek(lastWeek), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_month", | ||||
|  |         label: "This Month", | ||||
|  |         from: current, | ||||
|  |         to: endOfMonth(current), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_month", | ||||
|  |         label: "Next Month", | ||||
|  |         from: nextMonth(current), | ||||
|  |         to: endOfMonth(nextMonth(current)), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_month", | ||||
|  |         label: "Last Month", | ||||
|  |         from: lastMonth(current), | ||||
|  |         to: endOfMonth(lastMonth(current)), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_year", | ||||
|  |         label: "This Year", | ||||
|  |         from: startOfYear(now), | ||||
|  |         to: endOfYear(now), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_year", | ||||
|  |         label: "Next Year", | ||||
|  |         from: startOfYear(new Date(Date.now() + (366.25 * 86400000))), | ||||
|  |         to: endOfYear(new Date(Date.now() + (365.25 * 86400000))), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_year", | ||||
|  |         label: "Last Year", | ||||
|  |         from: startOfYear(new Date(Date.now() - (365.25 * 86400000))), | ||||
|  |         to: endOfYear(new Date(Date.now() - (365.25 * 86400000))), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "custom", | ||||
|  |         label: "Specific Dates", | ||||
|  |         from: null, | ||||
|  |         to: null, | ||||
|  |       }); | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   $: { | ||||
|  |     if (selected !== "custom") { | ||||
|  |       const option = options.find(o => o.id === selected); | ||||
|  |       if (option != null) { | ||||
|  |         fromValue = formatFormTime(option.from); | ||||
|  |         toValue = formatFormTime(option.to); | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <EveryMinute bind:now={now} /> | ||||
|  | <div class:styled> | ||||
|  |   <label for="timeRange">Time Period</label> | ||||
|  |   <select name="timeRange" disabled={disabled} bind:value={selected}> | ||||
|  |     {#each options as option (option.id)} | ||||
|  |       <option value={option.id}>{option.label}</option> | ||||
|  |     {/each} | ||||
|  |   </select> | ||||
|  |   {#if selected === "custom"} | ||||
|  |     <label for="startTime">Start Time</label> | ||||
|  |     <input disabled={disabled} name="startTime" type="datetime-local" bind:value={fromValue} /> | ||||
|  |     <label for="endTime">End Time</label> | ||||
|  |     <input disabled={disabled} name="endTime" type="datetime-local" bind:value={toValue} /> | ||||
|  |   {/if} | ||||
|  | </div> | ||||
| @ -0,0 +1,118 @@ | |||||
|  | <script lang="ts"> | ||||
|  |   import { onMount } from "svelte"; | ||||
|  |   import { endOfMonth, endOfWeek, endOfYear, formatFormTime, lastMonth, monthName, nextMonth, startOfMonth, startOfWeek, startOfYear } from "../utils/time"; | ||||
|  |   import EveryMinute from "./EveryMinute.svelte"; | ||||
|  | 
 | ||||
|  |   interface DateOption { | ||||
|  |     id: string | ||||
|  |     label: string | ||||
|  |     value: Date | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   export let value: string; | ||||
|  |   export let disabled: boolean; | ||||
|  | 
 | ||||
|  |   let selected: string = "custom"; | ||||
|  |   let options: DateOption[] = []; | ||||
|  |   let now: Date = new Date(); | ||||
|  | 
 | ||||
|  |   onMount(() => { | ||||
|  |     if (value === "") { | ||||
|  |       selected = "none"; | ||||
|  |       return; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     for (const option of options) { | ||||
|  |       if (formatFormTime(option.value) === value) { | ||||
|  |         selected = option.id; | ||||
|  |       } | ||||
|  |     } | ||||
|  |   }); | ||||
|  | 
 | ||||
|  |   $: { | ||||
|  |     if (options.length === 0) { | ||||
|  |       let current = startOfMonth(now); | ||||
|  |       const nextWeek = new Date(now.getTime() + (86400000 * 7)); | ||||
|  |       const lastWeek = new Date(now.getTime() - (86400000 * 7)); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "none", | ||||
|  |         label: "No deadline", | ||||
|  |         value: new Date(Number.NaN), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_week", | ||||
|  |         label: "End of this Week", | ||||
|  |         value: endOfWeek(now), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_week", | ||||
|  |         label: "End of next Week", | ||||
|  |         value: endOfWeek(nextWeek), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_week", | ||||
|  |         label: "End of last Week", | ||||
|  |         value: endOfWeek(lastWeek), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_month", | ||||
|  |         label: "End of this month", | ||||
|  |         value: endOfMonth(current), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_month", | ||||
|  |         label: "End of next month", | ||||
|  |         value: endOfMonth(nextMonth(current)), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_month", | ||||
|  |         label: "End of last month", | ||||
|  |         value: endOfMonth(lastMonth(current)), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "this_year", | ||||
|  |         label: "This Year", | ||||
|  |         value: endOfYear(now), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "next_year", | ||||
|  |         label: "Next Year", | ||||
|  |         value: endOfYear(new Date(Date.now() + (365.25 * 86400000))), | ||||
|  |       }); | ||||
|  |       options.push({ | ||||
|  |         id: "last_year", | ||||
|  |         label: "Last Year", | ||||
|  |         value: endOfYear(new Date(Date.now() - (365.25 * 86400000))), | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       options.push({ | ||||
|  |         id: "custom", | ||||
|  |         label: "Specific Dates", | ||||
|  |         value: null, | ||||
|  |       }); | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   $: { | ||||
|  |     if (selected !== "custom") { | ||||
|  |       const option = options.find(o => o.id === selected); | ||||
|  |       if (option != null) { | ||||
|  |         value = formatFormTime(option.value); | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <EveryMinute bind:now={now} /> | ||||
|  | <select name="endTime" disabled={disabled} bind:value={selected}> | ||||
|  |   {#each options as option (option.id)} | ||||
|  |     <option value={option.id}>{option.label}</option> | ||||
|  |   {/each} | ||||
|  | </select> | ||||
|  | {#if selected === "custom"} | ||||
|  |   <input disabled={disabled} name="value" type="datetime-local" bind:value={value} /> | ||||
|  | {/if} | ||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue