mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
feat: show map in main page
This commit is contained in:
parent
f8bfbde9b5
commit
0b93cf7af8
@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import GlobalBackButton from "@/components/GlobalBackButton";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type GlobalInfoProps = {
|
||||
@ -11,7 +10,6 @@ export default function GlobalInfo({ countries }: GlobalInfoProps) {
|
||||
const t = useTranslations("Global");
|
||||
return (
|
||||
<section className="flex items-center justify-between">
|
||||
<GlobalBackButton />
|
||||
<p className="text-sm font-medium opacity-40">
|
||||
{t("Distributions")} {countries.length} {t("Regions")}
|
||||
</p>
|
||||
|
@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import GlobalBackButton from "@/components/GlobalBackButton";
|
||||
import { Loader } from "@/components/loading/Loader";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
@ -8,7 +7,6 @@ export default function GlobalLoading() {
|
||||
const t = useTranslations("Global");
|
||||
return (
|
||||
<section className="flex flex-col gap-4 mt-[3.2px]">
|
||||
<GlobalBackButton />
|
||||
<div className="flex min-h-40 flex-col items-center justify-center font-medium text-sm">
|
||||
{t("Loading")}
|
||||
<Loader visible={true} />
|
||||
|
@ -10,19 +10,25 @@ import { useStatus } from "@/lib/status-context";
|
||||
import { cn, nezhaFetcher } from "@/lib/utils";
|
||||
import { MapIcon, ViewColumnsIcon } from "@heroicons/react/20/solid";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
import GlobalLoading from "./GlobalLoading";
|
||||
|
||||
const ServerGlobal = dynamic(() => import("./Global"), {
|
||||
loading: () => <GlobalLoading />,
|
||||
});
|
||||
|
||||
export default function ServerListClient() {
|
||||
const { status } = useStatus();
|
||||
const { filter } = useFilter();
|
||||
const t = useTranslations("ServerListClient");
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const defaultTag = "defaultTag";
|
||||
const router = useRouter();
|
||||
|
||||
const [tag, setTag] = useState<string>(defaultTag);
|
||||
const [showMap, setShowMap] = useState<boolean>(false);
|
||||
const [inline, setInline] = useState<string>("0");
|
||||
|
||||
useEffect(() => {
|
||||
@ -131,9 +137,14 @@ export default function ServerListClient() {
|
||||
<section className="flex items-center gap-2 w-full overflow-hidden">
|
||||
<button
|
||||
onClick={() => {
|
||||
router.push(`/?global=true`);
|
||||
setShowMap(!showMap);
|
||||
}}
|
||||
className="rounded-[50px] text-white cursor-pointer [text-shadow:_0_1px_0_rgb(0_0_0_/_20%)] bg-blue-600 hover:bg-blue-500 p-[10px] transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] hover:shadow-[inset_0_1px_0_rgba(0,0,0,0.2)] "
|
||||
className={cn(
|
||||
"rounded-[50px] text-white cursor-pointer [text-shadow:_0_1px_0_rgb(0_0_0_/_20%)] bg-blue-600 p-[10px] transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)]",
|
||||
{
|
||||
"shadow-[inset_0_1px_0_rgba(0,0,0,0.2)] bg-blue-500": showMap,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<MapIcon className="size-[13px]" />
|
||||
</button>
|
||||
@ -161,6 +172,7 @@ export default function ServerListClient() {
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
{showMap && <ServerGlobal />}
|
||||
{inline === "1" && (
|
||||
<section
|
||||
ref={containerRef}
|
||||
|
@ -14,7 +14,6 @@ import {
|
||||
} from "@heroicons/react/20/solid";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Image from "next/image";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
|
||||
export default function ServerOverviewClient() {
|
||||
@ -30,10 +29,6 @@ export default function ServerOverviewClient() {
|
||||
);
|
||||
const disableCartoon = getEnv("NEXT_PUBLIC_DisableCartoon") === "true";
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const global = searchParams.get("global");
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
@ -50,14 +45,10 @@ export default function ServerOverviewClient() {
|
||||
<section className="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
||||
<Card
|
||||
onClick={() => {
|
||||
if (!global) {
|
||||
setFilter(false);
|
||||
setStatus("all");
|
||||
}
|
||||
}}
|
||||
className={cn("cursor-pointer hover:border-blue-500 transition-all", {
|
||||
"pointer-events-none": global,
|
||||
})}
|
||||
className={cn("cursor-pointer hover:border-blue-500 transition-all")}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
@ -83,19 +74,14 @@ export default function ServerOverviewClient() {
|
||||
</Card>
|
||||
<Card
|
||||
onClick={() => {
|
||||
if (!global) {
|
||||
setFilter(false);
|
||||
setStatus("online");
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-green-500 ring-1 ring-transparent transition-all",
|
||||
{
|
||||
"ring-green-500 ring-2 border-transparent": status === "online",
|
||||
},
|
||||
{
|
||||
"pointer-events-none": global,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
@ -123,19 +109,14 @@ export default function ServerOverviewClient() {
|
||||
</Card>
|
||||
<Card
|
||||
onClick={() => {
|
||||
if (!global) {
|
||||
setFilter(false);
|
||||
setStatus("offline");
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-red-500 ring-1 ring-transparent transition-all",
|
||||
{
|
||||
"ring-red-500 ring-2 border-transparent": status === "offline",
|
||||
},
|
||||
{
|
||||
"pointer-events-none": global,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
@ -163,19 +144,14 @@ export default function ServerOverviewClient() {
|
||||
</Card>
|
||||
<Card
|
||||
onClick={() => {
|
||||
if (!global) {
|
||||
setStatus("all");
|
||||
setFilter(true);
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-purple-500 ring-1 ring-transparent transition-all",
|
||||
{
|
||||
"ring-purple-500 ring-2 border-transparent": filter === true,
|
||||
},
|
||||
{
|
||||
"pointer-events-none": global,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center relative px-6 py-3">
|
||||
|
@ -1,24 +1,11 @@
|
||||
import ServerList from "@/components/ServerList";
|
||||
import ServerOverview from "@/components/ServerOverview";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import GlobalLoading from "./ClientComponents/GlobalLoading";
|
||||
|
||||
const ServerGlobal = dynamic(() => import("./ClientComponents/Global"), {
|
||||
loading: () => <GlobalLoading />,
|
||||
});
|
||||
|
||||
export default async function Home({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
|
||||
}) {
|
||||
const global = (await searchParams).global;
|
||||
export default async function Home() {
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6">
|
||||
<ServerOverview />
|
||||
{!global && <ServerList />}
|
||||
{global && <ServerGlobal />}
|
||||
<ServerList />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user