/** * Creator detail page. * * Shows creator info (name, genres, video/technique counts) and lists * their technique pages with links. Handles loading and 404 states. */ import { useEffect, useState } from "react"; import { Link, useParams } from "react-router-dom"; import { fetchCreator, fetchTechniques, type CreatorDetailResponse, type TechniqueListItem, } from "../api/public-client"; import CreatorAvatar from "../components/CreatorAvatar"; export default function CreatorDetail() { const { slug } = useParams<{ slug: string }>(); const [creator, setCreator] = useState(null); const [techniques, setTechniques] = useState([]); const [loading, setLoading] = useState(true); const [notFound, setNotFound] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!slug) return; let cancelled = false; setLoading(true); setNotFound(false); setError(null); void (async () => { try { const [creatorData, techData] = await Promise.all([ fetchCreator(slug), fetchTechniques({ creator_slug: slug, limit: 100 }), ]); if (!cancelled) { setCreator(creatorData); setTechniques(techData.items); } } catch (err) { if (!cancelled) { if (err instanceof Error && err.message.includes("404")) { setNotFound(true); } else { setError( err instanceof Error ? err.message : "Failed to load creator", ); } } } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, [slug]); if (loading) { return
Loading creator…
; } if (notFound) { return (

Creator Not Found

The creator "{slug}" doesn't exist.

Back to Creators
); } if (error || !creator) { return (
Error: {error ?? "Unknown error"}
); } return (
← Creators {/* Header */}

{creator.name}

{creator.genres && creator.genres.length > 0 && ( {creator.genres.map((g) => ( {g} ))} )} {creator.video_count} video{creator.video_count !== 1 ? "s" : ""} {techniques.length > 0 && ( <> · {Object.entries( techniques.reduce>((acc, t) => { const cat = t.topic_category || "Uncategorized"; acc[cat] = (acc[cat] || 0) + 1; return acc; }, {}), ) .sort(([, a], [, b]) => b - a) .map(([cat, count], i) => ( {i > 0 && ·} {cat}: {count} ))} )}
{/* Technique pages */}

Techniques ({techniques.length})

{techniques.length === 0 ? (
No techniques yet.
) : (
{techniques.map((t, i) => ( {t.title} {t.topic_category} {t.topic_tags && t.topic_tags.length > 0 && ( {t.topic_tags.map((tag) => ( {tag} ))} )} {t.summary && ( {t.summary.length > 120 ? `${t.summary.slice(0, 120)}…` : t.summary} )} ))}
)}
); }