From 5b291c1a17534633a5b1897f7f752024bbc15966 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Jan 2026 20:38:49 +0000 Subject: [PATCH] feat(skilltree): add edit, level-up celebration, templates, and tree view - Edit skill modal with delete confirmation - Animated level-up celebration with particles - Skill templates for quick onboarding (Web Dev, Fitness, Languages, etc.) - Radial skill tree visualization (/tree) - Export/import functionality for data backup - Tree view link in header https://claude.ai/code/session_015XCsTDS9aLZ64Zin4HU6ex --- .../src/lib/components/EditSkillModal.svelte | 196 ++++++++++++++ .../lib/components/LevelUpCelebration.svelte | 171 +++++++++++++ .../web/src/lib/components/SkillCard.svelte | 7 + .../src/lib/components/SkillTemplates.svelte | 211 +++++++++++++++ .../apps/web/src/routes/+page.svelte | 185 ++++++++++++-- .../apps/web/src/routes/tree/+page.svelte | 241 ++++++++++++++++++ 6 files changed, 985 insertions(+), 26 deletions(-) create mode 100644 apps/skilltree/apps/web/src/lib/components/EditSkillModal.svelte create mode 100644 apps/skilltree/apps/web/src/lib/components/LevelUpCelebration.svelte create mode 100644 apps/skilltree/apps/web/src/lib/components/SkillTemplates.svelte create mode 100644 apps/skilltree/apps/web/src/routes/tree/+page.svelte diff --git a/apps/skilltree/apps/web/src/lib/components/EditSkillModal.svelte b/apps/skilltree/apps/web/src/lib/components/EditSkillModal.svelte new file mode 100644 index 000000000..ce137d615 --- /dev/null +++ b/apps/skilltree/apps/web/src/lib/components/EditSkillModal.svelte @@ -0,0 +1,196 @@ + + + diff --git a/apps/skilltree/apps/web/src/lib/components/LevelUpCelebration.svelte b/apps/skilltree/apps/web/src/lib/components/LevelUpCelebration.svelte new file mode 100644 index 000000000..df79c4c41 --- /dev/null +++ b/apps/skilltree/apps/web/src/lib/components/LevelUpCelebration.svelte @@ -0,0 +1,171 @@ + + + + + diff --git a/apps/skilltree/apps/web/src/lib/components/SkillCard.svelte b/apps/skilltree/apps/web/src/lib/components/SkillCard.svelte index e0840e1e6..4e824e5a2 100644 --- a/apps/skilltree/apps/web/src/lib/components/SkillCard.svelte +++ b/apps/skilltree/apps/web/src/lib/components/SkillCard.svelte @@ -91,6 +91,13 @@ XP hinzufügen + + + +

+ Starte schnell mit vorgefertigten Skill-Sets. Wähle eine Vorlage und füge einzelne Skills oder alle auf einmal hinzu. +

+ + +
+ {#each Object.entries(templates) as [name, skills]} +
+ + + + {selectedTemplate === name ? '−' : '+'} + +
+ + + + {#if selectedTemplate === name} +
+ {#each skills as skill} + {@const isAdded = addedSkills.has(skill.name)} +
+
+ +
+ {skill.name} + - {skill.description} +
+
+ +
+ {/each} +
+ {/if} +
+ {/each} + + + +
+ +
+ + diff --git a/apps/skilltree/apps/web/src/routes/+page.svelte b/apps/skilltree/apps/web/src/routes/+page.svelte index 5c8cdeadb..7275bf2db 100644 --- a/apps/skilltree/apps/web/src/routes/+page.svelte +++ b/apps/skilltree/apps/web/src/routes/+page.svelte @@ -1,37 +1,110 @@ @@ -44,13 +117,47 @@

SkillTree

- +
+ + + + + + + + + + + +
@@ -110,7 +217,7 @@ openAddXpModal(skill)} - onEdit={() => {}} + onEdit={() => openEditModal(skill)} onDelete={() => skillStore.deleteSkill(skill.id)} /> {/each} @@ -130,7 +237,7 @@ {#if skill}
-
+
+{activity.xpEarned}
@@ -161,18 +268,44 @@ /> {/if} -{#if showAddXpModal && selectedSkillForXp} +{#if showAddXpModal && selectedSkill} { - if (selectedSkillForXp) { - const result = await skillStore.addXp(selectedSkillForXp.id, xp, description, duration); - if (result.leveledUp) { - // Could show a level-up celebration here - } + skill={selectedSkill} + onClose={closeModals} + onSave={handleAddXp} + /> +{/if} + +{#if showEditSkillModal && selectedSkill} + { + if (selectedSkill) { + await skillStore.updateSkill(selectedSkill.id, updates); + } + }} + onDelete={() => { + if (selectedSkill) { + skillStore.deleteSkill(selectedSkill.id); } - closeAddXpModal(); + }} + /> +{/if} + +{#if showLevelUp} + (showLevelUp = false)} + /> +{/if} + +{#if showTemplatesModal} + (showTemplatesModal = false)} + onAddSkill={async (skill) => { + await skillStore.addSkill(skill); }} /> {/if} diff --git a/apps/skilltree/apps/web/src/routes/tree/+page.svelte b/apps/skilltree/apps/web/src/routes/tree/+page.svelte new file mode 100644 index 000000000..955ce25bc --- /dev/null +++ b/apps/skilltree/apps/web/src/routes/tree/+page.svelte @@ -0,0 +1,241 @@ + + + + Skill Tree View - SkillTree + + +
+ +
+
+
+ + + Zurück + +

Skill Tree Visualisierung

+
+
+
+ +
+ {#if skillStore.skills.length === 0} +
+

Noch keine Skills vorhanden. Erstelle zuerst einige Skills!

+ + Skills erstellen + +
+ {:else} + +
+ {#each Object.entries(BRANCH_INFO) as [branch, info]} + {@const count = skillStore.skills.filter((s) => s.branch === branch).length} + {#if count > 0} +
+ + {info.name} ({count}) +
+ {/if} + {/each} +
+ + +
+ + + + + + + + + + + + YOU + + + + {#each branches as branch, i} + {@const pos = getBranchPosition(i, branches.length)} + {@const branchSkills = skillStore.skills.filter((s) => s.branch === branch)} + {#if branchSkills.length > 0} + + + + + + {BRANCH_INFO[branch].name} + + + + {#each branchSkills as skill, j} + {@const skillPos = getSkillPosition(i, j, branchSkills.length, branches.length)} + {@const size = getNodeSize(skill.level)} + + + + + + + + {#if skill.level >= 4} + + {/if} + + + + + + + {skill.level} + + + + {skill.name} (Level {skill.level} - {skill.totalXp} XP) + + + + + {skill.name.length > 12 ? skill.name.slice(0, 12) + '...' : skill.name} + + {/each} + {/if} + {/each} + +
+ + +
+ {#each LEVEL_NAMES as name, level} +
+
+ {level} +
+ {name} +
+ {/each} +
+ {/if} +
+
+ +