feat: align home category and recommendation figma assets

This commit is contained in:
TerryM
2026-05-28 15:36:24 +08:00
parent 4b497380ee
commit 3ed3d00655
7 changed files with 55 additions and 53 deletions

View File

@@ -20,14 +20,35 @@ import {
} from "../../utils/postResourceAdapter";
import type { Post } from "../../types/post";
const FIGMA_CATEGORY_LABELS: Record<string, string> = {
"project-ppt": "项目资料",
"daily-class": "每日课堂",
"official-announcement": "官方公告",
"academy-materials": "学堂教育",
"global-evangelism": "全球布道",
"daily-poster": "每日海报",
"community-tweets": "社群动向",
"video-hub": "视频汇总",
"subsidy-policy": "补贴政策",
};
const FIGMA_CATEGORY_ORDER = Object.keys(FIGMA_CATEGORY_LABELS);
function figmaCategoryRank(category: Category): number {
const index = FIGMA_CATEGORY_ORDER.indexOf(category.slug);
return index === -1 ? FIGMA_CATEGORY_ORDER.length : index;
}
function figmaCategoryName(category: Category): string {
return FIGMA_CATEGORY_LABELS[category.slug] ?? category.name;
}
export function Home() {
const { t, lang } = useI18n();
const [cats, setCats] = useState<Category[]>([]);
const [rec, setRec] = useState<PostBackedResource[]>([]);
const [latest, setLatest] = useState<PostBackedResource[]>([]);
const [latestPosts, setLatestPosts] = useState<Post[]>([]);
const [popular, setPopular] = useState<PostBackedResource[]>([]);
const [popularPosts, setPopularPosts] = useState<Post[]>([]);
const [err, setErr] = useState<string | null>(null);
const recRowRef = useRef<HTMLDivElement>(null);
const categoryRowRef = useRef<HTMLDivElement>(null);
@@ -44,9 +65,8 @@ export function Home() {
getJSON<Category[]>(`/api/categories${catQ}`),
getJSON<{ items: Post[] }>(`/api/posts/recommended${postQ}&limit=12`),
getJSON<{ items: Post[] }>(`/api/posts/latest${postQ}&limit=8`),
getJSON<{ items: Post[] }>(`/api/posts${postQ}&sort=popular&limit=8`),
])
.then(([c, r, l, p]) => {
.then(([c, r, l]) => {
setCats(itemsOrEmpty(c));
setRec(
itemsOrEmpty(r.items).map((post) =>
@@ -60,13 +80,6 @@ export function Home() {
postToResource(post, lang, itemsOrEmpty(c)),
),
);
const popularItems = itemsOrEmpty(p.items);
setPopularPosts(popularItems);
setPopular(
popularItems.map((post) =>
postToResource(post, lang, itemsOrEmpty(c)),
),
);
})
.catch((e) => setErr(String(e)));
}, [lang]);
@@ -74,9 +87,13 @@ export function Home() {
const iconKeyForResource = (r: PostBackedResource) =>
cats.find((c) => c.id === r.categoryId)?.iconKey ?? "folder";
const figmaOrderedCategories = [...cats].sort(
(a, b) => figmaCategoryRank(a) - figmaCategoryRank(b),
);
const categoryPages: Category[][] = [];
for (let index = 0; index < cats.length; index += 9) {
categoryPages.push(cats.slice(index, index + 9));
for (let index = 0; index < figmaOrderedCategories.length; index += 9) {
categoryPages.push(figmaOrderedCategories.slice(index, index + 9));
}
const activeCategoryCount = categoryPages[activeCategoryPage]?.length ?? 0;
const activeCategoryRows = Math.ceil(activeCategoryCount / 3);
@@ -137,7 +154,6 @@ export function Home() {
};
const latestPlaceholderCount = Math.max(0, 5 - latest.length);
const popularPlaceholderCount = Math.max(0, 5 - popular.length);
const recommendedDotCount = Math.max(1, Math.min(4, rec.length || 4));
const activeRecommendedDot = Math.min(
recommendedDotCount - 1,
@@ -191,7 +207,7 @@ export function Home() {
className="h-9 w-9 shrink-0 text-ark-gold"
/>
<div className="w-full truncate text-[13px] font-medium leading-[19.5px] text-white">
{c.name}
{figmaCategoryName(c)}
</div>
</Link>
))}
@@ -231,8 +247,8 @@ export function Home() {
</div>
<div className="mt-7 hidden grid-cols-3 gap-3 min-[440px]:gap-3.5 md:grid md:grid-cols-5 md:gap-3 lg:grid-cols-6 xl:grid-cols-7 xl:gap-4">
{cats.map((c) => {
const { line1, line2 } = categoryCardLines(c.name);
{figmaOrderedCategories.map((c) => {
const { line1, line2 } = categoryCardLines(figmaCategoryName(c));
return (
<Link
key={c.id}
@@ -275,7 +291,7 @@ export function Home() {
>
{rec.map((r, index) => (
<div key={r.id} className="snap-start">
<RecommendedCard r={r} visualIndex={index} />
<RecommendedCard r={r} visualIndex={index} useFigmaDesign />
</div>
))}
</div>
@@ -351,31 +367,7 @@ export function Home() {
</div>
</section>
<section id="popular" className="scroll-mt-24">
<div className="px-4 md:px-0">
<SectionHeader
title={t("popularSection")}
viewAllTo="/browse?sort=popular"
viewAllLabel={t("viewAll")}
/>
</div>
<div className="flex flex-col gap-3 md:hidden">
{popularPosts.slice(0, 4).map((post) => (
<MessageBubble key={post.id} post={post} />
))}
</div>
<div className="mt-7 hidden gap-3 min-[576px]:grid-cols-2 md:grid md:gap-4 lg:grid-cols-3 xl:grid-cols-5">
{popular.map((r) => (
<LatestUpdateRow key={r.id} r={r} iconKey={iconKeyForResource(r)} />
))}
{Array.from({ length: popularPlaceholderCount }).map((_, index) => (
<ComingSoonLatestUpdateRow
key={`popular-coming-soon-${index}`}
index={popular.length + index}
/>
))}
</div>
</section>
<span id="popular" className="block scroll-mt-24" aria-hidden="true" />
</div>
);
}