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