275f66fb8f
- Kopfleiste zusammengefasst: Suche-Pill + Themenfilter-Icon + Heute-Chip - Monats-Grid neutralisiert: weisser Grund, Punkt-Marker statt Zahl-Badge - Terminliste als Karten statt Zebra-Rows; Urgency in getönte Datums-Kachel - Aktionsleiste ans Card-Ende verschoben, ruhige Text+Icon-Links Enthält zusätzlich bestehende lokale Änderungen (Card, Header, ContactCard, InfoCard, PostCardCompact, FilesBlock, app.css, Storybook-Fixtures). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.2 KiB
Svelte
67 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import Icon from "@iconify/svelte";
|
|
import "$lib/iconify-offline";
|
|
import type { ContactEntry } from "$lib/block-types";
|
|
import { downloadVCard } from "$lib/vcard";
|
|
import Badge from "$lib/components/Badge.svelte";
|
|
|
|
let { contact }: { contact: ContactEntry } = $props();
|
|
|
|
const orgNames = $derived(
|
|
(contact.organisations ?? [])
|
|
.filter((o): o is { _slug?: string; name?: string } => typeof o === "object" && o !== null)
|
|
.map((o) => o.name)
|
|
.filter(Boolean) as string[]
|
|
);
|
|
</script>
|
|
|
|
<div
|
|
class="not-prose card-surface card-hover-lift relative flex h-full min-w-0 flex-col gap-2 overflow-hidden p-4"
|
|
>
|
|
<div class="flex flex-col gap-1.5">
|
|
<p class="truncate pr-6 text-sm font-medium leading-tight text-stein-900">{contact.name ?? ""}</p>
|
|
|
|
{#if contact.role || orgNames.length > 0}
|
|
<div class="flex flex-wrap gap-1">
|
|
{#if contact.role}
|
|
<Badge>{contact.role}</Badge>
|
|
{/if}
|
|
{#each orgNames as org}
|
|
<Badge color="green">{org}</Badge>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<!-- vCard download -->
|
|
<button
|
|
type="button"
|
|
title="Kontakt speichern (.vcf)"
|
|
onclick={() => downloadVCard(contact)}
|
|
class="absolute top-3 right-3 text-stein-300 transition-colors hover:text-wald-600"
|
|
>
|
|
<Icon icon="lucide:id-card" class="size-4" />
|
|
</button>
|
|
|
|
{#if contact.phone || contact.email}
|
|
<div class="flex flex-col gap-1">
|
|
{#if contact.phone}
|
|
<a href="tel:{contact.phone.replace(/\s/g, '')}" class="inline-flex items-center gap-1.5 text-xs text-stein-600 no-underline hover:text-wald-700">
|
|
<Icon icon="lucide:phone" class="size-3.5 shrink-0 text-stein-400" />
|
|
<span class="truncate">{contact.phone}</span>
|
|
</a>
|
|
{/if}
|
|
{#if contact.email}
|
|
<a href="mailto:{contact.email}" class="inline-flex items-center gap-1.5 text-xs text-stein-600 no-underline hover:text-wald-700">
|
|
<Icon icon="lucide:mail" class="size-3.5 shrink-0 text-stein-400" />
|
|
<span class="truncate">{contact.email}</span>
|
|
</a>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
|
|
{#if contact.note}
|
|
<p class="text-[11px] text-stein-400">{contact.note}</p>
|
|
{/if}
|
|
</div>
|