♻️ 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:
Till-JS 2026-01-29 13:15:13 +01:00
parent c21f780581
commit b89749deed
86 changed files with 1736 additions and 904 deletions

View file

@ -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"

View file

@ -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}

View file

@ -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

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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>

View file

@ -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" />

View file

@ -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>

View file

@ -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}

View file

@ -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