diff --git a/src/App.tsx b/src/App.tsx index 14cfb01..b366566 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { PublicLayout } from "./layouts/PublicLayout"; import { Home } from "./pages/Home"; import { Browse } from "./pages/Browse"; import { CategoriesPage } from "./pages/Categories"; +import { CategoryPage } from "./pages/Category"; import { OfficialRecommendationsPage } from "./pages/OfficialRecommendations"; import { SearchPage } from "./pages/Search"; import { PostRedirect } from "./pages/PostRedirect"; @@ -33,10 +34,7 @@ export default function App() { path="/official-recommendations" element={} /> - } - /> + } /> } /> } /> } /> diff --git a/src/components/AssetStreamPage.tsx b/src/components/AssetStreamPage.tsx new file mode 100644 index 0000000..9402fd6 --- /dev/null +++ b/src/components/AssetStreamPage.tsx @@ -0,0 +1,19 @@ +import type { PostScope } from "../types/post"; +import { MessageStream } from "./messageStream/MessageStream"; +import { SectionHeader } from "./SectionHeader"; + +type AssetStreamPageProps = { + title: string; + scope: PostScope; +}; + +export function AssetStreamPage({ title, scope }: AssetStreamPageProps) { + return ( + + + + + + + ); +} diff --git a/src/pages/Browse/index.tsx b/src/pages/Browse/index.tsx index 12275a8..426d7f3 100644 --- a/src/pages/Browse/index.tsx +++ b/src/pages/Browse/index.tsx @@ -1,6 +1,5 @@ import { useSearchParams } from "react-router-dom"; -import { MessageStream } from "../../components/messageStream/MessageStream"; -import { SectionHeader } from "../../components/SectionHeader"; +import { AssetStreamPage } from "../../components/AssetStreamPage"; import { useI18n } from "../../i18n"; export function Browse() { @@ -17,12 +16,5 @@ export function Browse() { : sort === "popular" ? t("popular") : t("all"); - return ( - - - - - - - ); + return ; } diff --git a/src/pages/Categories/index.tsx b/src/pages/Categories/index.tsx index bf77f01..e8ec19b 100644 --- a/src/pages/Categories/index.tsx +++ b/src/pages/Categories/index.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { Link } from "react-router-dom"; import { getJSON, itemsOrEmpty, type Category } from "../../api"; import { CategoryIcon } from "../../components/CategoryIcon"; import { SectionHeader } from "../../components/SectionHeader"; @@ -30,7 +31,6 @@ function figmaCategoryRank(category: Category): number { export function CategoriesPage() { const { t, lang } = useI18n(); const [cats, setCats] = useState([]); - const [unavailableOpen, setUnavailableOpen] = useState(false); const [err, setErr] = useState(null); useEffect(() => { @@ -60,10 +60,9 @@ export function CategoriesPage() { {cats.map((category) => ( - setUnavailableOpen(true)} + to={`/category/${encodeURIComponent(category.slug)}`} className="flex h-[88px] min-w-0 flex-col items-center justify-center gap-2 rounded-xl border border-[#27292E] bg-[#1D1E23] px-4 py-3 text-center outline-none transition hover:border-ark-gold/55 hover:bg-[#252630] focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg" > {cleanCategoryDisplayName(category.name)} - + ))} - - {unavailableOpen ? ( - setUnavailableOpen(false)} - > - event.stopPropagation()} - > - - {t("featureUnavailable")} - - - {t("featureUnavailableDesc")} - - setUnavailableOpen(false)} - className="mt-5 h-10 w-full rounded-full bg-ark-gold text-sm font-semibold text-black transition hover:bg-ark-gold2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#1D1E23]" - > - {t("confirm")} - - - - ) : null} ); } diff --git a/src/pages/Category/index.tsx b/src/pages/Category/index.tsx index 55fab9c..e5b265c 100644 --- a/src/pages/Category/index.tsx +++ b/src/pages/Category/index.tsx @@ -1,31 +1,31 @@ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import { getJSON, itemsOrEmpty, type Category } from "../../api"; -import { MessageStream } from "../../components/messageStream/MessageStream"; +import { AssetStreamPage } from "../../components/AssetStreamPage"; import { langQuery, useI18n } from "../../i18n"; +import { cleanCategoryDisplayName } from "../../utils/categoryDisplay"; export function CategoryPage() { const { slug = "" } = useParams(); const { lang } = useI18n(); - const [title, setTitle] = useState(""); + const [title, setTitle] = useState(slug); + const scope = useMemo(() => ({ kind: "category" as const, slug }), [slug]); useEffect(() => { if (!slug) return; + setTitle(slug); getJSON( `/api/categories?lang=${encodeURIComponent(langQuery(lang))}`, ) .then((cats) => - setTitle(itemsOrEmpty(cats).find((x) => x.slug === slug)?.name ?? slug), + setTitle( + cleanCategoryDisplayName( + itemsOrEmpty(cats).find((x) => x.slug === slug)?.name ?? slug, + ), + ), ) .catch(() => setTitle(slug)); }, [slug, lang]); - return ( - - - {title || slug} - - - - ); + return ; } diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 4a9ef62..953567f 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,5 +1,5 @@ import { ChevronLeft, ChevronRight } from "lucide-react"; -import { useLocation } from "react-router-dom"; +import { Link, useLocation } from "react-router-dom"; import { useEffect, useRef, useState } from "react"; import { getJSON, itemsOrEmpty, type Category } from "../../api"; import { CategoryIcon } from "../../components/CategoryIcon"; @@ -51,7 +51,6 @@ export function Home() { const [latestPosts, setLatestPosts] = useState([]); const [popular, setPopular] = useState([]); const [popularPosts, setPopularPosts] = useState([]); - const [categoryUnavailableOpen, setCategoryUnavailableOpen] = useState(false); const [err, setErr] = useState(null); const recRowRef = useRef(null); const latestRowRef = useRef(null); @@ -253,10 +252,9 @@ export function Home() { className="grid w-full shrink-0 snap-start grid-cols-3 gap-2 px-4" > {page.map((c) => ( - setCategoryUnavailableOpen(true)} + to={`/category/${encodeURIComponent(c.slug)}`} className="flex h-[88px] min-w-0 flex-col items-center justify-center gap-2 rounded-xl border border-[#27292E] bg-[#1D1E23] px-4 py-3 text-center outline-none transition hover:border-ark-gold/55 hover:bg-[#252630] focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg" > {cleanCategoryDisplayName(c.name)} - + ))} ))} @@ -306,10 +304,9 @@ export function Home() { {figmaOrderedCategories.map((c) => ( - setCategoryUnavailableOpen(true)} + to={`/category/${encodeURIComponent(c.slug)}`} className="flex h-[88px] min-w-0 flex-col items-center justify-center gap-2 rounded-xl border border-[#27292E] bg-[#1D1E23] px-4 py-3 text-center outline-none transition hover:border-ark-gold/55 hover:bg-[#252630] focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg" > {cleanCategoryDisplayName(c.name)} - + ))} @@ -486,38 +483,6 @@ export function Home() { ) : null} - - {categoryUnavailableOpen ? ( - setCategoryUnavailableOpen(false)} - > - event.stopPropagation()} - > - - {t("featureUnavailable")} - - - {t("featureUnavailableDesc")} - - setCategoryUnavailableOpen(false)} - className="mt-5 h-10 w-full rounded-full bg-ark-gold text-sm font-semibold text-black transition hover:bg-ark-gold2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#1D1E23]" - > - {t("confirm")} - - - - ) : null} ); }
- {t("featureUnavailableDesc")} -