diff --git a/index.html b/index.html index f2c5ab4..7d5b322 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,6 @@ - Work Hours Tracker diff --git a/public/favicon/initial.ico b/public/favicon/initial.ico new file mode 100644 index 0000000..d62c8f9 Binary files /dev/null and b/public/favicon/initial.ico differ diff --git a/public/favicon/on-break.ico b/public/favicon/on-break.ico new file mode 100644 index 0000000..a441db6 Binary files /dev/null and b/public/favicon/on-break.ico differ diff --git a/public/favicon/working.ico b/public/favicon/working.ico new file mode 100644 index 0000000..1e4fc16 Binary files /dev/null and b/public/favicon/working.ico differ diff --git a/src/App.svelte b/src/App.svelte index ddf613f..9da338b 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -4,6 +4,7 @@ import { type User } from "./lib/tracker"; import WorkdayForm from "./ui/WorkdayForm.svelte"; import { getDatabase } from "./lib/database"; + import Favicon from "./ui/Favicon.svelte"; let user: User | null = $state(null); @@ -30,6 +31,12 @@ } + + {#if !user} + + {/if} + +

Welcome {user ? user.settings.username : "to Work Hours Tracker"}

diff --git a/src/ui/Favicon.svelte b/src/ui/Favicon.svelte new file mode 100644 index 0000000..29cd2e0 --- /dev/null +++ b/src/ui/Favicon.svelte @@ -0,0 +1,9 @@ + + + diff --git a/src/ui/Status.svelte b/src/ui/Status.svelte new file mode 100644 index 0000000..8a74adb --- /dev/null +++ b/src/ui/Status.svelte @@ -0,0 +1,38 @@ + + +
{mapping[getStatusClass()]}
+ + diff --git a/src/ui/WorkdayEvents.svelte b/src/ui/WorkdayEvents.svelte index 18a47fd..fc14508 100644 --- a/src/ui/WorkdayEvents.svelte +++ b/src/ui/WorkdayEvents.svelte @@ -21,7 +21,7 @@ {#if type === "start-workday"} Workday Started {:else if type === "break-ongoing"} - On Break + Break started {:else if type === "break"} Break {:else if type === "end-workday"} diff --git a/src/ui/WorkdayForm.svelte b/src/ui/WorkdayForm.svelte index 24c592f..d2b18b2 100644 --- a/src/ui/WorkdayForm.svelte +++ b/src/ui/WorkdayForm.svelte @@ -2,6 +2,8 @@ import { createTracker, type User } from "../lib/tracker"; import Button from "./Button.svelte"; import ConfirmationModal from "./ConfirmationModal.svelte"; + import Favicon from "./Favicon.svelte"; + import Status from "./Status.svelte"; import WorkdayEvents from "./WorkdayEvents.svelte"; import WorkDuration from "./WorkDuration.svelte"; @@ -26,6 +28,18 @@ } + + + + + + {#if tracker.hasWorkdayStarted()} {/if} diff --git a/tests/e2e.spec.ts b/tests/e2e.spec.ts index d6d906e..dcab8bf 100644 --- a/tests/e2e.spec.ts +++ b/tests/e2e.spec.ts @@ -4,6 +4,10 @@ test("first visit, full workday", async ({ page }) => { await page.goto("/"); await expect(page).toHaveTitle("Work Hours Tracker"); + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/initial.ico", + ); await expect( page.getByRole("heading", { name: "Welcome to Work Hours Tracker" }), ).toBeVisible(); @@ -36,6 +40,18 @@ test("first visit, full workday", async ({ page }) => { page.getByRole("button", { name: "End Workday" }), ).toBeDisabled(); + await expect(page.getByText("Not working")).toBeVisible(); + await expect(page.getByText("Not working")).toHaveCSS( + "color", + "rgb(255, 0, 0)", + ); + + // Favicon updated + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/initial.ico", + ); + // Workday starts at 8:05:00 await page.clock.setFixedTime(new Date(2025, 2, 2, 8, 5, 0)); await page.getByRole("button", { name: "Start Workday" }).click(); @@ -45,6 +61,15 @@ test("first visit, full workday", async ({ page }) => { ).toBeDisabled(); await expect(page.getByRole("button", { name: "Start Break" })).toBeEnabled(); await expect(page.getByRole("button", { name: "End Workday" })).toBeEnabled(); + await expect(page.getByText("Working")).toBeVisible(); + await expect(page.getByText("Working")).toHaveCSS( + "color", + "rgb(127, 255, 0)", + ); + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/working.ico", + ); // Take a break at 8:35:00 await page.clock.setFixedTime(new Date(2025, 2, 2, 8, 35, 0)); @@ -60,6 +85,15 @@ test("first visit, full workday", async ({ page }) => { page.getByRole("button", { name: "Start Break" }), ).not.toBeVisible(); await expect(page.getByRole("button", { name: "End Break" })).toBeVisible(); + await expect(page.getByText("On break")).toBeVisible(); + await expect(page.getByText("On break")).toHaveCSS( + "color", + "rgb(255, 234, 0)", + ); + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/on-break.ico", + ); // End the break at 9:05:00 await page.clock.setFixedTime(new Date(2025, 2, 2, 9, 5, 0)); @@ -89,6 +123,10 @@ test("first visit, full workday", async ({ page }) => { page.getByRole("button", { name: "Yes, I'm done for today" }), ).toBeVisible(); await expect(page.getByRole("button", { name: "Cancel" })).toBeVisible(); + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/working.ico", + ); await page.getByRole("button", { name: "Yes, I'm done for today" }).click(); @@ -115,6 +153,15 @@ test("first visit, full workday", async ({ page }) => { await expect( page.getByRole("button", { name: "End Workday" }), ).toBeDisabled(); + await expect(page.getByText("Not working")).toBeVisible(); + await expect(page.getByText("Not working")).toHaveCSS( + "color", + "rgb(255, 0, 0)", + ); + await expect(page.getByTestId("favicon")).toHaveAttribute( + "href", + "/work-hours-tracker/favicon/initial.ico", + ); }); test("User data persists through reloads", async ({ page }) => {