From eecf64c1c60b1a0ad509ca52119ec97bce40395f Mon Sep 17 00:00:00 2001
From: Till JS
Date: Mon, 27 Apr 2026 14:14:08 +0200
Subject: [PATCH] feat(community,feedback): +5 reward chip + Phase 3.F
legacy-cleanup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
UI:
- FeedbackQuickModal Success-State + Onboarding-Wish Confirm zeigen
+5-Mana-Reward-Chip mit reward-in-Animation. Sofortiger Sichtbarer
Reziprozitäts-Loop.
Legacy-Cleanup (Phase 3.F):
- @mana/feedback dropped:
- FeedbackPage.svelte, FeedbackCard.svelte, FeedbackList.svelte,
FeedbackForm.svelte, VoteButton.svelte, StatusBadge.svelte
(alles Pre-Reactions-Markup, durch Community-Modul ersetzt)
- vote/unvote/toggleVote/getPublicFeedback service-shims
- VoteResponse, voteCount, userHasVoted Types
- mana-web dropped:
- lib/modules/feedback/ListView.svelte
- routes/(app)/feedback/+page.svelte
- app-registry-Eintrag 'feedback' (nur Bug-Reports — Community macht
das ohnehin besser via /community)
Pre-launch saubere Lösung: keine Backward-Compat-Shims, keine alten
Markup-Reste. ReactionBar bleibt der einzige Voting-Surface, /community
ist die einzige Feedback-Surface.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
.../apps/web/src/lib/app-registry/apps.ts | 10 -
.../feedback/FeedbackQuickModal.svelte | 43 ++
.../src/lib/modules/feedback/ListView.svelte | 20 -
.../src/routes/(app)/feedback/+page.svelte | 10 -
.../routes/(app)/onboarding/wish/+page.svelte | 49 ++-
packages/feedback/src/FeedbackCard.svelte | 165 --------
packages/feedback/src/FeedbackForm.svelte | 191 ---------
packages/feedback/src/FeedbackList.svelte | 58 ---
packages/feedback/src/FeedbackPage.svelte | 395 ------------------
packages/feedback/src/StatusBadge.svelte | 31 --
packages/feedback/src/VoteButton.svelte | 91 ----
packages/feedback/src/api.ts | 7 -
.../feedback/src/createFeedbackService.ts | 27 --
packages/feedback/src/feedback.ts | 3 -
packages/feedback/src/index.ts | 7 -
15 files changed, 90 insertions(+), 1017 deletions(-)
delete mode 100644 apps/mana/apps/web/src/lib/modules/feedback/ListView.svelte
delete mode 100644 apps/mana/apps/web/src/routes/(app)/feedback/+page.svelte
delete mode 100644 packages/feedback/src/FeedbackCard.svelte
delete mode 100644 packages/feedback/src/FeedbackForm.svelte
delete mode 100644 packages/feedback/src/FeedbackList.svelte
delete mode 100644 packages/feedback/src/FeedbackPage.svelte
delete mode 100644 packages/feedback/src/StatusBadge.svelte
delete mode 100644 packages/feedback/src/VoteButton.svelte
diff --git a/apps/mana/apps/web/src/lib/app-registry/apps.ts b/apps/mana/apps/web/src/lib/app-registry/apps.ts
index 7aa4fc18a..010b223fd 100644
--- a/apps/mana/apps/web/src/lib/app-registry/apps.ts
+++ b/apps/mana/apps/web/src/lib/app-registry/apps.ts
@@ -1323,16 +1323,6 @@ registerApp({
},
});
-registerApp({
- id: 'feedback',
- name: 'Feedback',
- color: '#8B5CF6',
- icon: ChatCircleDots,
- views: {
- list: { load: () => import('$lib/modules/feedback/ListView.svelte') },
- },
-});
-
registerApp({
id: 'community',
name: 'Community',
diff --git a/apps/mana/apps/web/src/lib/components/feedback/FeedbackQuickModal.svelte b/apps/mana/apps/web/src/lib/components/feedback/FeedbackQuickModal.svelte
index 9fe31b021..8c5b6cf1e 100644
--- a/apps/mana/apps/web/src/lib/components/feedback/FeedbackQuickModal.svelte
+++ b/apps/mana/apps/web/src/lib/components/feedback/FeedbackQuickModal.svelte
@@ -105,6 +105,10 @@
Dein Feedback ist eingegangen — sichtbar als
{submittedDisplayName}.
+
+ +5
+ Mana Credits
+
{#if isPublic}
Es taucht in der Community-Page auf, sobald wir es freigeben.
{:else}
@@ -261,6 +265,45 @@
margin-top: 0.5rem;
}
+ .reward-chip {
+ align-self: flex-start;
+ display: inline-flex;
+ align-items: baseline;
+ gap: 0.375rem;
+ padding: 0.4375rem 0.75rem;
+ border-radius: 999px;
+ background: linear-gradient(
+ 135deg,
+ hsl(var(--color-primary) / 0.18),
+ hsl(var(--color-primary) / 0.08)
+ );
+ color: hsl(var(--color-primary));
+ border: 1px solid hsl(var(--color-primary) / 0.3);
+ font-weight: 600;
+ animation: reward-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
+ }
+
+ .reward-amount {
+ font-size: 1rem;
+ font-variant-numeric: tabular-nums;
+ }
+
+ .reward-label {
+ font-size: 0.8125rem;
+ opacity: 0.85;
+ }
+
+ @keyframes reward-in {
+ from {
+ opacity: 0;
+ transform: translateY(-6px) scale(0.92);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+ }
+
.context-badge {
align-self: flex-start;
padding: 0.25rem 0.5rem;
diff --git a/apps/mana/apps/web/src/lib/modules/feedback/ListView.svelte b/apps/mana/apps/web/src/lib/modules/feedback/ListView.svelte
deleted file mode 100644
index e51eac279..000000000
--- a/apps/mana/apps/web/src/lib/modules/feedback/ListView.svelte
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/apps/mana/apps/web/src/routes/(app)/feedback/+page.svelte b/apps/mana/apps/web/src/routes/(app)/feedback/+page.svelte
deleted file mode 100644
index 573842145..000000000
--- a/apps/mana/apps/web/src/routes/(app)/feedback/+page.svelte
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
diff --git a/apps/mana/apps/web/src/routes/(app)/onboarding/wish/+page.svelte b/apps/mana/apps/web/src/routes/(app)/onboarding/wish/+page.svelte
index 5c43f0e96..fa02ca6dc 100644
--- a/apps/mana/apps/web/src/routes/(app)/onboarding/wish/+page.svelte
+++ b/apps/mana/apps/web/src/routes/(app)/onboarding/wish/+page.svelte
@@ -138,7 +138,11 @@
{#if submittedDisplayName}
{/if}
@@ -319,11 +323,52 @@
}
.preview {
- padding: 0.625rem 0.875rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.75rem 0.875rem;
border-radius: 0.625rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
font-size: 0.8125rem;
text-align: center;
}
+
+ .reward-chip {
+ display: inline-flex;
+ align-items: baseline;
+ gap: 0.375rem;
+ padding: 0.4375rem 0.75rem;
+ border-radius: 999px;
+ background: linear-gradient(
+ 135deg,
+ hsl(var(--color-primary) / 0.18),
+ hsl(var(--color-primary) / 0.08)
+ );
+ border: 1px solid hsl(var(--color-primary) / 0.35);
+ font-weight: 600;
+ animation: reward-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
+ }
+
+ .reward-amount {
+ font-size: 1rem;
+ font-variant-numeric: tabular-nums;
+ }
+
+ .reward-label {
+ font-size: 0.8125rem;
+ opacity: 0.85;
+ }
+
+ @keyframes reward-in {
+ from {
+ opacity: 0;
+ transform: translateY(-6px) scale(0.92);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+ }
diff --git a/packages/feedback/src/FeedbackCard.svelte b/packages/feedback/src/FeedbackCard.svelte
deleted file mode 100644
index ee3d75c78..000000000
--- a/packages/feedback/src/FeedbackCard.svelte
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
{feedback.feedbackText}
-
- {#if feedback.adminResponse}
-
-
Admin-Antwort:
-
{feedback.adminResponse}
-
- {/if}
-
-
-
-
-
-
diff --git a/packages/feedback/src/FeedbackForm.svelte b/packages/feedback/src/FeedbackForm.svelte
deleted file mode 100644
index 22f337729..000000000
--- a/packages/feedback/src/FeedbackForm.svelte
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-
-
-
diff --git a/packages/feedback/src/FeedbackList.svelte b/packages/feedback/src/FeedbackList.svelte
deleted file mode 100644
index 15d1fa93c..000000000
--- a/packages/feedback/src/FeedbackList.svelte
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
- {#if items.length === 0}
-
- {:else}
- {#each items as feedback (feedback.id)}
-
- {/each}
- {/if}
-
-
-
diff --git a/packages/feedback/src/FeedbackPage.svelte b/packages/feedback/src/FeedbackPage.svelte
deleted file mode 100644
index 676719248..000000000
--- a/packages/feedback/src/FeedbackPage.svelte
+++ /dev/null
@@ -1,395 +0,0 @@
-
-
-
- {pageTitle} - {appName}
-
-
-
-
-
-
-
-
- {#if successMessage}
-
-
- {successMessage}
-
- {/if}
-
-
-
- {#if showForm}
-
-
Neues Feedback
- (showForm = false)}
- {isSubmitting}
- />
-
- {:else}
-
- {/if}
-
-
-
-
-
-
-
-
-
-
- {#if isLoading}
-
- {:else if activeTab === 'community'}
-
- {:else}
-
- {/if}
-
-
-
-
-
diff --git a/packages/feedback/src/StatusBadge.svelte b/packages/feedback/src/StatusBadge.svelte
deleted file mode 100644
index 6d95c6f46..000000000
--- a/packages/feedback/src/StatusBadge.svelte
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- {config.label}
-
-
-
diff --git a/packages/feedback/src/VoteButton.svelte b/packages/feedback/src/VoteButton.svelte
deleted file mode 100644
index 433816963..000000000
--- a/packages/feedback/src/VoteButton.svelte
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
diff --git a/packages/feedback/src/api.ts b/packages/feedback/src/api.ts
index 1691edf39..e978b827a 100644
--- a/packages/feedback/src/api.ts
+++ b/packages/feedback/src/api.ts
@@ -73,10 +73,3 @@ export interface AdminPatchInput {
}
export type ReactInput = { emoji: ReactionEmoji };
-
-export interface VoteResponse {
- success: boolean;
- newVoteCount?: number;
- userHasVoted?: boolean;
- error?: string;
-}
diff --git a/packages/feedback/src/createFeedbackService.ts b/packages/feedback/src/createFeedbackService.ts
index bf18356a2..432464e0b 100644
--- a/packages/feedback/src/createFeedbackService.ts
+++ b/packages/feedback/src/createFeedbackService.ts
@@ -16,7 +16,6 @@ import type {
ReactionResponse,
AdminPatchInput,
ReactInput,
- VoteResponse,
} from './api';
import type { FeedbackServiceConfig } from './types';
import type { PublicFeedbackItem, ReactionEmoji } from './feedback';
@@ -148,27 +147,6 @@ export function createFeedbackService(config: FeedbackServiceConfig) {
});
}
- // ── Legacy (back-compat shims) ─────────────────────────────────
- // Older callers still use vote/unvote — translate to 👍-reaction toggles.
-
- async function vote(feedbackId: string): Promise {
- const res = await toggleReaction(feedbackId, '👍');
- return {
- success: true,
- newVoteCount: res.reactions['👍'] ?? 0,
- userHasVoted: res.userHasReacted,
- };
- }
- const unvote = vote; // toggle, semantically idempotent for legacy callers
- async function toggleVote(feedbackId: string): Promise {
- return vote(feedbackId);
- }
-
- async function getPublicFeedback(query?: FeedbackQueryParams): Promise {
- const items = await getPublicFeed(query);
- return { items: items as unknown as FeedbackListResponse['items'] };
- }
-
return {
createFeedback,
getPublicFeed,
@@ -180,11 +158,6 @@ export function createFeedbackService(config: FeedbackServiceConfig) {
deleteFeedback,
adminListAll,
adminPatch,
- // Legacy (deprecated):
- getPublicFeedback,
- vote,
- unvote,
- toggleVote,
};
}
diff --git a/packages/feedback/src/feedback.ts b/packages/feedback/src/feedback.ts
index fee300e72..bedcda457 100644
--- a/packages/feedback/src/feedback.ts
+++ b/packages/feedback/src/feedback.ts
@@ -78,7 +78,6 @@ export interface Feedback {
status: FeedbackStatus;
isPublic: boolean;
adminResponse?: string;
- voteCount: number;
displayHash?: string;
displayName?: string;
moduleContext?: string;
@@ -90,8 +89,6 @@ export interface Feedback {
updatedAt: string;
publishedAt?: string;
completedAt?: string;
- // Legacy / derived for older UI surfaces:
- userHasVoted?: boolean;
}
export const FEEDBACK_CATEGORY_LABELS: Record = {
diff --git a/packages/feedback/src/index.ts b/packages/feedback/src/index.ts
index a81685d1c..59520dfaa 100644
--- a/packages/feedback/src/index.ts
+++ b/packages/feedback/src/index.ts
@@ -31,7 +31,6 @@ export {
type ReactionResponse,
type AdminPatchInput,
type ReactInput,
- type VoteResponse,
} from './api';
// Services
@@ -43,10 +42,4 @@ export {
export type { FeedbackServiceConfig, PublicFeedbackServiceConfig } from './types';
// UI Components
-export { default as FeedbackPage } from './FeedbackPage.svelte';
-export { default as FeedbackForm } from './FeedbackForm.svelte';
-export { default as FeedbackList } from './FeedbackList.svelte';
-export { default as FeedbackCard } from './FeedbackCard.svelte';
-export { default as VoteButton } from './VoteButton.svelte';
export { default as ReactionBar } from './ReactionBar.svelte';
-export { default as StatusBadge } from './StatusBadge.svelte';