React-Frontend: Profilseite und Statistik, Dev-Proxy-Fix

- UserPage mit Profilkopf, Einstellungen (Avatar, Name, Konto löschen)
  und Nutzer-Feed im unveränderten Markup
- StatsPage mit Kacheln und Balken wie bisher
- Feed-Container wählbar (section/div) wie im alten Markup
- Vite-Proxy mit changeOrigin: false -- sonst scheitert jeder POST im
  Dev-Betrieb am Origin-Check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
irrlicht
2026-09-26 23:44:40 +02:00
co-authored by Claude Opus 5.5
parent ca65ddcacc
commit 728ac9b45e
4 changed files with 259 additions and 10 deletions
+9 -4
View File
@@ -10,8 +10,13 @@ const maxPage = 100;
// Feed lädt Seiten per Infinite-Scroll: queryKey identifiziert den Feed im
// Cache (zum Invalidieren nach eigenen Beiträgen), urlFor(page) baut den
// API-Pfad der Seite.
export function Feed({ queryKey, urlFor }: { queryKey: unknown[]; urlFor: (page: number) => string }) {
// API-Pfad der Seite. as ist das Container-Element wie im alten Markup:
// <section> auf der Startseite, <div> innerhalb des Profils.
export function Feed({ queryKey, urlFor, as: Container = "section" }: {
queryKey: unknown[];
urlFor: (page: number) => string;
as?: "section" | "div";
}) {
const feed = useInfiniteQuery({
queryKey,
queryFn: ({ pageParam }) => api.get<Entry[]>(urlFor(pageParam)),
@@ -48,11 +53,11 @@ export function Feed({ queryKey, urlFor }: { queryKey: unknown[]; urlFor: (page:
return (
<>
<section id="feed">
<Container id="feed">
{entries.map((e) => <EntryCard key={e.pid} entry={e} />)}
{feed.isError && <p className="msg">{errMsg(feed.error, "Feed konnte nicht geladen werden.")}</p>}
{feed.isSuccess && !hasNextPage && <p className="muted">YOU REACHED THE END!</p>}
</section>
</Container>
<div id="sentinel" ref={sentinel}></div>
</>
);