diff options
| author | ivarlovlie <git@ivarlovlie.no> | 2022-09-20 09:24:27 +0200 |
|---|---|---|
| committer | ivarlovlie <git@ivarlovlie.no> | 2022-09-20 09:24:27 +0200 |
| commit | a9072370ca1eb9a5cce928b1d487db0f307edea6 (patch) | |
| tree | 59c3c23df930a8b5f888dc7813923abf4ceefed4 /old-apps/projects/src/app/pages/home.svelte | |
| parent | 56fa963a1d63cbe0bf28e29e717cceaa417c45c1 (diff) | |
| download | greatoffice-a9072370ca1eb9a5cce928b1d487db0f307edea6.tar.xz greatoffice-a9072370ca1eb9a5cce928b1d487db0f307edea6.zip | |
feat: Move old apps into it's own directory
Diffstat (limited to 'old-apps/projects/src/app/pages/home.svelte')
| -rw-r--r-- | old-apps/projects/src/app/pages/home.svelte | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/old-apps/projects/src/app/pages/home.svelte b/old-apps/projects/src/app/pages/home.svelte new file mode 100644 index 0000000..1f398b5 --- /dev/null +++ b/old-apps/projects/src/app/pages/home.svelte @@ -0,0 +1,178 @@ +<script lang="ts"> + import LL from "$app/lib/i18n/i18n-svelte"; + import { delete_time_entry, get_time_entries, get_time_entry } from "$shared/lib/api/time-entry"; + import { IconNames, QueryKeys } from "$shared/lib/configuration"; + import { TimeEntryDto } from "$shared/lib/models/TimeEntryDto"; + import { Temporal } from "@js-temporal/polyfill"; + import { useMutation, useQuery, useQueryClient } from "@sveltestack/svelte-query"; + import { onMount } from "svelte"; + import Tile from "$shared/components/tile.svelte"; + import Button from "$shared/components/button.svelte"; + import Stopwatch from "$shared/components/stopwatch.svelte"; + import { Table, THead, TBody, TCell, TRow } from "$shared/components/table"; + import Layout from "./_layout.svelte"; + import EntryFrom from "$app/pages/views/entry-form/index.svelte"; + import { seconds_to_hour_minute, unwrap_date_time_from_entry } from "$shared/lib/helpers"; + import { TimeEntryQueryDuration } from "$shared/lib/models/TimeEntryQuery"; + + let currentTime = ""; + let isLoading = false; + let EditEntryForm: any; + let timeEntries = [] as Array<TimeEntryDto>; + let timeLoggedTodayString = $LL.home.loggedTimeTodayString({hours: 0, minutes: 0}); + let loggedSecondsToday = 0; + + const queryClient = useQueryClient(); + const queryResult = useQuery(QueryKeys.entries, async () => await get_time_entries({ + duration: TimeEntryQueryDuration.TODAY, + page: 1, + pageSize: 100, + })?.data ?? [] + ); + + function set_current_time() { + currentTime = Temporal.Now.plainTimeISO().toLocaleString(undefined, { + timeStyle: "short", + }); + } + + const delete_entry_mutation = useMutation(delete_time_entry, { + onSuccess: (data) => { + queryClient.invalidateQueries([QueryKeys.entries, data.data.id]); + }, + }); + + async function on_edit_entry_button_click(event, entryId: string) { + const response = useQuery([QueryKeys.entries, entryId], () => { + return get_time_entry(entryId); + }); + + EditEntryForm.set_values(response); + } + + async function on_delete_entry_button_click(event, entryId: string) { + if (confirm($LL.home.confirmDeleteEntry())) { + $delete_entry_mutation.mutate(entryId); + } + } + + function on_create_from_stopwatch(event) { + EditEntryForm.set_time({to: event.detail.to, from: event.detail.from}); + if (event.detail.description) { + EditEntryForm.set_description(event.detail.description); + } + } + + onMount(async () => { + set_current_time(); + setInterval(() => { + set_current_time(); + }, 1e4); + queryResult.subscribe((result) => { + const newEntries = []; + loggedSecondsToday = 0; + for (const entry of result.data?.results ?? []) { + const date_time = unwrap_date_time_from_entry(entry); + newEntries.push({ + id: entry.id, + start: date_time.start_time, + stop: date_time.stop_time, + category: entry.category, + }); + loggedSecondsToday += (date_time.duration.hours * 60 * 60) + (date_time.duration.minutes * 60); + } + timeLoggedTodayString = $LL.home.loggedTimeTodayString(seconds_to_hour_minute(loggedSecondsToday)); + timeEntries = newEntries; + }); + }); +</script> + +<Layout> + <div class="grid gap-md margin-top-xs flex-row@md items-start flex-column-reverse"> + <Tile class="col"> + <h3 class="text-md padding-bottom-xxxs">{$LL.home.newEntry()}</h3> + <EntryFrom bind:functions={EditEntryForm}/> + </Tile> + <div class="col grid gap-sm"> + <Tile class="col-6@md col-12"> + <p class="text-xxl">{timeLoggedTodayString}</p> + <p class="text-xs margin-bottom-xxs">{$LL.home.loggedTimeToday()}</p> + <pre class="text-xxl">{currentTime}</pre> + <p class="text-xs">{$LL.home.currentTime()}</p> + </Tile> + <Tile class="col-6@md col-12"> + <Stopwatch on:create={on_create_from_stopwatch}> + <h3 slot="header" + class="text-md">{$LL.home.stopwatch()}</h3> + </Stopwatch> + </Tile> + <Tile class="col-12"> + <h3 class="text-md padding-bottom-xxxs">{$LL.home.todayEntries()}</h3> + <div class="max-width-100% overflow-auto"> + <Table class="width-100% text-sm"> + <THead> + <TCell type="th" + class="text-left"> + <span>{$LL.home.category()}</span> + </TCell> + <TCell type="th" + class="text-left"> + <span>{$LL.home.timespan()}</span> + </TCell> + <TCell type="th" + class="text-right"> + <Button icon="{IconNames.refresh}" + variant="reset" + icon_width="1.2rem" + icon_height="1.2rem" + title="{$LL.home.refreshTodayEntries()}" + on:click={() => queryClient.invalidateQueries(QueryKeys.entries)}/> + </TCell> + </THead> + <TBody> + {#if timeEntries.length > 0} + {#each timeEntries as entry} + <TRow class="text-nowrap text-left" + data-id={entry.id}> + <TCell> + <span data-id={entry.category?.id}> + {entry.category?.name} + </span> + </TCell> + <TCell> + {entry.start.toLocaleString(undefined, {timeStyle: "short"})} + <span>-</span> + {entry.stop.toLocaleString(undefined, {timeStyle: "short"})} + </TCell> + <TCell class="flex flex-row justify-end items-center"> + <Button icon="{IconNames.pencilSquare}" + variant="reset" + icon_width="1.2rem" + icon_height="1.2rem" + on:click={(e) => on_edit_entry_button_click(e, entry.id)} + title="{$LL.home.editEntry()}"/> + <Button icon="{IconNames.trash}" + variant="reset" + icon_width="1.2rem" + icon_height="1.2rem" + on:click={(e) => on_delete_entry_button_click(e, entry.id)} + title="{$LL.home.deleteEntry()}"/> + </TCell> + </TRow> + {/each} + {:else} + <TRow class="text-nowrap"> + <TCell type="th" + thScope="row" + colspan="7"> + {isLoading ? $LL.home.loading() + "..." : $LL.home.noEntriesToday()} + </TCell> + </TRow> + {/if} + </TBody> + </Table> + </div> + </Tile> + </div> + </div> +</Layout> |
