diff --git a/frontend/src/components/ServerCardMetrics.tsx b/frontend/src/components/ServerCardMetrics.tsx new file mode 100644 index 0000000..7cca7ce --- /dev/null +++ b/frontend/src/components/ServerCardMetrics.tsx @@ -0,0 +1,59 @@ +import { useEffect, useState } from "react"; +import api from "../Api"; +import { ServerTypeLabels, type ServersType } from "../types/enums"; + +interface ServerCount { + type: ServersType; + total: number; +} + +export const ServerCardMetrics = () => { + const [counts, setCounts] = useState([]); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchCounts = async () => { + try { + const { data } = await api.get>("/api/servers/type"); + const normalized = Object.entries(data).map(([type, total]) => ({ + type: type as ServersType, + total, + })); + setCounts(normalized); + } catch (err: any) { + const message = err?.response?.data?.message || "Falha ao carregar o total de servidores."; + setError(message); + } + }; + + fetchCounts(); + }, []); + + if (error) { + return
{error}
; + } + + if (counts.length === 0) { + return
Carregando métricas...
; + } + + return ( +
+ {counts.map(({ type, total }) => ( +
+

{ServerTypeLabels[type]}

+

{total}

+
+ ))} +
+ ); +}; + +const Styles = { + grid: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", + card: "rounded-lg border border-cardBorder bg-card p-4 shadow-sm space-y-1", + label: "text-sm text-text-secondary uppercase tracking-wide", + value: "text-3xl font-semibold text-text", + placeholder: "p-4 rounded-lg border border-cardBorder bg-card text-text-secondary text-sm", + error: "p-4 rounded-lg border border-red-200 bg-red-50 text-red-600 text-sm", +}; diff --git a/frontend/src/components/ServersTable.tsx b/frontend/src/components/ServersTable.tsx new file mode 100644 index 0000000..7851b9f --- /dev/null +++ b/frontend/src/components/ServersTable.tsx @@ -0,0 +1,64 @@ +import type { Server } from "../types/Server"; + +interface Props { + servers: Server[]; + loading: boolean; + error: string | null; +} + +export const ServersTable = ({ servers, loading, error }: Props) => { + return ( +
+ {loading &&
Carregando servidores...
} + {error &&
{error}
} + {!loading && !error && servers.length === 0 && ( +
Nenhum servidor encontrado.
+ )} + {!loading && !error && servers.length > 0 && ( +
+ + + + + + + + + + + + + + {servers.map((server) => ( + + + + + + + + + + ))} + +
NomeIPPortaUsuárioTipoAplicaçãoBanco
{server.name}{server.ip}{server.port}{server.user}{server.type.toLowerCase()}{server.application.toLowerCase()}{server.dbType.toLowerCase()}
+
+ )} +
+ ); +}; + +const Styles = { + card: "bg-card border border-cardBorder shadow-sm rounded-lg overflow-hidden", + status: "p-4 text-text-secondary text-sm", + error: "p-4 text-red-600 text-sm", + tableWrapper: "overflow-x-auto rounded-lg shadow-sm border border-cardBorder", + table: "min-w-full divide-y divide-cardBorder table-auto", + tableHead: "bg-gray-50 sticky top-0", + tableHeadCell: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-text-secondary", + tableBody: "bg-white divide-y divide-cardBorder", + rowCell: "px-4 py-3 text-sm text-text", +}; diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index cb9b619..7a5863d 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -1,6 +1,8 @@ import { useEffect, useState } from "react"; import api from "../Api"; import { Layout } from "../components/Layout"; +import { ServerCardMetrics } from "../components/ServerCardMetrics"; +import { ServersTable } from "../components/ServersTable"; import type { Server } from "../types/Server"; export const Dashboard = () => { @@ -27,52 +29,9 @@ export const Dashboard = () => { return (
-

Servidores

- -
- {loading &&
Carregando servidores...
} - {error &&
{error}
} - {!loading && !error && servers.length === 0 && ( -
Nenhum servidor encontrado.
- )} - {!loading && !error && servers.length > 0 && ( -
- - - - - - - - - - - - - - {servers.map((server) => ( - - - - - - - - - - ))} - -
NomeIPPortaUsuárioTipoAplicaçãoBanco
{server.name}{server.ip}{server.port}{server.user}{server.type.toLowerCase()}{server.application.toLowerCase()}{server.dbType.toLowerCase()}
-
- )} -
+ +
); }; - -const Styles = { - card: "bg-card border border-cardBorder shadow-sm rounded-lg overflow-hidden", - tableHeadCell: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-text-secondary", - rowCell: "px-4 py-3 text-sm text-text", -}; diff --git a/frontend/src/types/enums.ts b/frontend/src/types/enums.ts index 5760ce0..6aa33a7 100644 --- a/frontend/src/types/enums.ts +++ b/frontend/src/types/enums.ts @@ -16,3 +16,9 @@ export type Applications = | 'HITPHONE'; export type ServersType = 'PRODUCTION' | 'HOMOLOGATION' | 'DATABASE'; + +export const ServerTypeLabels: Record = { + PRODUCTION: "Produção", + HOMOLOGATION: "Homologação", + DATABASE: "Banco de Dados", +};