From 499e74aaf4fc83d8f6b02f92610cbee5dce81d70 Mon Sep 17 00:00:00 2001 From: zhixian Date: Tue, 17 Feb 2026 01:51:14 +0900 Subject: [PATCH] feat: migrate Doctor page to shadcn Card/Badge/Button Co-Authored-By: Claude Opus 4.6 --- src/pages/Doctor.tsx | 299 ++++++++++++++++++++++++++++--------------- 1 file changed, 196 insertions(+), 103 deletions(-) diff --git a/src/pages/Doctor.tsx b/src/pages/Doctor.tsx index 63ab7fd..a70b01a 100644 --- a/src/pages/Doctor.tsx +++ b/src/pages/Doctor.tsx @@ -1,14 +1,25 @@ -import React, { useEffect, useMemo, useReducer, useState } from "react"; +import { useEffect, useMemo, useReducer, useState } from "react"; import { api } from "../lib/api"; import { initialState, reducer } from "../lib/state"; import type { MemoryFile, SessionFile } from "../lib/types"; +import { + Card, + CardHeader, + CardTitle, + CardContent, +} from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; function formatBytes(bytes: number) { if (bytes <= 0) return "0 B"; const units = ["B", "KB", "MB", "GB"]; let index = 0; let value = bytes; - while (value >= 1024 && index < units.length - 1) { value /= 1024; index += 1; } + while (value >= 1024 && index < units.length - 1) { + value /= 1024; + index += 1; + } return `${value.toFixed(1)} ${units[index]}`; } @@ -20,7 +31,9 @@ export function Doctor() { const hasReport = Boolean(state.doctor); const autoFixable = hasReport - ? state.doctor!.issues.filter((issue) => issue.autoFixable).map((issue) => issue.id) + ? state.doctor!.issues + .filter((issue) => issue.autoFixable) + .map((issue) => issue.id) : []; const agents = useMemo(() => { @@ -48,37 +61,62 @@ export function Doctor() { ); function refreshData() { - api.listMemoryFiles().then(setMemoryFiles).catch(() => setDataMessage("Failed to load memory files")); - api.listSessionFiles().then(setSessionFiles).catch(() => setDataMessage("Failed to load session files")); + api + .listMemoryFiles() + .then(setMemoryFiles) + .catch(() => setDataMessage("Failed to load memory files")); + api + .listSessionFiles() + .then(setSessionFiles) + .catch(() => setDataMessage("Failed to load session files")); } useEffect(() => { api .runDoctor() .then((report) => dispatch({ type: "setDoctor", doctor: report })) - .catch(() => dispatch({ type: "setMessage", message: "Failed to run doctor" })); + .catch(() => + dispatch({ type: "setMessage", message: "Failed to run doctor" }), + ); refreshData(); }, []); return (
-

Doctor

+

Doctor

- {/* ── Config Diagnostics ── */} + {/* Config Diagnostics */} {state.doctor && (
-

Health score: {state.doctor.score}

-
    +

    + Health score: {state.doctor.score} +

    +
    {state.doctor.issues.map((issue) => ( -
  • - {issue.severity.toUpperCase()} {issue.message} +
    + {issue.severity === "error" && ( + ERROR + )} + {issue.severity === "warn" && ( + WARN + )} + {issue.severity === "info" && ( + INFO + )} + {issue.message} {issue.autoFixable && ( - + )} -
  • +
    ))} -
- - +
+
+ + +
)} - {!hasReport ? : null} -

{state.message}

+ {!hasReport ? ( + + ) : null} +

{state.message}

- {/* ── Data Cleanup ── */} -

Data Cleanup

- {dataMessage &&

{dataMessage}

} + {/* Data Cleanup */} +

+ Data Cleanup +

+ {dataMessage && ( +

{dataMessage}

+ )} -
+
{/* Memory */} -
-

Memory

-

{memoryFiles.length} files ({formatBytes(totalMemoryBytes)})

- -
+ + + Memory + + +

+ {memoryFiles.length} files ({formatBytes(totalMemoryBytes)}) +

+ +
+
{/* Sessions */} -
-

Sessions

-

{sessionFiles.length} files ({formatBytes(totalSessionBytes)})

- {agents.map((a) => ( -
- {a.agent}: {a.count} files ({formatBytes(a.size)}) - -
- ))} - -
+ + {a.agent}: {a.count} files ({formatBytes(a.size)}) + + +
+ ))} + + +
);