From eb97378438528739fed6303e7b0fa6230281c9d8 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 2 Apr 2026 21:21:07 +0200 Subject: [PATCH] feat(manacore/web): add page carousel to contacts module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ContactPage and ContactPagePicker components using the shared PageCarousel/PageShell system. Available pages: Alle Kontakte, Favoriten, Bald Geburtstag, Mit E-Mail, Mit Telefon, Mit Unternehmen, Mit Adresse, Kürzlich hinzugefügt. Default opens "Alle" + "Favoriten". Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/pages/ContactPage.svelte | 439 +++++++++++++++ .../components/pages/ContactPagePicker.svelte | 243 ++++++++ .../src/routes/(app)/contacts/+page.svelte | 522 +++++++++--------- 3 files changed, 928 insertions(+), 276 deletions(-) create mode 100644 apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPage.svelte create mode 100644 apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPagePicker.svelte diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPage.svelte b/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPage.svelte new file mode 100644 index 000000000..0dd88787d --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPage.svelte @@ -0,0 +1,439 @@ + + + + + {#snippet badge()} + {filtered.length} + {/snippet} + +
+ {#if filtered.length === 0} +
+ + Keine Kontakte +
+ {:else if groups} + + {#each letters as letter (letter)} +
+
{letter}
+ {#each groups[letter] as contact (contact.id)} + {@render contactRow(contact)} + {/each} +
+ {/each} + {:else} + + {#each filtered as contact (contact.id)} + {@render contactRow(contact)} + {/each} + {/if} +
+
+ +{#snippet contactRow(contact: Contact)} + +
onOpenContact?.(contact)} + use:dropTarget={{ + accepts: ['tag'], + onDrop: (payload) => onTagDrop?.(contact, payload), + canDrop: tagNotAlreadyOnContact(contact), + }} + > + +
+ {#if contact.photoUrl} + {getDisplayName(contact)} + {:else} + {getInitials(contact)} + {/if} +
+ + +
+
+ {getDisplayName(contact)} + {#if contact.isFavorite} + + {/if} +
+ {#if contact.company || contact.jobTitle} +
+ {[contact.jobTitle, contact.company].filter(Boolean).join(' @ ')} +
+ {/if} + {#if pageId === 'birthday-soon' && contact.birthday} +
+ 🎂 {getBirthdayLabel(contact.birthday)} +
+ {/if} + {#if getContactTags(contact).length > 0} +
+ {#each getContactTags(contact).slice(0, 3) as tag (tag.id)} + + {tag.name} + + {/each} +
+ {/if} +
+ + +
+ contactsStore.toggleFavorite(contact.id)} + variant="star" + size={14} + activeColor="#f59e0b" + /> +
+
+{/snippet} + + diff --git a/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPagePicker.svelte b/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPagePicker.svelte new file mode 100644 index 000000000..cb44cd045 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/contacts/components/pages/ContactPagePicker.svelte @@ -0,0 +1,243 @@ + + +
+
+

Neue Seite

+ +
+
+ {#each availableOptions as option, i (option.id)} + {#if i > 0}
{/if} + + {/each} + {#if availableOptions.length === 0} +

Alle Seiten sind bereits geöffnet

+ {/if} +
+
+ + diff --git a/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte b/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte index a479d0315..f4d6a3985 100644 --- a/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte @@ -1,39 +1,20 @@ Kontakte - ManaCore -
+
-
+
-

Kontakte

-

- {totalCount} Kontakte{favoriteCount > 0 ? ` · ${favoriteCount} Favoriten` : ''} +

Kontakte

+

+ {allContacts.filter((c) => !c.isArchived).length} Kontakte

- +
+ + + +
- -
-
- + (showPicker = !showPicker)} + addLabel="Seite hinzufügen" + > + {#snippet page(p)} + handleRemovePage(p.id)} + onMinimize={() => handleMinimizePage(p.id)} + onMaximize={() => handleMaximizePage(p.id)} + onResize={(w) => handleResize(p.id, w)} + onOpenContact={navigateToContact} + onTagDrop={handleTagDrop} + {tagMap} /> - contactsFilterStore.setSearchQuery(e.currentTarget.value)} - class="w-full rounded-lg border border-border bg-card py-2.5 pl-10 pr-4 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20" + {/snippet} + {#snippet picker()} + (showPicker = false)} + activePageIds={openPages.map((p) => p.id)} /> -
- -
- - - {#if showFilters} -
- {#each [{ value: 'all', label: 'Alle' }, { value: 'favorites', label: 'Favoriten' }, { value: 'hasEmail', label: 'Mit E-Mail' }, { value: 'hasPhone', label: 'Mit Telefon' }, { value: 'incomplete', label: 'Unvollstaendig' }] as filter} - - {/each} -
- {/if} - - - {#if sorted.length === 0} -
-
- -
- {#if contactsFilterStore.searchQuery} -

Keine Ergebnisse

-

- Keine Kontakte gefunden fuer "{contactsFilterStore.searchQuery}" -

- {:else} -

Noch keine Kontakte

-

- Erstelle deinen ersten Kontakt oder importiere bestehende. -

-
- - - Importieren - -
- {/if} -
- {:else} - - {#each letters as letter (letter)} - - {/each} - -

- {sorted.length} Kontakt{sorted.length !== 1 ? 'e' : ''} -

- {/if} + {/snippet} +
- + {#if contactModalStore.isOpen} {@const isEditing = !!contactModalStore.editContactId} @@ -329,7 +230,6 @@ role="dialog" aria-modal="true" > -
@@ -373,10 +273,8 @@ }} class="space-y-0" > -
-
@@ -397,12 +295,8 @@
-
-
- - -
+
-
-
- - -
+
-
-
- - -
+
-
-
- 🎂 - -
+
-
-
- - -
+
-
- 🔗 - +
@@ -495,7 +371,6 @@
-