aboutsummaryrefslogtreecommitdiffstats
path: root/old-apps/projects/src/app/pages/home.svelte
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-09-20 09:24:27 +0200
committerivarlovlie <git@ivarlovlie.no>2022-09-20 09:24:27 +0200
commita9072370ca1eb9a5cce928b1d487db0f307edea6 (patch)
tree59c3c23df930a8b5f888dc7813923abf4ceefed4 /old-apps/projects/src/app/pages/home.svelte
parent56fa963a1d63cbe0bf28e29e717cceaa417c45c1 (diff)
downloadgreatoffice-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.svelte178
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>