From df7c39b16ab4720f48103f5d4fae43116685acfd Mon Sep 17 00:00:00 2001 From: Florian <45694132+flo-bit@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:55:04 +0100 Subject: [PATCH 1/2] refactor --- .../[[actor=actor]]/events/+page.svelte | 14 +- .../events/[rkey]/+page.svelte | 2 +- .../events/[rkey]/edit/+page.server.ts | 10 +- .../events/[rkey]/edit/+page.svelte | 203 ++-- .../[[actor=actor]]/events/new/+page.svelte | 967 ------------------ 5 files changed, 146 insertions(+), 1050 deletions(-) delete mode 100644 src/routes/[[actor=actor]]/events/new/+page.svelte diff --git a/src/routes/[[actor=actor]]/events/+page.svelte b/src/routes/[[actor=actor]]/events/+page.svelte index 07b8c28c..d69df228 100644 --- a/src/routes/[[actor=actor]]/events/+page.svelte +++ b/src/routes/[[actor=actor]]/events/+page.svelte @@ -4,6 +4,8 @@ import { user } from '$lib/atproto/auth.svelte'; import { Avatar as FoxAvatar, Badge, Button } from '@foxui/core'; import Avatar from 'svelte-boring-avatars'; + import * as TID from '@atcute/tid'; + import { goto } from '$app/navigation'; let { data } = $props(); @@ -110,7 +112,17 @@ {#if isOwner} - + {/if} diff --git a/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte b/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte index 89da235b..ddc9d0cc 100644 --- a/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte +++ b/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte @@ -251,7 +251,7 @@ {eventData.name} {#if isOwner} - + {/if} diff --git a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts index 463a15e7..83344078 100644 --- a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts +++ b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts @@ -22,7 +22,7 @@ export async function load({ params, platform, request }) { did: did as Did, collection: 'community.lexicon.calendar.event', rkey - }), + }).catch(() => null), cache ? cache.getProfile(did as Did).catch(() => null) : getBlentoOrBskyProfile({ did: did as Did }) @@ -40,7 +40,13 @@ export async function load({ params, platform, request }) { ]); if (!eventRecord?.value) { - throw error(404, 'Event not found'); + return { + eventData: null, + did, + rkey, + hostProfile: hostProfile ?? null, + eventCid: null + }; } const eventData: EventData = eventRecord.value as EventData; diff --git a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte index 1095c581..a475591e 100644 --- a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte +++ b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte @@ -12,10 +12,12 @@ import { browser } from '$app/environment'; import { putImage, getImage, deleteImage } from '$lib/components/image-store'; import Modal from '$lib/components/modal/Modal.svelte'; + import Avatar from 'svelte-boring-avatars'; let { data } = $props(); let rkey: string = $derived(data.rkey); + let isNew = $derived(data.eventData === null); let DRAFT_KEY = $derived(`blento-event-edit-${rkey}`); type EventMode = 'inperson' | 'virtual' | 'hybrid'; @@ -81,16 +83,9 @@ return 'inperson'; } - function populateFromEventData() { + function populateLocationFromEventData() { const eventData = data.eventData; - name = eventData.name || ''; - description = eventData.description || ''; - startsAt = eventData.startsAt ? isoToDatetimeLocal(eventData.startsAt) : ''; - endsAt = eventData.endsAt ? isoToDatetimeLocal(eventData.endsAt) : ''; - mode = eventData.mode ? stripModePrefix(eventData.mode) : 'inperson'; - links = eventData.uris ? eventData.uris.map((l) => ({ uri: l.uri, name: l.name || '' })) : []; - - // Load existing location + if (!eventData) return; if (eventData.locations && eventData.locations.length > 0) { const loc = eventData.locations.find((v) => v.$type === 'community.lexicon.location.address'); if (loc) { @@ -109,8 +104,11 @@ } } locationChanged = false; + } - // Load existing thumbnail from CDN + function populateThumbnailFromEventData() { + const eventData = data.eventData; + if (!eventData) return; if (eventData.media && eventData.media.length > 0) { const media = eventData.media.find((m) => m.role === 'thumbnail'); if (media?.content) { @@ -123,7 +121,29 @@ } } + function populateFromEventData() { + const eventData = data.eventData; + if (!eventData) return; + name = eventData.name || ''; + description = eventData.description || ''; + startsAt = eventData.startsAt ? isoToDatetimeLocal(eventData.startsAt) : ''; + endsAt = eventData.endsAt ? isoToDatetimeLocal(eventData.endsAt) : ''; + mode = eventData.mode ? stripModePrefix(eventData.mode) : 'inperson'; + links = eventData.uris ? eventData.uris.map((l) => ({ uri: l.uri, name: l.name || '' })) : []; + populateLocationFromEventData(); + populateThumbnailFromEventData(); + } + onMount(async () => { + // Migrate old creation draft if this is a new event + if (isNew) { + const oldDraft = localStorage.getItem('blento-event-draft'); + if (oldDraft && !localStorage.getItem(DRAFT_KEY)) { + localStorage.setItem(DRAFT_KEY, oldDraft); + localStorage.removeItem('blento-event-draft'); + } + } + const saved = localStorage.getItem(DRAFT_KEY); if (saved) { try { @@ -137,6 +157,9 @@ locationChanged = draft.locationChanged || false; if (draft.locationChanged) { location = draft.location || null; + } else if (!isNew) { + // For edits without location changes, load from event data + populateLocationFromEventData(); } thumbnailChanged = draft.thumbnailChanged || false; @@ -148,29 +171,17 @@ thumbnailPreview = URL.createObjectURL(img.blob); thumbnailChanged = true; } - } else if (!thumbnailChanged) { + } else if (!thumbnailChanged && !isNew) { // No new thumbnail in draft, show existing one from event data - if (data.eventData.media && data.eventData.media.length > 0) { - const media = data.eventData.media.find((m) => m.role === 'thumbnail'); - if (media?.content) { - const url = getCDNImageBlobUrl({ - did: data.did, - blob: media.content, - type: 'jpeg' - }); - if (url) { - thumbnailPreview = url; - } - } - } + populateThumbnailFromEventData(); } hasDraft = true; } catch { localStorage.removeItem(DRAFT_KEY); - populateFromEventData(); + if (!isNew) populateFromEventData(); } - } else { + } else if (!isNew) { populateFromEventData(); } draftLoaded = true; @@ -218,7 +229,20 @@ if (thumbnailKey) deleteImage(thumbnailKey); thumbnailKey = null; thumbnailChanged = false; - populateFromEventData(); + if (isNew) { + name = ''; + description = ''; + startsAt = ''; + endsAt = ''; + links = []; + mode = 'inperson'; + location = null; + thumbnailFile = null; + if (thumbnailPreview) URL.revokeObjectURL(thumbnailPreview); + thumbnailPreview = null; + } else { + populateFromEventData(); + } hasDraft = false; } @@ -447,7 +471,7 @@ try { let media: Array> | undefined; - if (thumbnailChanged) { + if (isNew || thumbnailChanged) { if (thumbnailFile) { const compressed = await compressImage(thumbnailFile); const blobRef = await uploadBlob({ blob: compressed.blob }); @@ -464,17 +488,18 @@ ]; } } - // If thumbnailChanged but no thumbnailFile, media stays undefined (thumbnail removed) + // If changed/new but no thumbnailFile, media stays undefined (thumbnail removed/absent) } else { // Thumbnail not changed — reuse original media from eventData - if (data.eventData.media && data.eventData.media.length > 0) { + if (data.eventData?.media && data.eventData.media.length > 0) { media = data.eventData.media as Array>; } } - // Preserve original createdAt - const originalCreatedAt = - (data.eventData as Record).createdAt || new Date().toISOString(); + const createdAt = isNew + ? new Date().toISOString() + : ((data.eventData as Record)?.createdAt as string) || + new Date().toISOString(); const record: Record = { $type: 'community.lexicon.calendar.event', @@ -482,7 +507,7 @@ mode: `community.lexicon.calendar.event#${mode}`, status: 'community.lexicon.calendar.event#scheduled', startsAt: new Date(startsAt).toISOString(), - createdAt: originalCreatedAt + createdAt }; const trimmedDescription = description.trim(); @@ -503,7 +528,7 @@ if (links.length > 0) { record.uris = links; } - if (locationChanged) { + if (isNew || locationChanged) { if (location) { record.locations = [ { @@ -512,8 +537,8 @@ } ]; } - // If locationChanged but no location, locations stays undefined (removed) - } else if (data.eventData.locations && data.eventData.locations.length > 0) { + // If changed/new but no location, locations stays undefined (removed/absent) + } else if (data.eventData?.locations && data.eventData.locations.length > 0) { record.locations = data.eventData.locations; } @@ -532,11 +557,11 @@ : user.did; goto(`/${handle}/events/${rkey}`); } else { - error = 'Failed to save event. Please try again.'; + error = `Failed to ${isNew ? 'create' : 'save'} event. Please try again.`; } } catch (e) { - console.error('Failed to save event:', e); - error = 'Failed to save event. Please try again.'; + console.error(`Failed to ${isNew ? 'create' : 'save'} event:`, e); + error = `Failed to ${isNew ? 'create' : 'save'} event. Please try again.`; } finally { submitting = false; } @@ -544,7 +569,7 @@ - Edit Event + {isNew ? 'Create Event' : 'Edit Event'}
@@ -558,19 +583,21 @@
-

Log in to edit this event.

+

+ Log in to {isNew ? 'create an event' : 'edit this event'}. +

{:else}
- Local edit + {isNew ? 'Local draft' : 'Local edit'} {#if hasDraft} {/if}
@@ -600,39 +627,32 @@ onchange={onFileChange} class="hidden" /> - {#if thumbnailPreview} -
- - -
- {:else} + +
+ {/if} + - {/if} + {#if thumbnailPreview} + + {/if} + @@ -662,7 +701,7 @@ bind:value={name} required placeholder="Event name" - class="text-base-900 dark:text-base-50 placeholder:text-base-300 dark:placeholder:text-base-700 mb-2 w-full border-0 bg-transparent text-4xl leading-tight font-bold focus:border-0 focus:ring-0 focus:outline-none sm:text-5xl" + class="text-base-900 dark:text-base-50 placeholder:text-base-500 dark:placeholder:text-base-500 mb-2 w-full border-0 bg-transparent text-4xl leading-tight font-bold focus:border-0 focus:ring-0 focus:outline-none sm:text-5xl" /> @@ -844,7 +883,7 @@ bind:value={description} rows={4} placeholder="What's this event about? @mentions, #hashtags and links will be detected automatically." - class="text-base-700 dark:text-base-300 placeholder:text-base-300 dark:placeholder:text-base-700 w-full resize-none border-0 bg-transparent leading-relaxed focus:border-0 focus:ring-0 focus:outline-none" + class="text-base-700 dark:text-base-300 placeholder:text-base-500 dark:placeholder:text-base-500 w-full resize-none border-0 bg-transparent leading-relaxed focus:border-0 focus:ring-0 focus:outline-none" > @@ -853,7 +892,13 @@ {/if} diff --git a/src/routes/[[actor=actor]]/events/new/+page.svelte b/src/routes/[[actor=actor]]/events/new/+page.svelte deleted file mode 100644 index 0c248cdd..00000000 --- a/src/routes/[[actor=actor]]/events/new/+page.svelte +++ /dev/null @@ -1,967 +0,0 @@ - - - - Create Event - - -
-
- {#if user.isInitializing} -
-
-
-
- {:else if !user.isLoggedIn} -
-

Log in to create an event.

- -
- {:else} -
- Local draft - {#if hasDraft} - - {/if} -
- -
{ - e.preventDefault(); - handleSubmit(); - }} - > - -
- - -
- - {#if thumbnailPreview} -
- - -
- {:else} - - {/if} -
- - -
- - - - -
- { - return mode; - }, - (val) => { - if (val) mode = val; - } - } - class="w-fit" - > - In Person - Virtual - Hybrid - -
- - -
-
- {#if startDate} - - {formatMonth(startDate)} - - - {formatDay(startDate)} - - {:else} - - - - {/if} -
-
- {#if startDate} -

- {formatWeekday(startDate)}, {formatFullDate(startDate)} - {#if endDate && !isSameDay} - - {formatWeekday(endDate)}, {formatFullDate(endDate)} - {/if} -

-

- {formatTime(startDate)} - {#if endDate && isSameDay} - - {formatTime(endDate)} - {/if} -

- {/if} -
- - -
-
-
- - - {#if location} -
-
- - - - -
-

- {getLocationDisplayString(location)} -

- -
- {:else} - - {/if} - - -
-

- About -

- -
- - {#if error} -

{error}

- {/if} - - -
- - -
-

- Hosted By -

-
- - - {hostName} - -
-
- - -
-

- Links -

-
- {#each links as link, i (i)} -
- - - - - {link.name || link.uri.replace(/^https?:\/\//, '')} - - -
- {/each} -
- -
- - - {#if showLinkPopup} -
- - -
- - -
-
- {/if} -
-
-
-
- {/if} -
-
- - - -

Add location

-
{ - e.preventDefault(); - searchLocation(); - }} - class="mt-2" - > -
- - -
-
- - {#if locationError} -

{locationError}

- {/if} - - {#if locationResult} -
-
- - - - -
-

- {getLocationDisplayString(locationResult.location)} -

-

- {locationResult.displayName} -

-
-
-
- -
-
- {/if} - -

- Geocoding by Nominatim - / © - OpenStreetMap contributors -

-
From 6bf9d2b4a22b2e876ffcc5e5ca4c5338c5006aec Mon Sep 17 00:00:00 2001 From: Florian <45694132+flo-bit@users.noreply.github.com> Date: Sun, 22 Feb 2026 04:20:49 +0100 Subject: [PATCH 2/2] add datetimepicker, lots of other small improvements --- .claude/settings.local.json | 66 +-- package.json | 1 + pnpm-lock.yaml | 21 +- src/lib/components/DatePicker.svelte | 244 +++++++++ src/lib/components/DateTimePicker.svelte | 73 +++ src/lib/components/TimePicker.svelte | 101 ++++ .../events/[rkey]/edit/+page.svelte | 487 ++++++++++++------ 7 files changed, 787 insertions(+), 206 deletions(-) create mode 100644 src/lib/components/DatePicker.svelte create mode 100644 src/lib/components/DateTimePicker.svelte create mode 100644 src/lib/components/TimePicker.svelte diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 003711fc..a2b5d10d 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,34 +1,36 @@ { - "permissions": { - "allow": [ - "Bash(pnpm check:*)", - "mcp__ide__getDiagnostics", - "mcp__plugin_svelte_svelte__svelte-autofixer", - "mcp__plugin_svelte_svelte__list-sections", - "Bash(pkill:*)", - "Bash(timeout 8 pnpm dev:*)", - "Bash(git checkout:*)", - "Bash(npx svelte-kit:*)", - "Bash(ls:*)", - "Bash(pnpm format:*)", - "Bash(pnpm add:*)", - "WebSearch", - "WebFetch(domain:github.com)", - "WebFetch(domain:flipclockjs.com)", - "WebFetch(domain:codepen.io)", - "WebFetch(domain:flo-bit.dev)", - "Bash(pnpm install)", - "Bash(pnpm install:*)", - "Bash(pnpm config:*)", - "Bash(lsof:*)", - "Bash(pnpm dev)", - "Bash(pnpm exec svelte-kit:*)", - "Bash(pnpm build:*)", - "Bash(pnpm remove:*)", - "Bash(grep:*)", - "Bash(find:*)", - "Bash(npx prettier:*)", - "Bash(node -e:*)" - ] - } + "permissions": { + "allow": [ + "Bash(pnpm check:*)", + "mcp__ide__getDiagnostics", + "mcp__plugin_svelte_svelte__svelte-autofixer", + "mcp__plugin_svelte_svelte__list-sections", + "Bash(pkill:*)", + "Bash(timeout 8 pnpm dev:*)", + "Bash(git checkout:*)", + "Bash(npx svelte-kit:*)", + "Bash(ls:*)", + "Bash(pnpm format:*)", + "Bash(pnpm add:*)", + "WebSearch", + "WebFetch(domain:github.com)", + "WebFetch(domain:flipclockjs.com)", + "WebFetch(domain:codepen.io)", + "WebFetch(domain:flo-bit.dev)", + "Bash(pnpm install)", + "Bash(pnpm install:*)", + "Bash(pnpm config:*)", + "Bash(lsof:*)", + "Bash(pnpm dev)", + "Bash(pnpm exec svelte-kit:*)", + "Bash(pnpm build:*)", + "Bash(pnpm remove:*)", + "Bash(grep:*)", + "Bash(find:*)", + "Bash(npx prettier:*)", + "Bash(node -e:*)", + "mcp__plugin_svelte_svelte__get-documentation", + "WebFetch(domain:bits-ui.com)" + ] + } } diff --git a/package.json b/package.json index d889dbef..71c40663 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@foxui/social": "^0.4.7", "@foxui/time": "^0.4.7", "@foxui/visual": "^0.4.7", + "@internationalized/date": "^3.11.0", "@number-flow/svelte": "^0.3.10", "@tailwindcss/typography": "^0.5.19", "@threlte/core": "^8.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 320fabac..a1ad7dba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: '@foxui/visual': specifier: ^0.4.7 version: 0.4.7(svelte@5.48.0)(tailwindcss@4.1.18) + '@internationalized/date': + specifier: ^3.11.0 + version: 3.11.0 '@number-flow/svelte': specifier: ^0.3.10 version: 0.3.10(svelte@5.48.0) @@ -124,7 +127,7 @@ importers: version: 0.176.0 bits-ui: specifier: ^2.15.4 - version: 2.15.4(@internationalized/date@3.10.1)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0) + version: 2.15.4(@internationalized/date@3.11.0)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -964,8 +967,8 @@ packages: cpu: [x64] os: [win32] - '@internationalized/date@3.10.1': - resolution: {integrity: sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==} + '@internationalized/date@3.11.0': + resolution: {integrity: sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q==, tarball: https://registry.npmjs.org/@internationalized/date/-/date-3.11.0.tgz} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -1233,7 +1236,7 @@ packages: vite: ^6.3.0 || ^7.0.0 '@swc/helpers@0.5.18': - resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==, tarball: https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz} '@tailwindcss/forms@0.5.11': resolution: {integrity: sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==} @@ -3043,7 +3046,7 @@ packages: typescript: '>=4.8.4' tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, tarball: https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz} turndown@7.2.2: resolution: {integrity: sha512-1F7db8BiExOKxjSMU2b7if62D/XOyQyZbPKq/nUwopfgnHlqXHqQ0lvfUTeUIr1lZJzOPFn43dODyMSIfvWRKQ==} @@ -3811,7 +3814,7 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@internationalized/date@3.10.1': + '@internationalized/date@3.11.0': dependencies: '@swc/helpers': 0.5.18 @@ -4587,7 +4590,7 @@ snapshots: dependencies: '@floating-ui/core': 1.7.3 '@floating-ui/dom': 1.7.5 - '@internationalized/date': 3.10.1 + '@internationalized/date': 3.11.0 css.escape: 1.5.1 esm-env: 1.2.2 runed: 0.23.4(svelte@5.48.0) @@ -4595,11 +4598,11 @@ snapshots: svelte-toolbelt: 0.7.1(svelte@5.48.0) tabbable: 6.4.0 - bits-ui@2.15.4(@internationalized/date@3.10.1)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0): + bits-ui@2.15.4(@internationalized/date@3.11.0)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0): dependencies: '@floating-ui/core': 1.7.3 '@floating-ui/dom': 1.7.5 - '@internationalized/date': 3.10.1 + '@internationalized/date': 3.11.0 esm-env: 1.2.2 runed: 0.35.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0) svelte: 5.48.0 diff --git a/src/lib/components/DatePicker.svelte b/src/lib/components/DatePicker.svelte new file mode 100644 index 00000000..b3a03326 --- /dev/null +++ b/src/lib/components/DatePicker.svelte @@ -0,0 +1,244 @@ + + + +
+ + {#snippet children({ segments })} + {#each segments as segment, i (segment.part + i)} + {#if segment.part === 'literal'} + {segment.value} + {:else} + + {segment.value} + + {/if} + {/each} + {/snippet} + + + + + + + +
+ + + + {#snippet children({ months, weekdays })} + + + + + + + +
+ + +
+ + + + + + +
+ + {#each months as month (month.value.month)} + + + + {#each weekdays as weekday, i (i)} + + {weekday} + + {/each} + + + + + {#each month.weeks as week, weekIndex (weekIndex)} + + {#each week as day (day.toString())} + + + {#snippet children({ selected, disabled, day: dayText })} +
+ {dayText} + {#if day.day === todayDay && day.month === todayMonth && day.year === todayYear} + + {/if} +
+ {/snippet} +
+
+ {/each} +
+ {/each} +
+
+ {/each} + {/snippet} +
+
+
diff --git a/src/lib/components/DateTimePicker.svelte b/src/lib/components/DateTimePicker.svelte new file mode 100644 index 00000000..df75172b --- /dev/null +++ b/src/lib/components/DateTimePicker.svelte @@ -0,0 +1,73 @@ + + +
+ +
+ +
+
diff --git a/src/lib/components/TimePicker.svelte b/src/lib/components/TimePicker.svelte new file mode 100644 index 00000000..e9b565fa --- /dev/null +++ b/src/lib/components/TimePicker.svelte @@ -0,0 +1,101 @@ + + + +
+ + {#snippet children({ segments })} + {#each segments as segment, i (segment.part + i)} + {#if segment.part === 'literal'} + {segment.value} + {:else} + + {segment.value} + + {/if} + {/each} + {/snippet} + + + + + +
+
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte index a475591e..b3a0212d 100644 --- a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte +++ b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte @@ -1,10 +1,20 @@ @@ -589,19 +624,6 @@ {:else} -
- {isNew ? 'Local draft' : 'Local edit'} - {#if hasDraft} - - {/if} -
-
{ e.preventDefault(); @@ -672,37 +694,49 @@ Upload thumbnail {#if thumbnailPreview} - + {/if}
- - + +
+ + +
@@ -725,9 +759,9 @@
-
+
{#if startDate}
- {#if startDate} -

- {formatWeekday(startDate)}, {formatFullDate(startDate)} - {#if endDate && !isSameDay} - - {formatWeekday(endDate)}, {formatFullDate(endDate)} + {#if startDate && !editingDates} + +

+ + +
+ {:else} + +
+
+ {#if endsAt} + Start + {/if} + +
+ {#if endsAt} +
+ End + + +
+ {:else} + {/if} -

-

- {formatTime(startDate)} - {#if endDate && isSameDay} - - {formatTime(endDate)} + {#if startDate} + {/if} -

+
{/if} -
- - -
@@ -796,7 +918,7 @@ {#if location}
{getLocationDisplayString(location)}

-
{:else} -
- Add location - + Add location + +
{/if} @@ -883,7 +994,8 @@ bind:value={description} rows={4} placeholder="What's this event about? @mentions, #hashtags and links will be detected automatically." - class="text-base-700 dark:text-base-300 placeholder:text-base-500 dark:placeholder:text-base-500 w-full resize-none border-0 bg-transparent leading-relaxed focus:border-0 focus:ring-0 focus:outline-none" + class="text-base-700 dark:text-base-300 placeholder:text-base-500 dark:placeholder:text-base-500 w-full resize-none border-0 bg-transparent px-0 leading-relaxed focus:border-0 focus:ring-0 focus:outline-none" + style="field-sizing: content;" >
@@ -891,7 +1003,7 @@

{error}

{/if} - +
{/each} -
- +
+ + + - + +
-
- {/if} + + + + {#if !isNew} +
+ {#if showDeleteConfirm} +
+

+ Are you sure? This cannot be undone. +

+ + +
+ {:else} + + {/if} +
+ {/if}
{/if} @@ -1038,12 +1200,7 @@ class="mt-2" >
- +