From d4d65ad0f9ffe2c8032e82a0e78b4f624c3b8549 Mon Sep 17 00:00:00 2001 From: Artur Oliveira Date: Tue, 16 Dec 2025 18:09:54 -0300 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20consumir=20tipos=20din=C3=A2m?= =?UTF-8?q?icos=20-=20remove=20listas=20fixas=20em=20Dashboard,=20Header?= =?UTF-8?q?=20e=20FilterBar=20-=20busca=20op=C3=A7=C3=B5es=20via=20API=20e?= =?UTF-8?q?=20reutiliza=20nos=20selects=20e=20m=C3=A9tricas=20-=20fallback?= =?UTF-8?q?=20dos=20labels=20agora=20trata=20tipos=20desconhecidos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Header.tsx | 26 +++++------ frontend/src/components/ServerCardMetrics.tsx | 12 ++--- frontend/src/components/ServersFilterBar.tsx | 34 +++++++------- frontend/src/components/header/types.ts | 8 ++-- frontend/src/pages/Dashboard.tsx | 45 ++++++++++++++++--- frontend/src/types/enums.ts | 32 +++---------- 6 files changed, 85 insertions(+), 72 deletions(-) diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index 6b89790..9af1ab6 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -19,6 +19,9 @@ interface HeaderProps { userError: string | null; onServerCreated?: () => Promise | void; onProfileUpdated?: (user: User) => void; + serverTypeOptions?: ServersType[]; + applicationOptions?: Applications[]; + databaseOptions?: DatabaseType[]; } const defaultServerForm: ServerFormState = { @@ -39,20 +42,15 @@ const defaultProfileForm: ProfileFormState = { password: "", }; -const serverTypeOptions: ServersType[] = ["PRODUCTION", "HOMOLOGATION", "DATABASE"]; -const applicationOptions: Applications[] = [ - "ASTERISK", - "HITMANAGER", - "HITMANAGER_V2", - "OMNIHIT", - "HITPHONE", - "CDR", - "FUNCIONALIDADE", - "VOICEMAIL", -]; -const databaseOptions: DatabaseType[] = ["MYSQL", "POSTGRESQL", "SQLSERVER", "ORACLE", "REDIS", "MONGODB", "MARIADB", "NONE"]; - -export const Header = ({ currentUser, userError, onServerCreated, onProfileUpdated }: HeaderProps) => { +export const Header = ({ + currentUser, + userError, + onServerCreated, + onProfileUpdated, + serverTypeOptions = [], + applicationOptions = [], + databaseOptions = [], +}: HeaderProps) => { const navigate = useNavigate(); const [isMenuOpen, setMenuOpen] = useState(false); const [activeModal, setActiveModal] = useState(null); diff --git a/frontend/src/components/ServerCardMetrics.tsx b/frontend/src/components/ServerCardMetrics.tsx index f96eb27..aa980cd 100644 --- a/frontend/src/components/ServerCardMetrics.tsx +++ b/frontend/src/components/ServerCardMetrics.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from "react"; import api from "../Api"; -import { ServerTypeLabels, type ServersType } from "../types/enums"; +import { ServerTypeLabels } from "../types/enums"; import { Code, Database, FlaskConical, Server } from "lucide-icons-react"; interface ServerCount { - type: ServersType; + type: string; total: number; } @@ -15,9 +15,9 @@ export const ServerCardMetrics = () => { useEffect(() => { const fetchCounts = async () => { try { - const { data } = await api.get>("/api/servers/type"); + const { data } = await api.get>("/api/servers/type"); const normalized = Object.entries(data).map(([type, total]) => ({ - type: type as ServersType, + type, total, })); setCounts(normalized); @@ -38,7 +38,7 @@ export const ServerCardMetrics = () => { return
Carregando métricas...
; } - const handleCardIcon = (type: ServersType) => { + const handleCardIcon = (type: string) => { const iconProps = { size: 32, strokeWidth: 1.5 }; switch (type) { @@ -64,7 +64,7 @@ export const ServerCardMetrics = () => {

{formatTotal(total)}

-

{ServerTypeLabels[type]}

+

{ServerTypeLabels[type] ?? type}

))} diff --git a/frontend/src/components/ServersFilterBar.tsx b/frontend/src/components/ServersFilterBar.tsx index 55867ee..06d81b6 100644 --- a/frontend/src/components/ServersFilterBar.tsx +++ b/frontend/src/components/ServersFilterBar.tsx @@ -12,21 +12,18 @@ interface Props { onTypeChange: (value: ServersType | OptionAll) => void; onApplicationChange: (value: Applications | OptionAll) => void; onDbTypeChange: (value: DatabaseType | OptionAll) => void; + serverTypeOptions?: ServersType[]; + applicationOptions?: Applications[]; + databaseOptions?: DatabaseType[]; } -const typeOptions: Array = ["ALL", "PRODUCTION", "HOMOLOGATION", "DATABASE"]; -const applicationOptions: Array = [ - "ALL", - "ASTERISK", - "HITMANAGER", - "HITMANAGER_V2", - "OMNIHIT", - "HITPHONE", - "CDR", - "FUNCIONALIDADE", - "VOICEMAIL", -]; -const databaseOptions: Array = ["ALL", "MYSQL", "POSTGRESQL", "SQLSERVER", "ORACLE", "REDIS", "MONGODB", "MARIADB", "NONE"]; +const withAllOption = (options?: T[]): Array => { + if (!options || options.length === 0) { + return ["ALL"]; + } + const unique = Array.from(new Set(options)); + return ["ALL", ...unique]; +}; export const ServersFilterBar = ({ search, @@ -37,7 +34,14 @@ export const ServersFilterBar = ({ onTypeChange, onApplicationChange, onDbTypeChange, + serverTypeOptions, + applicationOptions, + databaseOptions, }: Props) => { + const typeOptions = withAllOption(serverTypeOptions); + const applicationOptionsList = withAllOption(applicationOptions); + const databaseOptionsList = withAllOption(databaseOptions); + return (
@@ -61,13 +65,13 @@ export const ServersFilterBar = ({ label="Aplicação" value={application} onChange={(event) => onApplicationChange(event.target.value as Applications | OptionAll)} - options={applicationOptions} + options={applicationOptionsList} />