diff --git a/frontend/index.html b/frontend/index.html
index 7cfb423..0a76d12 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -2,9 +2,9 @@
-
+
- frontned
+ Hit Servers Manager
diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png
new file mode 100644
index 0000000..4a9105c
Binary files /dev/null and b/frontend/public/favicon.png differ
diff --git a/frontend/src/App.css b/frontend/src/App.css
index bd6213e..ab13784 100644
--- a/frontend/src/App.css
+++ b/frontend/src/App.css
@@ -1,3 +1,31 @@
@tailwind base;
@tailwind components;
-@tailwind utilities;
\ No newline at end of file
+@tailwind utilities;
+
+:root {
+ --color-bg: 250 250 249;
+ --color-card: 244 244 242;
+ --color-card-border: 229 231 235;
+ --color-text: 26 26 26;
+ --color-text-secondary: 107 114 128;
+ --color-hover: 208 74 15;
+ --color-accent: 233 90 27;
+ color-scheme: light;
+}
+
+.dark {
+ --color-bg: 2 6 23;
+ --color-card: 15 23 42;
+ --color-card-border: 51 65 85;
+ --color-text: 241 245 249;
+ --color-text-secondary: 148 163 184;
+ --color-hover: 249 115 22;
+ --color-accent: 233 90 27;
+ color-scheme: dark;
+}
+
+@layer base {
+ body {
+ @apply bg-bg text-text antialiased transition-colors duration-200;
+ }
+}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 3d73571..1f15119 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -5,18 +5,19 @@ import { Dashboard } from './pages/Dashboard';
import { ProtectedRoute } from './routes/ProtectedRoute';
function App() {
-
return (
-
-
-
-
-
- } />
- } />
-
-
+
+
+
+
+
+
+ } />
+ } />
+
+
+
);
}
diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx
index 9af1ab6..355990c 100644
--- a/frontend/src/components/Header.tsx
+++ b/frontend/src/components/Header.tsx
@@ -254,5 +254,5 @@ export const Header = ({
};
const Styles = {
- wrapper: "flex items-center justify-between rounded-xl border border-cardBorder bg-card px-6 py-4 shadow-sm",
+ wrapper: "flex items-center justify-between rounded-xl border border-cardBorder bg-card px-6 py-4 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:shadow-slate-900/50",
};
diff --git a/frontend/src/components/ServerCardMetrics.tsx b/frontend/src/components/ServerCardMetrics.tsx
index aa980cd..9c271a9 100644
--- a/frontend/src/components/ServerCardMetrics.tsx
+++ b/frontend/src/components/ServerCardMetrics.tsx
@@ -74,11 +74,11 @@ export const ServerCardMetrics = () => {
const Styles = {
grid: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
- card: "flex items-center gap-4 rounded-xl border border-cardBorder bg-gradient-to-br from-white/90 to-card p-5 shadow-sm",
- iconWrapper: "flex h-14 w-14 items-center justify-center rounded-lg border border-accent/20 bg-accent/10 text-accent",
+ card: "flex items-center gap-4 rounded-xl border border-cardBorder bg-gradient-to-br from-white/90 to-card p-5 shadow-sm dark:border-slate-800 dark:from-slate-900 dark:to-slate-950 dark:shadow-slate-900/40",
+ iconWrapper: "flex h-14 w-14 items-center justify-center rounded-lg border border-accent/20 bg-accent/10 text-accent dark:border-slate-800 dark:bg-slate-800/60",
textGroup: "flex flex-col",
- label: "text-xs font-medium uppercase tracking-wide text-text-secondary",
- value: "text-3xl font-semibold text-text leading-tight",
- 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",
+ label: "text-xs font-medium uppercase tracking-wide text-text-secondary dark:text-slate-400",
+ value: "text-3xl font-semibold leading-tight text-text dark:text-white",
+ placeholder: "rounded-lg border border-cardBorder bg-card p-4 text-sm text-text-secondary dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400",
+ error: "rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-400/30 dark:bg-red-950/40 dark:text-red-300",
};
diff --git a/frontend/src/components/ServersFilterBar.tsx b/frontend/src/components/ServersFilterBar.tsx
index 06d81b6..cad9618 100644
--- a/frontend/src/components/ServersFilterBar.tsx
+++ b/frontend/src/components/ServersFilterBar.tsx
@@ -15,6 +15,8 @@ interface Props {
serverTypeOptions?: ServersType[];
applicationOptions?: Applications[];
databaseOptions?: DatabaseType[];
+ hideSensitive: boolean;
+ onToggleSensitive: () => void;
}
const withAllOption = (options?: T[]): Array => {
@@ -37,6 +39,8 @@ export const ServersFilterBar = ({
serverTypeOptions,
applicationOptions,
databaseOptions,
+ hideSensitive,
+ onToggleSensitive,
}: Props) => {
const typeOptions = withAllOption(serverTypeOptions);
const applicationOptionsList = withAllOption(applicationOptions);
@@ -73,6 +77,11 @@ export const ServersFilterBar = ({
onChange={(event) => onDbTypeChange(event.target.value as DatabaseType | OptionAll)}
options={databaseOptionsList}
/>
+
+
+
);
};
@@ -100,10 +109,12 @@ const Select = ({ label, value, onChange, options }: SelectPro
};
const Styles = {
- wrapper: "flex flex-wrap gap-4 rounded-lg border border-cardBorder bg-white/70 p-4 shadow-sm",
+ wrapper: "flex flex-wrap items-end gap-4 rounded-lg border border-cardBorder bg-white/70 p-4 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:shadow-slate-900/40",
searchGroup: "flex-1 min-w-[220px]",
selectGroup: "flex min-w-[150px] flex-col gap-1",
- label: "text-xs font-semibold uppercase tracking-wide text-text-secondary",
- input: "w-full 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: "w-full 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",
+ label: "text-xs font-semibold uppercase tracking-wide text-text-secondary dark:text-slate-400",
+ input: "w-full 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 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100",
+ select: "w-full 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 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100",
+ toggleWrapper: "flex min-w-[200px] items-center justify-end",
+ toggleButton: "rounded-md border border-cardBorder px-4 py-2 text-xs font-semibold uppercase tracking-wide text-text-secondary hover:bg-bg dark:border-slate-700 dark:text-slate-300 dark:hover:bg-slate-800",
};
diff --git a/frontend/src/components/ServersTable.tsx b/frontend/src/components/ServersTable.tsx
index 9844099..51d59e8 100644
--- a/frontend/src/components/ServersTable.tsx
+++ b/frontend/src/components/ServersTable.tsx
@@ -1,4 +1,3 @@
-import { useState } from "react";
import type { Server } from "../types/Server";
interface Props {
@@ -9,6 +8,7 @@ interface Props {
pageSize: number;
totalPages: number;
totalItems: number;
+ hideSensitive: boolean;
onPageChange: (page: number) => void;
onPageSizeChange: (size: number) => void;
}
@@ -23,38 +23,36 @@ export const ServersTable = ({
pageSize,
totalPages,
totalItems,
+ hideSensitive,
onPageChange,
onPageSizeChange,
}: Props) => {
- const [hideSensitive, setHideSensitive] = useState(false);
const showingFrom = totalItems === 0 ? 0 : page * pageSize + 1;
const showingTo = totalItems === 0 ? 0 : Math.min((page + 1) * pageSize, totalItems);
const hasResults = servers.length > 0;
+ const isInitialLoad = loading && !hasResults;
+ const showOverlay = loading && hasResults;
const formatSensitiveValue = (value: string | number) => (hideSensitive ? "••••" : value);
return (
-
- {loading &&
Carregando servidores...
}
+ {isInitialLoad &&
Carregando servidores...
}
{error &&
{error}
}
{!loading && !error && servers.length === 0 && (
Nenhum servidor encontrado.
)}
- {!loading && !error && hasResults && (
- <>
+ {hasResults && (
+
+ {showOverlay && (
+
+ Atualizando lista...
+
+ )}
-
+
| Nome |
IP |
Porta |
@@ -69,14 +67,14 @@ export const ServersTable = ({
{servers.map((server) => (
| {server.name} |
{formatSensitiveValue(server.ip)} |
{formatSensitiveValue(server.port)} |
{formatSensitiveValue(server.user)} |
-
+
{hideSensitive ? "••••" : server.password}
|
@@ -130,29 +128,34 @@ export const ServersTable = ({
- >
+
)}
+
);
};
const Styles = {
- card: "relative 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",
- pagination: "flex flex-col gap-2 border-t border-cardBorder bg-white px-4 py-3 sm:flex-row sm:items-center sm:justify-between",
- pageInfo: "text-sm text-text-secondary",
+ card: "overflow-hidden rounded-lg border border-cardBorder bg-card shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:shadow-slate-900/40",
+ status: "p-4 text-sm text-text-secondary dark:text-slate-400",
+ error: "p-4 text-sm text-red-600 dark:text-red-400",
+ tableWrapper: "overflow-x-auto rounded-lg border border-cardBorder shadow-sm dark:border-slate-800 dark:bg-slate-950/40",
+ table: "min-w-full table-auto divide-y divide-cardBorder dark:divide-slate-800",
+ tableHead: "sticky top-0 bg-gray-50 dark:bg-slate-800",
+ tableHeadRow: "text-left text-text dark:text-slate-200",
+ tableHeadCell: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-text-secondary dark:text-slate-300",
+ tableBody: "divide-y divide-cardBorder bg-white dark:divide-slate-800 dark:bg-slate-900",
+ tableRow: "transition-colors even:bg-gray-50/50 hover:bg-gray-50 dark:even:bg-slate-900 dark:hover:bg-slate-800",
+ rowCell: "px-4 py-3 text-sm text-text dark:text-slate-100",
+ password: "rounded bg-gray-100 px-2 py-1 text-xs dark:bg-slate-800 dark:text-slate-100",
+ pagination: "flex flex-col gap-2 border-t border-cardBorder bg-white px-4 py-3 dark:border-slate-800 dark:bg-slate-900 sm:flex-row sm:items-center sm:justify-between",
+ pageInfo: "text-sm text-text-secondary dark:text-slate-400",
paginationControls: "flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4",
- pageSizeLabel: "text-sm text-text flex items-center gap-2",
- pageSizeSelect: "rounded-md border border-cardBorder bg-white px-2 py-1 text-sm text-text outline-none focus:border-accent focus:ring-1 focus:ring-accent",
+ pageSizeLabel: "text-sm text-text dark:text-slate-100 flex items-center gap-2",
+ pageSizeSelect: "rounded-md border border-cardBorder bg-white px-2 py-1 text-sm text-text outline-none focus:border-accent focus:ring-1 focus:ring-accent dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100",
pageButtons: "flex items-center gap-3",
- pageButton: "rounded-md border border-cardBorder px-3 py-1.5 text-sm font-medium text-text hover:bg-bg disabled:opacity-50 disabled:hover:bg-transparent",
- pageIndicator: "text-sm text-text-secondary",
- hideButton: "absolute right-3 top-3 rounded-md border border-cardBorder px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-text-secondary hover:bg-bg disabled:opacity-50 disabled:hover:bg-transparent bg-white shadow-sm",
+ pageButton: "rounded-md border border-cardBorder px-3 py-1.5 text-sm font-medium text-text transition-colors hover:bg-bg disabled:opacity-50 disabled:hover:bg-transparent dark:border-slate-700 dark:text-slate-100 dark:hover:bg-slate-800",
+ pageIndicator: "text-sm text-text-secondary dark:text-slate-400",
+ footerSpacer: "h-4",
+ loadingOverlay: "absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-white/70 text-sm font-medium text-text backdrop-blur-sm dark:bg-slate-900/80 dark:text-slate-100",
};
diff --git a/frontend/src/components/common/Modal.tsx b/frontend/src/components/common/Modal.tsx
index f41e470..14012f7 100644
--- a/frontend/src/components/common/Modal.tsx
+++ b/frontend/src/components/common/Modal.tsx
@@ -64,11 +64,11 @@ export const Modal = ({ isOpen, title, onClose, children, description, bodyClass
};
const Styles = {
- overlay: "fixed inset-0 z-40 flex items-center justify-center bg-black/40 backdrop-blur-sm px-4 !mt-0",
- dialog: "w-full max-w-2xl rounded-2xl border border-cardBorder bg-card p-6 shadow-xl transform transition-all duration-200 animate-fade-up",
- header: "flex items-start justify-between gap-4 pb-4 border-b border-cardBorder",
- title: "text-lg font-semibold text-text",
- closeButton: "text-2xl leading-none text-text-secondary hover:text-text",
- description: "pt-3 text-sm text-text-secondary",
+ overlay: "fixed inset-0 z-40 flex items-center justify-center bg-black/40 px-4 backdrop-blur-sm !mt-0 dark:bg-black/60",
+ dialog: "w-full max-w-2xl transform animate-fade-up rounded-2xl border border-cardBorder bg-card p-6 shadow-xl transition-all duration-200 dark:border-slate-800 dark:bg-slate-900 dark:shadow-slate-900/70",
+ header: "flex items-start justify-between gap-4 border-b border-cardBorder pb-4 dark:border-slate-800",
+ title: "text-lg font-semibold text-text dark:text-white",
+ closeButton: "text-2xl leading-none text-text-secondary hover:text-text dark:text-slate-400 dark:hover:text-white",
+ description: "pt-3 text-sm text-text-secondary dark:text-slate-400",
body: "pt-4",
};
diff --git a/frontend/src/components/header/BulkImportModal.tsx b/frontend/src/components/header/BulkImportModal.tsx
index 6b09733..0d50b0c 100644
--- a/frontend/src/components/header/BulkImportModal.tsx
+++ b/frontend/src/components/header/BulkImportModal.tsx
@@ -34,7 +34,7 @@ export const BulkImportModal = ({