import { type ChangeEvent, type FormEvent, useEffect, useState } from "react"; import toast from "react-hot-toast"; import api from "../Api"; import type { Applications, DatabaseType, ServersType } from "../types/enums"; import type { User } from "../types/User"; type ModalType = "addServer" | "editProfile" | null; interface HeaderProps { currentUser: User | null; userError: string | null; onServerCreated?: () => Promise | void; onProfileUpdated?: (user: User) => void; } type ServerFormState = { name: string; ip: string; port: string; user: string; password: string; type: ServersType; application: Applications; dbType: DatabaseType; }; type ProfileFormState = { firstName: string; lastName: string; email: string; password: string; }; const defaultServerForm: ServerFormState = { name: "", ip: "", port: "", user: "", password: "", type: "PRODUCTION", application: "ASTERISK", dbType: "MYSQL", }; const defaultProfileForm: ProfileFormState = { firstName: "", lastName: "", email: "", password: "", }; const serverTypeOptions: ServersType[] = ["PRODUCTION", "HOMOLOGATION", "DATABASE"]; const applicationOptions: Applications[] = ["ASTERISK", "HITMANAGER", "HITMANAGER_V2", "OMNIHIT", "HITPHONE"]; const databaseOptions: DatabaseType[] = ["MYSQL", "POSTGRESQL", "SQLSERVER", "ORACLE", "REDIS", "MONGODB", "MARIADB", "NONE"]; export const Header = ({ currentUser, userError, onServerCreated, onProfileUpdated }: HeaderProps) => { const [isMenuOpen, setMenuOpen] = useState(false); const [activeModal, setActiveModal] = useState(null); const [serverForm, setServerForm] = useState(defaultServerForm); const [profileForm, setProfileForm] = useState(defaultProfileForm); const [serverLoading, setServerLoading] = useState(false); const [profileLoading, setProfileLoading] = useState(false); useEffect(() => { if (currentUser) { setProfileForm((prev) => ({ ...prev, firstName: currentUser.firstName ?? "", lastName: currentUser.lastName ?? "", email: currentUser.email ?? "", })); } }, [currentUser]); const toggleMenu = () => setMenuOpen((prev) => !prev); const openModal = (modal: ModalType) => { setMenuOpen(false); setActiveModal(modal); }; const closeModal = () => { setActiveModal(null); setServerForm(defaultServerForm); setProfileForm((prev) => ({ ...prev, password: "" })); }; const handleServerFormChange = (e: ChangeEvent) => { const { name, value } = e.target; setServerForm((prev) => ({ ...prev, [name]: value })); }; const handleProfileFormChange = (e: ChangeEvent) => { const { name, value } = e.target; setProfileForm((prev) => ({ ...prev, [name]: value })); }; const handleServerSubmit = async (event: FormEvent) => { event.preventDefault(); setServerLoading(true); try { await api.post("/api/servers", { ...serverForm, port: Number(serverForm.port), }); toast.success("Servidor criado com sucesso!"); setServerForm(defaultServerForm); setActiveModal(null); if (onServerCreated) { await Promise.resolve(onServerCreated()); } } catch (err: any) { const message = err?.response?.data?.message || "Falha ao criar servidor."; toast.error(message); } finally { setServerLoading(false); } }; const handleProfileSubmit = async (event: FormEvent) => { event.preventDefault(); if (!currentUser) { toast.error("Usuário não identificado."); return; } setProfileLoading(true); try { const { data } = await api.put(`/api/users/${currentUser.id}`, { firstName: profileForm.firstName, lastName: profileForm.lastName, email: profileForm.email, password: profileForm.password, }); toast.success("Perfil atualizado com sucesso!"); setProfileForm((prev) => ({ ...prev, password: "" })); setActiveModal(null); onProfileUpdated?.(data); } catch (err: any) { const message = err?.response?.data?.message || "Falha ao atualizar o perfil."; toast.error(message); } finally { setProfileLoading(false); } }; const renderModalContent = () => { if (activeModal === "addServer") { return (
); } if (activeModal === "editProfile") { if (userError) { return

{userError}

; } return (

Informe uma nova senha para confirmar a alteração.

); } return null; }; return ( <>
Logo Hit Communications

Hit Communications

Servers Manager

{isMenuOpen && (
)}
{activeModal && (

{activeModal === "addServer" ? "Adicionar novo servidor" : "Editar perfil"}

{renderModalContent()}
)} ); }; const Styles = { wrapper: "flex items-center justify-between rounded-xl border border-cardBorder bg-card px-6 py-4 shadow-sm", brand: "flex items-center gap-3", logo: "h-10 w-10 object-contain", title: "text-base font-semibold text-text", subtitle: "text-xs uppercase tracking-wide text-text-secondary", actions: "flex items-center gap-3", menuTrigger: "rounded-lg border border-cardBorder bg-white/70 px-4 py-2 text-sm font-medium text-text flex items-center gap-2 hover:bg-white transition-colors", dropdown: "absolute right-0 mt-2 w-48 rounded-lg border border-cardBorder bg-white py-2 shadow-lg z-10", dropdownItem: "w-full px-4 py-2 text-left text-sm text-text-secondary hover:bg-bg hover:text-text transition-colors", logoutButton: "rounded-md bg-accent px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-hover", modalOverlay: "fixed inset-0 z-40 flex items-center justify-center bg-black/40 px-4", modal: "w-full max-w-2xl rounded-2xl border border-cardBorder bg-card p-6 shadow-xl", modalHeader: "flex items-start justify-between gap-4 pb-4 border-b border-cardBorder", modalTitle: "text-lg font-semibold text-text", closeButton: "text-2xl leading-none text-text-secondary hover:text-text", modalBody: "pt-4", form: "space-y-4", formGrid: "grid gap-4 md:grid-cols-2", field: "flex flex-col gap-2", label: "text-xs font-semibold uppercase tracking-wide text-text-secondary", input: "rounded-lg border border-cardBorder bg-white px-3 py-2 text-sm text-text outline-none focus:border-accent focus:ring-1 focus:ring-accent", select: "rounded-lg border border-cardBorder bg-white px-3 py-2 text-sm text-text outline-none focus:border-accent focus:ring-1 focus:ring-accent capitalize", helperText: "text-xs text-text-secondary", modalActions: "flex justify-end gap-3 pt-2", secondaryButton: "rounded-md border border-cardBorder px-4 py-2 text-sm font-medium text-text hover:bg-bg disabled:opacity-50", primaryButton: "rounded-md bg-accent px-4 py-2 text-sm font-semibold text-white hover:bg-hover disabled:opacity-70", };