74 lines
2.5 KiB
JavaScript
74 lines
2.5 KiB
JavaScript
import Refresh from "@mui/icons-material/Refresh";
|
|
import Skeleton from "@mui/material/Skeleton";
|
|
import { useTimeZone } from "@/app/timezone/TimeZoneProvider.jsx";
|
|
import { DashboardCharts } from "@/features/dashboard/components/DashboardCharts.jsx";
|
|
import { DashboardStats } from "@/features/dashboard/components/DashboardStats.jsx";
|
|
import { useDashboardPage } from "@/features/dashboard/hooks/useDashboardPage.js";
|
|
import { Button } from "@/shared/ui/Button.jsx";
|
|
import { usePageLoadingStatus } from "@/shared/ui/PageLoadBoundary.jsx";
|
|
|
|
export function DashboardUserProfile() {
|
|
const page = useDashboardPage();
|
|
const { formatMillis } = useTimeZone();
|
|
// 首次请求接入整页加载边界;边界释放后的 App/时区切换则展示本区域自己的骨架,避免页面空白。
|
|
usePageLoadingStatus(page.loading);
|
|
|
|
return (
|
|
<section className="dashboard-profile-section" aria-labelledby="dashboard-profile-title">
|
|
<div className="dashboard-profile-head">
|
|
<h2 id="dashboard-profile-title">用户画像</h2>
|
|
{page.overview?.updatedAtMs ? <span>数据更新时间 {formatMillis(page.overview.updatedAtMs)}</span> : null}
|
|
</div>
|
|
{renderContent(page)}
|
|
</section>
|
|
);
|
|
}
|
|
|
|
function renderContent(page) {
|
|
if (page.loading) {
|
|
return <DashboardUserProfileSkeleton />;
|
|
}
|
|
if (page.error) {
|
|
return (
|
|
<div className="dashboard-profile-state" role="alert">
|
|
<span>{page.error}</span>
|
|
<Button onClick={page.reload}>
|
|
<Refresh fontSize="small" />
|
|
重试
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
if (!page.overview) {
|
|
return (
|
|
<div className="dashboard-profile-state" role="status">
|
|
当前无数据
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<DashboardStats overview={page.overview} />
|
|
<DashboardCharts overview={page.overview} />
|
|
</>
|
|
);
|
|
}
|
|
|
|
function DashboardUserProfileSkeleton() {
|
|
return (
|
|
<div className="dashboard-profile-skeleton" aria-hidden="true">
|
|
<div className="dashboard-profile-skeleton__kpis">
|
|
{Array.from({ length: 3 }, (_, index) => (
|
|
<Skeleton animation="wave" className="dashboard-profile-skeleton__kpi" key={index} variant="rounded" />
|
|
))}
|
|
</div>
|
|
<div className="dashboard-profile-skeleton__charts">
|
|
{Array.from({ length: 2 }, (_, index) => (
|
|
<Skeleton animation="wave" className="dashboard-profile-skeleton__chart" key={index} variant="rounded" />
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|