mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:01:09 +02:00
♻️ refactor: migrate all web apps to Phosphor icons
Replace lucide-svelte with @manacore/shared-icons across all web apps for consistent icon usage throughout the monorepo. Apps migrated: - calendar (12 files) - contacts (1 file) - matrix (16 files) - nutriphi (7 files) - presi (6 files) - questions (9 files) - skilltree (9 files) - storage (16 files) - todo (package.json only) Key icon mappings: - Trash2 → Trash - ChevronLeft/Right/Up/Down → CaretLeft/Right/Up/Down - Search → MagnifyingGlass - Settings → Gear - Loader2 → CircleNotch - AlertCircle → WarningCircle - ExternalLink → ArrowSquareOut - LogOut → SignOut
This commit is contained in:
parent
c21f780581
commit
b89749deed
86 changed files with 1736 additions and 904 deletions
|
|
@ -52,7 +52,6 @@
|
|||
"@neodrag/svelte": "^2.3.3",
|
||||
"d3-force": "^3.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-svelte": "^0.559.0",
|
||||
"suncalc": "^1.9.0",
|
||||
"svelte-dnd-action": "^0.9.68",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Calendar, CheckSquare, Filter } from 'lucide-svelte';
|
||||
import { Calendar, CheckSquare, Funnel } from '@manacore/shared-icons';
|
||||
import { FilterDropdown, type FilterDropdownOption } from '@manacore/shared-ui';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
<div class="filter-group">
|
||||
<div class="range-selector">
|
||||
<Filter size={14} />
|
||||
<Funnel size={14} />
|
||||
<FilterDropdown
|
||||
options={rangeOptions}
|
||||
value={timeRange}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { todosStore } from '$lib/stores/todos.svelte';
|
||||
import TodoCheckbox from '$lib/components/todo/TodoCheckbox.svelte';
|
||||
import PriorityBadge from '$lib/components/todo/PriorityBadge.svelte';
|
||||
import { Calendar, MapPin, Clock } from 'lucide-svelte';
|
||||
import { Calendar, MapPin, Clock } from '@manacore/shared-icons';
|
||||
import { format } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import { toDate } from '$lib/utils/eventDateHelpers';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { env } from '$env/dynamic/public';
|
||||
import type { BirthdayEvent } from '$lib/api/birthdays';
|
||||
import { settingsStore } from '$lib/stores/settings.svelte';
|
||||
import { X, User, ExternalLink, Cake } from 'lucide-svelte';
|
||||
import { X, User, ArrowSquareOut, Cake } from '@manacore/shared-icons';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
|
||||
|
|
@ -124,7 +124,7 @@
|
|||
<a href={contactUrl} target="_blank" rel="noopener noreferrer" class="action-btn primary">
|
||||
<User size={16} />
|
||||
<span>Kontakt öffnen</span>
|
||||
<ExternalLink size={14} class="external-icon" />
|
||||
<ArrowSquareOut size={14} class="external-icon" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { Task } from '$lib/api/todos';
|
||||
import { todosStore } from '$lib/stores/todos.svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { CheckSquare, Square } from 'lucide-svelte';
|
||||
import { CheckSquare, Square } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
task: Task;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import { PRIORITY_COLORS } from '$lib/api/todos';
|
||||
import TodoCheckbox from '$lib/components/todo/TodoCheckbox.svelte';
|
||||
import TodoDetailModal from '$lib/components/todo/TodoDetailModal.svelte';
|
||||
import { Check } from 'lucide-svelte';
|
||||
import { Check } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
date: Date;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import TodoItem from '$lib/components/todo/TodoItem.svelte';
|
||||
import TodoDetailModal from '$lib/components/todo/TodoDetailModal.svelte';
|
||||
import QuickAddTodo from '$lib/components/todo/QuickAddTodo.svelte';
|
||||
import { ChevronDown, ChevronRight, Plus, CheckSquare, AlertTriangle } from 'lucide-svelte';
|
||||
import { CaretDown, CaretRight, Plus, CheckSquare, Warning } from '@manacore/shared-icons';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
|
|
@ -67,9 +67,9 @@
|
|||
<button type="button" class="header-toggle" onclick={toggleExpanded}>
|
||||
<div class="header-left">
|
||||
{#if isExpanded}
|
||||
<ChevronDown size={16} />
|
||||
<CaretDown size={16} />
|
||||
{:else}
|
||||
<ChevronRight size={16} />
|
||||
<CaretRight size={16} />
|
||||
{/if}
|
||||
<CheckSquare size={16} class="section-icon" />
|
||||
<span class="section-title">Aufgaben</span>
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
{/if}
|
||||
{#if overdueCount > 0}
|
||||
<span class="overdue-badge" title="{overdueCount} überfällig">
|
||||
<AlertTriangle size={12} />
|
||||
<Warning size={12} />
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
<div class="section-content">
|
||||
{#if !todosStore.serviceAvailable}
|
||||
<div class="service-unavailable">
|
||||
<AlertTriangle size={16} />
|
||||
<Warning size={16} />
|
||||
<span>Todo-Service nicht erreichbar</span>
|
||||
</div>
|
||||
{:else if todosStore.loading}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { EventAttendee, AttendeeStatus } from '@calendar/shared';
|
||||
import type { ContactSummary, ContactOrManual, ManualContactEntry } from '@manacore/shared-types';
|
||||
import { ContactSelector, ContactAvatar } from '@manacore/shared-ui';
|
||||
import { Check, X, HelpCircle, Clock, ChevronDown } from 'lucide-svelte';
|
||||
import { Check, X, Question, Clock, CaretDown } from '@manacore/shared-icons';
|
||||
import { contactsStore } from '$lib/stores/contacts.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -178,12 +178,12 @@
|
|||
{:else if attendee.status === 'declined'}
|
||||
<X size={12} />
|
||||
{:else if attendee.status === 'tentative'}
|
||||
<HelpCircle size={12} />
|
||||
<Question size={12} />
|
||||
{:else}
|
||||
<Clock size={12} />
|
||||
{/if}
|
||||
<span class="hidden sm:inline">{getStatusLabel(attendee.status)}</span>
|
||||
<ChevronDown size={12} />
|
||||
<CaretDown size={12} />
|
||||
</button>
|
||||
|
||||
{#if showStatusDropdown === attendee.email}
|
||||
|
|
@ -213,7 +213,7 @@
|
|||
{:else if option.value === 'declined'}
|
||||
<X size={12} />
|
||||
{:else if option.value === 'tentative'}
|
||||
<HelpCircle size={12} />
|
||||
<Question size={12} />
|
||||
{:else}
|
||||
<Clock size={12} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
FilterDropdown,
|
||||
type FilterDropdownOption,
|
||||
} from '@manacore/shared-ui';
|
||||
import { Users } from 'lucide-svelte';
|
||||
import { Users } from '@manacore/shared-icons';
|
||||
import { format, addMinutes } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import { toDate } from '$lib/utils/eventDateHelpers';
|
||||
|
|
|
|||
|
|
@ -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, ExternalLink } from 'lucide-svelte';
|
||||
import { X, ArrowSquareOut } from '@manacore/shared-icons';
|
||||
import { contactsStore } from '$lib/stores/contacts.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
"
|
||||
title="Kontakt öffnen"
|
||||
>
|
||||
<ExternalLink size={16} />
|
||||
<ArrowSquareOut size={16} />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { todosStore } from '$lib/stores/todos.svelte';
|
||||
import { Plus, X } from 'lucide-svelte';
|
||||
import { Plus, X } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
placeholder?: string;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Check } from 'lucide-svelte';
|
||||
import { Check } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
checked: boolean;
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
Clock,
|
||||
Folder,
|
||||
Tag,
|
||||
Trash2,
|
||||
Trash,
|
||||
CheckSquare,
|
||||
AlertCircle,
|
||||
CalendarClock,
|
||||
WarningCircle,
|
||||
CalendarCheck,
|
||||
Timer,
|
||||
} from 'lucide-svelte';
|
||||
} from '@manacore/shared-icons';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
|
||||
|
|
@ -239,7 +239,7 @@
|
|||
<!-- Time-Blocking Section -->
|
||||
<div class="form-section">
|
||||
<span class="section-label">
|
||||
<CalendarClock size={16} />
|
||||
<CalendarCheck size={16} />
|
||||
Zeitplanung (Time-Blocking)
|
||||
</span>
|
||||
<div class="form-row">
|
||||
|
|
@ -313,7 +313,7 @@
|
|||
<!-- Time-Blocking Display -->
|
||||
{#if task.scheduledDate}
|
||||
<div class="detail-item scheduled">
|
||||
<CalendarClock size={16} />
|
||||
<CalendarCheck size={16} />
|
||||
<span>
|
||||
Geplant: {formatDisplayDate(task.scheduledDate)}
|
||||
{#if task.scheduledStartTime}
|
||||
|
|
@ -334,7 +334,7 @@
|
|||
{/if}
|
||||
|
||||
<div class="detail-item">
|
||||
<AlertCircle size={16} />
|
||||
<WarningCircle size={16} />
|
||||
<PriorityBadge {priority} variant="pill" showLabel />
|
||||
</div>
|
||||
|
||||
|
|
@ -397,7 +397,7 @@
|
|||
</button>
|
||||
{:else}
|
||||
<button type="button" class="btn btn-danger" onclick={handleDelete} disabled={isDeleting}>
|
||||
<Trash2 size={16} />
|
||||
<Trash size={16} />
|
||||
{#if isDeleting}
|
||||
Löschen...
|
||||
{:else}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
"d3-selection": "^3.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-svelte": "^0.556.0",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { _ } from 'svelte-i18n';
|
||||
import { onMount } from 'svelte';
|
||||
import { PillViewSwitcher, FilterDropdown, type FilterDropdownOption } from '@manacore/shared-ui';
|
||||
import { X } from 'lucide-svelte';
|
||||
import { X } from '@manacore/shared-icons';
|
||||
import { contactsFilterStore } from '$lib/stores/filter.svelte';
|
||||
import { tagsApi, type ContactTag, type Contact } from '$lib/api/contacts';
|
||||
import type { ContactFilter, BirthdayFilter } from '$lib/components/FilterBar.svelte';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ A minimal, privacy-focused Matrix client that connects to your self-hosted Synap
|
|||
| Frontend | SvelteKit 2, Svelte 5 (runes), Tailwind CSS 4 |
|
||||
| Matrix SDK | matrix-js-sdk |
|
||||
| State Management | Svelte 5 runes ($state, $derived) |
|
||||
| Icons | lucide-svelte |
|
||||
| Icons | @manacore/shared-icons (Phosphor) |
|
||||
| Date Handling | date-fns |
|
||||
|
||||
## Project Structure
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
"@manacore/shared-tailwind": "workspace:*",
|
||||
"@manacore/shared-i18n": "workspace:*",
|
||||
"@manacore/shared-icons": "workspace:*",
|
||||
"lucide-svelte": "^0.509.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import { X, Users, MessageCircle, Lock, Globe, Loader2 } from 'lucide-svelte';
|
||||
import { X, Users, ChatCircle, Lock, Globe, CircleNotch } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
|
@ -102,7 +102,10 @@
|
|||
|
||||
{#if open}
|
||||
<!-- Backdrop -->
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onclick={handleClose}>
|
||||
<div
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
|
||||
onclick={handleClose}
|
||||
>
|
||||
<!-- Dialog -->
|
||||
<div
|
||||
class="w-full max-w-md rounded-xl bg-base-100 shadow-xl"
|
||||
|
|
@ -128,7 +131,7 @@
|
|||
class:btn-ghost={!isDirect}
|
||||
onclick={() => (isDirect = true)}
|
||||
>
|
||||
<MessageCircle class="h-4 w-4" />
|
||||
<ChatCircle class="h-4 w-4" />
|
||||
Direktnachricht
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -182,11 +185,7 @@
|
|||
Öffentlicher Raum
|
||||
{/if}
|
||||
</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle"
|
||||
bind:checked={isPrivate}
|
||||
/>
|
||||
<input type="checkbox" class="toggle" bind:checked={isPrivate} />
|
||||
</label>
|
||||
<p class="text-xs text-base-content/60 ml-1">
|
||||
{isPrivate
|
||||
|
|
@ -213,7 +212,7 @@
|
|||
placeholder="@benutzer:server.de oder Name"
|
||||
/>
|
||||
{#if searching}
|
||||
<Loader2 class="absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin" />
|
||||
<CircleNotch class="absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
|
@ -222,10 +221,7 @@
|
|||
<ul class="menu mt-2 max-h-40 overflow-y-auto rounded-lg bg-base-200 p-2">
|
||||
{#each searchResults as user}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
onclick={() => selectUser(user)}
|
||||
>
|
||||
<button class="flex items-center gap-2" onclick={() => selectUser(user)}>
|
||||
<div class="avatar placeholder">
|
||||
<div class="w-8 rounded-full bg-neutral text-neutral-content">
|
||||
{#if user.avatarUrl}
|
||||
|
|
@ -275,7 +271,7 @@
|
|||
<button class="btn btn-ghost" onclick={handleClose}>Abbrechen</button>
|
||||
<button class="btn btn-primary" onclick={handleCreate} disabled={loading}>
|
||||
{#if loading}
|
||||
<Loader2 class="h-4 w-4 animate-spin" />
|
||||
<CircleNotch class="h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
{isDirect ? 'Chat starten' : 'Raum erstellen'}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
import { format, isToday, isYesterday } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import {
|
||||
Reply,
|
||||
Pencil,
|
||||
Trash2,
|
||||
MoreHorizontal,
|
||||
Download,
|
||||
FileIcon,
|
||||
ArrowBendUpLeft,
|
||||
PencilSimple,
|
||||
Trash,
|
||||
DotsThree,
|
||||
DownloadSimple,
|
||||
File as FileIcon,
|
||||
Play,
|
||||
Image as ImageIcon,
|
||||
Lock,
|
||||
AlertTriangle,
|
||||
} from 'lucide-svelte';
|
||||
Warning,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
message: SimpleMessage;
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
<div
|
||||
class="mb-1 flex items-center gap-2 rounded border-l-2 border-primary/50 bg-muted px-2 py-1 text-sm"
|
||||
>
|
||||
<Reply class="h-3 w-3 flex-shrink-0 text-muted-foreground" />
|
||||
<ArrowBendUpLeft class="h-3 w-3 flex-shrink-0 text-muted-foreground" />
|
||||
<span class="truncate text-muted-foreground">{message.replyToBody}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
{:else if isDecryptionError}
|
||||
<!-- Decryption error -->
|
||||
<div class="flex items-center gap-2 rounded-lg bg-warning/10 px-3 py-2 text-warning">
|
||||
<AlertTriangle class="h-4 w-4 flex-shrink-0" />
|
||||
<Warning class="h-4 w-4 flex-shrink-0" />
|
||||
<span class="text-sm">
|
||||
Nachricht kann nicht entschlüsselt werden. Möglicherweise fehlen Schlüssel.
|
||||
</span>
|
||||
|
|
@ -224,7 +224,7 @@
|
|||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
<Download class="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||
<DownloadSimple class="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||
</a>
|
||||
{:else if message.type === 'm.emote'}
|
||||
<p class="italic text-muted-foreground">* {message.senderName} {message.body}</p>
|
||||
|
|
@ -251,16 +251,16 @@
|
|||
class="absolute -top-2 right-2 flex items-center gap-1 rounded-lg border border-border bg-surface p-1 shadow-sm"
|
||||
>
|
||||
<button class="btn-ghost rounded p-1" title="Antworten" onclick={() => onReply?.(message)}>
|
||||
<Reply class="h-4 w-4" />
|
||||
<ArrowBendUpLeft class="h-4 w-4" />
|
||||
</button>
|
||||
{#if message.isOwn && message.type === 'm.text'}
|
||||
<button class="btn-ghost rounded p-1" title="Bearbeiten" onclick={() => onEdit?.(message)}>
|
||||
<Pencil class="h-4 w-4" />
|
||||
<PencilSimple class="h-4 w-4" />
|
||||
</button>
|
||||
{/if}
|
||||
{#if message.isOwn}
|
||||
<button class="btn-ghost rounded p-1 text-error" title="Löschen" onclick={handleDelete}>
|
||||
<Trash2 class="h-4 w-4" />
|
||||
<Trash class="h-4 w-4" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { matrixStore, type SimpleMessage } from '$lib/matrix';
|
||||
import { Send, Paperclip, Smile, X, Image, File, Loader2 } from 'lucide-svelte';
|
||||
import {
|
||||
PaperPlaneTilt,
|
||||
Paperclip,
|
||||
Smiley,
|
||||
X,
|
||||
Image,
|
||||
File,
|
||||
CircleNotch,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
replyTo?: SimpleMessage | null;
|
||||
|
|
@ -163,7 +171,7 @@
|
|||
<!-- Upload Progress -->
|
||||
{#if uploading}
|
||||
<div class="flex items-center gap-3 px-4 py-2">
|
||||
<Loader2 class="h-5 w-5 animate-spin text-primary" />
|
||||
<CircleNotch class="h-5 w-5 animate-spin text-primary" />
|
||||
<div class="flex-1">
|
||||
<div class="h-2 overflow-hidden rounded-full bg-base-300">
|
||||
<div
|
||||
|
|
@ -242,7 +250,7 @@
|
|||
title="Emoji hinzufügen"
|
||||
disabled
|
||||
>
|
||||
<Smile class="h-5 w-5" />
|
||||
<Smiley class="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -253,7 +261,7 @@
|
|||
disabled={!message.trim() || uploading}
|
||||
title={editMessage ? 'Speichern' : 'Senden'}
|
||||
>
|
||||
<Send class="h-5 w-5" />
|
||||
<PaperPlaneTilt class="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import {
|
||||
Menu,
|
||||
List,
|
||||
Phone,
|
||||
Video,
|
||||
VideoCamera,
|
||||
Info,
|
||||
LockOpen,
|
||||
ShieldCheck,
|
||||
ShieldAlert,
|
||||
ShieldWarning,
|
||||
Users,
|
||||
} from 'lucide-svelte';
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onMenuClick?: () => void;
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
<header class="flex items-center gap-3 border-b border-border bg-surface px-4 py-3">
|
||||
<!-- Mobile menu button -->
|
||||
<button class="btn-ghost rounded p-2 lg:hidden" onclick={onMenuClick}>
|
||||
<Menu class="h-5 w-5" />
|
||||
<List class="h-5 w-5" />
|
||||
</button>
|
||||
|
||||
<!-- Room avatar -->
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
class="flex-shrink-0"
|
||||
title="Verschlüsselt - {encryptionStatus.unverifiedDevices} unverifizierte Geräte"
|
||||
>
|
||||
<ShieldAlert class="h-4 w-4 text-warning" />
|
||||
<ShieldWarning class="h-4 w-4 text-warning" />
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
<Phone class="h-5 w-5" />
|
||||
</button>
|
||||
<button class="btn-ghost rounded p-2" title="Videoanruf" disabled>
|
||||
<Video class="h-5 w-5" />
|
||||
<VideoCamera class="h-5 w-5" />
|
||||
</button>
|
||||
<button class="btn-ghost rounded p-2" title="Rauminfo" onclick={onInfoClick}>
|
||||
<Info class="h-5 w-5" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { SimpleRoom } from '$lib/matrix';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { de } from 'date-fns/locale';
|
||||
import { Lock, Users } from 'lucide-svelte';
|
||||
import { Lock, Users } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
room: SimpleRoom;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import RoomItem from './RoomItem.svelte';
|
||||
import { Search, Plus, Users, MessageCircle } from 'lucide-svelte';
|
||||
import { MagnifyingGlass, Plus, Users, ChatCircle } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onCreateRoom?: () => void;
|
||||
|
|
@ -23,7 +23,9 @@
|
|||
<!-- Search -->
|
||||
<div class="p-3">
|
||||
<div class="relative">
|
||||
<Search class="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-base-content/50" />
|
||||
<MagnifyingGlass
|
||||
class="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-base-content/50"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={search}
|
||||
|
|
@ -36,7 +38,7 @@
|
|||
<!-- Tabs -->
|
||||
<div class="tabs tabs-boxed mx-3 mb-2">
|
||||
<button class="tab flex-1" class:tab-active={showDMs} onclick={() => (showDMs = true)}>
|
||||
<MessageCircle class="mr-1 h-4 w-4" />
|
||||
<ChatCircle class="mr-1 h-4 w-4" />
|
||||
Direct
|
||||
{#if matrixStore.directRooms.length > 0}
|
||||
<span class="badge badge-sm ml-1">{matrixStore.directRooms.length}</span>
|
||||
|
|
@ -62,10 +64,10 @@
|
|||
{:else}
|
||||
<div class="flex flex-col items-center justify-center p-8 text-base-content/50">
|
||||
{#if search}
|
||||
<Search class="mb-2 h-8 w-8" />
|
||||
<MagnifyingGlass class="mb-2 h-8 w-8" />
|
||||
<p>No rooms match "{search}"</p>
|
||||
{:else}
|
||||
<MessageCircle class="mb-2 h-8 w-8" />
|
||||
<ChatCircle class="mb-2 h-8 w-8" />
|
||||
<p>No {showDMs ? 'direct messages' : 'rooms'} yet</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
import {
|
||||
X,
|
||||
Users,
|
||||
Settings,
|
||||
Gear,
|
||||
UserPlus,
|
||||
LogOut,
|
||||
SignOut,
|
||||
Crown,
|
||||
Shield,
|
||||
Bell,
|
||||
BellOff,
|
||||
Loader2,
|
||||
} from 'lucide-svelte';
|
||||
BellSlash,
|
||||
CircleNotch,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
|
@ -79,7 +79,9 @@
|
|||
|
||||
{#if open && room}
|
||||
<!-- Slide-in Panel -->
|
||||
<div class="fixed inset-y-0 right-0 z-40 flex w-80 flex-col border-l border-base-300 bg-base-100 shadow-xl">
|
||||
<div
|
||||
class="fixed inset-y-0 right-0 z-40 flex w-80 flex-col border-l border-base-300 bg-base-100 shadow-xl"
|
||||
>
|
||||
<!-- Header -->
|
||||
<header class="flex items-center justify-between border-b border-base-300 px-4 py-3">
|
||||
<h2 class="font-semibold">Raum-Details</h2>
|
||||
|
|
@ -126,7 +128,7 @@
|
|||
class:tab-active={activeTab === 'settings'}
|
||||
onclick={() => (activeTab = 'settings')}
|
||||
>
|
||||
<Settings class="mr-1 h-4 w-4" />
|
||||
<Gear class="mr-1 h-4 w-4" />
|
||||
Einstellungen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -145,7 +147,7 @@
|
|||
placeholder="Benutzer einladen..."
|
||||
/>
|
||||
{#if searching}
|
||||
<Loader2 class="absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin" />
|
||||
<CircleNotch class="absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
|
@ -215,7 +217,7 @@
|
|||
|
||||
<!-- Leave Room -->
|
||||
<button class="btn btn-ghost w-full justify-start text-error" onclick={leaveRoom}>
|
||||
<LogOut class="h-4 w-4" />
|
||||
<SignOut class="h-4 w-4" />
|
||||
Raum verlassen
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import Message from './Message.svelte';
|
||||
import TypingIndicator from './TypingIndicator.svelte';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import { Loader2, ArrowDown } from 'lucide-svelte';
|
||||
import { CircleNotch, ArrowDown } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onReply?: (message: SimpleMessage) => void;
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
<!-- Loading indicator at top -->
|
||||
{#if loadingMore}
|
||||
<div class="flex justify-center py-4">
|
||||
<Loader2 class="h-6 w-6 animate-spin text-base-content/50" />
|
||||
<CircleNotch class="h-6 w-6 animate-spin text-base-content/50" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import type { VerificationRequest, SasVerification } from '$lib/matrix/types';
|
||||
import { Check, X, Loader2, ShieldCheck } from 'lucide-svelte';
|
||||
import { Check, X, CircleNotch, ShieldCheck } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
request: VerificationRequest;
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
<div class="space-y-6">
|
||||
{#if phase === 'waiting'}
|
||||
<div class="flex flex-col items-center gap-4 py-8">
|
||||
<Loader2 class="h-12 w-12 animate-spin text-primary" />
|
||||
<CircleNotch class="h-12 w-12 animate-spin text-primary" />
|
||||
<p class="text-center text-muted-foreground">Warte auf Antwort vom anderen Gerät...</p>
|
||||
<p class="text-sm text-muted-foreground/70">
|
||||
Öffne die Verifizierungsanfrage auf deinem anderen Gerät.
|
||||
|
|
@ -128,7 +128,7 @@
|
|||
</div>
|
||||
{:else if phase === 'confirming'}
|
||||
<div class="flex flex-col items-center gap-4 py-8">
|
||||
<Loader2 class="h-12 w-12 animate-spin text-primary" />
|
||||
<CircleNotch class="h-12 w-12 animate-spin text-primary" />
|
||||
<p class="text-center text-muted-foreground">Bestätige Verifizierung...</p>
|
||||
</div>
|
||||
{:else if phase === 'done'}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
import {
|
||||
X,
|
||||
Key,
|
||||
Download,
|
||||
DownloadSimple,
|
||||
Copy,
|
||||
Check,
|
||||
Loader2,
|
||||
AlertTriangle,
|
||||
CircleNotch,
|
||||
Warning,
|
||||
ShieldCheck,
|
||||
} from 'lucide-svelte';
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
|
@ -185,7 +185,7 @@
|
|||
</p>
|
||||
|
||||
<div class="flex items-start gap-3 rounded-lg bg-warning/10 p-3 text-warning">
|
||||
<AlertTriangle class="h-5 w-5 flex-shrink-0 mt-0.5" />
|
||||
<Warning class="h-5 w-5 flex-shrink-0 mt-0.5" />
|
||||
<span class="text-sm">
|
||||
Ohne Recovery Key verlierst du den Zugriff auf deine verschlüsselten Nachrichten,
|
||||
wenn du dich abmeldest.
|
||||
|
|
@ -267,7 +267,7 @@
|
|||
{:else if step === 'show-key'}
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-start gap-3 rounded-lg bg-warning/10 p-3 text-warning">
|
||||
<AlertTriangle class="h-5 w-5 flex-shrink-0 mt-0.5" />
|
||||
<Warning class="h-5 w-5 flex-shrink-0 mt-0.5" />
|
||||
<span class="text-sm">
|
||||
Speichere diesen Schlüssel an einem sicheren Ort. Du benötigst ihn, um deine
|
||||
Nachrichten wiederherzustellen.
|
||||
|
|
@ -298,7 +298,7 @@
|
|||
class="btn-secondary flex-1 flex items-center justify-center gap-2"
|
||||
onclick={downloadKey}
|
||||
>
|
||||
<Download class="h-4 w-4" />
|
||||
<DownloadSimple class="h-4 w-4" />
|
||||
Herunterladen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -333,7 +333,7 @@
|
|||
disabled={loading}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="h-4 w-4 animate-spin" />
|
||||
<CircleNotch class="h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Weiter
|
||||
</button>
|
||||
|
|
@ -344,7 +344,7 @@
|
|||
disabled={loading || !inputRecoveryKey.trim()}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="h-4 w-4 animate-spin" />
|
||||
<CircleNotch class="h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Wiederherstellen
|
||||
</button>
|
||||
|
|
@ -357,7 +357,7 @@
|
|||
disabled={loading || !passphrase || passphrase !== passphraseConfirm}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="h-4 w-4 animate-spin" />
|
||||
<CircleNotch class="h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Schlüssel erstellen
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
X,
|
||||
Shield,
|
||||
ShieldCheck,
|
||||
ShieldAlert,
|
||||
Smartphone,
|
||||
ShieldWarning,
|
||||
DeviceMobile,
|
||||
Monitor,
|
||||
Loader2,
|
||||
RefreshCw,
|
||||
} from 'lucide-svelte';
|
||||
CircleNotch,
|
||||
ArrowsClockwise,
|
||||
} from '@manacore/shared-icons';
|
||||
import EmojiVerification from './EmojiVerification.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
name.includes('android') ||
|
||||
name.includes('ios')
|
||||
) {
|
||||
return Smartphone;
|
||||
return DeviceMobile;
|
||||
}
|
||||
return Monitor;
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
|
||||
{#if loading}
|
||||
<div class="flex justify-center py-8">
|
||||
<Loader2 class="h-8 w-8 animate-spin text-primary" />
|
||||
<CircleNotch class="h-8 w-8 animate-spin text-primary" />
|
||||
</div>
|
||||
{:else if devices.length === 0}
|
||||
<div class="py-8 text-center text-muted-foreground">
|
||||
|
|
@ -175,12 +175,12 @@
|
|||
{:else if device.blocked}
|
||||
<div class="relative">
|
||||
<DeviceIcon class="h-10 w-10 text-muted-foreground" />
|
||||
<ShieldAlert class="absolute -right-1 -bottom-1 h-5 w-5 text-error" />
|
||||
<ShieldWarning class="absolute -right-1 -bottom-1 h-5 w-5 text-error" />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="relative">
|
||||
<DeviceIcon class="h-10 w-10 text-muted-foreground" />
|
||||
<ShieldAlert class="absolute -right-1 -bottom-1 h-5 w-5 text-warning" />
|
||||
<ShieldWarning class="absolute -right-1 -bottom-1 h-5 w-5 text-warning" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -225,7 +225,7 @@
|
|||
onclick={loadDevices}
|
||||
disabled={loading}
|
||||
>
|
||||
<RefreshCw class={`h-4 w-4 ${loading ? 'animate-spin' : ''}`} />
|
||||
<ArrowsClockwise class={`h-4 w-4 ${loading ? 'animate-spin' : ''}`} />
|
||||
Aktualisieren
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { Loader2, AlertCircle, RefreshCw } from 'lucide-svelte';
|
||||
import { CircleNotch, WarningCircle, ArrowsClockwise } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
{#if loading}
|
||||
<!-- Loading State -->
|
||||
<div class="flex h-screen flex-col items-center justify-center gap-4">
|
||||
<Loader2 class="h-12 w-12 animate-spin text-primary" />
|
||||
<CircleNotch class="h-12 w-12 animate-spin text-primary" />
|
||||
<div class="text-center">
|
||||
<p class="font-medium">Connecting to Matrix...</p>
|
||||
<p class="text-sm text-base-content/60">
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
<!-- Error State -->
|
||||
<div class="flex h-screen flex-col items-center justify-center gap-4 p-4">
|
||||
<div class="rounded-full bg-error/10 p-4">
|
||||
<AlertCircle class="h-12 w-12 text-error" />
|
||||
<WarningCircle class="h-12 w-12 text-error" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h2 class="text-xl font-semibold">Connection Failed</h2>
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="btn btn-primary" onclick={retry}>
|
||||
<RefreshCw class="h-4 w-4" />
|
||||
<ArrowsClockwise class="h-4 w-4" />
|
||||
Retry
|
||||
</button>
|
||||
<button class="btn btn-ghost" onclick={logout}> Sign Out </button>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import CreateRoomDialog from '$lib/components/chat/CreateRoomDialog.svelte';
|
||||
import RoomSettingsPanel from '$lib/components/chat/RoomSettingsPanel.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Settings, LogOut, MessageSquare, Plus } from 'lucide-svelte';
|
||||
import { Gear, SignOut, ChatCircle, Plus } from '@manacore/shared-icons';
|
||||
|
||||
let sidebarOpen = $state(true);
|
||||
let showCreateRoom = $state(false);
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
<!-- Sidebar Header -->
|
||||
<header class="flex items-center justify-between border-b border-base-300 p-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<MessageSquare class="h-6 w-6 text-primary" />
|
||||
<ChatCircle class="h-6 w-6 text-primary" />
|
||||
<h1 class="text-xl font-bold">Mana Matrix</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
</button>
|
||||
<div class="dropdown dropdown-end">
|
||||
<button tabindex="0" class="btn btn-ghost btn-sm btn-circle">
|
||||
<Settings class="h-5 w-5" />
|
||||
<Gear class="h-5 w-5" />
|
||||
</button>
|
||||
<ul
|
||||
tabindex="0"
|
||||
|
|
@ -69,13 +69,13 @@
|
|||
>
|
||||
<li>
|
||||
<a href="/settings">
|
||||
<Settings class="h-4 w-4" />
|
||||
<Gear class="h-4 w-4" />
|
||||
Einstellungen
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<button onclick={handleLogout} class="text-error">
|
||||
<LogOut class="h-4 w-4" />
|
||||
<SignOut class="h-4 w-4" />
|
||||
Abmelden
|
||||
</button>
|
||||
</li>
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
{:else}
|
||||
<!-- No Room Selected -->
|
||||
<div class="flex flex-1 flex-col items-center justify-center gap-4 p-8 text-base-content/50">
|
||||
<MessageSquare class="h-16 w-16" />
|
||||
<ChatCircle class="h-16 w-16" />
|
||||
<div class="text-center">
|
||||
<h2 class="text-xl font-semibold text-base-content">Willkommen bei Mana Matrix</h2>
|
||||
<p class="mt-2">
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
Bell,
|
||||
Palette,
|
||||
Shield,
|
||||
LogOut,
|
||||
Server,
|
||||
SignOut,
|
||||
HardDrive,
|
||||
ShieldCheck,
|
||||
ShieldAlert,
|
||||
ShieldWarning,
|
||||
Key,
|
||||
Smartphone,
|
||||
Loader2,
|
||||
} from 'lucide-svelte';
|
||||
DeviceMobile,
|
||||
CircleNotch,
|
||||
} from '@manacore/shared-icons';
|
||||
import { VerificationDialog, RecoveryKeyDialog } from '$lib/components/crypto';
|
||||
|
||||
let verificationDialogOpen = $state(false);
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
<section class="card">
|
||||
<div class="space-y-4">
|
||||
<h2 class="flex items-center gap-2 text-lg font-semibold">
|
||||
<Server class="h-5 w-5" />
|
||||
<HardDrive class="h-5 w-5" />
|
||||
Server
|
||||
</h2>
|
||||
<div class="space-y-2 text-sm">
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
|
||||
{#if !cryptoReady}
|
||||
<div class="flex items-center gap-3 text-warning">
|
||||
<Loader2 class="h-5 w-5 animate-spin" />
|
||||
<CircleNotch class="h-5 w-5 animate-spin" />
|
||||
<span>Verschlüsselung wird initialisiert...</span>
|
||||
</div>
|
||||
{:else}
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
{#if verificationStatus === 'verified'}
|
||||
<ShieldCheck class="h-8 w-8 text-success" />
|
||||
{:else}
|
||||
<ShieldAlert class="h-8 w-8 text-warning" />
|
||||
<ShieldWarning class="h-8 w-8 text-warning" />
|
||||
{/if}
|
||||
<div>
|
||||
<p class="font-medium">
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
class="btn-primary flex items-center gap-2 text-sm"
|
||||
onclick={() => (verificationDialogOpen = true)}
|
||||
>
|
||||
<Smartphone class="h-4 w-4" />
|
||||
<DeviceMobile class="h-4 w-4" />
|
||||
Geräte
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
class="flex w-full items-center justify-center gap-2 rounded-lg bg-error p-3 text-white hover:brightness-90"
|
||||
onclick={handleLogout}
|
||||
>
|
||||
<LogOut class="h-5 w-5" />
|
||||
<SignOut class="h-5 w-5" />
|
||||
Abmelden
|
||||
</button>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,16 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { browser } from '$app/environment';
|
||||
import { loginWithPassword, discoverHomeserver, checkHomeserver, matrixStore } from '$lib/matrix';
|
||||
import { Eye, EyeOff, Loader2, Server, User, Lock, AlertCircle, LogIn } from 'lucide-svelte';
|
||||
import {
|
||||
Eye,
|
||||
EyeSlash,
|
||||
CircleNotch,
|
||||
HardDrive,
|
||||
User,
|
||||
Lock,
|
||||
WarningCircle,
|
||||
SignIn,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
// Form state
|
||||
let homeserver = $state('matrix.mana.how');
|
||||
|
|
@ -100,7 +109,7 @@
|
|||
<!-- Error Alert -->
|
||||
{#if error}
|
||||
<div class="alert alert-error mb-4">
|
||||
<AlertCircle class="h-5 w-5" />
|
||||
<WarningCircle class="h-5 w-5" />
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -111,12 +120,12 @@
|
|||
<div class="form-control">
|
||||
<label class="label" for="homeserver">
|
||||
<span class="label-text flex items-center gap-2">
|
||||
<Server class="h-4 w-4" />
|
||||
<HardDrive class="h-4 w-4" />
|
||||
Homeserver
|
||||
</span>
|
||||
{#if checkingServer}
|
||||
<span class="label-text-alt">
|
||||
<Loader2 class="h-4 w-4 animate-spin" />
|
||||
<CircleNotch class="h-4 w-4 animate-spin" />
|
||||
</span>
|
||||
{:else if serverValid === true}
|
||||
<span class="label-text-alt text-success">Connected</span>
|
||||
|
|
@ -182,7 +191,7 @@
|
|||
tabindex={-1}
|
||||
>
|
||||
{#if showPassword}
|
||||
<EyeOff class="h-5 w-5" />
|
||||
<EyeSlash class="h-5 w-5" />
|
||||
{:else}
|
||||
<Eye class="h-5 w-5" />
|
||||
{/if}
|
||||
|
|
@ -193,7 +202,7 @@
|
|||
<!-- Submit Button -->
|
||||
<button type="submit" class="btn btn-primary w-full" disabled={loading}>
|
||||
{#if loading}
|
||||
<Loader2 class="h-5 w-5 animate-spin" />
|
||||
<CircleNotch class="h-5 w-5 animate-spin" />
|
||||
Signing in...
|
||||
{:else}
|
||||
Sign In
|
||||
|
|
@ -212,10 +221,10 @@
|
|||
disabled={loadingSSO}
|
||||
>
|
||||
{#if loadingSSO}
|
||||
<Loader2 class="h-5 w-5 animate-spin" />
|
||||
<CircleNotch class="h-5 w-5 animate-spin" />
|
||||
Redirecting...
|
||||
{:else}
|
||||
<LogIn class="h-5 w-5" />
|
||||
<SignIn class="h-5 w-5" />
|
||||
Sign in with Mana Core
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
import { CircleNotch } from '@manacore/shared-icons';
|
||||
|
||||
let checking = $state(true);
|
||||
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<div class="flex h-screen items-center justify-center">
|
||||
<div class="text-center">
|
||||
<Loader2 class="mx-auto h-8 w-8 animate-spin text-primary" />
|
||||
<CircleNotch class="mx-auto h-8 w-8 animate-spin text-primary" />
|
||||
<p class="mt-4 text-base-content/60">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
"@manacore/shared-ui": "workspace:*",
|
||||
"@manacore/shared-utils": "workspace:*",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-svelte": "^0.559.0",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Camera, PenLine, Plus, X } from 'lucide-svelte';
|
||||
import { Camera, PencilLine, Plus, X } from '@manacore/shared-icons';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
let isOpen = $state(false);
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
onclick={handleText}
|
||||
class="flex items-center gap-3 px-5 py-3 bg-[var(--color-background-card)] border border-[var(--color-border)] rounded-full shadow-lg hover:bg-[var(--color-background-elevated)] transition-all"
|
||||
>
|
||||
<PenLine class="w-5 h-5 text-[var(--color-secondary)]" />
|
||||
<PencilLine class="w-5 h-5 text-[var(--color-secondary)]" />
|
||||
<span class="text-[var(--color-text-primary)] font-medium">Text</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { mealsStore } from '$lib/stores/meals.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import ProgressRing from './ProgressRing.svelte';
|
||||
import { AlertCircle, RefreshCw } from 'lucide-svelte';
|
||||
import { WarningCircle, ArrowsClockwise } from '@manacore/shared-icons';
|
||||
|
||||
onMount(() => {
|
||||
mealsStore.fetchDailySummary();
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<div
|
||||
class="bg-red-500/10 border border-red-500/20 rounded-xl p-3 flex items-center gap-2 text-red-400 text-sm"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<WarningCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<span class="flex-1">{mealsStore.summaryError}</span>
|
||||
<button onclick={retry} class="p-1 hover:bg-red-500/20 rounded transition-colors">
|
||||
<RefreshCw class="w-4 h-4" />
|
||||
<ArrowsClockwise class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
{:else if mealsStore.summaryLoading}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Settings } from 'lucide-svelte';
|
||||
import { Gear } from '@manacore/shared-icons';
|
||||
</script>
|
||||
|
||||
<header
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
class="p-2 rounded-lg hover:bg-[var(--color-background-card)] transition-colors"
|
||||
title="Einstellungen"
|
||||
>
|
||||
<Settings class="w-5 h-5 text-[var(--color-text-secondary)]" />
|
||||
<Gear class="w-5 h-5 text-[var(--color-text-secondary)]" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@
|
|||
import { mealsStore } from '$lib/stores/meals.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { MEAL_TYPE_LABELS } from '@nutriphi/shared';
|
||||
import { Trash2, Camera, PenLine, AlertCircle, RefreshCw, Loader2 } from 'lucide-svelte';
|
||||
import {
|
||||
Trash,
|
||||
Camera,
|
||||
PencilLine,
|
||||
WarningCircle,
|
||||
ArrowsClockwise,
|
||||
CircleNotch,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let deleting = $state<string | null>(null);
|
||||
|
||||
|
|
@ -34,10 +41,10 @@
|
|||
<div
|
||||
class="bg-red-500/10 border border-red-500/20 rounded-xl p-4 flex items-center gap-3 text-red-400"
|
||||
>
|
||||
<AlertCircle class="w-5 h-5 flex-shrink-0" />
|
||||
<WarningCircle class="w-5 h-5 flex-shrink-0" />
|
||||
<span class="flex-1 text-sm">{mealsStore.error}</span>
|
||||
<button onclick={retry} class="p-2 hover:bg-red-500/20 rounded-lg transition-colors">
|
||||
<RefreshCw class="w-4 h-4" />
|
||||
<ArrowsClockwise class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -46,7 +53,7 @@
|
|||
<div
|
||||
class="bg-red-500/10 border border-red-500/20 rounded-xl p-3 flex items-center gap-2 text-red-400 text-sm"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<WarningCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<span>{mealsStore.deleteError}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -71,7 +78,7 @@
|
|||
{#if meal.inputType === 'photo'}
|
||||
<Camera class="w-4 h-4 text-[var(--color-text-muted)]" />
|
||||
{:else}
|
||||
<PenLine class="w-4 h-4 text-[var(--color-text-muted)]" />
|
||||
<PencilLine class="w-4 h-4 text-[var(--color-text-muted)]" />
|
||||
{/if}
|
||||
<span class="text-xs text-[var(--color-text-muted)] uppercase tracking-wide">
|
||||
{MEAL_TYPE_LABELS[meal.mealType as keyof typeof MEAL_TYPE_LABELS]?.de ??
|
||||
|
|
@ -104,9 +111,9 @@
|
|||
class="p-2 rounded-lg hover:bg-[var(--color-background-elevated)] text-[var(--color-text-muted)] hover:text-red-400 transition-colors disabled:opacity-50"
|
||||
>
|
||||
{#if deleting === meal.id}
|
||||
<Loader2 class="w-4 h-4 animate-spin" />
|
||||
<CircleNotch class="w-4 h-4 animate-spin" />
|
||||
{:else}
|
||||
<Trash2 class="w-4 h-4" />
|
||||
<Trash class="w-4 h-4" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import DailySummary from '$lib/components/DailySummary.svelte';
|
||||
import MealList from '$lib/components/MealList.svelte';
|
||||
import AddMealButton from '$lib/components/AddMealButton.svelte';
|
||||
import { Camera, PenLine } from 'lucide-svelte';
|
||||
import { Camera, PencilLine } from '@manacore/shared-icons';
|
||||
|
||||
// Redirect to login if not authenticated
|
||||
$effect(() => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { apiClient } from '$lib/api/client';
|
||||
import { suggestMealType, MEAL_TYPE_LABELS } from '@nutriphi/shared';
|
||||
import type { AIAnalysisResult } from '@nutriphi/shared';
|
||||
import { Camera, ArrowLeft, Loader2, Check, AlertCircle, X } from 'lucide-svelte';
|
||||
import { Camera, ArrowLeft, CircleNotch, Check, WarningCircle, X } from '@manacore/shared-icons';
|
||||
|
||||
let inputType = $derived($page.url.searchParams.get('type') || 'photo');
|
||||
let mealType = $state(suggestMealType());
|
||||
|
|
@ -180,7 +180,7 @@
|
|||
<div
|
||||
class="bg-red-500/10 border border-red-500/20 rounded-xl p-3 mb-4 flex items-center gap-2 text-red-400"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<WarningCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<span class="flex-1 text-sm">{error}</span>
|
||||
<button
|
||||
onclick={() => (error = '')}
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
class="w-full py-3 bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] text-white font-medium rounded-xl transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
|
||||
>
|
||||
{#if analyzing}
|
||||
<Loader2 class="w-5 h-5 animate-spin" />
|
||||
<CircleNotch class="w-5 h-5 animate-spin" />
|
||||
Analysiere...
|
||||
{:else}
|
||||
Analysieren
|
||||
|
|
@ -273,7 +273,7 @@
|
|||
class="w-full py-3 bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] text-white font-medium rounded-xl transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
|
||||
>
|
||||
{#if saving}
|
||||
<Loader2 class="w-5 h-5 animate-spin" />
|
||||
<CircleNotch class="w-5 h-5 animate-spin" />
|
||||
Speichern...
|
||||
{:else}
|
||||
<Check class="w-5 h-5" />
|
||||
|
|
|
|||
|
|
@ -4,7 +4,15 @@
|
|||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { apiClient } from '$lib/api/client';
|
||||
import { DEFAULT_DAILY_VALUES } from '@nutriphi/shared';
|
||||
import { ArrowLeft, Save, Loader2, AlertCircle, LogOut, User, Target } from 'lucide-svelte';
|
||||
import {
|
||||
ArrowLeft,
|
||||
FloppyDisk,
|
||||
CircleNotch,
|
||||
WarningCircle,
|
||||
SignOut,
|
||||
User,
|
||||
Target,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface UserGoals {
|
||||
dailyCalories: number;
|
||||
|
|
@ -117,7 +125,7 @@
|
|||
onclick={handleLogout}
|
||||
class="w-full py-2.5 px-4 bg-[var(--color-background-elevated)] hover:bg-red-500/20 text-[var(--color-text-secondary)] hover:text-red-400 font-medium rounded-lg transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<LogOut class="w-4 h-4" />
|
||||
<SignOut class="w-4 h-4" />
|
||||
Abmelden
|
||||
</button>
|
||||
</section>
|
||||
|
|
@ -140,7 +148,7 @@
|
|||
|
||||
{#if loading}
|
||||
<div class="flex items-center justify-center py-8">
|
||||
<Loader2 class="w-6 h-6 animate-spin text-[var(--color-text-muted)]" />
|
||||
<CircleNotch class="w-6 h-6 animate-spin text-[var(--color-text-muted)]" />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="space-y-4">
|
||||
|
|
@ -238,7 +246,7 @@
|
|||
<div
|
||||
class="bg-red-500/10 border border-red-500/20 rounded-lg p-3 flex items-center gap-2 text-red-400 text-sm"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<WarningCircle class="w-4 h-4 flex-shrink-0" />
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -257,10 +265,10 @@
|
|||
class="w-full py-3 bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] text-white font-medium rounded-lg transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
|
||||
>
|
||||
{#if saving}
|
||||
<Loader2 class="w-5 h-5 animate-spin" />
|
||||
<CircleNotch class="w-5 h-5 animate-spin" />
|
||||
Speichern...
|
||||
{:else}
|
||||
<Save class="w-5 h-5" />
|
||||
<FloppyDisk class="w-5 h-5" />
|
||||
Ziele speichern
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
"@manacore/shared-theme": "workspace:*",
|
||||
"@manacore/shared-theme-ui": "workspace:*",
|
||||
"@manacore/shared-ui": "workspace:*",
|
||||
"lucide-svelte": "^0.460.0",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,14 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { decksStore } from '$lib/stores/decks.svelte';
|
||||
import { PageHeader } from '@manacore/shared-ui';
|
||||
import { Plus, Presentation, Trash2, MoreVertical, Clock, Layers } from 'lucide-svelte';
|
||||
import {
|
||||
Plus,
|
||||
Presentation,
|
||||
Trash,
|
||||
DotsThreeVertical,
|
||||
Clock,
|
||||
Stack,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let showCreateModal = $state(false);
|
||||
let showDeleteModal = $state(false);
|
||||
|
|
@ -132,7 +139,7 @@
|
|||
class="p-2 text-slate-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/30 rounded-lg transition-colors opacity-0 group-hover:opacity-100"
|
||||
aria-label="Delete deck"
|
||||
>
|
||||
<Trash2 class="w-4 h-4" />
|
||||
<Trash class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,22 +11,22 @@
|
|||
ArrowLeft,
|
||||
Play,
|
||||
Plus,
|
||||
Trash2,
|
||||
GripVertical,
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
Trash,
|
||||
DotsSixVertical,
|
||||
CaretUp,
|
||||
CaretDown,
|
||||
Image,
|
||||
Type,
|
||||
TextT,
|
||||
List,
|
||||
Edit3,
|
||||
PencilSimple,
|
||||
X,
|
||||
Save,
|
||||
Share2,
|
||||
FloppyDisk,
|
||||
ShareNetwork,
|
||||
Link,
|
||||
Copy,
|
||||
Check,
|
||||
ExternalLink,
|
||||
} from 'lucide-svelte';
|
||||
ArrowSquareOut,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let showSlideModal = $state(false);
|
||||
let editingSlide = $state<Slide | null>(null);
|
||||
|
|
@ -250,7 +250,7 @@
|
|||
onclick={openShareModal}
|
||||
class="flex items-center gap-2 px-4 py-2 bg-slate-100 dark:bg-slate-700 hover:bg-slate-200 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-200 font-medium rounded-lg transition-colors"
|
||||
>
|
||||
<Share2 class="w-5 h-5" />
|
||||
<ShareNetwork class="w-5 h-5" />
|
||||
Share
|
||||
</button>
|
||||
{#if decksStore.currentSlides.length > 0}
|
||||
|
|
@ -271,7 +271,7 @@
|
|||
<div
|
||||
class="mx-auto w-16 h-16 bg-slate-100 dark:bg-slate-800 rounded-full flex items-center justify-center mb-4"
|
||||
>
|
||||
<Type class="w-8 h-8 text-slate-400" />
|
||||
<TextT class="w-8 h-8 text-slate-400" />
|
||||
</div>
|
||||
<h2 class="text-lg font-medium text-slate-900 dark:text-white mb-2">No slides yet</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">Add your first slide to get started</p>
|
||||
|
|
@ -339,7 +339,7 @@
|
|||
class="p-1.5 hover:bg-slate-100 dark:hover:bg-slate-700 rounded disabled:opacity-30"
|
||||
aria-label="Move up"
|
||||
>
|
||||
<ChevronUp class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
<CaretUp class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
</button>
|
||||
<button
|
||||
onclick={() => moveSlide(slide, 'down')}
|
||||
|
|
@ -347,21 +347,21 @@
|
|||
class="p-1.5 hover:bg-slate-100 dark:hover:bg-slate-700 rounded disabled:opacity-30"
|
||||
aria-label="Move down"
|
||||
>
|
||||
<ChevronDown class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
<CaretDown class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
</button>
|
||||
<button
|
||||
onclick={() => openEditSlide(slide)}
|
||||
class="p-1.5 hover:bg-slate-100 dark:hover:bg-slate-700 rounded"
|
||||
aria-label="Edit"
|
||||
>
|
||||
<Edit3 class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
<PencilSimple class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
</button>
|
||||
<button
|
||||
onclick={() => confirmDeleteSlide(slide)}
|
||||
class="p-1.5 hover:bg-red-50 dark:hover:bg-red-900/30 rounded"
|
||||
aria-label="Delete"
|
||||
>
|
||||
<Trash2 class="w-4 h-4 text-red-500" />
|
||||
<Trash class="w-4 h-4 text-red-500" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -517,7 +517,7 @@
|
|||
disabled={isSaving}
|
||||
class="flex items-center gap-2 px-4 py-2 bg-primary-600 hover:bg-primary-700 text-white font-medium rounded-lg transition-colors disabled:opacity-50"
|
||||
>
|
||||
<Save class="w-4 h-4" />
|
||||
<FloppyDisk class="w-4 h-4" />
|
||||
{isSaving ? 'Saving...' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -564,7 +564,7 @@
|
|||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 bg-primary-100 dark:bg-primary-900/30 rounded-lg">
|
||||
<Share2 class="w-5 h-5 text-primary-600 dark:text-primary-400" />
|
||||
<ShareNetwork class="w-5 h-5 text-primary-600 dark:text-primary-400" />
|
||||
</div>
|
||||
<h2 class="text-xl font-semibold text-slate-900 dark:text-white">Share Presentation</h2>
|
||||
</div>
|
||||
|
|
@ -624,7 +624,7 @@
|
|||
class="p-2 hover:bg-slate-200 dark:hover:bg-slate-600 rounded-lg transition-colors"
|
||||
title="Open in new tab"
|
||||
>
|
||||
<ExternalLink class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
<ArrowSquareOut class="w-4 h-4 text-slate-600 dark:text-slate-400" />
|
||||
</a>
|
||||
<button
|
||||
onclick={() => copyShareLink(share)}
|
||||
|
|
@ -642,7 +642,7 @@
|
|||
class="p-2 hover:bg-red-50 dark:hover:bg-red-900/30 rounded-lg transition-colors"
|
||||
title="Delete link"
|
||||
>
|
||||
<Trash2 class="w-4 h-4 text-red-500" />
|
||||
<Trash class="w-4 h-4 text-red-500" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@
|
|||
import type { Slide } from '@presi/shared';
|
||||
import {
|
||||
X,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
CaretLeft,
|
||||
CaretRight,
|
||||
Play,
|
||||
Pause,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Maximize,
|
||||
Minimize,
|
||||
EyeSlash,
|
||||
ArrowsOut,
|
||||
ArrowsIn,
|
||||
Clock,
|
||||
} from 'lucide-svelte';
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let currentSlideIndex = $state(0);
|
||||
let isFullscreen = $state(false);
|
||||
|
|
@ -248,7 +248,7 @@
|
|||
class="p-3 hover:bg-white/10 rounded-lg transition-colors disabled:opacity-30"
|
||||
aria-label="Previous slide"
|
||||
>
|
||||
<ChevronLeft class="w-6 h-6" />
|
||||
<CaretLeft class="w-6 h-6" />
|
||||
</button>
|
||||
|
||||
<!-- Slide Dots -->
|
||||
|
|
@ -271,7 +271,7 @@
|
|||
class="p-3 hover:bg-white/10 rounded-lg transition-colors disabled:opacity-30"
|
||||
aria-label="Next slide"
|
||||
>
|
||||
<ChevronRight class="w-6 h-6" />
|
||||
<CaretRight class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -283,7 +283,7 @@
|
|||
aria-label={showNotes ? 'Hide notes' : 'Show notes'}
|
||||
>
|
||||
{#if showNotes}
|
||||
<EyeOff class="w-5 h-5" />
|
||||
<EyeSlash class="w-5 h-5" />
|
||||
{:else}
|
||||
<Eye class="w-5 h-5" />
|
||||
{/if}
|
||||
|
|
@ -294,9 +294,9 @@
|
|||
aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
|
||||
>
|
||||
{#if isFullscreen}
|
||||
<Minimize class="w-5 h-5" />
|
||||
<ArrowsIn class="w-5 h-5" />
|
||||
{:else}
|
||||
<Maximize class="w-5 h-5" />
|
||||
<ArrowsOut class="w-5 h-5" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import { auth } from '$lib/stores/auth.svelte';
|
||||
import { decksStore } from '$lib/stores/decks.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { FolderOpen, Layers, Calendar } from 'lucide-svelte';
|
||||
import { FolderOpen, Stack, Calendar } from '@manacore/shared-icons';
|
||||
|
||||
let isLoading = $state(true);
|
||||
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
</div>
|
||||
<div class="text-center p-4 bg-black/5 dark:bg-white/5 rounded-xl">
|
||||
<div class="flex justify-center mb-2">
|
||||
<Layers class="w-6 h-6 text-primary" />
|
||||
<Stack class="w-6 h-6 text-primary" />
|
||||
</div>
|
||||
<div class="text-2xl font-bold text-foreground">-</div>
|
||||
<div class="text-sm text-muted-foreground">Folien</div>
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@
|
|||
import { shareApi } from '$lib/api/client';
|
||||
import type { Slide } from '@presi/shared';
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
CaretLeft,
|
||||
CaretRight,
|
||||
Play,
|
||||
Pause,
|
||||
Maximize,
|
||||
Minimize,
|
||||
ArrowsOut,
|
||||
ArrowsIn,
|
||||
Clock,
|
||||
Presentation,
|
||||
AlertCircle,
|
||||
} from 'lucide-svelte';
|
||||
WarningCircle,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
let deck = $state<any>(null);
|
||||
let slides = $state<Slide[]>([]);
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
{:else if error}
|
||||
<div class="flex-1 flex flex-col items-center justify-center px-4">
|
||||
<div class="p-4 bg-red-900/30 rounded-full mb-4">
|
||||
<AlertCircle class="w-12 h-12 text-red-400" />
|
||||
<WarningCircle class="w-12 h-12 text-red-400" />
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold mb-2">Unable to load presentation</h1>
|
||||
<p class="text-slate-400 text-center max-w-md mb-6">{error}</p>
|
||||
|
|
@ -257,7 +257,7 @@
|
|||
class="p-3 hover:bg-white/10 rounded-lg transition-colors disabled:opacity-30"
|
||||
aria-label="Previous slide"
|
||||
>
|
||||
<ChevronLeft class="w-6 h-6" />
|
||||
<CaretLeft class="w-6 h-6" />
|
||||
</button>
|
||||
|
||||
<!-- Slide Dots -->
|
||||
|
|
@ -280,7 +280,7 @@
|
|||
class="p-3 hover:bg-white/10 rounded-lg transition-colors disabled:opacity-30"
|
||||
aria-label="Next slide"
|
||||
>
|
||||
<ChevronRight class="w-6 h-6" />
|
||||
<CaretRight class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -292,9 +292,9 @@
|
|||
aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
|
||||
>
|
||||
{#if isFullscreen}
|
||||
<Minimize class="w-5 h-5" />
|
||||
<ArrowsIn class="w-5 h-5" />
|
||||
{:else}
|
||||
<Maximize class="w-5 h-5" />
|
||||
<ArrowsOut class="w-5 h-5" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
"@manacore/shared-theme-ui": "workspace:*",
|
||||
"@manacore/shared-ui": "workspace:*",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-svelte": "^0.556.0",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { X } from 'lucide-svelte';
|
||||
import { X } from '@manacore/shared-icons';
|
||||
import { collectionsStore } from '$lib/stores';
|
||||
import type { Collection, CreateCollectionDto, UpdateCollectionDto } from '$lib/types';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { AlertCircle, X, RefreshCw } from 'lucide-svelte';
|
||||
import { WarningCircle, X, ArrowsClockwise } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
message: string;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
class="flex items-start gap-3 rounded-lg border border-destructive/20 bg-destructive/10 p-4"
|
||||
role="alert"
|
||||
>
|
||||
<AlertCircle class="mt-0.5 h-5 w-5 flex-shrink-0 text-destructive" />
|
||||
<WarningCircle class="mt-0.5 h-5 w-5 flex-shrink-0 text-destructive" />
|
||||
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-medium text-destructive">Error</p>
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
onclick={onRetry}
|
||||
class="mt-2 inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline"
|
||||
>
|
||||
<RefreshCw class="h-4 w-4" />
|
||||
<ArrowsClockwise class="h-4 w-4" />
|
||||
Try again
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@
|
|||
import { authStore, collectionsStore, questionsStore } from '$lib/stores';
|
||||
import { apiClient } from '$lib/api/client';
|
||||
import {
|
||||
Search,
|
||||
MagnifyingGlass,
|
||||
Plus,
|
||||
FolderOpen,
|
||||
Settings,
|
||||
LogOut,
|
||||
Gear,
|
||||
SignOut,
|
||||
Moon,
|
||||
Sun,
|
||||
HelpCircle,
|
||||
ChevronRight,
|
||||
} from 'lucide-svelte';
|
||||
Question,
|
||||
CaretRight,
|
||||
} from '@manacore/shared-icons';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
|
||||
let { children } = $props();
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
onclick={() => (sidebarOpen = !sidebarOpen)}
|
||||
class="rounded-lg p-2 text-muted-foreground hover:bg-secondary"
|
||||
>
|
||||
<ChevronRight class="h-5 w-5 transition-transform" class:rotate-180={sidebarOpen} />
|
||||
<CaretRight class="h-5 w-5 transition-transform" class:rotate-180={sidebarOpen} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
class="collection-item flex w-full items-center gap-3 rounded-lg px-3 py-2 text-foreground"
|
||||
class:active={!collectionsStore.selectedId}
|
||||
>
|
||||
<HelpCircle class="h-5 w-5" />
|
||||
<Question class="h-5 w-5" />
|
||||
{#if sidebarOpen}
|
||||
<span>All Questions</span>
|
||||
<span class="ml-auto text-xs text-muted-foreground">{questionsStore.total}</span>
|
||||
|
|
@ -111,7 +111,8 @@
|
|||
<FolderOpen class="h-5 w-5" style="color: {collection.color}" />
|
||||
{#if sidebarOpen}
|
||||
<span class="truncate">{collection.name}</span>
|
||||
<span class="ml-auto text-xs text-muted-foreground">{collection.questionCount || 0}</span
|
||||
<span class="ml-auto text-xs text-muted-foreground"
|
||||
>{collection.questionCount || 0}</span
|
||||
>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
@ -148,7 +149,7 @@
|
|||
href="/settings"
|
||||
class="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground hover:bg-secondary hover:text-foreground"
|
||||
>
|
||||
<Settings class="h-5 w-5" />
|
||||
<Gear class="h-5 w-5" />
|
||||
{#if sidebarOpen}
|
||||
<span>Settings</span>
|
||||
{/if}
|
||||
|
|
@ -158,7 +159,7 @@
|
|||
onclick={handleSignOut}
|
||||
class="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground hover:bg-secondary hover:text-foreground"
|
||||
>
|
||||
<LogOut class="h-5 w-5" />
|
||||
<SignOut class="h-5 w-5" />
|
||||
{#if sidebarOpen}
|
||||
<span>Sign Out</span>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { questionsStore, collectionsStore } from '$lib/stores';
|
||||
import { QuestionSkeleton, ErrorAlert } from '$lib/components';
|
||||
import { Search, Filter, Clock, CheckCircle, Loader2, Archive } from 'lucide-svelte';
|
||||
import {
|
||||
MagnifyingGlass,
|
||||
Funnel,
|
||||
Clock,
|
||||
CheckCircle,
|
||||
CircleNotch,
|
||||
Archive,
|
||||
} from '@manacore/shared-icons';
|
||||
import type { QuestionStatus, ResearchDepth } from '$lib/types';
|
||||
|
||||
let searchQuery = $state('');
|
||||
|
|
@ -9,7 +16,7 @@
|
|||
|
||||
const statusIcons = {
|
||||
open: { icon: Clock, color: 'text-gray-500' },
|
||||
researching: { icon: Loader2, color: 'text-blue-500' },
|
||||
researching: { icon: CircleNotch, color: 'text-blue-500' },
|
||||
answered: { icon: CheckCircle, color: 'text-green-500' },
|
||||
archived: { icon: Archive, color: 'text-gray-400' },
|
||||
};
|
||||
|
|
@ -60,7 +67,9 @@
|
|||
<!-- Search and Filters -->
|
||||
<div class="mb-6 flex gap-4">
|
||||
<div class="relative flex-1">
|
||||
<Search class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-muted-foreground" />
|
||||
<MagnifyingGlass
|
||||
class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-muted-foreground"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={searchQuery}
|
||||
|
|
@ -86,7 +95,7 @@
|
|||
onclick={handleSearch}
|
||||
class="flex items-center gap-2 rounded-lg bg-secondary px-4 py-2 text-foreground hover:bg-secondary-hover"
|
||||
>
|
||||
<Filter class="h-5 w-5" />
|
||||
<Funnel class="h-5 w-5" />
|
||||
<span>Filter</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { collectionsStore } from '$lib/stores';
|
||||
import CollectionModal from '$lib/components/CollectionModal.svelte';
|
||||
import { ArrowLeft, Plus, Edit2, Trash2, FolderOpen, GripVertical } from 'lucide-svelte';
|
||||
import {
|
||||
ArrowLeft,
|
||||
Plus,
|
||||
PencilSimple,
|
||||
Trash,
|
||||
FolderOpen,
|
||||
DotsSixVertical,
|
||||
} from '@manacore/shared-icons';
|
||||
import type { Collection } from '$lib/types';
|
||||
|
||||
let showModal = $state(false);
|
||||
|
|
@ -47,9 +54,7 @@
|
|||
Back to questions
|
||||
</a>
|
||||
<h1 class="text-2xl font-bold text-foreground">Collections</h1>
|
||||
<p class="mt-1 text-muted-foreground">
|
||||
Organize your questions into collections
|
||||
</p>
|
||||
<p class="mt-1 text-muted-foreground">Organize your questions into collections</p>
|
||||
</div>
|
||||
<button
|
||||
onclick={openCreateModal}
|
||||
|
|
@ -84,7 +89,7 @@
|
|||
>
|
||||
<!-- Drag Handle -->
|
||||
<div class="cursor-grab text-muted-foreground">
|
||||
<GripVertical class="h-5 w-5" />
|
||||
<DotsSixVertical class="h-5 w-5" />
|
||||
</div>
|
||||
|
||||
<!-- Icon & Color -->
|
||||
|
|
@ -122,7 +127,7 @@
|
|||
class="rounded-lg p-2 text-muted-foreground hover:bg-secondary hover:text-foreground"
|
||||
title="Edit"
|
||||
>
|
||||
<Edit2 class="h-4 w-4" />
|
||||
<PencilSimple class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
{#if deleteConfirm === collection.id}
|
||||
|
|
@ -146,7 +151,7 @@
|
|||
class="rounded-lg p-2 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
||||
title="Delete"
|
||||
>
|
||||
<Trash2 class="h-4 w-4" />
|
||||
<Trash class="h-4 w-4" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { questionsStore, collectionsStore } from '$lib/stores';
|
||||
import { researchApi } from '$lib/api/research';
|
||||
import { ArrowLeft, Zap, Clock, Sparkles } from 'lucide-svelte';
|
||||
import { ArrowLeft, Lightning, Clock, Sparkle } from '@manacore/shared-icons';
|
||||
import type { ResearchDepth, QuestionPriority } from '$lib/types';
|
||||
|
||||
let title = $state('');
|
||||
|
|
@ -17,10 +17,15 @@
|
|||
let loading = $state(false);
|
||||
let error = $state<string | null>(null);
|
||||
|
||||
const depthOptions: { value: ResearchDepth; label: string; description: string; icon: typeof Zap }[] = [
|
||||
{ value: 'quick', label: 'Quick', description: '5 sources, fast results', icon: Zap },
|
||||
const depthOptions: {
|
||||
value: ResearchDepth;
|
||||
label: string;
|
||||
description: string;
|
||||
icon: typeof Lightning;
|
||||
}[] = [
|
||||
{ value: 'quick', label: 'Quick', description: '5 sources, fast results', icon: Lightning },
|
||||
{ value: 'standard', label: 'Standard', description: '15 sources, balanced', icon: Clock },
|
||||
{ value: 'deep', label: 'Deep', description: '30+ sources, comprehensive', icon: Sparkles },
|
||||
{ value: 'deep', label: 'Deep', description: '30+ sources, comprehensive', icon: Sparkle },
|
||||
];
|
||||
|
||||
function addTag() {
|
||||
|
|
@ -79,9 +84,7 @@
|
|||
Back to questions
|
||||
</a>
|
||||
<h1 class="text-2xl font-bold text-foreground">Ask a Question</h1>
|
||||
<p class="mt-1 text-muted-foreground">
|
||||
Enter your question and let AI research it for you
|
||||
</p>
|
||||
<p class="mt-1 text-muted-foreground">Enter your question and let AI research it for you</p>
|
||||
</div>
|
||||
|
||||
<form onsubmit={handleSubmit} class="space-y-6">
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
import {
|
||||
ArrowLeft,
|
||||
Clock,
|
||||
Loader2,
|
||||
CircleNotch,
|
||||
CheckCircle,
|
||||
Archive,
|
||||
Play,
|
||||
ExternalLink,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
} from 'lucide-svelte';
|
||||
ArrowSquareOut,
|
||||
CaretDown,
|
||||
CaretUp,
|
||||
} from '@manacore/shared-icons';
|
||||
import type { Question, ResearchResult, Source } from '$lib/types';
|
||||
|
||||
let question = $state<Question | null>(null);
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
<ErrorAlert message={error} onRetry={loadQuestion} />
|
||||
</div>
|
||||
{:else if question}
|
||||
<div class="p-6">
|
||||
<div class="p-6">
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<a
|
||||
|
|
@ -160,7 +160,7 @@
|
|||
class="flex items-center gap-2 rounded-lg bg-primary px-4 py-2 font-medium text-primary-foreground hover:bg-primary-hover disabled:opacity-50"
|
||||
>
|
||||
{#if researchLoading}
|
||||
<Loader2 class="h-5 w-5 animate-spin" />
|
||||
<CircleNotch class="h-5 w-5 animate-spin" />
|
||||
Researching...
|
||||
{:else}
|
||||
<Play class="h-5 w-5" />
|
||||
|
|
@ -252,7 +252,7 @@
|
|||
>
|
||||
{source.title}
|
||||
</a>
|
||||
<ExternalLink class="h-4 w-4 text-muted-foreground" />
|
||||
<ArrowSquareOut class="h-4 w-4 text-muted-foreground" />
|
||||
</div>
|
||||
|
||||
<p class="mt-1 text-sm text-muted-foreground">{source.domain}</p>
|
||||
|
|
@ -299,9 +299,9 @@
|
|||
class="rounded-lg p-2 text-muted-foreground hover:bg-secondary hover:text-foreground"
|
||||
>
|
||||
{#if expandedSources.has(source.id)}
|
||||
<ChevronUp class="h-5 w-5" />
|
||||
<CaretUp class="h-5 w-5" />
|
||||
{:else}
|
||||
<ChevronDown class="h-5 w-5" />
|
||||
<CaretDown class="h-5 w-5" />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
|
|
@ -311,5 +311,5 @@
|
|||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
import { ArrowLeft, User, Moon, Sun, Monitor, Bell, Shield, Trash2 } from 'lucide-svelte';
|
||||
import { ArrowLeft, User, Moon, Sun, Desktop, Bell, Shield, Trash } from '@manacore/shared-icons';
|
||||
|
||||
let currentTheme = $state(theme.current);
|
||||
let deleteConfirm = $state(false);
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
const themeOptions = [
|
||||
{ value: 'light', label: 'Light', icon: Sun },
|
||||
{ value: 'dark', label: 'Dark', icon: Moon },
|
||||
{ value: 'system', label: 'System', icon: Monitor },
|
||||
{ value: 'system', label: 'System', icon: Desktop },
|
||||
] as const;
|
||||
</script>
|
||||
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
onclick={() => (deleteConfirm = true)}
|
||||
class="flex items-center gap-2 rounded-lg border border-destructive px-4 py-2 text-sm font-medium text-destructive hover:bg-destructive/10"
|
||||
>
|
||||
<Trash2 class="h-4 w-4" />
|
||||
<Trash class="h-4 w-4" />
|
||||
Delete Account
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { ArrowLeft } from 'lucide-svelte';
|
||||
import { ArrowLeft } from '@manacore/shared-icons';
|
||||
|
||||
let email = $state('');
|
||||
let error = $state<string | null>(null);
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@manacore/shared-auth": "workspace:*",
|
||||
"@manacore/shared-icons": "workspace:*",
|
||||
"@manacore/shared-tailwind": "workspace:*",
|
||||
"@manacore/shared-theme": "workspace:*",
|
||||
"@manacore/shared-utils": "workspace:*",
|
||||
"idb": "^8.0.0",
|
||||
"lucide-svelte": "^0.556.0",
|
||||
"uuid": "^11.0.0"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { Skill, SkillBranch } from '$lib/types';
|
||||
import { BRANCH_INFO } from '$lib/types';
|
||||
import { X } from 'lucide-svelte';
|
||||
import { X } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
|
@ -59,9 +59,7 @@
|
|||
<form onsubmit={handleSubmit} class="space-y-4">
|
||||
<!-- Name -->
|
||||
<div>
|
||||
<label for="name" class="mb-1 block text-sm font-medium text-gray-300">
|
||||
Name *
|
||||
</label>
|
||||
<label for="name" class="mb-1 block text-sm font-medium text-gray-300"> Name * </label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
|
|
@ -88,22 +86,18 @@
|
|||
|
||||
<!-- Branch -->
|
||||
<div>
|
||||
<label for="branch" class="mb-2 block text-sm font-medium text-gray-300">
|
||||
Kategorie
|
||||
</label>
|
||||
<label for="branch" class="mb-2 block text-sm font-medium text-gray-300"> Kategorie </label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each Object.entries(BRANCH_INFO) as [key, info]}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (branch = key as SkillBranch)}
|
||||
class="flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors {branch === key
|
||||
class="flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors {branch ===
|
||||
key
|
||||
? 'border-emerald-500 bg-emerald-500/20 text-white'
|
||||
: 'border-gray-600 bg-gray-700/50 text-gray-300 hover:border-gray-500'}"
|
||||
>
|
||||
<span
|
||||
class="h-3 w-3 rounded-full"
|
||||
style="background-color: {info.color}"
|
||||
></span>
|
||||
<span class="h-3 w-3 rounded-full" style="background-color: {info.color}"></span>
|
||||
{info.name}
|
||||
</button>
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { Skill } from '$lib/types';
|
||||
import { LEVEL_NAMES } from '$lib/types';
|
||||
import { X, Zap, Clock, Star } from 'lucide-svelte';
|
||||
import { X, Lightning, Clock, Star } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
skill: Skill;
|
||||
|
|
@ -75,15 +75,14 @@
|
|||
<form onsubmit={handleSubmit} class="space-y-4">
|
||||
<!-- Quick XP Presets -->
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-300">
|
||||
Schnellauswahl
|
||||
</label>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-300"> Schnellauswahl </label>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{#each xpPresets as preset}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => selectPreset(preset)}
|
||||
class="rounded-lg border px-3 py-1.5 text-sm font-medium transition-colors {xp === preset.value
|
||||
class="rounded-lg border px-3 py-1.5 text-sm font-medium transition-colors {xp ===
|
||||
preset.value
|
||||
? 'border-emerald-500 bg-emerald-500/20 text-emerald-400'
|
||||
: 'border-gray-600 bg-gray-700/50 text-gray-300 hover:border-gray-500'}"
|
||||
>
|
||||
|
|
@ -96,7 +95,7 @@
|
|||
<!-- Custom XP -->
|
||||
<div>
|
||||
<label for="xp" class="mb-1 block text-sm font-medium text-gray-300">
|
||||
<Zap class="mr-1 inline h-4 w-4 text-yellow-500" />
|
||||
<Lightning class="mr-1 inline h-4 w-4 text-yellow-500" />
|
||||
XP Menge
|
||||
</label>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { Skill, SkillBranch } from '$lib/types';
|
||||
import { BRANCH_INFO } from '$lib/types';
|
||||
import { X, Trash2 } from 'lucide-svelte';
|
||||
import { X, Trash } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
skill: Skill;
|
||||
|
|
@ -68,8 +68,10 @@
|
|||
{#if showDeleteConfirm}
|
||||
<!-- Delete Confirmation -->
|
||||
<div class="text-center">
|
||||
<div class="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-red-500/20">
|
||||
<Trash2 class="h-8 w-8 text-red-500" />
|
||||
<div
|
||||
class="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-red-500/20"
|
||||
>
|
||||
<Trash class="h-8 w-8 text-red-500" />
|
||||
</div>
|
||||
<h3 class="mb-2 text-lg font-semibold text-white">Skill löschen?</h3>
|
||||
<p class="mb-6 text-gray-400">
|
||||
|
|
@ -94,9 +96,7 @@
|
|||
<form onsubmit={handleSubmit} class="space-y-4">
|
||||
<!-- Name -->
|
||||
<div>
|
||||
<label for="name" class="mb-1 block text-sm font-medium text-gray-300">
|
||||
Name *
|
||||
</label>
|
||||
<label for="name" class="mb-1 block text-sm font-medium text-gray-300"> Name * </label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
|
|
@ -123,22 +123,18 @@
|
|||
|
||||
<!-- Branch -->
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-300">
|
||||
Kategorie
|
||||
</label>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-300"> Kategorie </label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each Object.entries(BRANCH_INFO) as [key, info]}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (branch = key as SkillBranch)}
|
||||
class="flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors {branch === key
|
||||
class="flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors {branch ===
|
||||
key
|
||||
? 'border-emerald-500 bg-emerald-500/20 text-white'
|
||||
: 'border-gray-600 bg-gray-700/50 text-gray-300 hover:border-gray-500'}"
|
||||
>
|
||||
<span
|
||||
class="h-3 w-3 rounded-full"
|
||||
style="background-color: {info.color}"
|
||||
></span>
|
||||
<span class="h-3 w-3 rounded-full" style="background-color: {info.color}"></span>
|
||||
{info.name}
|
||||
</button>
|
||||
{/each}
|
||||
|
|
@ -173,7 +169,7 @@
|
|||
class="rounded-lg bg-red-600/20 p-2 text-red-400 transition-colors hover:bg-red-600/30"
|
||||
title="Löschen"
|
||||
>
|
||||
<Trash2 class="h-5 w-5" />
|
||||
<Trash class="h-5 w-5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { LEVEL_NAMES } from '$lib/types';
|
||||
import { Star, Trophy, Sparkles } from 'lucide-svelte';
|
||||
import { Star, Trophy, Sparkle } from '@manacore/shared-icons';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -42,11 +42,8 @@
|
|||
<!-- Sparkle effects -->
|
||||
<div class="sparkles">
|
||||
{#each Array(12) as _, i}
|
||||
<div
|
||||
class="sparkle"
|
||||
style="--delay: {i * 0.1}s; --angle: {i * 30}deg"
|
||||
>
|
||||
<Sparkles class="h-6 w-6 text-yellow-400" />
|
||||
<div class="sparkle" style="--delay: {i * 0.1}s; --angle: {i * 30}deg">
|
||||
<Sparkle class="h-6 w-6 text-yellow-400" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
@ -54,20 +51,26 @@
|
|||
<!-- Main content -->
|
||||
<div class="relative z-10">
|
||||
<!-- Trophy icon -->
|
||||
<div class="mx-auto mb-4 flex h-24 w-24 items-center justify-center rounded-full bg-gradient-to-br {getLevelColor(newLevel)} level-up-bounce shadow-lg shadow-yellow-500/30">
|
||||
<div
|
||||
class="mx-auto mb-4 flex h-24 w-24 items-center justify-center rounded-full bg-gradient-to-br {getLevelColor(
|
||||
newLevel
|
||||
)} level-up-bounce shadow-lg shadow-yellow-500/30"
|
||||
>
|
||||
<Trophy class="h-12 w-12 text-white" />
|
||||
</div>
|
||||
|
||||
<!-- Level up text -->
|
||||
<h2 class="mb-2 text-3xl font-bold text-white level-up-text">
|
||||
LEVEL UP!
|
||||
</h2>
|
||||
<h2 class="mb-2 text-3xl font-bold text-white level-up-text">LEVEL UP!</h2>
|
||||
|
||||
<!-- Skill name -->
|
||||
<p class="mb-4 text-xl text-gray-300">{skillName}</p>
|
||||
|
||||
<!-- New level badge -->
|
||||
<div class="inline-flex items-center gap-2 rounded-full bg-gradient-to-r {getLevelColor(newLevel)} px-6 py-3 text-lg font-bold text-white shadow-lg">
|
||||
<div
|
||||
class="inline-flex items-center gap-2 rounded-full bg-gradient-to-r {getLevelColor(
|
||||
newLevel
|
||||
)} px-6 py-3 text-lg font-bold text-white shadow-lg"
|
||||
>
|
||||
<Star class="h-5 w-5 fill-current" />
|
||||
Level {newLevel} - {levelName}
|
||||
<Star class="h-5 w-5 fill-current" />
|
||||
|
|
@ -149,7 +152,9 @@
|
|||
text-shadow: 0 0 10px rgba(251, 191, 36, 0.5);
|
||||
}
|
||||
to {
|
||||
text-shadow: 0 0 30px rgba(251, 191, 36, 0.8), 0 0 60px rgba(251, 191, 36, 0.4);
|
||||
text-shadow:
|
||||
0 0 30px rgba(251, 191, 36, 0.8),
|
||||
0 0 60px rgba(251, 191, 36, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { Skill } from '$lib/types';
|
||||
import { BRANCH_INFO, LEVEL_NAMES, xpProgress, xpForNextLevel } from '$lib/types';
|
||||
import { Plus, Trash2, Edit, Star } from 'lucide-svelte';
|
||||
import { Plus, Trash, PencilSimple, Star } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
skill: Skill;
|
||||
|
|
@ -31,7 +31,9 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="skill-card group relative overflow-hidden rounded-xl border border-gray-700 bg-gray-800/50 p-4">
|
||||
<div
|
||||
class="skill-card group relative overflow-hidden rounded-xl border border-gray-700 bg-gray-800/50 p-4"
|
||||
>
|
||||
<!-- Branch Indicator -->
|
||||
<div
|
||||
class="branch-indicator absolute left-0 top-0 h-full"
|
||||
|
|
@ -56,7 +58,11 @@
|
|||
|
||||
<!-- Level Badge -->
|
||||
<div class="mb-3 pl-3">
|
||||
<span class="inline-flex items-center gap-1 rounded-full bg-gray-700/50 px-3 py-1 text-sm {getLevelColor(skill.level)}">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 rounded-full bg-gray-700/50 px-3 py-1 text-sm {getLevelColor(
|
||||
skill.level
|
||||
)}"
|
||||
>
|
||||
Lvl {skill.level} - {levelName}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -96,14 +102,14 @@
|
|||
class="rounded-lg bg-gray-600/20 p-2 text-gray-400 opacity-0 transition-all hover:bg-gray-600/30 hover:text-white group-hover:opacity-100"
|
||||
title="Bearbeiten"
|
||||
>
|
||||
<Edit class="h-4 w-4" />
|
||||
<PencilSimple class="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onclick={onDelete}
|
||||
class="rounded-lg bg-red-600/20 p-2 text-red-400 opacity-0 transition-all hover:bg-red-600/30 group-hover:opacity-100"
|
||||
title="Löschen"
|
||||
>
|
||||
<Trash2 class="h-4 w-4" />
|
||||
<Trash class="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { Skill, SkillBranch } from '$lib/types';
|
||||
import { BRANCH_INFO } from '$lib/types';
|
||||
import { X, Plus, Sparkles } from 'lucide-svelte';
|
||||
import { X, Plus, Sparkle } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
|
@ -41,14 +41,14 @@
|
|||
{ name: 'Schreiben', description: 'Kreatives Schreiben', branch: 'creativity' },
|
||||
{ name: 'Design', description: 'Visuelles Design', branch: 'creativity' },
|
||||
],
|
||||
'Sprachen': [
|
||||
Sprachen: [
|
||||
{ name: 'Englisch', description: 'Die Weltsprache', branch: 'intellect' },
|
||||
{ name: 'Spanisch', description: 'Spanisch sprechen', branch: 'intellect' },
|
||||
{ name: 'Französisch', description: 'La langue française', branch: 'intellect' },
|
||||
{ name: 'Japanisch', description: '日本語', branch: 'intellect' },
|
||||
{ name: 'Deutsch', description: 'Deutsche Sprache', branch: 'intellect' },
|
||||
],
|
||||
'Produktivität': [
|
||||
Produktivität: [
|
||||
{ name: 'Zeitmanagement', description: 'Zeit effektiv nutzen', branch: 'mindset' },
|
||||
{ name: 'Fokus', description: 'Konzentration verbessern', branch: 'mindset' },
|
||||
{ name: 'Organisation', description: 'Ordnung und Struktur', branch: 'practical' },
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<!-- Header -->
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<Sparkles class="h-6 w-6 text-yellow-500" />
|
||||
<Sparkle class="h-6 w-6 text-yellow-500" />
|
||||
<h2 class="text-xl font-bold text-white">Skill-Vorlagen</h2>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -126,7 +126,8 @@
|
|||
</div>
|
||||
|
||||
<p class="mb-6 text-gray-400">
|
||||
Starte schnell mit vorgefertigten Skill-Sets. Wähle eine Vorlage und füge einzelne Skills oder alle auf einmal hinzu.
|
||||
Starte schnell mit vorgefertigten Skill-Sets. Wähle eine Vorlage und füge einzelne Skills oder
|
||||
alle auf einmal hinzu.
|
||||
</p>
|
||||
|
||||
<!-- Template List -->
|
||||
|
|
@ -184,7 +185,12 @@
|
|||
>
|
||||
{#if isAdded}
|
||||
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<Plus class="h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { skillStore } from '$lib/stores/skills.svelte';
|
||||
import { Trophy, Zap, Target, Flame } from 'lucide-svelte';
|
||||
import { Trophy, Lightning, Target, Fire } from '@manacore/shared-icons';
|
||||
</script>
|
||||
|
||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<div class="rounded-xl border border-gray-700 bg-gray-800/50 p-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-yellow-500/20">
|
||||
<Zap class="h-6 w-6 text-yellow-500" />
|
||||
<Lightning class="h-6 w-6 text-yellow-500" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-400">Gesamt-XP</p>
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
<div class="rounded-xl border border-gray-700 bg-gray-800/50 p-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-orange-500/20">
|
||||
<Flame class="h-6 w-6 text-orange-500" />
|
||||
<Fire class="h-6 w-6 text-orange-500" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-400">Streak</p>
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
import SkillTemplates from '$lib/components/SkillTemplates.svelte';
|
||||
import {
|
||||
Plus,
|
||||
TreeDeciduous,
|
||||
Zap,
|
||||
Download,
|
||||
Upload,
|
||||
Sparkles,
|
||||
Network,
|
||||
} from 'lucide-svelte';
|
||||
Tree,
|
||||
Lightning,
|
||||
DownloadSimple,
|
||||
UploadSimple,
|
||||
Sparkle,
|
||||
Graph,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
// Modal states
|
||||
let showAddSkillModal = $state(false);
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<div class="mx-auto max-w-7xl px-4 py-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<TreeDeciduous class="h-8 w-8 text-emerald-500" />
|
||||
<Tree class="h-8 w-8 text-emerald-500" />
|
||||
<h1 class="text-2xl font-bold text-white">SkillTree</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -124,7 +124,7 @@
|
|||
class="rounded-lg p-2 text-gray-400 transition-colors hover:bg-gray-800 hover:text-emerald-400"
|
||||
title="Skill-Tree Ansicht"
|
||||
>
|
||||
<Network class="h-5 w-5" />
|
||||
<Graph class="h-5 w-5" />
|
||||
</a>
|
||||
<!-- Templates -->
|
||||
<button
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
class="rounded-lg p-2 text-gray-400 transition-colors hover:bg-gray-800 hover:text-yellow-500"
|
||||
title="Skill-Vorlagen"
|
||||
>
|
||||
<Sparkles class="h-5 w-5" />
|
||||
<Sparkle class="h-5 w-5" />
|
||||
</button>
|
||||
<!-- Export/Import -->
|
||||
<button
|
||||
|
|
@ -140,14 +140,14 @@
|
|||
class="rounded-lg p-2 text-gray-400 transition-colors hover:bg-gray-800 hover:text-white"
|
||||
title="Daten exportieren"
|
||||
>
|
||||
<Download class="h-5 w-5" />
|
||||
<DownloadSimple class="h-5 w-5" />
|
||||
</button>
|
||||
<button
|
||||
onclick={handleImport}
|
||||
class="rounded-lg p-2 text-gray-400 transition-colors hover:bg-gray-800 hover:text-white"
|
||||
title="Daten importieren"
|
||||
>
|
||||
<Upload class="h-5 w-5" />
|
||||
<UploadSimple class="h-5 w-5" />
|
||||
</button>
|
||||
<!-- Add Skill -->
|
||||
<button
|
||||
|
|
@ -171,7 +171,8 @@
|
|||
<div class="flex flex-wrap gap-2">
|
||||
<button
|
||||
onclick={() => (selectedBranch = 'all')}
|
||||
class="rounded-full px-4 py-2 text-sm font-medium transition-colors {selectedBranch === 'all'
|
||||
class="rounded-full px-4 py-2 text-sm font-medium transition-colors {selectedBranch ===
|
||||
'all'
|
||||
? 'bg-emerald-600 text-white'
|
||||
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'}"
|
||||
>
|
||||
|
|
@ -182,7 +183,8 @@
|
|||
{#if count > 0 || branch !== 'custom'}
|
||||
<button
|
||||
onclick={() => (selectedBranch = branch as SkillBranch)}
|
||||
class="rounded-full px-4 py-2 text-sm font-medium transition-colors {selectedBranch === branch
|
||||
class="rounded-full px-4 py-2 text-sm font-medium transition-colors {selectedBranch ===
|
||||
branch
|
||||
? 'bg-emerald-600 text-white'
|
||||
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'}"
|
||||
>
|
||||
|
|
@ -196,13 +198,13 @@
|
|||
<!-- Skills Grid -->
|
||||
{#if filteredSkills().length === 0}
|
||||
<div class="mt-16 text-center">
|
||||
<div class="mx-auto mb-6 flex h-24 w-24 items-center justify-center rounded-full bg-gray-800">
|
||||
<TreeDeciduous class="h-12 w-12 text-gray-600" />
|
||||
<div
|
||||
class="mx-auto mb-6 flex h-24 w-24 items-center justify-center rounded-full bg-gray-800"
|
||||
>
|
||||
<Tree class="h-12 w-12 text-gray-600" />
|
||||
</div>
|
||||
<h2 class="mb-2 text-xl font-semibold text-gray-300">Noch keine Skills</h2>
|
||||
<p class="mb-6 text-gray-500">
|
||||
Füge deinen ersten Skill hinzu und beginne dein Abenteuer!
|
||||
</p>
|
||||
<p class="mb-6 text-gray-500">Füge deinen ersten Skill hinzu und beginne dein Abenteuer!</p>
|
||||
<button
|
||||
onclick={() => (showAddSkillModal = true)}
|
||||
class="inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-6 py-3 font-medium text-white transition-colors hover:bg-emerald-500"
|
||||
|
|
@ -228,7 +230,7 @@
|
|||
{#if skillStore.recentActivities().length > 0}
|
||||
<div class="mt-12">
|
||||
<h2 class="mb-4 flex items-center gap-2 text-lg font-semibold text-white">
|
||||
<Zap class="h-5 w-5 text-yellow-500" />
|
||||
<Lightning class="h-5 w-5 text-yellow-500" />
|
||||
Letzte Aktivitäten
|
||||
</h2>
|
||||
<div class="space-y-2">
|
||||
|
|
@ -237,7 +239,9 @@
|
|||
{#if skill}
|
||||
<div class="flex items-center justify-between rounded-lg bg-gray-800/50 px-4 py-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-8 w-8 items-center justify-center rounded-full bg-emerald-900/50 text-sm font-medium text-emerald-400">
|
||||
<div
|
||||
class="flex h-8 w-8 items-center justify-center rounded-full bg-emerald-900/50 text-sm font-medium text-emerald-400"
|
||||
>
|
||||
+{activity.xpEarned}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -269,11 +273,7 @@
|
|||
{/if}
|
||||
|
||||
{#if showAddXpModal && selectedSkill}
|
||||
<AddXpModal
|
||||
skill={selectedSkill}
|
||||
onClose={closeModals}
|
||||
onSave={handleAddXp}
|
||||
/>
|
||||
<AddXpModal skill={selectedSkill} onClose={closeModals} onSave={handleAddXp} />
|
||||
{/if}
|
||||
|
||||
{#if showEditSkillModal && selectedSkill}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { skillStore } from '$lib/stores/skills.svelte';
|
||||
import { BRANCH_INFO, LEVEL_NAMES } from '$lib/types';
|
||||
import type { SkillBranch } from '$lib/types';
|
||||
import { ArrowLeft, Star } from 'lucide-svelte';
|
||||
import { ArrowLeft, Star } from '@manacore/shared-icons';
|
||||
|
||||
// Group skills by branch for radial layout
|
||||
const branches = Object.keys(BRANCH_INFO) as SkillBranch[];
|
||||
|
|
@ -31,7 +31,9 @@
|
|||
const radiusStep = 60;
|
||||
|
||||
// Spread skills in a small arc
|
||||
const skillAngle = branchAngle + (skillIndex - (skillCount - 1) / 2) * (spreadAngle / Math.max(skillCount - 1, 1));
|
||||
const skillAngle =
|
||||
branchAngle +
|
||||
(skillIndex - (skillCount - 1) / 2) * (spreadAngle / Math.max(skillCount - 1, 1));
|
||||
const radius = baseRadius + skillIndex * radiusStep * 0.3;
|
||||
|
||||
return {
|
||||
|
|
@ -104,9 +106,33 @@
|
|||
style="min-width: 600px; height: auto; max-height: 80vh;"
|
||||
>
|
||||
<!-- Background circles -->
|
||||
<circle cx="400" cy="400" r="120" fill="none" stroke="#374151" stroke-width="1" stroke-dasharray="4" />
|
||||
<circle cx="400" cy="400" r="200" fill="none" stroke="#374151" stroke-width="1" stroke-dasharray="4" />
|
||||
<circle cx="400" cy="400" r="280" fill="none" stroke="#374151" stroke-width="1" stroke-dasharray="4" />
|
||||
<circle
|
||||
cx="400"
|
||||
cy="400"
|
||||
r="120"
|
||||
fill="none"
|
||||
stroke="#374151"
|
||||
stroke-width="1"
|
||||
stroke-dasharray="4"
|
||||
/>
|
||||
<circle
|
||||
cx="400"
|
||||
cy="400"
|
||||
r="200"
|
||||
fill="none"
|
||||
stroke="#374151"
|
||||
stroke-width="1"
|
||||
stroke-dasharray="4"
|
||||
/>
|
||||
<circle
|
||||
cx="400"
|
||||
cy="400"
|
||||
r="280"
|
||||
fill="none"
|
||||
stroke="#374151"
|
||||
stroke-width="1"
|
||||
stroke-dasharray="4"
|
||||
/>
|
||||
|
||||
<!-- Center node -->
|
||||
<circle cx="400" cy="400" r="50" fill="#10b981" opacity="0.2" />
|
||||
|
|
@ -162,7 +188,10 @@
|
|||
/>
|
||||
|
||||
<!-- Skill node -->
|
||||
<g class="tree-node cursor-pointer" transform="translate({skillPos.x}, {skillPos.y})">
|
||||
<g
|
||||
class="tree-node cursor-pointer"
|
||||
transform="translate({skillPos.x}, {skillPos.y})"
|
||||
>
|
||||
<!-- Glow effect for high level -->
|
||||
{#if skill.level >= 4}
|
||||
<circle
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@
|
|||
"@manacore/shared-theme": "workspace:*",
|
||||
"@manacore/shared-theme-ui": "workspace:*",
|
||||
"@manacore/shared-ui": "workspace:*",
|
||||
"svelte-i18n": "^4.0.1",
|
||||
"lucide-svelte": "^0.469.0"
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { ChevronRight, Home } from 'lucide-svelte';
|
||||
import { CaretRight, House } from '@manacore/shared-icons';
|
||||
|
||||
interface BreadcrumbItem {
|
||||
id: string | null;
|
||||
|
|
@ -18,13 +18,13 @@
|
|||
<ol class="breadcrumb-list">
|
||||
<li class="breadcrumb-item">
|
||||
<button onclick={() => onNavigate(null)} class="breadcrumb-link" aria-label="Home">
|
||||
<Home size={16} />
|
||||
<House size={16} />
|
||||
<span>Meine Dateien</span>
|
||||
</button>
|
||||
</li>
|
||||
{#each items as item, index (item.id)}
|
||||
<li class="breadcrumb-item">
|
||||
<ChevronRight size={16} class="separator" />
|
||||
<CaretRight size={16} class="separator" />
|
||||
{#if index === items.length - 1}
|
||||
<span class="breadcrumb-current">{item.name}</span>
|
||||
{:else}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
FileText,
|
||||
FileVideo,
|
||||
FileAudio,
|
||||
FileArchive,
|
||||
FileZip,
|
||||
Heart,
|
||||
MoreVertical,
|
||||
} from 'lucide-svelte';
|
||||
DotsThreeVertical,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
file: StorageFile;
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
if (mimeType.startsWith('video/')) return FileVideo;
|
||||
if (mimeType.startsWith('audio/')) return FileAudio;
|
||||
if (mimeType.startsWith('text/')) return FileText;
|
||||
if (mimeType.includes('zip') || mimeType.includes('archive')) return FileArchive;
|
||||
if (mimeType.includes('zip') || mimeType.includes('archive')) return FileZip;
|
||||
return File;
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
<span class="file-size">{formatFileSize(file.size)}</span>
|
||||
</div>
|
||||
<button class="menu-button" onclick={handleMenuClick} type="button">
|
||||
<MoreVertical size={16} />
|
||||
<DotsThreeVertical size={16} />
|
||||
</button>
|
||||
|
||||
{#if showMenu}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
FileText,
|
||||
FileVideo,
|
||||
FileAudio,
|
||||
FileArchive,
|
||||
FileZip,
|
||||
Heart,
|
||||
MoreVertical,
|
||||
} from 'lucide-svelte';
|
||||
DotsThreeVertical,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
file: StorageFile;
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
if (mimeType.startsWith('video/')) return FileVideo;
|
||||
if (mimeType.startsWith('audio/')) return FileAudio;
|
||||
if (mimeType.startsWith('text/')) return FileText;
|
||||
if (mimeType.includes('zip') || mimeType.includes('archive')) return FileArchive;
|
||||
if (mimeType.includes('zip') || mimeType.includes('archive')) return FileZip;
|
||||
return File;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<span class="col-date">{formatDate(file.updatedAt)}</span>
|
||||
<span class="col-actions">
|
||||
<button class="menu-button" onclick={handleMenuClick} type="button">
|
||||
<MoreVertical size={16} />
|
||||
<DotsThreeVertical size={16} />
|
||||
</button>
|
||||
{#if showMenu}
|
||||
<div class="menu-dropdown">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import type { StorageFolder } from '$lib/api/client';
|
||||
import { Folder, Heart, MoreVertical } from 'lucide-svelte';
|
||||
import { Folder, Heart, DotsThreeVertical } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
folder: StorageFolder;
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
<span class="folder-name" title={folder.name}>{folder.name}</span>
|
||||
</div>
|
||||
<button class="menu-button" onclick={handleMenuClick} type="button">
|
||||
<MoreVertical size={16} />
|
||||
<DotsThreeVertical size={16} />
|
||||
</button>
|
||||
|
||||
{#if showMenu}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import type { StorageFolder } from '$lib/api/client';
|
||||
import { Folder, Heart, MoreVertical } from 'lucide-svelte';
|
||||
import { Folder, Heart, DotsThreeVertical } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
folder: StorageFolder;
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<span class="col-date">{formatDate(folder.updatedAt)}</span>
|
||||
<span class="col-actions">
|
||||
<button class="menu-button" onclick={handleMenuClick} type="button">
|
||||
<MoreVertical size={16} />
|
||||
<DotsThreeVertical size={16} />
|
||||
</button>
|
||||
{#if showMenu}
|
||||
<div class="menu-dropdown">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { X } from 'lucide-svelte';
|
||||
import { X } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Upload, X } from 'lucide-svelte';
|
||||
import { UploadSimple } from '@manacore/shared-icons';
|
||||
|
||||
interface Props {
|
||||
onUpload: (files: FileList) => void;
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
</div>
|
||||
{:else}
|
||||
<div class="upload-content">
|
||||
<Upload size={32} />
|
||||
<UploadSimple size={32} />
|
||||
<span class="upload-text">
|
||||
Dateien hierher ziehen oder <strong>klicken</strong> zum Auswählen
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { Heart, Grid, List } from 'lucide-svelte';
|
||||
import { Heart, GridFour, List } from '@manacore/shared-icons';
|
||||
import { searchApi } from '$lib/api/client';
|
||||
import type { StorageFile, StorageFolder } from '$lib/api/client';
|
||||
import { filesStore } from '$lib/stores/files.svelte';
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
onclick={() => filesStore.setViewMode('grid')}
|
||||
aria-label="Rasteransicht"
|
||||
>
|
||||
<Grid size={18} />
|
||||
<GridFour size={18} />
|
||||
</button>
|
||||
<button
|
||||
class="view-btn"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { MessageSquare, Send } from 'lucide-svelte';
|
||||
import { ChatCircle, PaperPlaneTilt } from '@manacore/shared-icons';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
|
||||
let type = $state<'bug' | 'feature' | 'other'>('feature');
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
<div class="feedback-page">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<MessageSquare size={24} />
|
||||
<ChatCircle size={24} />
|
||||
Feedback
|
||||
</h1>
|
||||
</div>
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn" disabled={!message.trim() || sending}>
|
||||
<Send size={18} />
|
||||
<PaperPlaneTilt size={18} />
|
||||
{sending ? 'Wird gesendet...' : 'Feedback senden'}
|
||||
</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { Grid, List, Plus, FolderPlus, Upload } from 'lucide-svelte';
|
||||
import { GridFour, List, Plus, FolderPlus, UploadSimple } from '@manacore/shared-icons';
|
||||
import { filesStore } from '$lib/stores/files.svelte';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
import type { StorageFile, StorageFolder } from '$lib/api/client';
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
onclick={() => filesStore.setViewMode('grid')}
|
||||
aria-label="Rasteransicht"
|
||||
>
|
||||
<Grid size={18} />
|
||||
<GridFour size={18} />
|
||||
</button>
|
||||
<button
|
||||
class="view-btn"
|
||||
|
|
@ -196,7 +196,7 @@
|
|||
</button>
|
||||
|
||||
<button class="action-btn primary" onclick={() => (showUploadZone = !showUploadZone)}>
|
||||
<Upload size={18} />
|
||||
<UploadSimple size={18} />
|
||||
<span>Hochladen</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -218,7 +218,7 @@
|
|||
</div>
|
||||
{:else if filesStore.files.length === 0 && filesStore.folders.length === 0}
|
||||
<div class="empty-state">
|
||||
<Upload size={48} />
|
||||
<UploadSimple size={48} />
|
||||
<h2>Noch keine Dateien</h2>
|
||||
<p>Lade deine ersten Dateien hoch oder erstelle einen Ordner.</p>
|
||||
<div class="empty-actions">
|
||||
|
|
@ -227,7 +227,7 @@
|
|||
<span>Neuer Ordner</span>
|
||||
</button>
|
||||
<button class="action-btn primary" onclick={() => (showUploadZone = true)}>
|
||||
<Upload size={18} />
|
||||
<UploadSimple size={18} />
|
||||
<span>Hochladen</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { Grid, List, FolderPlus, Upload, ArrowLeft } from 'lucide-svelte';
|
||||
import { GridFour, List, FolderPlus, UploadSimple, ArrowLeft } from '@manacore/shared-icons';
|
||||
import { filesStore } from '$lib/stores/files.svelte';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
import type { StorageFile, StorageFolder } from '$lib/api/client';
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
onclick={() => filesStore.setViewMode('grid')}
|
||||
aria-label="Rasteransicht"
|
||||
>
|
||||
<Grid size={18} />
|
||||
<GridFour size={18} />
|
||||
</button>
|
||||
<button
|
||||
class="view-btn"
|
||||
|
|
@ -215,7 +215,7 @@
|
|||
</button>
|
||||
|
||||
<button class="action-btn primary" onclick={() => (showUploadZone = !showUploadZone)}>
|
||||
<Upload size={18} />
|
||||
<UploadSimple size={18} />
|
||||
<span>Hochladen</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -237,7 +237,7 @@
|
|||
</div>
|
||||
{:else if filesStore.files.length === 0 && filesStore.folders.length === 0}
|
||||
<div class="empty-state">
|
||||
<Upload size={48} />
|
||||
<UploadSimple size={48} />
|
||||
<h2>Leerer Ordner</h2>
|
||||
<p>Dieser Ordner ist leer. Lade Dateien hoch oder erstelle Unterordner.</p>
|
||||
<div class="empty-actions">
|
||||
|
|
@ -246,7 +246,7 @@
|
|||
<span>Neuer Ordner</span>
|
||||
</button>
|
||||
<button class="action-btn primary" onclick={() => (showUploadZone = true)}>
|
||||
<Upload size={18} />
|
||||
<UploadSimple size={18} />
|
||||
<span>Hochladen</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { User } from 'lucide-svelte';
|
||||
import { User } from '@manacore/shared-icons';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { Search, Grid, List } from 'lucide-svelte';
|
||||
import { MagnifyingGlass, GridFour, List } from '@manacore/shared-icons';
|
||||
import { searchApi } from '$lib/api/client';
|
||||
import type { StorageFile, StorageFolder } from '$lib/api/client';
|
||||
import { filesStore } from '$lib/stores/files.svelte';
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
<div class="search-page">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<Search size={24} />
|
||||
<MagnifyingGlass size={24} />
|
||||
Suche
|
||||
</h1>
|
||||
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
onclick={() => filesStore.setViewMode('grid')}
|
||||
aria-label="Rasteransicht"
|
||||
>
|
||||
<Grid size={18} />
|
||||
<GridFour size={18} />
|
||||
</button>
|
||||
<button
|
||||
class="view-btn"
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
</div>
|
||||
|
||||
<div class="search-bar">
|
||||
<Search size={20} />
|
||||
<MagnifyingGlass size={20} />
|
||||
<input
|
||||
type="text"
|
||||
bind:value={query}
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
</div>
|
||||
{:else if searched && files.length === 0 && folders.length === 0}
|
||||
<div class="empty-state">
|
||||
<Search size={48} />
|
||||
<MagnifyingGlass size={48} />
|
||||
<h2>Keine Ergebnisse</h2>
|
||||
<p>Keine Dateien oder Ordner für "{query}" gefunden.</p>
|
||||
</div>
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
{/if}
|
||||
{:else}
|
||||
<div class="empty-state">
|
||||
<Search size={48} />
|
||||
<MagnifyingGlass size={48} />
|
||||
<h2>Dateien durchsuchen</h2>
|
||||
<p>Gib einen Suchbegriff ein, um Dateien und Ordner zu finden.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { Share2, Link, Copy, Trash2 } from 'lucide-svelte';
|
||||
import { ShareNetwork, Link, Copy, Trash } from '@manacore/shared-icons';
|
||||
import { sharesApi } from '$lib/api/client';
|
||||
import type { Share } from '$lib/api/client';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
<div class="shared-page">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<Share2 size={24} />
|
||||
<ShareNetwork size={24} />
|
||||
Geteilte Links
|
||||
</h1>
|
||||
</div>
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
</div>
|
||||
{:else if shares.length === 0}
|
||||
<div class="empty-state">
|
||||
<Share2 size={48} />
|
||||
<ShareNetwork size={48} />
|
||||
<h2>Keine geteilten Links</h2>
|
||||
<p>Teile Dateien oder Ordner, um Links hier zu verwalten.</p>
|
||||
</div>
|
||||
|
|
@ -128,7 +128,7 @@
|
|||
Link kopieren
|
||||
</button>
|
||||
<button class="delete-btn" onclick={() => deleteShare(share.id)}>
|
||||
<Trash2 size={16} />
|
||||
<Trash size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Palette, Check } from 'lucide-svelte';
|
||||
import { Palette, Check } from '@manacore/shared-icons';
|
||||
import { theme } from '$lib/stores/theme.svelte';
|
||||
import { THEME_DEFINITIONS, THEME_VARIANTS } from '@manacore/shared-theme';
|
||||
import type { ThemeVariant } from '@manacore/shared-theme';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { Trash2, RotateCcw, AlertTriangle } from 'lucide-svelte';
|
||||
import { Trash, ArrowCounterClockwise, Warning } from '@manacore/shared-icons';
|
||||
import { trashApi } from '$lib/api/client';
|
||||
import type { StorageFile, StorageFolder } from '$lib/api/client';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
|
|
@ -89,13 +89,13 @@
|
|||
<div class="trash-page">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<Trash2 size={24} />
|
||||
<Trash size={24} />
|
||||
Papierkorb
|
||||
</h1>
|
||||
|
||||
{#if files.length > 0 || folders.length > 0}
|
||||
<button class="empty-btn" onclick={handleEmptyTrash}>
|
||||
<AlertTriangle size={16} />
|
||||
<Warning size={16} />
|
||||
Papierkorb leeren
|
||||
</button>
|
||||
{/if}
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
</div>
|
||||
{:else if files.length === 0 && folders.length === 0}
|
||||
<div class="empty-state">
|
||||
<Trash2 size={48} />
|
||||
<Trash size={48} />
|
||||
<h2>Papierkorb ist leer</h2>
|
||||
<p>Gelöschte Dateien und Ordner erscheinen hier.</p>
|
||||
</div>
|
||||
|
|
@ -130,7 +130,7 @@
|
|||
</div>
|
||||
<div class="item-actions">
|
||||
<button class="restore-btn" onclick={() => handleRestore(folder.id, 'folder')}>
|
||||
<RotateCcw size={16} />
|
||||
<ArrowCounterClockwise size={16} />
|
||||
Wiederherstellen
|
||||
</button>
|
||||
<button class="delete-btn" onclick={() => handlePermanentDelete(folder.id, 'folder')}>
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
</div>
|
||||
<div class="item-actions">
|
||||
<button class="restore-btn" onclick={() => handleRestore(file.id, 'file')}>
|
||||
<RotateCcw size={16} />
|
||||
<ArrowCounterClockwise size={16} />
|
||||
Wiederherstellen
|
||||
</button>
|
||||
<button class="delete-btn" onclick={() => handlePermanentDelete(file.id, 'file')}>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
"@todo/shared": "workspace:*",
|
||||
"d3-force": "^3.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-svelte": "^0.556.0",
|
||||
"svelte-dnd-action": "^0.9.68",
|
||||
"svelte-i18n": "^4.0.1"
|
||||
},
|
||||
|
|
|
|||
1728
pnpm-lock.yaml
generated
1728
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue