diff --git a/bun.lockb b/bun.lockb index 13d1157..1afa12c 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 9b02900..e60af1c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@fontsource/inter": "^5.1.1", "@heroicons/react": "^2.2.0", + "@number-flow/react": "^0.5.5", "@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-dialog": "^1.0.5", @@ -20,14 +21,12 @@ "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-progress": "^1.1.1", "@radix-ui/react-separator": "^1.1.1", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.0.3", - "@radix-ui/react-tabs": "^1.0.4", - "@radix-ui/react-toast": "^1.1.5", - "@tanstack/react-query": "^5.14.2", - "@tanstack/react-query-devtools": "^5.64.2", + "@radix-ui/react-slot": "^1.1.1", + "@radix-ui/react-switch": "^1.1.2", + "@tanstack/react-query": "^5.65.1", + "@tanstack/react-query-devtools": "^5.65.1", "@tanstack/react-table": "^8.20.6", - "@trivago/prettier-plugin-sort-imports": "^5.2.1", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/d3-geo": "^3.1.0", "@types/luxon": "^3.4.2", "class-variance-authority": "^0.7.0", @@ -36,39 +35,36 @@ "country-flag-icons": "^1.5.14", "d3-geo": "^3.1.1", "dayjs": "^1.11.13", - "framer-motion": "^12.0.3", + "framer-motion": "^12.0.6", "i18n-iso-countries": "^7.13.0", - "i18next": "^23.7.11", - "lucide-react": "^0.302.0", + "i18next": "^24.2.2", + "lucide-react": "^0.460.0", "luxon": "^3.5.0", - "prettier-plugin-tailwindcss": "^0.6.10", - "react": "^18.2.0", - "react-day-picker": "^8.10.0", - "react-dom": "^18.2.0", - "react-i18next": "^14.0.0", - "react-router-dom": "^6.21.1", - "recharts": "^2.15.0", - "sonner": "^1.7.2", - "tailwind-merge": "^2.2.0", - "tailwindcss-animate": "^1.0.7", - "use-debounce": "^10.0.0", - "zod": "^3.22.4" + "prettier-plugin-tailwindcss": "^0.6.11", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-i18next": "^15.4.0", + "react-router-dom": "^7.1.3", + "recharts": "^2.15.1", + "sonner": "^1.7.3", + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@eslint/js": "^9.18.0", - "@types/node": "^20.10.5", - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@vitejs/plugin-react-swc": "^3.5.0", - "autoprefixer": "^10.4.16", - "eslint": "^8.55.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", + "@eslint/js": "^9.19.0", + "@types/node": "^22.12.0", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react-swc": "^3.7.2", + "autoprefixer": "^10.4.20", + "eslint": "^9.19.0", + "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-refresh": "^0.4.18", "globals": "^15.14.0", - "postcss": "^8.4.32", - "tailwindcss": "^3.4.0", - "typescript": "^5.2.2", - "typescript-eslint": "^8.21.0", - "vite": "^5.0.8" + "postcss": "^8.5.1", + "tailwindcss": "^3.4.17", + "typescript": "~5.6.3", + "typescript-eslint": "^8.22.0", + "vite": "^6.0.11" } } diff --git a/src/App.tsx b/src/App.tsx index 1b01be3..2ca7e94 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react" import { useTranslation } from "react-i18next" import { Route, BrowserRouter as Router, Routes } from "react-router-dom" +import { DashCommand } from "./components/DashCommand" import ErrorBoundary from "./components/ErrorBoundary" import Footer from "./components/Footer" import Header, { RefreshToast } from "./components/Header" @@ -15,7 +16,6 @@ import ErrorPage from "./pages/ErrorPage" import NotFound from "./pages/NotFound" import Server from "./pages/Server" import ServerDetail from "./pages/ServerDetail" -import { DashCommand } from "./components/DashCommand" const App: React.FC = () => { const { data: settingData, error } = useQuery({ diff --git a/src/components/DashCommand.tsx b/src/components/DashCommand.tsx index d847eb2..e56c304 100644 --- a/src/components/DashCommand.tsx +++ b/src/components/DashCommand.tsx @@ -69,27 +69,31 @@ export function DashCommand() { <> - + {t("NoResults")} - - {nezhaWsData.servers.map((server) => ( - { - navigate(`/server/${server.id}`) - setOpen(false) - }} - > - {formatNezhaInfo(nezhaWsData.now, server).online ? ( - - ) : ( - - )} - {server.name} - - ))} - + {nezhaWsData.servers && nezhaWsData.servers.length > 0 && ( + <> + + {nezhaWsData.servers.map((server) => ( + { + navigate(`/server/${server.id}`) + setOpen(false) + }} + > + {formatNezhaInfo(nezhaWsData.now, server).online ? ( + + ) : ( + + )} + {server.name} + + ))} + + + )} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 5718b71..555be57 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -5,6 +5,7 @@ import { useBackground } from "@/hooks/use-background" import { useWebSocketContext } from "@/hooks/use-websocket-context" import { fetchLoginUser, fetchSetting } from "@/lib/nezha-api" import { cn } from "@/lib/utils" +import NumberFlow, { NumberFlowGroup } from "@number-flow/react" import { useQuery } from "@tanstack/react-query" import { AnimatePresence, m } from "framer-motion" import { ImageMinus } from "lucide-react" @@ -266,31 +267,35 @@ function DashboardLink() { function Overview() { const { t } = useTranslation() - const [mouted, setMounted] = useState(false) + const [time, setTime] = useState({ + hh: DateTime.now().setLocale("en-US").hour, + mm: DateTime.now().setLocale("en-US").minute, + ss: DateTime.now().setLocale("en-US").second, + }) + useEffect(() => { - setMounted(true) - }, []) - const timeOption = DateTime.TIME_WITH_SECONDS - timeOption.hour12 = true - const [timeString, setTimeString] = useState(DateTime.now().setLocale("en-US").toLocaleString(timeOption)) - useEffect(() => { - const updateTime = () => { - const now = DateTime.now().setLocale("en-US").toLocaleString(timeOption) - setTimeString(now) - requestAnimationFrame(updateTime) - } - requestAnimationFrame(updateTime) + const timer = setInterval(() => { + setTime({ + hh: DateTime.now().setLocale("en-US").hour, + mm: DateTime.now().setLocale("en-US").minute, + ss: DateTime.now().setLocale("en-US").second, + }) + }, 1000) + + return () => clearInterval(timer) }, []) return (

👋 {t("overview")}

{t("whereTheTimeIs")}

- {mouted ? ( -

{timeString}

- ) : ( - - )} + +
+ + + +
+
) diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index 36ac680..4347ec7 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { cn } from "@/lib/utils" -import { CheckCircleIcon } from "@heroicons/react/20/solid" +import { CheckCircleIcon, LanguageIcon } from "@heroicons/react/20/solid" import { useTranslation } from "react-i18next" export function LanguageSwitcher() { @@ -34,7 +34,7 @@ export function LanguageSwitcher() { "bg-white/70 dark:bg-black/70": customBackgroundImage, })} > - {localeItems.find((item) => item.code === locale)?.name} + Change language diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx index 2d76f1e..119d622 100644 --- a/src/components/ui/command.tsx +++ b/src/components/ui/command.tsx @@ -33,7 +33,7 @@ const CommandDialog = ({ children, ...props }: DialogProps) => { const CommandInput = React.forwardRef, React.ComponentPropsWithoutRef>( ({ className, ...props }, ref) => ( -
+