.
All checks were successful
Deploy blog-frontend / build-and-deploy (push) Successful in 2m5s

This commit is contained in:
wypark
2026-06-07 11:43:52 +09:00
parent b466fa98c9
commit 8fedc8657e
3 changed files with 93 additions and 20 deletions

View File

@@ -29,10 +29,17 @@ import {
Category,
DashboardPostStat,
DashboardRange,
DashboardTrafficPoint,
PageMeta,
Post,
} from '@/types';
const dashboardRangeDays: Record<DashboardRange, number> = {
'7d': 7,
'30d': 30,
'90d': 90,
};
const countCategories = (categories: Category[] = []): number => {
return categories.reduce((count, category) => {
return count + 1 + countCategories(category.children || []);
@@ -89,6 +96,46 @@ const toPostStat = (post: Post): DashboardPostStat => ({
createdAt: post.createdAt,
});
const formatKstDateKey = (date: Date) => {
return new Intl.DateTimeFormat('sv-SE', {
timeZone: 'Asia/Seoul',
year: 'numeric',
month: '2-digit',
day: '2-digit',
}).format(date);
};
const getFallbackTraffic = (
posts: Post[],
range: DashboardRange,
): DashboardTrafficPoint[] => {
const days = dashboardRangeDays[range];
const today = new Date();
const points = Array.from({ length: days }, (_, index) => {
const date = new Date(today);
date.setDate(today.getDate() - (days - 1 - index));
return {
date: formatKstDateKey(date),
views: 0,
};
});
const pointMap = new Map(points.map((point) => [point.date, point]));
posts.forEach((post) => {
const createdAt = new Date(post.createdAt);
if (Number.isNaN(createdAt.getTime())) return;
const dateKey = formatKstDateKey(createdAt);
const point = pointMap.get(dateKey);
if (!point) return;
point.views += post.viewCount;
});
return points;
};
function RecentPostRow({ post }: { post: Post }) {
return (
<Link
@@ -249,6 +296,11 @@ export default function AdminPage() {
() => dashboard?.topPosts ?? (popularData?.content ?? []).map(toPostStat),
[dashboard?.topPosts, popularData?.content],
);
const fallbackTraffic = useMemo(
() => getFallbackTraffic([...(latestData?.content ?? []), ...(popularData?.content ?? [])], range),
[latestData?.content, popularData?.content, range],
);
const trafficPoints = dashboard?.traffic?.length ? dashboard.traffic : fallbackTraffic;
return (
<div className="space-y-8">
@@ -301,10 +353,10 @@ export default function AdminPage() {
/>
<AdminDashboardTrafficChart
points={dashboard?.traffic ?? []}
points={trafficPoints}
range={range}
onRangeChange={setRange}
isFallback={isFallback}
isFallback={isFallback || !dashboard?.traffic?.length}
/>
<div className="grid gap-6 xl:grid-cols-[1fr_0.8fr]">