diff --git a/apps/manacore/apps/web/src/lib/modules/calendar/views/DetailView.svelte b/apps/manacore/apps/web/src/lib/modules/calendar/views/DetailView.svelte index 5b434d539..27a208db2 100644 --- a/apps/manacore/apps/web/src/lib/modules/calendar/views/DetailView.svelte +++ b/apps/manacore/apps/web/src/lib/modules/calendar/views/DetailView.svelte @@ -6,9 +6,10 @@ import { liveQuery } from 'dexie'; import { db } from '$lib/data/database'; import { eventsStore } from '../stores/events.svelte'; - import { Trash, MapPin, Clock } from '@manacore/shared-icons'; + import { Trash, MapPin, Clock, X } from '@manacore/shared-icons'; import type { ViewProps } from '$lib/components/workbench/nav-stack'; import type { LocalEvent } from '../types'; + import { useAllTags, getTagsByIds } from '$lib/stores/tags.svelte'; let { navigate, goBack, params }: ViewProps = $props(); let eventId = $derived(params.eventId as string); @@ -26,6 +27,18 @@ let focused = $state(false); + const tagsQuery = useAllTags(); + let allTags = $derived(tagsQuery.value ?? []); + let eventTags = $derived(getTagsByIds(allTags, event?.tagIds ?? [])); + + async function removeTag(tagId: string) { + const current = event?.tagIds ?? []; + await eventsStore.updateTagIds( + eventId, + current.filter((id) => id !== tagId) + ); + } + $effect(() => { eventId; // track confirmDelete = false; @@ -145,6 +158,26 @@ {/if} + + {#if eventTags.length > 0} +
+ Tags +
+ {#each eventTags as tag (tag.id)} + + {/each} +
+
+ {/if} +
Beschreibung @@ -298,6 +331,42 @@ flex-direction: column; gap: 0.375rem; } + .tags-list { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + } + .tag-pill { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.125rem 0.5rem; + border-radius: 9999px; + border: none; + background: color-mix(in srgb, var(--tag-color) 12%, transparent); + font-size: 0.6875rem; + color: #6b7280; + cursor: pointer; + transition: all 0.15s; + } + .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 20%, transparent); + color: #ef4444; + } + :global(.dark) .tag-pill { + background: color-mix(in srgb, var(--tag-color) 18%, transparent); + color: #9ca3af; + } + :global(.dark) .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 28%, transparent); + color: #ef4444; + } + .tag-dot { + width: 6px; + height: 6px; + border-radius: 9999px; + flex-shrink: 0; + } .section-label { font-size: 0.6875rem; font-weight: 600; diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/views/DetailView.svelte b/apps/manacore/apps/web/src/lib/modules/contacts/views/DetailView.svelte index 24a135f6f..fcb09da32 100644 --- a/apps/manacore/apps/web/src/lib/modules/contacts/views/DetailView.svelte +++ b/apps/manacore/apps/web/src/lib/modules/contacts/views/DetailView.svelte @@ -14,9 +14,11 @@ MapPin, Briefcase, Globe, + X, } from '@manacore/shared-icons'; import type { ViewProps } from '$lib/components/workbench/nav-stack'; import type { LocalContact } from '../types'; + import { useAllTags, getTagsByIds } from '$lib/stores/tags.svelte'; let { navigate, goBack, params }: ViewProps = $props(); let contactId = $derived(params.contactId as string); @@ -40,6 +42,18 @@ let editWebsite = $state(''); let editNotes = $state(''); + const tagsQuery = useAllTags(); + let allTags = $derived(tagsQuery.value ?? []); + let contactTags = $derived(getTagsByIds(allTags, contact?.tagIds ?? [])); + + async function removeTag(tagId: string) { + const current = contact?.tagIds ?? []; + await contactsStore.updateTagIds( + contactId, + current.filter((id) => id !== tagId) + ); + } + $effect(() => { contactId; // track confirmDelete = false; @@ -255,6 +269,26 @@
+ + {#if contactTags.length > 0} +
+ Tags +
+ {#each contactTags as tag (tag.id)} + + {/each} +
+
+ {/if} +
Notizen @@ -447,6 +481,42 @@ flex-direction: column; gap: 0.375rem; } + .tags-list { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + } + .tag-pill { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.125rem 0.5rem; + border-radius: 9999px; + border: none; + background: color-mix(in srgb, var(--tag-color) 12%, transparent); + font-size: 0.6875rem; + color: #6b7280; + cursor: pointer; + transition: all 0.15s; + } + .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 20%, transparent); + color: #ef4444; + } + :global(.dark) .tag-pill { + background: color-mix(in srgb, var(--tag-color) 18%, transparent); + color: #9ca3af; + } + :global(.dark) .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 28%, transparent); + color: #ef4444; + } + .tag-dot { + width: 6px; + height: 6px; + border-radius: 9999px; + flex-shrink: 0; + } .section-label { font-size: 0.6875rem; font-weight: 600; diff --git a/apps/manacore/apps/web/src/lib/modules/todo/views/DetailView.svelte b/apps/manacore/apps/web/src/lib/modules/todo/views/DetailView.svelte index 949d95b1d..56c2685fe 100644 --- a/apps/manacore/apps/web/src/lib/modules/todo/views/DetailView.svelte +++ b/apps/manacore/apps/web/src/lib/modules/todo/views/DetailView.svelte @@ -6,9 +6,10 @@ import { liveQuery } from 'dexie'; import { db } from '$lib/data/database'; import { tasksStore } from '../stores/tasks.svelte'; - import { Check, Trash } from '@manacore/shared-icons'; + import { Check, Trash, X } from '@manacore/shared-icons'; import type { ViewProps } from '$lib/components/workbench/nav-stack'; import type { LocalTask, TaskPriority } from '../types'; + import { useAllTags, getTagsByIds } from '$lib/stores/tags.svelte'; let { navigate, goBack, params }: ViewProps = $props(); let taskId = $derived(params.taskId as string); @@ -25,6 +26,23 @@ // Track whether user is actively editing to prevent overwrite from liveQuery let focused = $state(false); + const tagsQuery = useAllTags(); + let allTags = $derived(tagsQuery.value ?? []); + + function getTaskTagIds(): string[] { + return ((task?.metadata as Record)?.labelIds as string[]) ?? []; + } + + let taskTags = $derived(getTagsByIds(allTags, getTaskTagIds())); + + async function removeTag(tagId: string) { + const current = getTaskTagIds(); + await tasksStore.updateLabels( + taskId, + current.filter((id) => id !== tagId) + ); + } + $effect(() => { taskId; // track confirmDelete = false; @@ -152,6 +170,26 @@ {/if}
+ + {#if taskTags.length > 0} +
+ Tags +
+ {#each taskTags as tag (tag.id)} + + {/each} +
+
+ {/if} +
Beschreibung @@ -349,6 +387,42 @@ flex-direction: column; gap: 0.375rem; } + .tags-list { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + } + .tag-pill { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.125rem 0.5rem; + border-radius: 9999px; + border: none; + background: color-mix(in srgb, var(--tag-color) 12%, transparent); + font-size: 0.6875rem; + color: #6b7280; + cursor: pointer; + transition: all 0.15s; + } + .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 20%, transparent); + color: #ef4444; + } + :global(.dark) .tag-pill { + background: color-mix(in srgb, var(--tag-color) 18%, transparent); + color: #9ca3af; + } + :global(.dark) .tag-pill:hover { + background: color-mix(in srgb, var(--tag-color) 28%, transparent); + color: #ef4444; + } + .tag-dot { + width: 6px; + height: 6px; + border-radius: 9999px; + flex-shrink: 0; + } .section-label { font-size: 0.6875rem; font-weight: 600;