From 9db0f70f75886ab1f97e231a3f9c16fcbbbe04bd Mon Sep 17 00:00:00 2001
From: ivarlovlie <git@ivarlovlie.no>
Date: Wed, 1 Jun 2022 22:20:31 +0200
Subject: refactor: Move projects-web to projects

---
 apps/projects/src/app/pages/home.svelte | 167 ++++++++++++++++++++++++++++++++
 1 file changed, 167 insertions(+)
 create mode 100644 apps/projects/src/app/pages/home.svelte

(limited to 'apps/projects/src/app/pages/home.svelte')

diff --git a/apps/projects/src/app/pages/home.svelte b/apps/projects/src/app/pages/home.svelte
new file mode 100644
index 0000000..c3e7af4
--- /dev/null
+++ b/apps/projects/src/app/pages/home.svelte
@@ -0,0 +1,167 @@
+<script lang="ts">
+    import {IconNames} from "$shared/lib/configuration";
+    import {TimeEntryDto} from "$shared/lib/models/TimeEntryDto";
+    import {Temporal} from "@js-temporal/polyfill";
+    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_string, unwrap_date_time_from_entry} from "$shared/lib/helpers";
+    import {TimeEntryQueryDuration} from "$shared/lib/models/TimeEntryQuery";
+    import entries, {delete_entry_async, get_time_entry, reload_entries} from "$app/lib/stores/entries";
+
+    let currentTime = "";
+    let isLoading = false;
+    let EditEntryForm: any;
+    let timeEntries = [] as Array<TimeEntryDto>;
+    let timeLoggedTodayString = "0h0m";
+
+    function set_current_time() {
+        currentTime = Temporal.Now.plainTimeISO().toLocaleString(undefined, {
+            timeStyle: "short",
+        });
+    }
+
+    async function on_edit_entry_button_click(event, entryId: string) {
+        const response = get_time_entry(entryId);
+        EditEntryForm.set_values(response);
+    }
+
+    async function on_delete_entry_button_click(event, entryId: string) {
+        if (confirm("Are you sure you want to delete this entry?")) {
+            await delete_entry_async(entryId);
+        }
+    }
+
+    async function load_todays_entries() {
+        await reload_entries({
+            duration: TimeEntryQueryDuration.TODAY,
+            page: 1,
+            pageSize: 100,
+        });
+    }
+
+    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);
+        await load_todays_entries();
+        entries.subscribe((val) => {
+            const newEntries = [];
+            let loggedSecondsToday = 0;
+            for (const entry of val) {
+                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 = seconds_to_hour_minute_string(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">New entry</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">Logged time today</p>
+                <pre class="text-xxl">{currentTime}</pre>
+                <p class="text-xs">Current time</p>
+            </Tile>
+            <Tile class="col-6@md col-12">
+                <Stopwatch on:create={on_create_from_stopwatch}>
+                    <h3 slot="header"
+                        class="text-md">Stopwatch</h3>
+                </Stopwatch>
+            </Tile>
+            <Tile class="col-12">
+                <h3 class="text-md padding-bottom-xxxs">Today's entries</h3>
+                <div class="max-width-100% overflow-auto">
+                    <Table class="width-100% text-sm">
+                        <THead>
+                        <TCell type="th"
+                               class="text-left">
+                            <span>Category</span>
+                        </TCell>
+                        <TCell type="th"
+                               class="text-left">
+                            <span>Timespan</span>
+                        </TCell>
+                        <TCell type="th"
+                               class="text-right">
+                            <Button icon="{IconNames.refresh}"
+                                    variant="reset"
+                                    icon_width="1.2rem"
+                                    icon_height="1.2rem"
+                                    title="Refresh today's entries"
+                                    on:click={load_todays_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="Edit entry"/>
+                                        <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="Delete entry"/>
+                                    </TCell>
+                                </TRow>
+                            {/each}
+                        {:else}
+                            <TRow class="text-nowrap">
+                                <TCell type="th"
+                                       thScope="row"
+                                       colspan="7">
+                                    {isLoading ? "Loading..." : "No entries today"}
+                                </TCell>
+                            </TRow>
+                        {/if}
+                        </TBody>
+                    </Table>
+                </div>
+            </Tile>
+        </div>
+    </div>
+</Layout>
-- 
cgit v1.3

