Merge pull request #38 from hamster1963/tag-switch

Tag switch
This commit is contained in:
仓鼠 2024-10-02 17:53:56 +08:00 committed by GitHub
commit 23897b43d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 81 additions and 7 deletions

View File

@ -4,3 +4,4 @@ DefaultLocale=zh
NEXT_PUBLIC_NezhaFetchInterval=5000 NEXT_PUBLIC_NezhaFetchInterval=5000
NEXT_PUBLIC_ShowFlag=true NEXT_PUBLIC_ShowFlag=true
NEXT_PUBLIC_DisableCartoon=true NEXT_PUBLIC_DisableCartoon=true
NEXT_PUBLIC_ShowTag=true

View File

@ -20,6 +20,7 @@
| NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**2000 | | NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**2000 |
| NEXT_PUBLIC_ShowFlag | 是否显示旗帜 | **默认**false | | NEXT_PUBLIC_ShowFlag | 是否显示旗帜 | **默认**false |
| NEXT_PUBLIC_DisableCartoon | 是否禁用卡通人物 | **默认**false | | NEXT_PUBLIC_DisableCartoon | 是否禁用卡通人物 | **默认**false |
| NEXT_PUBLIC_ShowTag | 是否显示标签 | **默认**false |
#### 多语言支持 #### 多语言支持

View File

@ -5,7 +5,14 @@ import ServerCard from "../../../../components/ServerCard";
import { nezhaFetcher } from "../../../../lib/utils"; import { nezhaFetcher } from "../../../../lib/utils";
import useSWR from "swr"; import useSWR from "swr";
import getEnv from "../../../../lib/env-entry"; import getEnv from "../../../../lib/env-entry";
import Switch from "@/components/Switch";
import { useState } from "react";
const defaultTag = "All";
export default function ServerListClient() { export default function ServerListClient() {
const [tag, setTag] = useState<string>(defaultTag);
const { data, error } = useSWR<ServerApi>("/api/server", nezhaFetcher, { const { data, error } = useSWR<ServerApi>("/api/server", nezhaFetcher, {
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000, refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000,
}); });
@ -23,17 +30,31 @@ export default function ServerListClient() {
const { result } = data; const { result } = data;
const allTag = result.map((server) => server.tag).filter((tag) => tag);
const uniqueTags = [...new Set(allTag)];
uniqueTags.unshift(defaultTag);
const sortedServers = result.sort((a, b) => { const sortedServers = result.sort((a, b) => {
const displayIndexDiff = (b.display_index || 0) - (a.display_index || 0); const displayIndexDiff = (b.display_index || 0) - (a.display_index || 0);
if (displayIndexDiff !== 0) return displayIndexDiff; if (displayIndexDiff !== 0) return displayIndexDiff;
return a.id - b.id; return a.id - b.id;
}); });
const filteredServers =
tag === defaultTag
? sortedServers
: sortedServers.filter((server) => server.tag === tag);
return ( return (
<>
{getEnv("NEXT_PUBLIC_ShowTag") === "true" && uniqueTags.length > 1 && (
<Switch allTag={uniqueTags} nowTag={tag} setTag={setTag} />
)}
<section className="grid grid-cols-1 gap-2 md:grid-cols-2"> <section className="grid grid-cols-1 gap-2 md:grid-cols-2">
{sortedServers.map((serverInfo) => ( {filteredServers.map((serverInfo) => (
<ServerCard key={serverInfo.id} serverInfo={serverInfo} /> <ServerCard key={serverInfo.id} serverInfo={serverInfo} />
))} ))}
</section> </section>
</>
); );
} }

BIN
bun.lockb

Binary file not shown.

48
components/Switch.tsx Normal file
View File

@ -0,0 +1,48 @@
"use client";
import React from "react";
import { cn } from "@/lib/utils";
import { motion } from "framer-motion";
export default function Switch({
allTag,
nowTag,
setTag,
}: {
allTag: string[];
nowTag: string;
setTag: (tag: string) => void;
}) {
return (
<div className="z-50 flex flex-col items-start">
<div className="flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800">
{allTag.map((tag) => (
<div
key={tag}
onClick={() => setTag(tag)}
className={cn(
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600] transition-all duration-500",
nowTag === tag
? "text-black dark:text-white"
: "text-stone-400 dark:text-stone-500",
)}
>
{nowTag === tag && (
<motion.div
layoutId="nav-item"
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">{tag}</p>
</div>
</div>
))}
</div>
</div>
);
}

View File

@ -4,3 +4,4 @@ DefaultLocale=zh
NEXT_PUBLIC_NezhaFetchInterval=5000 NEXT_PUBLIC_NezhaFetchInterval=5000
NEXT_PUBLIC_ShowFlag=true NEXT_PUBLIC_ShowFlag=true
NEXT_PUBLIC_DisableCartoon=true NEXT_PUBLIC_DisableCartoon=true
NEXT_PUBLIC_ShowTag=true

View File

@ -28,6 +28,7 @@
"country-flag-icons": "^1.5.13", "country-flag-icons": "^1.5.13",
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
"flag-icons": "^7.2.3", "flag-icons": "^7.2.3",
"framer-motion": "^11.9.0",
"lucide-react": "^0.414.0", "lucide-react": "^0.414.0",
"luxon": "^3.5.0", "luxon": "^3.5.0",
"next": "^14.2.13", "next": "^14.2.13",

View File

@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES6",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,