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 index e5fe3f8bf..bdf87d523 100644 --- 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 @@ -145,11 +145,16 @@ let meta = $derived(PAGE_META[pageId]); + let selfContact = $derived(allContacts.find((c) => c.id === SELF_CONTACT_ID && !c.isArchived)); + let filtered = $derived.by(() => { const active = allContacts.filter((c) => !c.isArchived); const byPage = active.filter(meta.filterFn); const searched = searchContacts(byPage, searchQuery); + // My-profile: just show the self contact + if (pageId === 'my-profile') return searched; + // Birthday-soon: sort by upcoming birthday if (pageId === 'birthday-soon') { const today = startOfDay(new Date()); @@ -167,7 +172,14 @@ ); } - return sortContacts(searched, 'firstName'); + // Default: sort alphabetically, pin self-contact to top + const sorted = sortContacts(searched, 'firstName'); + const selfIdx = sorted.findIndex((c) => c.id === SELF_CONTACT_ID); + if (selfIdx > 0) { + const [self] = sorted.splice(selfIdx, 1); + sorted.unshift(self); + } + return sorted; }); let groups = $derived( @@ -215,7 +227,10 @@ {/snippet}
- {#if filtered.length === 0} + {#if pageId === 'my-profile' && selfContact} + + {@render profileCard(selfContact)} + {:else if filtered.length === 0}
Keine Kontakte @@ -239,6 +254,51 @@
+{#snippet profileCard(contact: Contact)} + +
onOpenContact?.(contact)}> +
+ {#if contact.photoUrl} + {getDisplayName(contact)} + {:else} + {getInitials(contact)} + {/if} +
+
{getDisplayName(contact)}
+ {#if contact.email} +
+ + {contact.email} +
+ {/if} + {#if contact.phone || contact.mobile} +
+ + {contact.mobile || contact.phone} +
+ {/if} + {#if contact.company} +
+ + {[contact.jobTitle, contact.company].filter(Boolean).join(' @ ')} +
+ {/if} + {#if contact.city} +
+ + {[contact.street, contact.postalCode, contact.city].filter(Boolean).join(', ')} +
+ {/if} + {#if contact.birthday} +
+ + {contact.birthday} +
+ {/if} +
Tippe zum Bearbeiten
+
+{/snippet} + {#snippet contactRow(contact: Contact)}
{getDisplayName(contact)} + {#if contact.id === SELF_CONTACT_ID} + Du + {/if} {#if contact.isFavorite} {/if} @@ -445,4 +508,76 @@ .contact-row:hover .row-actions { opacity: 1; } + + /* Self badge */ + .self-badge { + font-size: 0.5625rem; + font-weight: 600; + padding: 0.0625rem 0.375rem; + border-radius: 9999px; + background: color-mix(in srgb, var(--color-primary, #8b5cf6) 12%, transparent); + color: var(--color-primary, #8b5cf6); + flex-shrink: 0; + } + + /* Profile card */ + .profile-card { + display: flex; + flex-direction: column; + align-items: center; + padding: 1.5rem 1rem; + cursor: pointer; + border-radius: 0.375rem; + transition: background 0.15s; + } + .profile-card:hover { + background: rgba(0, 0, 0, 0.02); + } + :global(.dark) .profile-card:hover { + background: rgba(255, 255, 255, 0.03); + } + .profile-avatar { + width: 4.5rem; + height: 4.5rem; + border-radius: 9999px; + background: color-mix(in srgb, var(--color-primary, #8b5cf6) 12%, transparent); + color: var(--color-primary, #8b5cf6); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + font-weight: 600; + overflow: hidden; + margin-bottom: 0.75rem; + } + .profile-avatar-img { + width: 100%; + height: 100%; + object-fit: cover; + } + .profile-name { + font-size: 1.125rem; + font-weight: 700; + color: #374151; + margin-bottom: 0.75rem; + } + :global(.dark) .profile-name { + color: #f3f4f6; + } + .profile-detail { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.8125rem; + color: #6b7280; + padding: 0.25rem 0; + } + :global(.dark) .profile-detail { + color: #9ca3af; + } + .profile-hint { + margin-top: 1rem; + font-size: 0.6875rem; + color: #9ca3af; + } 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 index cb44cd045..a0a069e0c 100644 --- 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 @@ -2,6 +2,7 @@ import { _ } from 'svelte-i18n'; import { Users, + User, Star, Cake, Envelope, @@ -21,6 +22,13 @@ let { onSelect, onClose, activePageIds = [] }: Props = $props(); const PAGE_OPTIONS = [ + { + id: 'my-profile', + title: 'Mein Profil', + description: 'Deine eigene Kontaktkarte', + icon: User, + color: '#8B5CF6', + }, { id: 'all', title: 'Alle Kontakte', 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 f4d6a3985..be42c20f5 100644 --- a/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/contacts/+page.svelte @@ -72,6 +72,7 @@ ]); const PAGE_META: Record = { + 'my-profile': { title: 'Mein Profil', color: '#8B5CF6' }, all: { title: 'Alle Kontakte', color: '#3B82F6' }, favorites: { title: 'Favoriten', color: '#F59E0B' }, 'birthday-soon': { title: 'Bald Geburtstag', color: '#EC4899' },