mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
Merge pull request #77 from hamster1963/new-server-page
feat: merge details and network pages
This commit is contained in:
commit
5dba593bf0
@ -37,7 +37,13 @@ interface ResultItem {
|
||||
[key: string]: number | null;
|
||||
}
|
||||
|
||||
export function NetworkChartClient({ server_id }: { server_id: number }) {
|
||||
export function NetworkChartClient({
|
||||
server_id,
|
||||
show,
|
||||
}: {
|
||||
server_id: number;
|
||||
show: boolean;
|
||||
}) {
|
||||
const t = useTranslations("NetworkChartClient");
|
||||
const { data, error } = useSWR<NezhaAPIMonitor[]>(
|
||||
`/api/monitor?server_id=${server_id}`,
|
||||
@ -45,6 +51,7 @@ export function NetworkChartClient({ server_id }: { server_id: number }) {
|
||||
{
|
||||
refreshInterval:
|
||||
Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 15000,
|
||||
isPaused: () => !show,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -55,8 +55,10 @@ type connectChartData = {
|
||||
|
||||
export default function ServerDetailChartClient({
|
||||
server_id,
|
||||
show,
|
||||
}: {
|
||||
server_id: number;
|
||||
show: boolean;
|
||||
}) {
|
||||
const t = useTranslations("ServerDetailChartClient");
|
||||
|
||||
@ -65,6 +67,7 @@ export default function ServerDetailChartClient({
|
||||
nezhaFetcher,
|
||||
{
|
||||
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 5000,
|
||||
isPaused: () => !show,
|
||||
},
|
||||
);
|
||||
|
||||
|
38
app/[locale]/(main)/[id]/page.tsx
Normal file
38
app/[locale]/(main)/[id]/page.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
"use client";
|
||||
|
||||
import { NetworkChartClient } from "@/app/[locale]/(main)/ClientComponents/NetworkChart";
|
||||
import ServerDetailChartClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailChartClient";
|
||||
import ServerDetailClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailClient";
|
||||
import TabSwitch from "@/components/TabSwitch";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function Page({ params }: { params: { id: string } }) {
|
||||
const t = useTranslations("TabSwitch");
|
||||
|
||||
const tabs = [t("Detail"), t("Network")];
|
||||
const [currentTab, setCurrentTab] = useState(tabs[0]);
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-5xl gap-2">
|
||||
<ServerDetailClient server_id={Number(params.id)} />
|
||||
<section className="flex items-center my-2 w-full">
|
||||
<Separator className="flex-1" />
|
||||
<div className="flex justify-center w-full max-w-[200px]">
|
||||
<TabSwitch
|
||||
tabs={tabs}
|
||||
currentTab={currentTab}
|
||||
setCurrentTab={setCurrentTab}
|
||||
/>
|
||||
</div>
|
||||
<Separator className="flex-1" />
|
||||
</section>
|
||||
{currentTab === tabs[0] && (
|
||||
<ServerDetailChartClient server_id={Number(params.id)} show={true} />
|
||||
)}
|
||||
{currentTab === tabs[1] && (
|
||||
<NetworkChartClient server_id={Number(params.id)} show={true} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import ServerDetailChartClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailChartClient";
|
||||
import ServerDetailClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailClient";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
||||
export default function Page({ params }: { params: { id: string } }) {
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-5xl gap-2">
|
||||
<ServerDetailClient server_id={Number(params.id)} />
|
||||
<Separator className="mt-1 mb-2" />
|
||||
<ServerDetailChartClient server_id={Number(params.id)} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { NetworkChartClient } from "@/app/[locale]/(main)/ClientComponents/NetworkChart";
|
||||
|
||||
export default function Page({ params }: { params: { id: string } }) {
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6">
|
||||
<NetworkChartClient server_id={Number(params.id)} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -33,15 +33,15 @@ export default function ServerCard({
|
||||
return online ? (
|
||||
<Card
|
||||
className={
|
||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 lg:flex-row"
|
||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 lg:flex-row cursor-pointer"
|
||||
}
|
||||
onClick={() => {
|
||||
router.push(`/${locale}/${id}`);
|
||||
}}
|
||||
>
|
||||
<section
|
||||
className="grid items-center gap-2 lg:w-28 cursor-pointer"
|
||||
className="grid items-center gap-2 lg:w-28 "
|
||||
style={{ gridTemplateColumns: "auto auto 1fr" }}
|
||||
onClick={() => {
|
||||
router.push(`/${locale}/detail/${id}`);
|
||||
}}
|
||||
>
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-green-500 self-center"></span>
|
||||
<div
|
||||
@ -61,12 +61,7 @@ export default function ServerCard({
|
||||
{name}
|
||||
</p>
|
||||
</section>
|
||||
<div
|
||||
onClick={() => {
|
||||
router.push(`/${locale}/network/${id}`);
|
||||
}}
|
||||
className="flex flex-col gap-2 cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<section className={"grid grid-cols-5 items-center gap-3"}>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
||||
|
48
components/TabSwitch.tsx
Normal file
48
components/TabSwitch.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { motion } from "framer-motion";
|
||||
import React, { useState } from "react";
|
||||
|
||||
export default function TabSwitch({
|
||||
tabs,
|
||||
currentTab,
|
||||
setCurrentTab,
|
||||
}: {
|
||||
tabs: string[];
|
||||
currentTab: string;
|
||||
setCurrentTab: (tab: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="z-50 flex flex-col items-start overflow-x-scroll rounded-[50px]">
|
||||
<div className="flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800">
|
||||
{tabs.map((tab: string) => (
|
||||
<div
|
||||
key={tab}
|
||||
onClick={() => setCurrentTab(tab)}
|
||||
className={cn(
|
||||
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600] transition-all duration-500",
|
||||
currentTab === tab
|
||||
? "text-black dark:text-white"
|
||||
: "text-stone-400 dark:text-stone-500",
|
||||
)}
|
||||
>
|
||||
{currentTab === tab && (
|
||||
<motion.div
|
||||
layoutId="tab-switch"
|
||||
className="absolute inset-0 z-10 h-full w-full content-center bg-white shadow-lg shadow-black/5 dark:bg-stone-700 dark:shadow-white/5"
|
||||
style={{
|
||||
originY: "0px",
|
||||
borderRadius: 46,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="relative z-20 flex items-center gap-1">
|
||||
<p className="whitespace-nowrap">{tab}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -19,6 +19,10 @@
|
||||
"Download": "Download",
|
||||
"Offline": "Offline"
|
||||
},
|
||||
"TabSwitch": {
|
||||
"Detail": "Detail",
|
||||
"Network": "Network"
|
||||
},
|
||||
"ServerCardPopover": {
|
||||
"System": "System",
|
||||
"CPU": "CPU",
|
||||
|
@ -19,6 +19,10 @@
|
||||
"Download": "Download",
|
||||
"Offline": "Offline"
|
||||
},
|
||||
"TabSwitch": {
|
||||
"Detail": "詳細",
|
||||
"Network": "ネットワーク"
|
||||
},
|
||||
"ServerCardPopover": {
|
||||
"System": "システム",
|
||||
"CPU": "CPU",
|
||||
|
@ -19,6 +19,10 @@
|
||||
"Download": "下載",
|
||||
"Offline": "離線"
|
||||
},
|
||||
"TabSwitch": {
|
||||
"Detail": "詳細",
|
||||
"Network": "網路"
|
||||
},
|
||||
"ServerCardPopover": {
|
||||
"System": "系統",
|
||||
"CPU": "CPU",
|
||||
|
@ -19,6 +19,10 @@
|
||||
"Download": "下载",
|
||||
"Offline": "离线"
|
||||
},
|
||||
"TabSwitch": {
|
||||
"Detail": "详情",
|
||||
"Network": "网络"
|
||||
},
|
||||
"ServerCardPopover": {
|
||||
"System": "系统",
|
||||
"CPU": "CPU",
|
||||
|
Loading…
Reference in New Issue
Block a user