diff --git a/client/src/Components/v2/monitors/FilterControls.tsx b/client/src/Components/v2/monitors/FilterControls.tsx index 09776f71e..d5ec8cc55 100644 --- a/client/src/Components/v2/monitors/FilterControls.tsx +++ b/client/src/Components/v2/monitors/FilterControls.tsx @@ -1,11 +1,92 @@ import Stack from "@mui/material/Stack"; -import { Select } from "@/Components/v2/inputs"; -export const FilterControls = () => { +import { Select, Button } from "@/Components/v2/inputs"; +import MenuItem from "@mui/material/MenuItem"; + +import type { MonitorType } from "@/Types/Monitor"; +import { Typography, useTheme } from "@mui/material"; + +const types = ["http", "ping", "port", "docker"]; +const statuses = ["up", "down"]; +const states = ["active", "paused"]; + +export const FilterControls = ({ + selectedTypes, + setSelectedTypes, + selectedStatus, + setSelectedStatus, + selectedState, + setSelectedState, +}: { + selectedTypes: MonitorType[]; + setSelectedTypes: React.Dispatch>; + selectedStatus: string; + setSelectedStatus: React.Dispatch>; + selectedState: string; + setSelectedState: React.Dispatch>; +}) => { + const theme = useTheme(); + const isFilterActive = + selectedTypes.length > 0 || selectedStatus !== "" || selectedState !== ""; return ( - - - + + + + + {isFilterActive && ( + + )} ); }; diff --git a/client/src/Pages/Uptime/Monitors/index.tsx b/client/src/Pages/Uptime/Monitors/index.tsx index 5dc1100bf..2d7a851d2 100644 --- a/client/src/Pages/Uptime/Monitors/index.tsx +++ b/client/src/Pages/Uptime/Monitors/index.tsx @@ -1,24 +1,71 @@ import { useGet } from "@/Hooks/UseApi"; import { MonitorBasePageWithStates } from "@/Components/v2/design-elements"; -import { type Monitor } from "@/Types/Monitor"; +import type { Monitor, MonitorType, MonitorsWithChecksResponse } from "@/Types/Monitor"; import { FilterControls } from "@/Components/v2/monitors"; +import { useState, useMemo } from "react"; +import { useSelector } from "react-redux"; +import type { RootState } from "@/Types/state"; const UptimeMonitorsPage = () => { + // Redux state + const rowsPerPage = useSelector((state: RootState) => state.ui.monitors.rowsPerPage); + + // Local state + const [selectedTypes, setSelectedTypes] = useState([]); + const [selectedStatus, setSelectedStatus] = useState(""); + const [selectedState, setSelectedState] = useState(""); + const [page, setPage] = useState(0); + const [search, setSearch] = useState(""); + const [sort, setSort] = useState< + { field: string; order: "asc" | "desc" } | undefined + >(); + + // Build URL for monitors with checks + const monitorsWithChecksUrl = useMemo(() => { + const params = new URLSearchParams(); + const types = + selectedTypes.length > 0 ? selectedTypes : ["http", "ping", "docker", "port"]; + types.forEach((type) => params.append("type", type)); + params.append("limit", "25"); + if (page) params.append("page", String(page)); + if (rowsPerPage) params.append("rowsPerPage", String(rowsPerPage)); + if (search) params.append("filter", search); + if (sort?.field) params.append("field", sort.field); + if (sort?.order) params.append("order", sort.order); + return `/monitors/team/with-checks?${params.toString()}`; + }, [selectedTypes, page, rowsPerPage, search, sort]); + + // Data fetching const { data: monitors, isLoading, error, } = useGet("/monitors/team?type=http&type=ping&type=port&type=docker"); + const { + data: monitorsWithChecksData, + isLoading: monitorsWithChecksLoading, + error: monitorsWithChecksError, + } = useGet(monitorsWithChecksUrl); + + const { monitors: monitorsWithChecks, summary, count } = monitorsWithChecksData ?? {}; + return ( - +
{JSON.stringify(monitors, null, 2)}
); diff --git a/client/src/Types/Monitor.ts b/client/src/Types/Monitor.ts index e01c9f844..8eff63518 100644 --- a/client/src/Types/Monitor.ts +++ b/client/src/Types/Monitor.ts @@ -1,6 +1,18 @@ import type { Check } from "@/Types/Check"; export type MonitorStatus = "up" | "down" | "initializing"; +export const MonitorTypes = [ + "http", + "ping", + "pagespeed", + "hardware", + "docker", + "port", + "game", + "unknown", +] as const; +export type MonitorType = (typeof MonitorTypes)[number]; + export interface Monitor { checks: Check[]; createdAt: string; @@ -18,3 +30,21 @@ export interface Monitor { __v: number; _id: string; } + +export interface MonitorWithChecks extends Monitor { + checks: Check[]; + uptimePercentage?: number; +} + +export interface MonitorsSummary { + totalMonitors: number; + totalUp: number; + totalDown: number; + totalPaused: number; +} + +export interface MonitorsWithChecksResponse { + count: number; + monitors: MonitorWithChecks[]; + summary: MonitorsSummary; +} diff --git a/client/src/Types/state.ts b/client/src/Types/state.ts new file mode 100644 index 000000000..fc25798c4 --- /dev/null +++ b/client/src/Types/state.ts @@ -0,0 +1,40 @@ +export interface AuthState { + isLoading: boolean; + authToken: string; + user: string; + success: boolean | null; + msg: string | null; +} + +export interface UIState { + monitors: { + rowsPerPage: number; + }; + team: { + rowsPerPage: number; + }; + maintenance: { + rowsPerPage: number; + }; + infrastructure: { + rowsPerPage: number; + }; + sidebar: { + collapsed: boolean; + }; + mode: "light" | "dark"; + showURL: boolean; + greeting: { + index: number; + lastUpdate: string | null; + }; + timezone: string; + distributedUptimeEnabled: boolean; + language: string; + starPromptOpen: boolean; +} + +export interface RootState { + auth: AuthState; + ui: UIState; +}