feat: QR-Code, vCard-Export, Org-Gruppenansicht im Adressbuch
- vcard.ts: shared vCard-Generator (downloadVCard, downloadVCardAll, buildVCardString) - QrModal.svelte + QrButton.svelte: wiederverwendbare QR-Komponenten mit PNG-Download - AdressbuchBlock: Org-Gruppenansicht (Toggle), QR + vCard pro Kontakt, Buchstaben-Trennzeilen, Such-Highlight, "Alle exportieren", Print-Styles - ContactCard: vCard-Download-Button - PostActions: QR-Button für Seiten-URL - qrcode npm-Paket hinzugefügt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import Icon from "@iconify/svelte";
|
||||
import "$lib/iconify-offline";
|
||||
import type { ContactEntry } from "$lib/block-types";
|
||||
import { downloadVCard } from "$lib/vcard";
|
||||
|
||||
let { contact }: { contact: ContactEntry } = $props();
|
||||
|
||||
@@ -17,24 +18,34 @@
|
||||
class="not-prose card-surface relative flex h-full min-w-0 flex-col gap-2 overflow-hidden rounded-sm p-4 transition-[transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 hover:border-wald-300 hover:shadow-md"
|
||||
>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<p class="truncate text-sm font-medium leading-tight text-stein-900">{contact.name ?? ""}</p>
|
||||
<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}
|
||||
<span class="shrink-0 rounded-full border border-stein-200 bg-stein-100 px-1.5 py-0 text-[0.65rem] font-medium text-stein-600">
|
||||
{contact.role}
|
||||
</span>
|
||||
{/if}
|
||||
{#each orgNames as org}
|
||||
<span class="shrink-0 rounded-full border border-wald-200 bg-wald-50 px-1.5 py-0 text-[0.65rem] font-medium text-wald-700">
|
||||
{org}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if contact.role || orgNames.length > 0}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#if contact.role}
|
||||
<span class="shrink-0 rounded-full border border-stein-200 bg-stein-100 px-1.5 py-0 text-[0.65rem] font-medium text-stein-600">
|
||||
{contact.role}
|
||||
</span>
|
||||
{/if}
|
||||
{#each orgNames as org}
|
||||
<span class="shrink-0 rounded-full border border-wald-200 bg-wald-50 px-1.5 py-0 text-[0.65rem] font-medium text-wald-700">
|
||||
{org}
|
||||
</span>
|
||||
{/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="mdi:card-account-details-outline" class="size-4" />
|
||||
</button>
|
||||
|
||||
{#if contact.phone || contact.email}
|
||||
<div class="flex flex-col gap-1">
|
||||
{#if contact.phone}
|
||||
|
||||
Reference in New Issue
Block a user