mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 02:39:41 +02:00
refactor(calendar,contacts): replace inline SVGs with Phosphor icons
Migrate all inline SVG icon paths to Phosphor components from @manacore/shared-icons across 38 files. Only spinners (loading animations) and brand logos (Google) remain as inline SVGs. Calendar: 0 inline icon SVGs remaining Contacts: 6 remaining (3 spinners, 1 spinner, 2 Google logos) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e68e5c6e5f
commit
9f6e463eae
38 changed files with 365 additions and 1717 deletions
|
|
@ -14,6 +14,7 @@
|
|||
import { toDate } from '$lib/utils/eventDateHelpers';
|
||||
import type { CalendarEvent, Calendar, CreateEventInput } from '@calendar/shared';
|
||||
import { ContextMenu, type ContextMenuItem } from '@manacore/shared-ui';
|
||||
import { CalendarBlank, MapPin, CaretRight } from '@manacore/shared-icons';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -195,14 +196,7 @@
|
|||
<div class="agenda-view">
|
||||
{#if groupedEvents.length === 0}
|
||||
<div class="empty-state">
|
||||
<svg class="empty-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={64} class="empty-icon" />
|
||||
<p>Keine Termine in diesem Zeitraum</p>
|
||||
</div>
|
||||
{:else}
|
||||
|
|
@ -256,25 +250,7 @@
|
|||
</span>
|
||||
{#if event.location}
|
||||
<div class="event-location">
|
||||
<svg
|
||||
class="location-icon"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin size={14} class="location-icon" />
|
||||
{event.location}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -285,14 +261,7 @@
|
|||
title="Details öffnen"
|
||||
aria-label="Details öffnen"
|
||||
>
|
||||
<svg class="chevron-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
<CaretRight size={16} class="chevron-icon" />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import type { Calendar } from '@calendar/shared';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { Plus, ArrowsClockwise } from '@manacore/shared-icons';
|
||||
|
||||
// Get calendars from layout context (live query)
|
||||
const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars');
|
||||
|
|
@ -33,9 +34,7 @@
|
|||
<div class="section-header">
|
||||
<h3 class="section-title">Meine Kalender</h3>
|
||||
<button class="add-btn" onclick={handleAddCalendar} aria-label="Kalender hinzufügen">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -64,14 +63,7 @@
|
|||
<div class="section-header external-header">
|
||||
<h3 class="section-title">Externe Kalender</h3>
|
||||
<button class="add-btn" onclick={() => goto('/settings/sync')} aria-label="Sync verwalten">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsClockwise size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
subMonths,
|
||||
} from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import { CaretLeft, CaretRight } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
selectedDate: Date;
|
||||
|
|
@ -51,15 +52,11 @@
|
|||
<div class="mini-calendar card">
|
||||
<div class="calendar-header">
|
||||
<button class="nav-btn" onclick={previousMonth} aria-label="Vorheriger Monat">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
<CaretLeft size={16} />
|
||||
</button>
|
||||
<span class="month-label">{format(currentMonth, 'MMMM yyyy', { locale: de })}</span>
|
||||
<button class="nav-btn" onclick={nextMonth} aria-label="Nächster Monat">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<CaretRight size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { calendarsStore } from '$lib/stores/calendars.svelte';
|
||||
import type { Calendar } from '@calendar/shared';
|
||||
import { goto } from '$app/navigation';
|
||||
import { CalendarBlank, CaretDown, Plus } from '@manacore/shared-icons';
|
||||
|
||||
// Get calendars from layout context (live query)
|
||||
const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars');
|
||||
|
|
@ -74,24 +75,9 @@
|
|||
class:glass-pill={!embedded}
|
||||
class:embedded-btn={embedded}
|
||||
>
|
||||
<svg class="pill-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={16} class="pill-icon" />
|
||||
<span class="pill-label">{visibleCount}/{totalCount}</span>
|
||||
<svg
|
||||
class="chevron-icon"
|
||||
class:rotated={isOpen}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<CaretDown size={12} class="chevron-icon {isOpen ? 'rotated' : ''}" />
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
|
|
@ -116,14 +102,7 @@
|
|||
<div class="dropdown-header">
|
||||
<span class="header-title">Kalender</span>
|
||||
<button class="add-btn" onclick={handleAddCalendar} aria-label="Kalender hinzufügen">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { getContext, type Snippet } from 'svelte';
|
||||
import { Stack, X } from '@manacore/shared-icons';
|
||||
import { QuickInputBar, TagStrip } from '@manacore/shared-ui';
|
||||
import type { QuickInputItem, CreatePreview } from '@manacore/shared-ui';
|
||||
import { unifiedBarStore } from '$lib/stores/unified-bar.svelte';
|
||||
|
|
@ -180,20 +181,7 @@
|
|||
<!-- Layers Menu FAB (only on calendar main page) -->
|
||||
{#if showCalendarLayers}
|
||||
<button class="layers-fab" onclick={toggleOverlay} title="Leisten anpassen">
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 2L2 7l10 5 10-5-10-5z" />
|
||||
<path d="M2 17l10 5 10-5" />
|
||||
<path d="M2 12l10 5 10-5" />
|
||||
</svg>
|
||||
<Stack size={20} />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -208,19 +196,7 @@
|
|||
<div class="overlay-header">
|
||||
<h3>Leisten</h3>
|
||||
<button class="overlay-close-btn" onclick={toggleOverlay} aria-label="Schließen">
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18" />
|
||||
<line x1="6" y1="6" x2="18" y2="18" />
|
||||
</svg>
|
||||
<X size={18} weight="bold" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { viewStore } from '$lib/stores/view.svelte';
|
||||
import { Columns, CalendarBlank, List } from '@manacore/shared-icons';
|
||||
import type { CalendarViewType } from '@calendar/shared';
|
||||
interface Props {
|
||||
isToolbarExpanded?: boolean;
|
||||
|
|
@ -33,27 +34,11 @@
|
|||
title={viewTitles[view]}
|
||||
>
|
||||
{#if view === 'week'}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
d="M3 4v16M6.5 4v16M10 4v16M13.5 4v16M17 4v16M20.5 4v16M24 4v16"
|
||||
/>
|
||||
</svg>
|
||||
<Columns size={18} />
|
||||
{:else if view === 'month'}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<rect x="3" y="4" width="18" height="16" rx="2" stroke-width="2" />
|
||||
<path stroke-linecap="round" stroke-width="2" d="M3 9h18M8 4v4M16 4v4" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-width="1.5"
|
||||
d="M7 13h2M11 13h2M15 13h2M7 17h2M11 17h2"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={18} />
|
||||
{:else if view === 'agenda'}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h12" />
|
||||
</svg>
|
||||
<List size={18} />
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { viewStore } from '$lib/stores/view.svelte';
|
||||
import type { CalendarViewType } from '@calendar/shared';
|
||||
import { SquaresFour } from '@manacore/shared-icons';
|
||||
interface Props {
|
||||
/** Bottom offset from viewport bottom (default: '70px') */
|
||||
bottomOffset?: string;
|
||||
|
|
@ -41,14 +42,7 @@
|
|||
<div class="views-bar" style="--bottom-offset: {bottomOffset}">
|
||||
<div class="views-container">
|
||||
<div class="views-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
|
||||
/>
|
||||
</svg>
|
||||
<SquaresFour size={20} />
|
||||
</div>
|
||||
|
||||
<div class="views-buttons">
|
||||
|
|
|
|||
|
|
@ -8,6 +8,21 @@
|
|||
import RecurrenceEditDialog from './RecurrenceEditDialog.svelte';
|
||||
import ReminderSelector from './ReminderSelector.svelte';
|
||||
import { TagBadge, toastStore as toast, focusTrap } from '@manacore/shared-ui';
|
||||
import {
|
||||
PencilSimple,
|
||||
Trash,
|
||||
X,
|
||||
Clock,
|
||||
ArrowsClockwise,
|
||||
Bell,
|
||||
MapPin,
|
||||
VideoCamera,
|
||||
ArrowSquareOut,
|
||||
Link,
|
||||
TextAlignLeft,
|
||||
Tag,
|
||||
UsersThree,
|
||||
} from '@manacore/shared-icons';
|
||||
import type { CalendarEvent, UpdateEventInput, Reminder } from '@calendar/shared';
|
||||
import { describeRecurrence, parseRRule } from '@calendar/shared';
|
||||
import * as api from '$lib/api/events';
|
||||
|
|
@ -215,37 +230,16 @@
|
|||
<div class="modal-actions">
|
||||
{#if !isEditing}
|
||||
<button class="btn btn-ghost" onclick={() => (isEditing = true)}>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
|
||||
/>
|
||||
</svg>
|
||||
<PencilSimple size={16} />
|
||||
Bearbeiten
|
||||
</button>
|
||||
<button class="btn btn-ghost text-destructive" onclick={handleDelete}>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={16} />
|
||||
Löschen
|
||||
</button>
|
||||
{/if}
|
||||
<button class="btn btn-ghost btn-close" onclick={onClose} aria-label="Schließen">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={20} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -271,14 +265,7 @@
|
|||
<!-- Zeit -->
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Clock size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Zeit</span>
|
||||
|
|
@ -290,14 +277,7 @@
|
|||
{#if event.recurrenceRule}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsClockwise size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Wiederholung</span>
|
||||
|
|
@ -309,14 +289,7 @@
|
|||
<!-- Erinnerungen -->
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
|
||||
/>
|
||||
</svg>
|
||||
<Bell size={20} />
|
||||
</span>
|
||||
<div class="detail-content" style="flex: 1;">
|
||||
<ReminderSelector
|
||||
|
|
@ -336,20 +309,7 @@
|
|||
{#if event.location || event.metadata?.locationDetails}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Ort</span>
|
||||
|
|
@ -380,14 +340,7 @@
|
|||
{#if event.metadata?.conferenceUrl}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<VideoCamera size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Videokonferenz</span>
|
||||
|
|
@ -398,14 +351,7 @@
|
|||
class="detail-link"
|
||||
>
|
||||
Beitreten
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowSquareOut size={14} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -415,14 +361,7 @@
|
|||
{#if event.metadata?.url}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
|
||||
/>
|
||||
</svg>
|
||||
<Link size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Link</span>
|
||||
|
|
@ -433,14 +372,7 @@
|
|||
class="detail-link"
|
||||
>
|
||||
{new URL(event.metadata.url).hostname}
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowSquareOut size={14} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -450,14 +382,7 @@
|
|||
{#if event.description}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 12h16M4 18h7"
|
||||
/>
|
||||
</svg>
|
||||
<TextAlignLeft size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Beschreibung</span>
|
||||
|
|
@ -470,14 +395,7 @@
|
|||
{#if event.tags && event.tags.length > 0}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
|
||||
/>
|
||||
</svg>
|
||||
<Tag size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Tags</span>
|
||||
|
|
@ -494,14 +412,7 @@
|
|||
{#if event.metadata?.attendees && event.metadata.attendees.length > 0}
|
||||
<div class="detail-row">
|
||||
<span class="detail-icon">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
|
||||
/>
|
||||
</svg>
|
||||
<UsersThree size={20} />
|
||||
</span>
|
||||
<div class="detail-content">
|
||||
<span class="detail-label">Teilnehmer ({event.metadata.attendees.length})</span>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
// Live data from layout context
|
||||
const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars');
|
||||
const tagsCtx: { readonly value: SharedTag[] } = getContext('tags');
|
||||
import { CaretRight } from '@manacore/shared-icons';
|
||||
import {
|
||||
TagSelector,
|
||||
FilterDropdown,
|
||||
|
|
@ -391,16 +392,7 @@
|
|||
aria-expanded={showLocationDetails}
|
||||
aria-controls="location-details"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 transition-transform"
|
||||
class:rotate-90={showLocationDetails}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<CaretRight size={16} class="transition-transform {showLocationDetails ? 'rotate-90' : ''}" />
|
||||
{showLocationDetails ? 'Adressdetails ausblenden' : 'Adressdetails hinzufügen'}
|
||||
</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,17 @@
|
|||
toastStore as toast,
|
||||
type FilterDropdownOption,
|
||||
} from '@manacore/shared-ui';
|
||||
import { Users } from '@manacore/shared-icons';
|
||||
import {
|
||||
Users,
|
||||
Trash,
|
||||
X,
|
||||
Clock,
|
||||
CalendarBlank,
|
||||
ArrowsClockwise,
|
||||
MapPin,
|
||||
CaretRight,
|
||||
TextAlignLeft,
|
||||
} from '@manacore/shared-icons';
|
||||
import { format, addMinutes } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import { toDate } from '$lib/utils/eventDateHelpers';
|
||||
|
|
@ -867,26 +877,12 @@
|
|||
placement="bottom"
|
||||
>
|
||||
<button type="button" class="delete-btn" disabled={submitting} aria-label="Löschen">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={16} />
|
||||
</button>
|
||||
</ConfirmationPopover>
|
||||
{/if}
|
||||
<button type="button" class="close-btn" onclick={onClose} aria-label="Schließen">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -928,14 +924,7 @@
|
|||
|
||||
<!-- Time display under title -->
|
||||
<div class="time-display">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Clock class="icon" size={18} />
|
||||
<span>
|
||||
{format(draftStart(), 'EEEE, d. MMMM yyyy', { locale: de })}
|
||||
{#if !isAllDay}
|
||||
|
|
@ -1078,14 +1067,7 @@
|
|||
aria-label="Ganztägig"
|
||||
>
|
||||
<div class="row-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content toggle-content">
|
||||
<span>Ganztägig</span>
|
||||
|
|
@ -1119,14 +1101,7 @@
|
|||
<!-- Recurrence -->
|
||||
<div class="form-row">
|
||||
<div class="row-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsClockwise class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content">
|
||||
<RecurrenceSelector
|
||||
|
|
@ -1143,14 +1118,7 @@
|
|||
<!-- Start date/time -->
|
||||
<div class="form-row">
|
||||
<div class="row-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content datetime-row">
|
||||
<div class="datetime-field">
|
||||
|
|
@ -1181,20 +1149,7 @@
|
|||
<!-- End date/time -->
|
||||
<div class="form-row">
|
||||
<div class="row-icon">
|
||||
<svg
|
||||
class="icon"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content datetime-row">
|
||||
<div class="datetime-field">
|
||||
|
|
@ -1225,20 +1180,7 @@
|
|||
<!-- Location -->
|
||||
<div class="form-row">
|
||||
<div class="row-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content">
|
||||
<input
|
||||
|
|
@ -1255,20 +1197,7 @@
|
|||
onclick={() => (showLocationDetails = !showLocationDetails)}
|
||||
aria-expanded={showLocationDetails}
|
||||
>
|
||||
<svg
|
||||
class="toggle-chevron"
|
||||
class:rotated={showLocationDetails}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
<CaretRight class="toggle-chevron {showLocationDetails ? 'rotated' : ''}" size={14} />
|
||||
{showLocationDetails ? 'Adressdetails ausblenden' : 'Adressdetails hinzufügen'}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -1324,14 +1253,7 @@
|
|||
<!-- Description -->
|
||||
<div class="form-row">
|
||||
<div class="row-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 12h16M4 18h7"
|
||||
/>
|
||||
</svg>
|
||||
<TextAlignLeft class="icon" size={18} />
|
||||
</div>
|
||||
<div class="row-content">
|
||||
<textarea
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { ResponsiblePerson } from '@calendar/shared';
|
||||
import type { ContactSummary, ContactOrManual, ManualContactEntry } from '@manacore/shared-types';
|
||||
import { ContactSelector, ContactAvatar } from '@manacore/shared-ui';
|
||||
import { X, ArrowSquareOut } from '@manacore/shared-icons';
|
||||
import { X, ArrowSquareOut, User } from '@manacore/shared-icons';
|
||||
import { contactsStore } from '$lib/stores/contacts.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -196,14 +196,7 @@
|
|||
"
|
||||
{disabled}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={16} />
|
||||
Verantwortliche Person hinzufügen
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,16 @@
|
|||
FilterDropdown,
|
||||
type FilterDropdownOption,
|
||||
} from '@manacore/shared-ui';
|
||||
import { X } from '@manacore/shared-icons';
|
||||
import {
|
||||
X,
|
||||
CalendarBlank,
|
||||
Plus,
|
||||
Eye,
|
||||
Clock,
|
||||
Microphone,
|
||||
Cake,
|
||||
User,
|
||||
} from '@manacore/shared-icons';
|
||||
import { focusTrap } from '@manacore/shared-ui';
|
||||
import type { CalendarViewType, Calendar } from '@calendar/shared';
|
||||
|
||||
|
|
@ -237,14 +246,7 @@
|
|||
<!-- Meine Kalender -->
|
||||
<SettingsSection title="Meine Kalender">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4">
|
||||
|
|
@ -253,14 +255,7 @@
|
|||
class="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium rounded-lg transition-colors bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] hover:bg-[hsl(var(--primary))]/90"
|
||||
onclick={() => (showNewCalendarForm = true)}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
Neuer Kalender
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -409,20 +404,7 @@
|
|||
<!-- Kalender-Ansicht -->
|
||||
<SettingsSection title="Kalender-Ansicht">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
|
||||
/>
|
||||
</svg>
|
||||
<Eye size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4 space-y-3">
|
||||
|
|
@ -577,14 +559,7 @@
|
|||
<!-- Termin-Einstellungen -->
|
||||
<SettingsSection title="Termine">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Clock size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4 space-y-3">
|
||||
|
|
@ -620,14 +595,7 @@
|
|||
<!-- Spracheingabe -->
|
||||
<SettingsSection title="Spracheingabe">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Microphone size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4 space-y-3">
|
||||
|
|
@ -662,14 +630,7 @@
|
|||
<!-- Geburtstage -->
|
||||
<SettingsSection title="Geburtstage">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 15.546c-.523 0-1.046.151-1.5.454a2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.701 2.701 0 00-1.5-.454M9 6v2m3-2v2m3-2v2M9 3h.01M12 3h.01M15 3h.01M21 21v-7a2 2 0 00-2-2H5a2 2 0 00-2 2v7h18zm-3-9v-2a2 2 0 00-2-2H8a2 2 0 00-2 2v2h12z"
|
||||
/>
|
||||
</svg>
|
||||
<Cake size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4 space-y-3">
|
||||
|
|
@ -714,14 +675,7 @@
|
|||
<!-- Konto -->
|
||||
<SettingsSection title="Konto">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-4 space-y-3">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { voiceRecordingStore } from '$lib/stores/voice-recording.svelte';
|
||||
import { Microphone } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
/** Called when voice recording completes with transcription */
|
||||
|
|
@ -79,20 +80,7 @@
|
|||
<div class="recording-dot"></div>
|
||||
{:else}
|
||||
<!-- Microphone icon -->
|
||||
<svg
|
||||
class="mic-icon"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Microphone class="mic-icon" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { voiceRecordingStore } from '$lib/stores/voice-recording.svelte';
|
||||
import { fade, scale } from 'svelte/transition';
|
||||
import { focusTrap } from '@manacore/shared-ui';
|
||||
import { WarningCircle, X, Check } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
/** Called when recording completes with transcription */
|
||||
|
|
@ -87,14 +88,7 @@
|
|||
<!-- Error state -->
|
||||
<div class="modal-content error">
|
||||
<div class="error-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<WarningCircle size={48} />
|
||||
</div>
|
||||
<p class="error-message">{errorMessage}</p>
|
||||
<button class="btn btn-primary" onclick={handleCancel}>Schließen</button>
|
||||
|
|
@ -120,14 +114,7 @@
|
|||
<!-- Controls -->
|
||||
<div class="controls">
|
||||
<button class="btn btn-icon btn-cancel" onclick={handleCancel} title="Abbrechen (Esc)">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={24} />
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -135,14 +122,7 @@
|
|||
onclick={handleStop}
|
||||
title="Aufnahme beenden (Enter)"
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={24} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
import type { CalendarEvent, Calendar } from '@calendar/shared';
|
||||
import { addMinutes } from 'date-fns';
|
||||
import { browser } from '$app/environment';
|
||||
import { CaretDoubleLeft } from '@manacore/shared-icons';
|
||||
|
||||
// Get calendars from layout context (live query)
|
||||
const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars');
|
||||
|
|
@ -186,14 +187,7 @@
|
|||
onclick={() => settingsStore.toggleSidebar()}
|
||||
title={$_('calendar.hideSidebar')}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 19l-7-7 7-7m8 14l-7-7 7-7"
|
||||
/>
|
||||
</svg>
|
||||
<CaretDoubleLeft size={16} />
|
||||
</button>
|
||||
|
||||
<TodoSidebarSection maxItems={5} />
|
||||
|
|
|
|||
|
|
@ -19,6 +19,17 @@
|
|||
} from '@manacore/shared-ui';
|
||||
import { APP_VERSION } from '$lib/version';
|
||||
import type { CalendarViewType, Calendar } from '@calendar/shared';
|
||||
import {
|
||||
CalendarBlank,
|
||||
Plus,
|
||||
ArrowsClockwise,
|
||||
UsersThree,
|
||||
Eye,
|
||||
Clock,
|
||||
Cake,
|
||||
User,
|
||||
Microphone,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
// Get calendars from layout context (live query)
|
||||
const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars');
|
||||
|
|
@ -210,14 +221,7 @@
|
|||
<!-- Meine Kalender -->
|
||||
<SettingsSection title={$_('settings.myCalendars')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-5">
|
||||
|
|
@ -226,14 +230,7 @@
|
|||
class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] hover:bg-[hsl(var(--primary))]/90"
|
||||
onclick={() => (showNewCalendarForm = true)}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
{$_('settings.newCalendar')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -370,14 +367,7 @@
|
|||
<!-- Externe Kalender -->
|
||||
<SettingsSection title={$_('settings.externalCalendars')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsClockwise size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="flex flex-col gap-3">
|
||||
|
|
@ -397,14 +387,7 @@
|
|||
<!-- Kalender-Freigaben -->
|
||||
<SettingsSection title={$_('settings.shares')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
||||
/>
|
||||
</svg>
|
||||
<UsersThree size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="flex flex-col gap-3">
|
||||
|
|
@ -432,20 +415,7 @@
|
|||
<!-- Kalender-Ansicht -->
|
||||
<SettingsSection title={$_('settings.calendarView')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
|
||||
/>
|
||||
</svg>
|
||||
<Eye size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-5 space-y-4">
|
||||
|
|
@ -588,14 +558,7 @@
|
|||
<!-- Termin-Einstellungen -->
|
||||
<SettingsSection title={$_('settings.events')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Clock size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-5 space-y-4">
|
||||
|
|
@ -648,14 +611,7 @@
|
|||
<!-- Geburtstage -->
|
||||
<SettingsSection title={$_('settings.birthdays')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 15.546c-.523 0-1.046.151-1.5.454a2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.701 2.701 0 00-1.5-.454M9 6v2m3-2v2m3-2v2M9 3h.01M12 3h.01M15 3h.01M21 21v-7a2 2 0 00-2-2H5a2 2 0 00-2 2v7h18zm-3-9v-2a2 2 0 00-2-2H8a2 2 0 00-2 2v2h12z"
|
||||
/>
|
||||
</svg>
|
||||
<Cake size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-5 space-y-4">
|
||||
|
|
@ -696,14 +652,7 @@
|
|||
<!-- Konto -->
|
||||
<SettingsSection title={$_('settings.account')}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={24} />
|
||||
{/snippet}
|
||||
<SettingsCard>
|
||||
<div class="p-5 space-y-4">
|
||||
|
|
|
|||
|
|
@ -8,6 +8,23 @@
|
|||
import SocialMediaFields from './forms/SocialMediaFields.svelte';
|
||||
import DateFields from './forms/DateFields.svelte';
|
||||
import SocialMediaLinks from './SocialMediaLinks.svelte';
|
||||
import {
|
||||
X,
|
||||
PencilSimple,
|
||||
Trash,
|
||||
Warning,
|
||||
Camera,
|
||||
Heart,
|
||||
Phone,
|
||||
Envelope,
|
||||
ChatCircle,
|
||||
User,
|
||||
Briefcase,
|
||||
MapPin,
|
||||
CalendarBlank,
|
||||
Check,
|
||||
Note,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
contactId: string;
|
||||
|
|
@ -288,14 +305,7 @@
|
|||
<!-- Header -->
|
||||
<header class="modal-header">
|
||||
<button onclick={onClose} class="back-button" aria-label="Schließen">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={24} class="icon" />
|
||||
</button>
|
||||
<h1 id="modal-title" class="title">{editing ? 'Bearbeiten' : 'Kontakt'}</h1>
|
||||
{#if contact && !editing && !loading}
|
||||
|
|
@ -308,14 +318,7 @@
|
|||
class="action-btn"
|
||||
aria-label="Bearbeiten"
|
||||
>
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
||||
/>
|
||||
</svg>
|
||||
<PencilSimple size={24} class="icon" />
|
||||
</button>
|
||||
{#if !contact?.isSelf}
|
||||
<button
|
||||
|
|
@ -324,14 +327,7 @@
|
|||
class="action-btn action-btn-danger"
|
||||
aria-label="Löschen"
|
||||
>
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={24} class="icon" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -347,14 +343,7 @@
|
|||
{:else if error && !contact}
|
||||
<div class="error-container">
|
||||
<div class="error-icon-wrapper">
|
||||
<svg class="error-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={48} class="error-icon" />
|
||||
</div>
|
||||
<p class="error-text">{error}</p>
|
||||
<button onclick={onClose} class="btn btn-secondary">Schließen</button>
|
||||
|
|
@ -362,14 +351,7 @@
|
|||
{:else if contact}
|
||||
{#if error}
|
||||
<div class="error-banner" role="alert">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={20} class="icon-sm" />
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -399,14 +381,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Name</h2>
|
||||
</div>
|
||||
|
|
@ -426,14 +401,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Kontakt</h2>
|
||||
</div>
|
||||
|
|
@ -457,14 +425,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Briefcase size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Arbeit</h2>
|
||||
</div>
|
||||
|
|
@ -482,20 +443,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Adresse</h2>
|
||||
</div>
|
||||
|
|
@ -523,14 +471,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
||||
/>
|
||||
</svg>
|
||||
<PencilSimple size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Notizen</h2>
|
||||
</div>
|
||||
|
|
@ -588,14 +529,7 @@
|
|||
</svg>
|
||||
<span>Speichern...</span>
|
||||
{:else}
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={16} class="icon-sm" />
|
||||
<span>Speichern</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
@ -645,14 +579,7 @@
|
|||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={16} />
|
||||
{/if}
|
||||
</button>
|
||||
{:else}
|
||||
|
|
@ -683,20 +610,7 @@
|
|||
{:else}
|
||||
<span class="avatar-initials">{initials()}</span>
|
||||
<span class="avatar-upload-overlay">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Camera size={24} />
|
||||
</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
@ -709,20 +623,9 @@
|
|||
: 'Zu Favoriten hinzufügen'}
|
||||
>
|
||||
{#if contact.isFavorite}
|
||||
<svg class="favorite-icon favorite-active" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={24} weight="fill" class="favorite-icon favorite-active" />
|
||||
{:else}
|
||||
<svg class="favorite-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={24} class="favorite-icon" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -739,14 +642,7 @@
|
|||
{#if contact.phone}
|
||||
<a href="tel:{contact.phone}" class="quick-action">
|
||||
<div class="quick-action-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
|
||||
/>
|
||||
</svg>
|
||||
<Phone size={24} />
|
||||
</div>
|
||||
<span>Anrufen</span>
|
||||
</a>
|
||||
|
|
@ -754,14 +650,7 @@
|
|||
{#if contact.email}
|
||||
<a href="mailto:{contact.email}" class="quick-action">
|
||||
<div class="quick-action-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={24} />
|
||||
</div>
|
||||
<span>E-Mail</span>
|
||||
</a>
|
||||
|
|
@ -769,14 +658,7 @@
|
|||
{#if contact.mobile}
|
||||
<a href="sms:{contact.mobile}" class="quick-action">
|
||||
<div class="quick-action-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
||||
/>
|
||||
</svg>
|
||||
<ChatCircle size={24} />
|
||||
</div>
|
||||
<span>Nachricht</span>
|
||||
</a>
|
||||
|
|
@ -789,14 +671,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={20} />
|
||||
</div>
|
||||
<h3 class="section-title">Kontakt</h3>
|
||||
</div>
|
||||
|
|
@ -833,14 +708,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Briefcase size={20} />
|
||||
</div>
|
||||
<h3 class="section-title">Arbeit</h3>
|
||||
</div>
|
||||
|
|
@ -869,20 +737,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin size={20} />
|
||||
</div>
|
||||
<h3 class="section-title">Adresse</h3>
|
||||
</div>
|
||||
|
|
@ -902,14 +757,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={20} />
|
||||
</div>
|
||||
<h3 class="section-title">Daten</h3>
|
||||
</div>
|
||||
|
|
@ -952,14 +800,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
||||
/>
|
||||
</svg>
|
||||
<Note size={20} />
|
||||
</div>
|
||||
<h3 class="section-title">Notizen</h3>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { Heart, Archive, Trash } from '@manacore/shared-icons';
|
||||
import { contactsStore } from '$lib/stores/contacts.svelte';
|
||||
import { viewModeStore } from '$lib/stores/view-mode.svelte';
|
||||
import { contactsFilterStore } from '$lib/stores/filter.svelte';
|
||||
|
|
@ -261,14 +262,7 @@
|
|||
class="batch-btn"
|
||||
title="Zu Favoriten hinzufügen"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={20} />
|
||||
<span class="hidden sm:inline">Favoriten</span>
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -278,14 +272,7 @@
|
|||
class="batch-btn"
|
||||
title="Archivieren"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||
/>
|
||||
</svg>
|
||||
<Archive size={20} />
|
||||
<span class="hidden sm:inline">Archivieren</span>
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -295,14 +282,7 @@
|
|||
class="batch-btn batch-btn-danger"
|
||||
title="Löschen"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={20} />
|
||||
<span class="hidden sm:inline">Löschen</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { NotePencil, Plus, PushPin, PencilSimple, Trash } from '@manacore/shared-icons';
|
||||
import { notesApi, type ContactNote } from '$lib/api/contacts';
|
||||
import { ContactNotesSkeleton } from '$lib/components/skeletons';
|
||||
|
||||
|
|
@ -137,14 +138,7 @@
|
|||
<section class="notes-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<NotePencil size={16} />
|
||||
</div>
|
||||
<h3 class="section-title">{$_('notes.title')}</h3>
|
||||
<button
|
||||
|
|
@ -152,9 +146,7 @@
|
|||
class="add-note-btn"
|
||||
aria-label={$_('notes.add')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -233,9 +225,7 @@
|
|||
<div class="note-content">
|
||||
{#if note.isPinned}
|
||||
<span class="pin-badge">
|
||||
<svg fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z" />
|
||||
</svg>
|
||||
<PushPin size={14} weight="fill" />
|
||||
</span>
|
||||
{/if}
|
||||
<p class="note-text">{note.content}</p>
|
||||
|
|
@ -249,18 +239,7 @@
|
|||
aria-label={note.isPinned ? $_('notes.unpin') : $_('notes.pin')}
|
||||
title={note.isPinned ? $_('notes.unpin') : $_('notes.pin')}
|
||||
>
|
||||
<svg
|
||||
fill={note.isPinned ? 'currentColor' : 'none'}
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
<PushPin size={14} weight={note.isPinned ? 'fill' : 'regular'} />
|
||||
</button>
|
||||
<button
|
||||
onclick={() => startEditing(note)}
|
||||
|
|
@ -268,14 +247,7 @@
|
|||
aria-label={$_('actions.edit')}
|
||||
title={$_('actions.edit')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
||||
/>
|
||||
</svg>
|
||||
<PencilSimple size={14} />
|
||||
</button>
|
||||
<button
|
||||
onclick={() => handleDelete(note.id)}
|
||||
|
|
@ -283,14 +255,7 @@
|
|||
aria-label={$_('actions.delete')}
|
||||
title={$_('actions.delete')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={14} />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { ClipboardText, Warning, Check } from '@manacore/shared-icons';
|
||||
import { todosStore } from '$lib/stores/todos.svelte';
|
||||
import { PRIORITY_COLORS, type Task } from '$lib/api/todos';
|
||||
|
||||
|
|
@ -100,14 +101,7 @@
|
|||
<section class="tasks-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
|
||||
/>
|
||||
</svg>
|
||||
<ClipboardText size={16} />
|
||||
</div>
|
||||
<h3 class="section-title">{$_('contact.tasks.title')}</h3>
|
||||
<label class="show-completed-toggle">
|
||||
|
|
@ -126,14 +120,7 @@
|
|||
</div>
|
||||
{:else if !todosStore.serviceAvailable}
|
||||
<div class="service-unavailable">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={24} />
|
||||
<p>{$_('contact.tasks.serviceUnavailable')}</p>
|
||||
</div>
|
||||
{:else if totalTasks === 0}
|
||||
|
|
@ -161,9 +148,7 @@
|
|||
style="--priority-color: {PRIORITY_COLORS[task.priority]}"
|
||||
>
|
||||
{#if task.isCompleted}
|
||||
<svg fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" />
|
||||
</svg>
|
||||
<Check size={12} weight="bold" class="text-white" />
|
||||
{/if}
|
||||
</button>
|
||||
<div class="task-content">
|
||||
|
|
@ -209,9 +194,7 @@
|
|||
style="--priority-color: {PRIORITY_COLORS[task.priority]}"
|
||||
>
|
||||
{#if task.isCompleted}
|
||||
<svg fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" />
|
||||
</svg>
|
||||
<Check size={12} weight="bold" class="text-white" />
|
||||
{/if}
|
||||
</button>
|
||||
<div class="task-content">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import { contactsFilterStore } from '$lib/stores/filter.svelte';
|
||||
import { viewModeStore } from '$lib/stores/view-mode.svelte';
|
||||
import type { Contact } from '$lib/api/contacts';
|
||||
import { SquaresFour, SortAscending } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
contacts: Contact[];
|
||||
|
|
@ -39,14 +40,7 @@
|
|||
onclick={() => viewModeStore.setMode('grid')}
|
||||
title={$_('views.grid')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1v-4zM14 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z"
|
||||
/>
|
||||
</svg>
|
||||
<SquaresFour />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -55,14 +49,7 @@
|
|||
onclick={() => viewModeStore.setMode('alphabet')}
|
||||
title={$_('views.alphabet')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<SortAscending />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { onMount } from 'svelte';
|
||||
import { Funnel, X } from '@manacore/shared-icons';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { tagsApi, type ContactTag, type Contact } from '$lib/api/contacts';
|
||||
|
||||
|
|
@ -125,14 +126,7 @@
|
|||
onclick={toggleFilters}
|
||||
title={$_('filters.title')}
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<Funnel size={16} />
|
||||
{#if activeFilterCount > 0}
|
||||
<span class="filter-badge-embedded">{activeFilterCount}</span>
|
||||
{/if}
|
||||
|
|
@ -236,14 +230,7 @@
|
|||
class:active={showFilters || activeFilterCount > 0}
|
||||
onclick={() => (showFilters = !showFilters)}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<Funnel size={16} />
|
||||
<span>{$_('filters.title')}</span>
|
||||
{#if activeFilterCount > 0}
|
||||
<span class="filter-badge">{activeFilterCount}</span>
|
||||
|
|
@ -259,54 +246,26 @@
|
|||
<button type="button" class="filter-pill" onclick={() => onTagChange(null)}>
|
||||
<span class="pill-color" style="background: {tag.color || '#6366f1'}"></span>
|
||||
{tag.name}
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={12} />
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if contactFilter !== 'all' && contactFilter !== 'favorites'}
|
||||
<button type="button" class="filter-pill" onclick={() => onContactFilterChange('all')}>
|
||||
{$_(`filters.contact.${contactFilter}`)}
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={12} />
|
||||
</button>
|
||||
{/if}
|
||||
{#if birthdayFilter !== 'all'}
|
||||
<button type="button" class="filter-pill" onclick={() => onBirthdayFilterChange('all')}>
|
||||
{$_(`filters.birthday.${birthdayFilter}`)}
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={12} />
|
||||
</button>
|
||||
{/if}
|
||||
{#if selectedCompany}
|
||||
<button type="button" class="filter-pill" onclick={() => onCompanyChange(null)}>
|
||||
{selectedCompany}
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={12} />
|
||||
</button>
|
||||
{/if}
|
||||
<button type="button" class="clear-all-btn" onclick={clearAllFilters}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { locale } from 'svelte-i18n';
|
||||
import { setLocale, supportedLocales } from '$lib/i18n';
|
||||
import type { SupportedLocale } from '$lib/i18n';
|
||||
import { CaretDown } from '@manacore/shared-icons';
|
||||
|
||||
const languageLabels: Record<SupportedLocale, string> = {
|
||||
de: 'Deutsch',
|
||||
|
|
@ -25,9 +26,7 @@
|
|||
class="flex items-center gap-2 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
{languageLabels[$locale as SupportedLocale] || 'Language'}
|
||||
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<CaretDown size={16} />
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,17 @@
|
|||
import { parseContactInput, formatParsedContactPreview } from '$lib/utils/contact-parser';
|
||||
import { findDuplicates, type DuplicateMatch } from '$lib/utils/duplicate-detector';
|
||||
import { contactCollection } from '$lib/data/local-store';
|
||||
import {
|
||||
X,
|
||||
Warning,
|
||||
Camera,
|
||||
User,
|
||||
Envelope,
|
||||
Briefcase,
|
||||
MapPin,
|
||||
PencilSimple,
|
||||
Check,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
|
@ -309,14 +320,7 @@
|
|||
<!-- Header -->
|
||||
<header class="modal-header">
|
||||
<button onclick={onClose} class="back-button" aria-label="Schließen">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={24} class="icon" />
|
||||
</button>
|
||||
<h1 id="modal-title" class="title">Neuer Kontakt</h1>
|
||||
<div class="header-spacer"></div>
|
||||
|
|
@ -343,14 +347,7 @@
|
|||
<!-- Duplicate Warning -->
|
||||
{#if duplicates.length > 0}
|
||||
<div class="duplicate-warning" role="alert">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={20} class="icon-sm" />
|
||||
<div class="duplicate-info">
|
||||
<span class="duplicate-label">Mögliches Duplikat:</span>
|
||||
{#each duplicates.slice(0, 3) as dup}
|
||||
|
|
@ -367,14 +364,7 @@
|
|||
|
||||
{#if error}
|
||||
<div class="error-banner" role="alert">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={20} class="icon-sm" />
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -398,37 +388,11 @@
|
|||
{#if photoPreview}
|
||||
<img src={photoPreview} alt="Vorschau" class="avatar-image" />
|
||||
<div class="avatar-overlay">
|
||||
<svg class="camera-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Camera size={24} class="camera-icon" />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="avatar-circle empty">
|
||||
<svg class="add-photo-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Camera size={24} class="add-photo-icon" />
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
@ -439,14 +403,7 @@
|
|||
onclick={removePhoto}
|
||||
title="Foto entfernen"
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={16} />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -467,14 +424,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Name</h2>
|
||||
</div>
|
||||
|
|
@ -507,14 +457,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Kontakt</h2>
|
||||
</div>
|
||||
|
|
@ -556,14 +499,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Briefcase size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Arbeit</h2>
|
||||
</div>
|
||||
|
|
@ -593,20 +529,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MapPin size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Adresse</h2>
|
||||
</div>
|
||||
|
|
@ -652,14 +575,7 @@
|
|||
<section class="form-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
||||
/>
|
||||
</svg>
|
||||
<PencilSimple size={20} />
|
||||
</div>
|
||||
<h2 class="section-title">Notizen</h2>
|
||||
</div>
|
||||
|
|
@ -714,14 +630,7 @@
|
|||
</svg>
|
||||
<span>Speichern...</span>
|
||||
{:else}
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={20} class="icon-sm" />
|
||||
<span>Kontakt erstellen</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { contactsApi, type Contact } from '$lib/api/contacts';
|
||||
import { newContactModalStore } from '$lib/stores/new-contact-modal.svelte';
|
||||
import { ContactsEvents } from '@manacore/shared-utils/analytics';
|
||||
import { MagnifyingGlass, Heart, Plus, Tag, Upload } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
|
@ -123,14 +124,7 @@
|
|||
<div class="search-modal">
|
||||
<!-- Search Input -->
|
||||
<div class="search-input-wrapper">
|
||||
<svg class="search-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MagnifyingGlass class="search-icon" />
|
||||
<input
|
||||
bind:this={inputElement}
|
||||
type="text"
|
||||
|
|
@ -186,11 +180,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{#if contact.isFavorite}
|
||||
<svg class="result-favorite" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart class="result-favorite" weight="fill" />
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
|
|
@ -207,37 +197,16 @@
|
|||
newContactModalStore.open();
|
||||
}}
|
||||
>
|
||||
<svg class="quick-action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={20} class="quick-action-icon" />
|
||||
<span>Neuen Kontakt erstellen</span>
|
||||
<kbd>N</kbd>
|
||||
</button>
|
||||
<a href="/tags" class="quick-action" onclick={onClose}>
|
||||
<svg class="quick-action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
|
||||
/>
|
||||
</svg>
|
||||
<Tag size={20} class="quick-action-icon" />
|
||||
<span>Tags verwalten</span>
|
||||
</a>
|
||||
<a href="/data?tab=import" class="quick-action" onclick={onClose}>
|
||||
<svg class="quick-action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<Upload size={20} class="quick-action-icon" />
|
||||
<span>Kontakte importieren</span>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { getSocialMediaEntries, hasSocialMedia } from '$lib/config/social-media';
|
||||
import type { Contact } from '$lib/api/contacts';
|
||||
import { ChatCircle } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
contact: Contact;
|
||||
|
|
@ -21,14 +22,7 @@
|
|||
<section class="detail-section">
|
||||
<div class="section-header">
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
|
||||
/>
|
||||
</svg>
|
||||
<ChatCircle size={16} />
|
||||
</div>
|
||||
<h3 class="section-title">Social Media</h3>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { viewModeStore, type ViewMode } from '$lib/stores/view-mode.svelte';
|
||||
import { SquaresFour, SortAscending } from '@manacore/shared-icons';
|
||||
|
||||
const modes: { id: ViewMode; icon: string; label: string }[] = [
|
||||
{ id: 'alphabet', icon: 'alphabet', label: 'views.alphabet' },
|
||||
|
|
@ -18,23 +19,9 @@
|
|||
title={$_(mode.label)}
|
||||
>
|
||||
{#if mode.icon === 'grid'}
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1v-4zM14 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z"
|
||||
/>
|
||||
</svg>
|
||||
<SquaresFour size={20} />
|
||||
{:else if mode.icon === 'alphabet'}
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<SortAscending size={20} />
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { _ } from 'svelte-i18n';
|
||||
import { exportApi, type ExportFormat } from '$lib/api/export';
|
||||
import { ContactsEvents } from '@manacore/shared-utils/analytics';
|
||||
import { X, AddressBook, ChartBar, Upload } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
isOpen: boolean;
|
||||
|
|
@ -65,14 +66,7 @@
|
|||
onclick={onClose}
|
||||
class="text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<X size={24} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -105,19 +99,7 @@
|
|||
: 'border-border hover:border-muted-foreground'}"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<svg
|
||||
class="w-8 h-8 text-primary"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
|
||||
/>
|
||||
</svg>
|
||||
<AddressBook size={32} class="text-primary" />
|
||||
<div>
|
||||
<div class="font-medium text-foreground">vCard</div>
|
||||
<div class="text-xs text-muted-foreground">.vcf</div>
|
||||
|
|
@ -131,19 +113,7 @@
|
|||
{format === 'csv' ? 'border-primary bg-primary/10' : 'border-border hover:border-muted-foreground'}"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<svg
|
||||
class="w-8 h-8 text-green-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<ChartBar size={32} class="text-green-500" />
|
||||
<div>
|
||||
<div class="font-medium text-foreground">CSV</div>
|
||||
<div class="text-xs text-muted-foreground">.csv</div>
|
||||
|
|
@ -180,14 +150,7 @@
|
|||
</span>
|
||||
{:else}
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<Upload size={20} />
|
||||
{$_('export.button')}
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { CalendarBlank, CaretDown, Cake, Trash, Plus } from '@manacore/shared-icons';
|
||||
|
||||
interface CustomDate {
|
||||
id: string;
|
||||
label: string;
|
||||
|
|
@ -53,25 +55,10 @@
|
|||
onclick={() => (isOpen = !isOpen)}
|
||||
>
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<CalendarBlank size={18} />
|
||||
</div>
|
||||
<h2 class="section-title">Daten</h2>
|
||||
<svg
|
||||
class="chevron-icon"
|
||||
class:chevron-open={isOpen}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<CaretDown size={20} class="chevron-icon {isOpen ? 'chevron-open' : ''}" />
|
||||
</button>
|
||||
{#if isOpen}
|
||||
<div class="dates-container">
|
||||
|
|
@ -79,14 +66,7 @@
|
|||
<div class="form-field birthday-field">
|
||||
<label for="birthday" class="label date-label">
|
||||
<span class="date-icon-label">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 15.546c-.523 0-1.046.151-1.5.454a2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0A2.704 2.704 0 003 15.546V20a1 1 0 001 1h16a1 1 0 001-1v-4.454zM3 15.546V12a2 2 0 012-2h14a2 2 0 012 2v3.546M9 10V4a2 2 0 012-2h2a2 2 0 012 2v6"
|
||||
/>
|
||||
</svg>
|
||||
<Cake size={14} />
|
||||
</span>
|
||||
Geburtstag
|
||||
</label>
|
||||
|
|
@ -123,28 +103,14 @@
|
|||
onclick={() => removeCustomDate(customDate.id)}
|
||||
aria-label="Datum entfernen"
|
||||
>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={18} />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<!-- Add button -->
|
||||
<button type="button" class="add-button" onclick={addCustomDate}>
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={16} />
|
||||
Datum hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { ChatCircle, CaretDown } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
linkedin: string;
|
||||
twitter: string;
|
||||
|
|
@ -64,25 +66,10 @@
|
|||
onclick={() => (isOpen = !isOpen)}
|
||||
>
|
||||
<div class="section-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
|
||||
/>
|
||||
</svg>
|
||||
<ChatCircle size={18} />
|
||||
</div>
|
||||
<h2 class="section-title">Social Media</h2>
|
||||
<svg
|
||||
class="chevron-icon"
|
||||
class:chevron-open={isOpen}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<CaretDown size={20} class="chevron-icon {isOpen ? 'chevron-open' : ''}" />
|
||||
</button>
|
||||
{#if isOpen}
|
||||
<div class="social-grid">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { CloudArrowUp, File, Table } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onFileSelect: (file: File) => void;
|
||||
|
|
@ -81,20 +82,7 @@
|
|||
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<div class="w-16 h-16 rounded-full bg-primary/10 flex items-center justify-center text-primary">
|
||||
<svg
|
||||
class="w-8 h-8"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
|
||||
/>
|
||||
</svg>
|
||||
<CloudArrowUp size={32} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -104,25 +92,11 @@
|
|||
|
||||
<div class="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<span class="flex items-center gap-1">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<File size={16} />
|
||||
vCard (.vcf)
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Table size={16} />
|
||||
CSV (.csv)
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
// contactsStore removed — live queries auto-update
|
||||
import { GoogleImportSkeleton } from '$lib/components/skeletons';
|
||||
import { ContactsEvents } from '@manacore/shared-utils/analytics';
|
||||
import { Check } from '@manacore/shared-icons';
|
||||
|
||||
type Step = 'connect' | 'select' | 'result';
|
||||
|
||||
|
|
@ -345,14 +346,7 @@
|
|||
<div
|
||||
class="w-20 h-20 mx-auto rounded-full bg-green-500/10 flex items-center justify-center text-green-500"
|
||||
>
|
||||
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={40} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Plus, Check, Heart, Phone, Envelope, TextAa, CaretDown } from '@manacore/shared-icons';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import type { Contact } from '$lib/api/contacts';
|
||||
import type { SortField } from '$lib/components/SortToggle.svelte';
|
||||
|
|
@ -173,14 +174,7 @@
|
|||
>
|
||||
<!-- Plus Avatar -->
|
||||
<div class="avatar-sm new-contact-avatar">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={18} />
|
||||
</div>
|
||||
|
||||
<!-- Text -->
|
||||
|
|
@ -220,9 +214,7 @@
|
|||
aria-label={selectedIds.has(contact.id) ? 'Auswahl aufheben' : 'Auswählen'}
|
||||
>
|
||||
{#if selectedIds.has(contact.id)}
|
||||
<svg class="w-5 h-5 text-primary" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
|
||||
</svg>
|
||||
<Check size={20} class="text-primary" />
|
||||
{:else}
|
||||
<div class="w-5 h-5 rounded border-2 border-border"></div>
|
||||
{/if}
|
||||
|
|
@ -262,11 +254,7 @@
|
|||
{getDisplayName(contact)}
|
||||
</span>
|
||||
{#if contact.isFavorite}
|
||||
<svg class="favorite-badge" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={13} weight="fill" class="favorite-badge" />
|
||||
{/if}
|
||||
{#if contact.company}
|
||||
<span class="contact-company-inline">@ {contact.company}</span>
|
||||
|
|
@ -297,26 +285,12 @@
|
|||
class="action-chip"
|
||||
title={contact.mobile || contact.phone}
|
||||
>
|
||||
<svg class="action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
|
||||
/>
|
||||
</svg>
|
||||
<Phone size={16} class="action-icon" />
|
||||
</a>
|
||||
{/if}
|
||||
{#if contact.email}
|
||||
<a href="mailto:{contact.email}" class="action-chip" title={contact.email}>
|
||||
<svg class="action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={16} class="action-icon" />
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -339,22 +313,11 @@
|
|||
? 'Alphabet-Navigation öffnen (Rechtsklick für Optionen)'
|
||||
: 'Alphabet-Navigation schließen (Rechtsklick für Optionen)'}
|
||||
>
|
||||
<svg class="fab-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
{#if isAlphabetNavCollapsed}
|
||||
<!-- ABC/Alphabet icon -->
|
||||
<text x="3" y="17" font-size="12" font-weight="bold" fill="currentColor" stroke="none"
|
||||
>AZ</text
|
||||
>
|
||||
{:else}
|
||||
<!-- Chevron down icon -->
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 9l-7 7-7-7"
|
||||
/>
|
||||
{/if}
|
||||
</svg>
|
||||
{#if isAlphabetNavCollapsed}
|
||||
<TextAa size={24} class="fab-icon" />
|
||||
{:else}
|
||||
<CaretDown size={24} class="fab-icon" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Plus, Check, Heart, Phone, Envelope } from '@manacore/shared-icons';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import type { Contact } from '$lib/api/contacts';
|
||||
import { newContactModalStore } from '$lib/stores/new-contact-modal.svelte';
|
||||
|
|
@ -118,14 +119,7 @@
|
|||
>
|
||||
<!-- Plus Avatar -->
|
||||
<div class="grid-avatar new-contact-avatar">
|
||||
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
<Plus size={40} />
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
|
|
@ -154,9 +148,7 @@
|
|||
aria-label={selectedIds.has(contact.id) ? 'Auswahl aufheben' : 'Auswählen'}
|
||||
>
|
||||
{#if selectedIds.has(contact.id)}
|
||||
<svg class="w-5 h-5 text-primary" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
|
||||
</svg>
|
||||
<Check size={20} class="text-primary" />
|
||||
{:else}
|
||||
<div class="w-5 h-5 rounded border-2 border-border"></div>
|
||||
{/if}
|
||||
|
|
@ -170,25 +162,9 @@
|
|||
title={contact.isFavorite ? $_('contacts.unfavorite') : $_('contacts.favorite')}
|
||||
>
|
||||
{#if contact.isFavorite}
|
||||
<svg class="w-5 h-5 text-red-500 fill-current" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={20} weight="fill" class="text-red-500" />
|
||||
{:else}
|
||||
<svg
|
||||
class="w-5 h-5 text-muted-foreground"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Heart size={20} class="text-muted-foreground" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
|
|
@ -225,14 +201,7 @@
|
|||
class="action-btn"
|
||||
title={$_('contacts.call')}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
|
||||
/>
|
||||
</svg>
|
||||
<Phone size={16} />
|
||||
</a>
|
||||
{/if}
|
||||
{#if contact.email}
|
||||
|
|
@ -242,14 +211,7 @@
|
|||
class="action-btn"
|
||||
title={$_('contacts.email')}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={16} />
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,16 @@
|
|||
import type { Contact } from '$lib/api/contacts';
|
||||
import { ContactListSkeleton } from '$lib/components/skeletons';
|
||||
import '$lib/i18n';
|
||||
import {
|
||||
CaretLeft,
|
||||
Archive,
|
||||
MagnifyingGlass,
|
||||
Warning,
|
||||
Users,
|
||||
Info,
|
||||
ArrowCounterClockwise,
|
||||
Trash,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let loading = $state(true);
|
||||
let contacts = $state<Contact[]>([]);
|
||||
|
|
@ -88,34 +98,18 @@
|
|||
<!-- Header -->
|
||||
<header class="header">
|
||||
<a href="/" class="back-button" aria-label="Zurück">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
<CaretLeft size={20} />
|
||||
</a>
|
||||
<h1 class="title">Archiv</h1>
|
||||
<div class="title-icon">
|
||||
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||
/>
|
||||
</svg>
|
||||
<Archive size={20} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Search -->
|
||||
{#if contacts.length > 0}
|
||||
<div class="search-wrapper">
|
||||
<svg class="search-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MagnifyingGlass class="search-icon" size={20} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Archiv durchsuchen..."
|
||||
|
|
@ -127,14 +121,7 @@
|
|||
|
||||
{#if error}
|
||||
<div class="error-banner" role="alert">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<Warning size={16} />
|
||||
<span>{error}</span>
|
||||
<button onclick={() => (error = null)} class="dismiss-btn">×</button>
|
||||
</div>
|
||||
|
|
@ -145,14 +132,7 @@
|
|||
{:else if contacts.length === 0}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||
/>
|
||||
</svg>
|
||||
<Archive size={40} />
|
||||
</div>
|
||||
<h2 class="empty-title">Archiv ist leer</h2>
|
||||
<p class="empty-description">
|
||||
|
|
@ -160,42 +140,21 @@
|
|||
löschen.
|
||||
</p>
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Users size={16} />
|
||||
Zu Kontakten
|
||||
</a>
|
||||
</div>
|
||||
{:else if filteredContacts().length === 0}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<MagnifyingGlass size={40} />
|
||||
</div>
|
||||
<h2 class="empty-title">Keine Ergebnisse</h2>
|
||||
<p class="empty-description">Keine archivierten Kontakte gefunden für "{searchQuery}"</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="info-banner">
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Info size={16} />
|
||||
<span>Archivierte Kontakte können wiederhergestellt oder endgültig gelöscht werden.</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -238,14 +197,7 @@
|
|||
aria-label="Wiederherstellen"
|
||||
title="Wiederherstellen"
|
||||
>
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowCounterClockwise size={16} />
|
||||
</button>
|
||||
<button
|
||||
onclick={(e) => handleDelete(e, contact)}
|
||||
|
|
@ -253,14 +205,7 @@
|
|||
aria-label="Endgültig löschen"
|
||||
title="Endgültig löschen"
|
||||
>
|
||||
<svg class="icon-sm" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,14 @@
|
|||
// contactsStore removed — live queries auto-update
|
||||
import { ImportPreviewSkeleton } from '$lib/components/skeletons';
|
||||
import { ContactsEvents } from '@manacore/shared-utils/analytics';
|
||||
import {
|
||||
Upload,
|
||||
DownloadSimple,
|
||||
File,
|
||||
FileText,
|
||||
AddressBook,
|
||||
Check,
|
||||
} from '@manacore/shared-icons';
|
||||
import '$lib/i18n';
|
||||
|
||||
type Tab = 'import' | 'export';
|
||||
|
|
@ -187,14 +195,7 @@
|
|||
? 'bg-card text-foreground shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground'}"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<Upload size={20} />
|
||||
Import
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -205,14 +206,7 @@
|
|||
? 'bg-card text-foreground shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground'}"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
||||
/>
|
||||
</svg>
|
||||
<DownloadSimple size={20} />
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -230,14 +224,7 @@
|
|||
: 'border-transparent text-muted-foreground hover:text-foreground'}"
|
||||
>
|
||||
<span class="flex items-center gap-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<File size={20} />
|
||||
Datei
|
||||
</span>
|
||||
</button>
|
||||
|
|
@ -292,14 +279,7 @@
|
|||
<div
|
||||
class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center text-primary flex-shrink-0"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0"
|
||||
/>
|
||||
</svg>
|
||||
<AddressBook size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">vCard (.vcf)</div>
|
||||
|
|
@ -312,14 +292,7 @@
|
|||
<div
|
||||
class="w-10 h-10 rounded-lg bg-green-500/10 flex items-center justify-center text-green-500 flex-shrink-0"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<FileText size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">CSV (.csv)</div>
|
||||
|
|
@ -336,14 +309,7 @@
|
|||
onclick={handleDownloadTemplate}
|
||||
class="text-primary hover:underline text-sm inline-flex items-center gap-2"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
||||
/>
|
||||
</svg>
|
||||
<DownloadSimple size={16} />
|
||||
CSV-Vorlage herunterladen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -366,14 +332,7 @@
|
|||
<div
|
||||
class="w-20 h-20 mx-auto rounded-full bg-green-500/10 flex items-center justify-center text-green-500"
|
||||
>
|
||||
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={40} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -433,14 +392,7 @@
|
|||
<div
|
||||
class="bg-green-500/10 border border-green-500/20 rounded-lg p-4 text-green-600 dark:text-green-400 flex items-center gap-3"
|
||||
>
|
||||
<svg class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<Check size={20} class="flex-shrink-0" />
|
||||
Export erfolgreich! Die Datei wurde heruntergeladen.
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -468,14 +420,7 @@
|
|||
<div
|
||||
class="w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center text-primary"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
|
||||
/>
|
||||
</svg>
|
||||
<AddressBook size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">vCard</div>
|
||||
|
|
@ -495,14 +440,7 @@
|
|||
<div
|
||||
class="w-12 h-12 rounded-lg bg-green-500/10 flex items-center justify-center text-green-500"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<FileText size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">CSV</div>
|
||||
|
|
@ -592,14 +530,7 @@
|
|||
</span>
|
||||
{:else}
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
||||
/>
|
||||
</svg>
|
||||
<DownloadSimple size={20} />
|
||||
Kontakte exportieren
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import MergeModal from '$lib/components/duplicates/MergeModal.svelte';
|
||||
import { DuplicateListSkeleton } from '$lib/components/skeletons';
|
||||
import { toastStore } from '@manacore/shared-ui';
|
||||
import { ArrowsClockwise } from '@manacore/shared-icons';
|
||||
|
||||
let duplicates = $state<DuplicateGroup[]>([]);
|
||||
let loading = $state(true);
|
||||
|
|
@ -118,14 +119,7 @@
|
|||
{#if loading}
|
||||
<span class="animate-spin mr-2">⏳</span>
|
||||
{:else}
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsClockwise size={20} class="mr-2" />
|
||||
{/if}
|
||||
Erneut suchen
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,37 @@
|
|||
SettingsDangerButton,
|
||||
GlobalSettingsSection,
|
||||
} from '@manacore/shared-ui';
|
||||
import {
|
||||
User,
|
||||
Envelope,
|
||||
ShieldCheck,
|
||||
Layout,
|
||||
List,
|
||||
SortAscending,
|
||||
ArrowsDownUp,
|
||||
Image,
|
||||
Buildings,
|
||||
Hash,
|
||||
AddressBook,
|
||||
Calendar,
|
||||
Cake,
|
||||
Bell,
|
||||
ArrowsLeftRight,
|
||||
Upload,
|
||||
Download,
|
||||
Archive,
|
||||
Copy,
|
||||
ClipboardText,
|
||||
Sliders,
|
||||
Lock,
|
||||
EyeSlash,
|
||||
ShareNetwork,
|
||||
Trash,
|
||||
Info,
|
||||
Tag,
|
||||
ArrowCounterClockwise,
|
||||
SignOut,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
// Options for selects
|
||||
const viewOptions = [
|
||||
|
|
@ -102,40 +133,19 @@
|
|||
<!-- Account Section -->
|
||||
<SettingsSection title="Konto">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
<SettingsRow label="E-Mail" description={authStore.user?.email || 'Nicht angemeldet'}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Envelope size={20} />
|
||||
{/snippet}
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow label="Konto-Status" description="Dein aktueller Kontostatus" border={false}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
||||
/>
|
||||
</svg>
|
||||
<ShieldCheck size={20} />
|
||||
{/snippet}
|
||||
<span
|
||||
class="rounded-full bg-green-100 px-3 py-1 text-xs font-medium text-green-800 dark:bg-green-900/20 dark:text-green-400"
|
||||
|
|
@ -152,14 +162,7 @@
|
|||
<!-- Display Settings Section -->
|
||||
<SettingsSection title="Anzeige">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
|
||||
/>
|
||||
</svg>
|
||||
<Layout size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
|
|
@ -172,14 +175,7 @@
|
|||
contactsSettings.set('defaultView', v as ContactView)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 10h16M4 14h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
<List size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
|
||||
|
|
@ -191,14 +187,7 @@
|
|||
onchange={(v: string | number | null) => contactsSettings.set('sortBy', v as ContactSortBy)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<SortAscending size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
|
||||
|
|
@ -211,14 +200,7 @@
|
|||
contactsSettings.set('sortOrder', v as ContactSortOrder)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsDownUp size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
|
||||
|
|
@ -229,14 +211,7 @@
|
|||
onToggle={(v) => contactsSettings.set('showPhotos', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Image size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -247,14 +222,7 @@
|
|||
onToggle={(v) => contactsSettings.set('showCompany', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
|
||||
/>
|
||||
</svg>
|
||||
<Buildings size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -268,14 +236,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14"
|
||||
/>
|
||||
</svg>
|
||||
<Hash size={20} />
|
||||
{/snippet}
|
||||
</SettingsNumberInput>
|
||||
</SettingsCard>
|
||||
|
|
@ -284,14 +245,7 @@
|
|||
<!-- Contact Format Section -->
|
||||
<SettingsSection title="Kontakt-Darstellung">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
|
||||
/>
|
||||
</svg>
|
||||
<AddressBook size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
|
|
@ -304,14 +258,7 @@
|
|||
contactsSettings.set('nameFormat', v as 'first-last' | 'last-first')}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
<User size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
|
||||
|
|
@ -324,14 +271,7 @@
|
|||
contactsSettings.set('dateFormat', v as DateFormat)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Calendar size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
|
||||
|
|
@ -342,14 +282,7 @@
|
|||
onToggle={(v) => contactsSettings.set('showBirthdayReminders', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 15.546c-.523 0-1.046.151-1.5.454a2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.704 2.704 0 00-3 0 2.704 2.704 0 01-3 0 2.701 2.701 0 00-1.5-.454M9 6v2m3-2v2m3-2v2M9 3h.01M12 3h.01M15 3h.01M21 21v-7a2 2 0 00-2-2H5a2 2 0 00-2 2v7h18zm-3-9v-2a2 2 0 00-2-2H8a2 2 0 00-2 2v2h12z"
|
||||
/>
|
||||
</svg>
|
||||
<Cake size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -363,14 +296,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
|
||||
/>
|
||||
</svg>
|
||||
<Bell size={20} />
|
||||
{/snippet}
|
||||
</SettingsNumberInput>
|
||||
</SettingsCard>
|
||||
|
|
@ -379,14 +305,7 @@
|
|||
<!-- Import/Export Section -->
|
||||
<SettingsSection title="Daten">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowsLeftRight size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
|
|
@ -396,14 +315,7 @@
|
|||
href="/data?tab=import"
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
|
||||
/>
|
||||
</svg>
|
||||
<Upload size={20} />
|
||||
{/snippet}
|
||||
</SettingsRow>
|
||||
|
||||
|
|
@ -413,14 +325,7 @@
|
|||
href="/data?tab=export"
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
||||
/>
|
||||
</svg>
|
||||
<Download size={20} />
|
||||
{/snippet}
|
||||
</SettingsRow>
|
||||
|
||||
|
|
@ -431,14 +336,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||
/>
|
||||
</svg>
|
||||
<Archive size={20} />
|
||||
{/snippet}
|
||||
</SettingsRow>
|
||||
</SettingsCard>
|
||||
|
|
@ -447,14 +345,7 @@
|
|||
<!-- Duplicates Section -->
|
||||
<SettingsSection title="Duplikate">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<Copy size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
|
|
@ -465,14 +356,7 @@
|
|||
onToggle={(v) => contactsSettings.set('autoDetectDuplicates', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
|
||||
/>
|
||||
</svg>
|
||||
<ClipboardText size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -486,14 +370,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"
|
||||
/>
|
||||
</svg>
|
||||
<Sliders size={20} />
|
||||
{/snippet}
|
||||
</SettingsSelect>
|
||||
</SettingsCard>
|
||||
|
|
@ -502,14 +379,7 @@
|
|||
<!-- Privacy Section -->
|
||||
<SettingsSection title="Datenschutz">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
||||
/>
|
||||
</svg>
|
||||
<Lock size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
|
|
@ -520,14 +390,7 @@
|
|||
onToggle={(v) => contactsSettings.set('privacyMode', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
|
||||
/>
|
||||
</svg>
|
||||
<EyeSlash size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -538,14 +401,7 @@
|
|||
onToggle={(v) => contactsSettings.set('confirmBeforeSharing', v)}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
|
||||
/>
|
||||
</svg>
|
||||
<ShareNetwork size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
|
||||
|
|
@ -557,14 +413,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
<Trash size={20} />
|
||||
{/snippet}
|
||||
</SettingsToggle>
|
||||
</SettingsCard>
|
||||
|
|
@ -573,27 +422,13 @@
|
|||
<!-- About Section -->
|
||||
<SettingsSection title="Über">
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<Info size={20} />
|
||||
{/snippet}
|
||||
|
||||
<SettingsCard>
|
||||
<SettingsRow label="Version" border={false}>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
|
||||
/>
|
||||
</svg>
|
||||
<Tag size={20} />
|
||||
{/snippet}
|
||||
<span class="text-[hsl(var(--muted-foreground))]">1.0.0</span>
|
||||
</SettingsRow>
|
||||
|
|
@ -609,14 +444,7 @@
|
|||
onclick={handleResetSettings}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
<ArrowCounterClockwise size={20} />
|
||||
{/snippet}
|
||||
</SettingsDangerButton>
|
||||
|
||||
|
|
@ -628,14 +456,7 @@
|
|||
border={false}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
||||
/>
|
||||
</svg>
|
||||
<SignOut size={20} />
|
||||
{/snippet}
|
||||
</SettingsDangerButton>
|
||||
</SettingsDangerZone>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue