From 709e781ecd8c0608fa4d84b85e730cc30956565e Mon Sep 17 00:00:00 2001 From: Till JS Date: Wed, 1 Apr 2026 21:38:33 +0200 Subject: [PATCH] feat(manacore): add DnD tag support to calendar and contacts modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calendar: - Add tagIds field to LocalEvent and CalendarEvent types - Add updateTagIds() to eventsStore - Add dropTarget on agenda view events, tag badge display - Register tagDropHandler for passive event→tag drops Contacts: - Add tagIds field to LocalContact and Contact types (alongside existing tags) - Add updateTagIds() to contactsStore - Add dropTarget on contact list items, tag badge display - Register tagDropHandler for passive contact→tag drops Both modules now support: - Drag tag from TagStrip onto item (Layer 1: pointer events) - Drag item onto tag in TagStrip (Layer 2: passive overlay) - Tag badges shown inline on items Co-Authored-By: Claude Opus 4.6 (1M context) --- .../web/src/lib/modules/calendar/queries.ts | 1 + .../modules/calendar/stores/events.svelte.ts | 11 +++ .../web/src/lib/modules/calendar/types.ts | 2 + .../web/src/lib/modules/contacts/queries.ts | 1 + .../contacts/stores/contacts.svelte.ts | 7 ++ .../web/src/lib/modules/contacts/types.ts | 2 + .../src/routes/(app)/calendar/+page.svelte | 93 ++++++++++++++++++- .../src/routes/(app)/contacts/+page.svelte | 92 +++++++++++++++++- 8 files changed, 206 insertions(+), 3 deletions(-) diff --git a/apps/manacore/apps/web/src/lib/modules/calendar/queries.ts b/apps/manacore/apps/web/src/lib/modules/calendar/queries.ts index 1de2beb43..696bd2a9f 100644 --- a/apps/manacore/apps/web/src/lib/modules/calendar/queries.ts +++ b/apps/manacore/apps/web/src/lib/modules/calendar/queries.ts @@ -41,6 +41,7 @@ export function toCalendarEvent(local: LocalEvent): CalendarEvent { recurrenceRule: local.recurrenceRule ?? null, parentEventId: null, color: local.color ?? null, + tagIds: local.tagIds ?? [], createdAt: local.createdAt ?? new Date().toISOString(), updatedAt: local.updatedAt ?? new Date().toISOString(), }; diff --git a/apps/manacore/apps/web/src/lib/modules/calendar/stores/events.svelte.ts b/apps/manacore/apps/web/src/lib/modules/calendar/stores/events.svelte.ts index 27fc14f89..e7936bfc1 100644 --- a/apps/manacore/apps/web/src/lib/modules/calendar/stores/events.svelte.ts +++ b/apps/manacore/apps/web/src/lib/modules/calendar/stores/events.svelte.ts @@ -122,6 +122,16 @@ export const eventsStore = { } }, + /** + * Update tag IDs on an event (merge-safe). + */ + async updateTagIds(id: string, tagIds: string[]) { + await db.table('events').update(id, { + tagIds, + updatedAt: new Date().toISOString(), + }); + }, + // ========== Draft Event Methods ========== createDraftEvent(data: Partial) { @@ -138,6 +148,7 @@ export const eventsStore = { recurrenceRule: null, parentEventId: null, color: data.color || null, + tagIds: data.tagIds || [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; diff --git a/apps/manacore/apps/web/src/lib/modules/calendar/types.ts b/apps/manacore/apps/web/src/lib/modules/calendar/types.ts index 94e722c25..13c998d34 100644 --- a/apps/manacore/apps/web/src/lib/modules/calendar/types.ts +++ b/apps/manacore/apps/web/src/lib/modules/calendar/types.ts @@ -23,6 +23,7 @@ export interface LocalEvent extends BaseRecord { recurrenceRule?: string | null; color?: string | null; reminders?: unknown | null; + tagIds?: string[]; } export type CalendarViewType = 'week' | 'month' | 'agenda'; @@ -40,6 +41,7 @@ export interface CalendarEvent { recurrenceRule: string | null; parentEventId: string | null; color: string | null; + tagIds: string[]; createdAt: string; updatedAt: string; } diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/queries.ts b/apps/manacore/apps/web/src/lib/modules/contacts/queries.ts index cd7ca5d85..c1b5c3922 100644 --- a/apps/manacore/apps/web/src/lib/modules/contacts/queries.ts +++ b/apps/manacore/apps/web/src/lib/modules/contacts/queries.ts @@ -27,6 +27,7 @@ export function toContact(local: LocalContact): Contact { photoUrl: local.photoUrl || null, birthday: local.birthday || null, tags: (local.tags || []).map((name, i) => ({ id: `tag-${i}`, name, color: null })), + tagIds: local.tagIds ?? [], isFavorite: local.isFavorite ?? false, isArchived: local.isArchived ?? false, createdAt: local.createdAt ?? new Date().toISOString(), diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/stores/contacts.svelte.ts b/apps/manacore/apps/web/src/lib/modules/contacts/stores/contacts.svelte.ts index 779c0220a..270d37901 100644 --- a/apps/manacore/apps/web/src/lib/modules/contacts/stores/contacts.svelte.ts +++ b/apps/manacore/apps/web/src/lib/modules/contacts/stores/contacts.svelte.ts @@ -69,6 +69,13 @@ export const contactsStore = { }); }, + async updateTagIds(id: string, tagIds: string[]) { + await contactTable.update(id, { + tagIds, + updatedAt: new Date().toISOString(), + }); + }, + async toggleArchive(id: string) { const local = await contactTable.get(id); if (!local) return; diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/types.ts b/apps/manacore/apps/web/src/lib/modules/contacts/types.ts index d9d4ceba1..b882fcc0a 100644 --- a/apps/manacore/apps/web/src/lib/modules/contacts/types.ts +++ b/apps/manacore/apps/web/src/lib/modules/contacts/types.ts @@ -16,6 +16,7 @@ export interface LocalContact extends BaseRecord { photoUrl?: string; birthday?: string; tags?: string[]; + tagIds?: string[]; isFavorite?: boolean; isArchived?: boolean; } @@ -36,6 +37,7 @@ export interface Contact { photoUrl?: string | null; birthday?: string | null; tags: Array<{ id: string; name: string; color: string | null }>; + tagIds: string[]; isFavorite: boolean; isArchived: boolean; createdAt: string; diff --git a/apps/manacore/apps/web/src/routes/(app)/calendar/+page.svelte b/apps/manacore/apps/web/src/routes/(app)/calendar/+page.svelte index c4f001eac..3a7b4c54b 100644 --- a/apps/manacore/apps/web/src/routes/(app)/calendar/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/calendar/+page.svelte @@ -1,5 +1,8 @@