4 page-implementations + server-route-proxies (admin-secret stays server-only): DOMAINS (apps/admin/pages/domains.vue): - UTable mit pending-submissions queue - Approve / Reject buttons per row - Reject-confirm-modal mit optional note - useToast + refresh nach action - 3 server-routes: GET list + POST approve/reject STATS (apps/admin/pages/stats.vue): - Stat-cards: Total Users + delta-week, Total Posts + delta-week, Domains pending (link to /domains), Domains approved, Feedback pending, Lyra-Posts (30d) - UProgress für Domain-Approval-Quote - Auto-refresh 60s + manual refresh-button - USkeleton während loading - 1 server-route: GET /api/stats USERS (apps/admin/pages/users.vue): - UTable mit avatar+nickname/username, plan-badge, streak, status, createdAt - Search-input + plan-filter dropdown - Action-dropdown per row: Plan-Change / Ban-Toggle / Soft-Delete - 3 separate UModals mit confirm-pattern - Cursor-pagination (Mehr laden button) - 3 server-routes: GET list, PATCH /:id, DELETE /:id MODERATION (apps/admin/pages/moderation.vue): - Stack-layout mit card-pro-item (statt table — content-preview braucht space) - Type-badge (Post/Comment), Author + Plan-badge, content-preview (200 chars), reportedAt - Action-buttons: Dismiss (gray), Delete Content (red soft + reason-modal), Ban User (red solid + warning-modal) - Empty-state, cursor-pagination - 4 server-routes: GET /queue, POST /:id/dismiss/delete/ban-user Server-route pattern (apps/admin/server/api/...): - Use useRuntimeConfig().adminSecret server-only - Client never sees x-admin-secret - Body/query passthrough to backend Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
20 lines
596 B
TypeScript
20 lines
596 B
TypeScript
// Admin-App proxy: PATCH /api/admin/users/[id]
|
|
// Forwards body 1:1 ans Backend mit x-admin-secret.
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const config = useRuntimeConfig();
|
|
const id = getRouterParam(event, "id");
|
|
if (!id) throw createError({ statusCode: 400, message: "User-ID fehlt" });
|
|
|
|
const body = await readBody(event).catch(() => ({}));
|
|
|
|
return $fetch(`${config.public.apiBase}/api/admin/users/${id}`, {
|
|
method: "PATCH",
|
|
headers: {
|
|
"x-admin-secret": config.adminSecret as string,
|
|
"content-type": "application/json",
|
|
},
|
|
body,
|
|
});
|
|
});
|