feat: sort provider

This commit is contained in:
hamster1963 2024-12-15 22:10:34 +08:00
parent 9551d46800
commit 6e9f1f11af
5 changed files with 100 additions and 45 deletions

View File

@ -0,0 +1,27 @@
import { createContext } from "react"
export type SortType = "default" | "cpu" | "mem" | "up" | "down" | "up total" | "down total"
export const SORT_TYPES: SortType[] = [
"default",
"cpu",
"mem",
"up",
"down",
"up total",
"down total",
]
export type SortOrder = "asc" | "desc"
export const SORT_ORDERS: SortOrder[] = [ "desc","asc"]
export interface SortContextType {
sortType: SortType
sortOrder: SortOrder
setSortType: (sortType: SortType) => void
setSortOrder: (sortOrder: SortOrder) => void
}
export const SortContext = createContext<SortContextType | undefined>(undefined)

View File

@ -0,0 +1,14 @@
import { ReactNode, useState } from "react"
import { SortContext, SortOrder, SortType } from "./sort-context"
export function SortProvider({ children }: { children: ReactNode }) {
const [sortType, setSortType] = useState<SortType>("default")
const [sortOrder, setSortOrder] = useState<SortOrder>("desc")
return (
<SortContext.Provider value={{ sortType, setSortType, sortOrder, setSortOrder }}>
{children}
</SortContext.Provider>
)
}

10
src/hooks/use-sort.tsx Normal file
View File

@ -0,0 +1,10 @@
import { SortContext } from "@/context/sort-context"
import { useContext } from "react"
export function useSort() {
const context = useContext(SortContext)
if (context === undefined) {
throw new Error("useStatus must be used within a SortProvider")
}
return context
}

View File

@ -7,6 +7,7 @@ import { Toaster } from "sonner"
import App from "./App" import App from "./App"
import { ThemeProvider } from "./components/ThemeProvider" import { ThemeProvider } from "./components/ThemeProvider"
import { MotionProvider } from "./components/motion/motion-provider" import { MotionProvider } from "./components/motion/motion-provider"
import { SortProvider } from "./context/sort-provider"
import { StatusProvider } from "./context/status-provider" import { StatusProvider } from "./context/status-provider"
import { TooltipProvider } from "./context/tooltip-provider" import { TooltipProvider } from "./context/tooltip-provider"
import { WebSocketProvider } from "./context/websocket-provider" import { WebSocketProvider } from "./context/websocket-provider"
@ -22,21 +23,23 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<WebSocketProvider url="/api/v1/ws/server"> <WebSocketProvider url="/api/v1/ws/server">
<StatusProvider> <StatusProvider>
<TooltipProvider> <SortProvider>
<App /> <TooltipProvider>
<Toaster <App />
duration={1000} <Toaster
toastOptions={{ duration={1000}
classNames: { toastOptions={{
default: classNames: {
"w-fit rounded-full px-2.5 py-1.5 bg-neutral-100 border border-neutral-200 backdrop-blur-xl shadow-none", default:
}, "w-fit rounded-full px-2.5 py-1.5 bg-neutral-100 border border-neutral-200 backdrop-blur-xl shadow-none",
}} },
position="top-center" }}
className={"flex items-center justify-center"} position="top-center"
/> className={"flex items-center justify-center"}
<ReactQueryDevtools /> />
</TooltipProvider> <ReactQueryDevtools />
</TooltipProvider>
</SortProvider>
</StatusProvider> </StatusProvider>
</WebSocketProvider> </WebSocketProvider>
</QueryClientProvider> </QueryClientProvider>

View File

@ -7,6 +7,8 @@ import { ServiceTracker } from "@/components/ServiceTracker"
import { Loader } from "@/components/loading/Loader" import { Loader } from "@/components/loading/Loader"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { forEachSortType, SORT_ORDERS, SORT_TYPES } from "@/context/sort-context"
import { useSort } from "@/hooks/use-sort"
import { useStatus } from "@/hooks/use-status" import { useStatus } from "@/hooks/use-status"
import { useWebSocketContext } from "@/hooks/use-websocket-context" import { useWebSocketContext } from "@/hooks/use-websocket-context"
import { fetchServerGroup } from "@/lib/nezha-api" import { fetchServerGroup } from "@/lib/nezha-api"
@ -21,6 +23,7 @@ import { toast } from "sonner"
export default function Servers() { export default function Servers() {
const { t } = useTranslation() const { t } = useTranslation()
const { sortType,sortOrder,setSortOrder,setSortType } = useSort()
const { data: groupData } = useQuery({ const { data: groupData } = useQuery({
queryKey: ["server-group"], queryKey: ["server-group"],
queryFn: () => fetchServerGroup(), queryFn: () => fetchServerGroup(),
@ -211,41 +214,39 @@ export default function Servers() {
<section className="flex flex-col gap-1"> <section className="flex flex-col gap-1">
<Label className=" text-stone-500 text-xs">Sort by</Label> <Label className=" text-stone-500 text-xs">Sort by</Label>
<section className="flex items-center gap-1 flex-wrap"> <section className="flex items-center gap-1 flex-wrap">
<button className="rounded-[5px] text-[11px] w-fit px-1 py-0.5 cursor-pointer [text-shadow:_0_1px_0_rgb(0_0_0_/_20%)] bg-black dark:bg-stone-600 text-white transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> {SORT_TYPES.map((type) => (
Default <button
</button> key={type}
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> onClick={() => setSortType(type)}
CPU className={cn(
</button> "rounded-[5px] text-[11px] w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] ",
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> {
Mem "bg-black text-white": sortType === type,
</button> },
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> )}
Stg >
</button> {type}
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> </button>
Up ))}
</button>
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] ">
Down
</button>
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] ">
Up Total
</button>
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] ">
Down Total
</button>
</section> </section>
</section> </section>
<section className="flex flex-col gap-1"> <section className="flex flex-col gap-1">
<Label className=" text-stone-500 text-xs">Sort order</Label> <Label className=" text-stone-500 text-xs">Sort order</Label>
<section className="flex items-center gap-1"> <section className="flex items-center gap-1">
<button className="rounded-[5px] text-[11px] w-fit px-1 py-0.5 cursor-pointer [text-shadow:_0_1px_0_rgb(0_0_0_/_20%)] bg-black dark:bg-stone-600 text-white transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> {SORT_ORDERS.map((order) => (
Asc <button
</button> key={order}
<button className="rounded-[5px] text-xs w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] "> onClick={() => setSortOrder(order)}
Desc className={cn(
</button> "rounded-[5px] text-[11px] w-fit px-1 py-0.5 cursor-pointer bg-transparent border transition-all shadow-[inset_0_1px_0_rgba(255,255,255,0.2)] ",
{
"bg-black text-white": sortOrder === order,
},
)}
>
{order}
</button>
))}
</section> </section>
</section> </section>
</div> </div>