diff --git a/dashboard/src/i18n/locales/en.json b/dashboard/src/i18n/locales/en.json index 387108f1..6d2dbe4c 100644 --- a/dashboard/src/i18n/locales/en.json +++ b/dashboard/src/i18n/locales/en.json @@ -52,8 +52,10 @@ "charts": { "growthTrend": "Growth Trend", "growthTrendDesc": "Daily memory creation volume", + "growthTrendNoData": "No memory creation data yet", "memoryCategories": "Memory Categories", "memoryCategoriesDesc": "Distribution by classification", + "memoryCategoriesNoData": "No memory categories yet", "hotMemories": "Hot Memories", "hotMemoriesDesc": "Top retrieved records by access count", "contentSnippet": "Content Snippet", diff --git a/dashboard/src/i18n/locales/zh.json b/dashboard/src/i18n/locales/zh.json index df5f76e9..a3dafbc2 100644 --- a/dashboard/src/i18n/locales/zh.json +++ b/dashboard/src/i18n/locales/zh.json @@ -52,8 +52,10 @@ "charts": { "growthTrend": "增长趋势", "growthTrendDesc": "每日记忆创建量", + "growthTrendNoData": "暂无记忆创建数据", "memoryCategories": "记忆分类", "memoryCategoriesDesc": "按分类分布", + "memoryCategoriesNoData": "暂无记忆分类数据", "hotMemories": "热门记忆", "hotMemoriesDesc": "按访问次数排序的热门记录", "contentSnippet": "内容摘要", diff --git a/dashboard/src/routes/index.tsx b/dashboard/src/routes/index.tsx index bccf4e2b..91109eb9 100644 --- a/dashboard/src/routes/index.tsx +++ b/dashboard/src/routes/index.tsx @@ -9,7 +9,7 @@ import { RefreshCcw, TrendingUp, } from "lucide-react"; -import { useState } from "react"; +import { useState, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { Bar, @@ -251,10 +251,12 @@ function OverviewPage() { const trendData = Object.entries(stats.growth_trend) .sort() .map(([date, count]) => ({ date, count })); + const hasTrendData = trendData.some((item) => item.count > 0); const ageData = Object.entries(stats.age_distribution).map( ([name, value]) => ({ name, value }), ); + const hasTypeData = typeData.some((item) => item.value > 0); const dynamicChartConfig = typeData.reduce((acc, curr) => { acc[curr.name] = { @@ -368,30 +370,37 @@ function OverviewPage() { {t("dashboard.charts.growthTrendDesc")} - - - - - - } /> - - - + {hasTrendData ? ( + + + + + + } /> + + + + ) : ( + } + message={t("dashboard.charts.growthTrendNoData")} + /> + )} @@ -407,30 +416,37 @@ function OverviewPage() { {t("dashboard.charts.memoryCategoriesDesc")} - - - - {typeData.map((entry, index) => ( - - ))} - - } /> - } - className="-translate-y-2 flex-wrap gap-2 [&>*]:basis-1/4 [&>*]:justify-center" - /> - - + {hasTypeData ? ( + + + + {typeData.map((entry, index) => ( + + ))} + + } /> + } + className="-translate-y-2 flex-wrap gap-2 [&>*]:basis-1/4 [&>*]:justify-center" + /> + + + ) : ( + } + message={t("dashboard.charts.memoryCategoriesNoData")} + /> + )} @@ -542,7 +558,7 @@ function StatCard({ value, description, }: { - icon: React.ReactNode; + icon: ReactNode; label: string; value: string; description: string; @@ -562,3 +578,18 @@ function StatCard({ ); } + +function EmptyChartState({ + icon, + message, +}: { + icon: ReactNode; + message: string; +}) { + return ( +
+
{icon}
+

{message}

+
+ ); +}