mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 04:41:09 +02:00
@mana/feedback wird zur Pflege-SSOT für Public-Community-Hub.
- PublicFeedbackItem-Typ: anonymisiertes Item, das nur display_name +
reactions + status führt — kein userId, displayHash, deviceInfo.
- ReactionEmoji ('👍' '❤️' '🚀' '🤔' '🎉') + REACTION_LABELS mit DE-Labels.
- CreateFeedbackInput erweitert um moduleContext + parentId. Reactions
+ score auf Feedback-Type optional gemacht.
- Service-Split:
createFeedbackService — auth-required Submit/React/Manage,
getPublicFeed (auth-enriched mit myReactions)
createPublicFeedbackService — anonymous, SSR-only, getFeed/getItem.
toggleReaction(emoji) statt vote/unvote (legacy-Shims bleiben für
back-compat zu vote → '👍'-Toggle).
- ReactionBar.svelte: Slack-Style emoji-row mit Active-Highlighting für
myReactions, ReadOnly-Mode für Public-SSR. Auto-disabled-Tooltip.
- index.ts re-exportiert die neuen Typen + ReactionBar; FeedbackVote
rausgeschmissen (durch FeedbackReactions im Server-Schema ersetzt).
FeedbackCard + FeedbackPage minimal angepasst, damit svelte-check
clean bleibt — die Legacy-Komponenten bleiben funktional, werden aber
in Phase 3 zu @mana/feedback's neuen Modul-Views ausgemistet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
/**
|
|
* Public, anonymous feedback service — for SSR / unauthenticated reads
|
|
* of the community feed (e.g. /community route, embeddable widget).
|
|
*
|
|
* No auth, no submit, no react. If you need write access, instantiate
|
|
* `createFeedbackService()` instead and pass a getAuthToken callback.
|
|
*/
|
|
|
|
import type { PublicFeedListResponse, PublicItemResponse, FeedbackQueryParams } from './api';
|
|
import type { PublicFeedbackItem } from './feedback';
|
|
import type { PublicFeedbackServiceConfig } from './types';
|
|
|
|
export function createPublicFeedbackService(config: PublicFeedbackServiceConfig) {
|
|
const { apiUrl, appId, publicEndpoint = '/api/v1/public/feedback' } = config;
|
|
const baseUrl = apiUrl.replace(/\/$/, '');
|
|
|
|
async function fetchPublic<T>(endpoint: string): Promise<T> {
|
|
const res = await fetch(`${baseUrl}${endpoint}`);
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
return res.json();
|
|
}
|
|
|
|
function feedQueryString(query?: FeedbackQueryParams): string {
|
|
const params = new URLSearchParams();
|
|
const effectiveAppId = query?.appId ?? appId;
|
|
if (effectiveAppId) params.set('appId', effectiveAppId);
|
|
if (query?.moduleContext) params.set('moduleContext', query.moduleContext);
|
|
if (query?.status) params.set('status', query.status);
|
|
if (query?.category) params.set('category', query.category);
|
|
if (query?.limit) params.set('limit', String(query.limit));
|
|
if (query?.offset) params.set('offset', String(query.offset));
|
|
return params.toString();
|
|
}
|
|
|
|
async function getFeed(query?: FeedbackQueryParams): Promise<PublicFeedbackItem[]> {
|
|
const qs = feedQueryString(query);
|
|
const res = await fetchPublic<PublicFeedListResponse>(`${publicEndpoint}/feed?${qs}`);
|
|
return res.items;
|
|
}
|
|
|
|
async function getItem(id: string): Promise<PublicItemResponse> {
|
|
return fetchPublic<PublicItemResponse>(`${publicEndpoint}/${id}`);
|
|
}
|
|
|
|
return { getFeed, getItem };
|
|
}
|
|
|
|
export type PublicFeedbackService = ReturnType<typeof createPublicFeedbackService>;
|