refactor(ui): shared form primitives (Switch, Section, SettingRow, HintLabel)
components/ui/form.tsx replaces the per-panel copies: - Switch — was duplicated in SettingsPanel (Switch) + ConfigPanel (Toggle) + Sidebar (inline labeled toggle). - Section (with a card variant) — was in SettingsPanel + Stats (plain) and AdminUsers (glass card). - SettingRow + HintLabel — the label+hint+control row was identical in SettingsPanel + Stats. No visual change intended (Sidebar's toggle gains the standard knob shadow).
This commit is contained in:
parent
5fcd64c1e1
commit
53c75f69e2
6 changed files with 125 additions and 147 deletions
|
|
@ -7,6 +7,7 @@ import { formatEta, quotaActionLabel } from "../lib/format";
|
|||
import { notify } from "../lib/notifications";
|
||||
import { LS, usePersistedState } from "../lib/storage";
|
||||
import Tooltip from "./Tooltip";
|
||||
import { Section, SettingRow } from "./ui/form";
|
||||
|
||||
const RANGES = [7, 30, 90] as const;
|
||||
type StatsTab = "overview" | "system";
|
||||
|
|
@ -47,31 +48,6 @@ export default function Stats({ me }: { me: Me }) {
|
|||
);
|
||||
}
|
||||
|
||||
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div className="text-xs uppercase tracking-wide text-muted mb-2">{title}</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Row({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-3 py-1.5 text-sm">
|
||||
<Tooltip hint={hint ?? ""}>
|
||||
<span
|
||||
className={
|
||||
hint ? "underline decoration-dotted decoration-muted/40 underline-offset-4 cursor-help" : ""
|
||||
}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Per-user view: sync status + your own API usage + (for real accounts) the manual sync actions.
|
||||
function Overview({ me }: { me: Me }) {
|
||||
|
|
@ -107,29 +83,29 @@ function Overview({ me }: { me: Me }) {
|
|||
<Section title={t("stats.sync.myStatus")}>
|
||||
{s ? (
|
||||
<div className="space-y-1.5 text-sm">
|
||||
<Row label={t("stats.sync.channels")} hint={t("stats.sync.channelsHint")}>
|
||||
<SettingRow label={t("stats.sync.channels")} hint={t("stats.sync.channelsHint")}>
|
||||
{s.channels_total}
|
||||
</Row>
|
||||
<Row label={t("stats.sync.recentSynced")} hint={t("stats.sync.recentSyncedHint")}>
|
||||
</SettingRow>
|
||||
<SettingRow label={t("stats.sync.recentSynced")} hint={t("stats.sync.recentSyncedHint")}>
|
||||
{`${s.channels_recent_synced}/${s.channels_total}`}
|
||||
</Row>
|
||||
<Row label={t("stats.sync.fullHistory")} hint={t("stats.sync.fullHistoryHint")}>
|
||||
</SettingRow>
|
||||
<SettingRow label={t("stats.sync.fullHistory")} hint={t("stats.sync.fullHistoryHint")}>
|
||||
{`${s.channels_deep_done}/${s.channels_deep_requested}`}
|
||||
</Row>
|
||||
</SettingRow>
|
||||
{s.deep_pending_count > 0 && (
|
||||
<Row
|
||||
<SettingRow
|
||||
label={t("stats.sync.fullHistoryEta")}
|
||||
hint={t("stats.sync.fullHistoryEtaHint", { count: s.deep_pending_count })}
|
||||
>
|
||||
{formatEta(s.deep_eta_seconds)}
|
||||
</Row>
|
||||
</SettingRow>
|
||||
)}
|
||||
<Row label={t("stats.sync.myVideos")} hint={t("stats.sync.myVideosHint")}>
|
||||
<SettingRow label={t("stats.sync.myVideos")} hint={t("stats.sync.myVideosHint")}>
|
||||
{s.my_videos.toLocaleString()}
|
||||
</Row>
|
||||
<Row label={t("stats.sync.quotaLeft")} hint={t("stats.sync.quotaLeftHint")}>
|
||||
</SettingRow>
|
||||
<SettingRow label={t("stats.sync.quotaLeft")} hint={t("stats.sync.quotaLeftHint")}>
|
||||
{s.quota_remaining_today.toLocaleString()}
|
||||
</Row>
|
||||
</SettingRow>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-muted text-sm">{t("stats.sync.loading")}</div>
|
||||
|
|
@ -140,12 +116,12 @@ function Overview({ me }: { me: Me }) {
|
|||
{usage.data ? (
|
||||
<>
|
||||
<div className="space-y-1.5 text-sm">
|
||||
<Row label={t("stats.sync.today")} hint={t("stats.sync.todayHint")}>
|
||||
<SettingRow label={t("stats.sync.today")} hint={t("stats.sync.todayHint")}>
|
||||
{usage.data.today.toLocaleString()}
|
||||
</Row>
|
||||
<Row label={t("stats.sync.last7d")}>{usage.data.last_7d.toLocaleString()}</Row>
|
||||
<Row label={t("stats.sync.last30d")}>{usage.data.last_30d.toLocaleString()}</Row>
|
||||
<Row label={t("stats.sync.allTime")}>{usage.data.all_time.toLocaleString()}</Row>
|
||||
</SettingRow>
|
||||
<SettingRow label={t("stats.sync.last7d")}>{usage.data.last_7d.toLocaleString()}</SettingRow>
|
||||
<SettingRow label={t("stats.sync.last30d")}>{usage.data.last_30d.toLocaleString()}</SettingRow>
|
||||
<SettingRow label={t("stats.sync.allTime")}>{usage.data.all_time.toLocaleString()}</SettingRow>
|
||||
</div>
|
||||
{Object.keys(usage.data.by_action).length > 0 && (
|
||||
<div className="mt-2 pt-2 border-t border-border space-y-1 text-xs text-muted">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue