From 6c35570e78813ca6af1bae6a0374d7483bff9824 Mon Sep 17 00:00:00 2001 From: Elias Schneider Date: Fri, 23 May 2025 11:56:08 +0200 Subject: [PATCH] fix: add back month and year selection for date picker --- .../lib/components/form/date-picker.svelte | 29 +++-- .../components/ui/calendar/calendar.svelte | 110 ++++++++++++++---- .../admin/api-keys/api-key-dialog.svelte | 3 +- tests/specs/api-key.spec.ts | 7 +- 4 files changed, 110 insertions(+), 39 deletions(-) diff --git a/frontend/src/lib/components/form/date-picker.svelte b/frontend/src/lib/components/form/date-picker.svelte index 2e58afae..83347b33 100644 --- a/frontend/src/lib/components/form/date-picker.svelte +++ b/frontend/src/lib/components/form/date-picker.svelte @@ -68,18 +68,23 @@
- - + + {#snippet child({ props })} + + {/snippet} - import { Calendar as CalendarPrimitive } from 'bits-ui'; - import * as Calendar from './index.js'; - import { cn, type WithoutChildrenOrChild } from '$lib/utils/style.js'; + import * as Calendar from '$lib/components/ui/calendar/index.js'; + import * as Select from '$lib/components/ui/select/index.js'; + import { cn } from '$lib/utils/style'; + import { CalendarDate, DateFormatter, getLocalTimeZone, today } from '@internationalized/date'; + import { Calendar as CalendarPrimitive, type WithoutChildrenOrChild } from 'bits-ui'; let { - ref = $bindable(null), value = $bindable(), - placeholder = $bindable(), - class: className, - weekdayFormat = 'short', - ...restProps - }: WithoutChildrenOrChild = $props(); + placeholder = $bindable() + }: WithoutChildrenOrChild & { + value: CalendarDate | undefined; + } = $props(); + + const currentDate = today(getLocalTimeZone()); + + const monthFmt = new DateFormatter('en-US', { + month: 'long' + }); + + const monthOptions = Array.from({ length: 12 }, (_, i) => { + const month = currentDate.set({ month: i + 1 }); + return { + value: month.month, + label: monthFmt.format(month.toDate(getLocalTimeZone())) + }; + }); + + const yearOptions = Array.from({ length: 100 }, (_, i) => ({ + label: String(new Date().getFullYear() + i), + value: new Date().getFullYear() + i + })); + + const defaultYear = $derived( + placeholder ? { value: placeholder.year, label: String(placeholder.year) } : undefined + ); + + const defaultMonth = $derived( + placeholder + ? { + value: placeholder.month, + label: monthFmt.format(placeholder.toDate(getLocalTimeZone())) + } + : undefined + ); + + const monthLabel = $derived( + monthOptions.find((m) => m.value === defaultMonth?.value)?.label ?? 'Select a month' + ); - {#snippet children({ months, weekdays })} - - - - + + { + if (!placeholder) return; + if (v === `${placeholder.month}`) return; + placeholder = placeholder.set({ month: Number.parseInt(v) }); + }} + > + + {monthLabel} + + + {#each monthOptions as { value, label } (value)} + + {/each} + + + { + if (!v || !placeholder) return; + if (v === `${placeholder?.year}`) return; + placeholder = placeholder.set({ year: Number.parseInt(v) }); + }} + > + + {defaultYear?.label ?? 'Select year'} + + + {#each yearOptions as { value, label } (value)} + + {/each} + + {#each months as month (month)} @@ -47,7 +111,7 @@ get along, so we shut typescript up by casting `value` to `never`. {#each month.weeks as weekDates (weekDates)} {#each weekDates as date (date)} - + {/each} diff --git a/frontend/src/routes/settings/admin/api-keys/api-key-dialog.svelte b/frontend/src/routes/settings/admin/api-keys/api-key-dialog.svelte index 0ff54043..fd0715f7 100644 --- a/frontend/src/routes/settings/admin/api-keys/api-key-dialog.svelte +++ b/frontend/src/routes/settings/admin/api-keys/api-key-dialog.svelte @@ -19,7 +19,7 @@ - + e.preventDefault()}> {m.api_key_created()} @@ -30,7 +30,6 @@
{m.name()}

{apiKeyResponse.apiKey.name}

- {#if apiKeyResponse.apiKey.description}
{m.description()}

{apiKeyResponse.apiKey.description}

diff --git a/tests/specs/api-key.spec.ts b/tests/specs/api-key.spec.ts index 11762a14..8c8e8b10 100644 --- a/tests/specs/api-key.spec.ts +++ b/tests/specs/api-key.spec.ts @@ -19,7 +19,7 @@ test.describe("API Key Management", () => { // Choose the date const currentDate = new Date(); - await page.getByLabel("Expires At").click(); + await page.getByRole("button", { name: "Select a date" }).click(); await page.getByLabel("Select year").click(); // Select the next year await page.getByText((currentDate.getFullYear() + 1).toString()).click(); @@ -45,7 +45,10 @@ test.describe("API Key Management", () => { expect(token?.length).toBe(32); // Close the dialog - await page.getByRole("button", { name: "Close" }).click(); + await page + .getByRole("button", { name: "Close", exact: true }) + .nth(1) + .click(); await page.reload();