14/02/2025
This commit is contained in:
parent
1e135f763f
commit
760aec0638
@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite --host",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
|
|||||||
77
src/App.css
77
src/App.css
@ -1,40 +1,78 @@
|
|||||||
/* Navbar styling jika diperlukan */
|
/* Navbar styling jika diperlukan */
|
||||||
body {
|
body {
|
||||||
padding-top: 56px; /* Sesuaikan dengan tinggi Navbar */
|
font-family: 'Poppins', sans-serif !important;
|
||||||
padding-left: 250px; /* Sesuaikan dengan tinggi Navbar */
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
padding-top: 70px; /* Sesuaikan dengan tinggi Navbar */
|
||||||
|
padding-left: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar {
|
body.light {
|
||||||
background-color: #ffffff !important;
|
background-color: #ffffff;
|
||||||
|
color: #1d1d1d;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark {
|
||||||
|
background-color: #161616;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-app {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
font-family: 'Poppins', sans-serif !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tambahan untuk Bootstrap override */
|
.light.navbar-app {
|
||||||
.bg-light {
|
background-color: #ffffff;
|
||||||
background-color: #f1f1f1 !important;
|
transition: background-color 0.3s, color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-dark {
|
.light.navbar-brand {
|
||||||
color: #fff !important;
|
color: #161616;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark.navbar-app {
|
||||||
|
background-color: #161616;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark.navbar-brand {
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #474747;
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styling Sidebar */
|
/* Styling Sidebar */
|
||||||
.sidebar {
|
.sidebar-app {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding-top: 75px;
|
padding-top: 100px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-right: 1px solid #ddd;/* Warna sidebar */
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
/* border-right: 1px solid #414141; */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styling Default Link */
|
/* Styling Default Link */
|
||||||
.sidebar .nav-link {
|
.sidebar-app .nav-link {
|
||||||
margin: 0 15px 0 15px;
|
margin: 5px 15px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding: 12px 15px;
|
padding: 12px 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -43,16 +81,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hover Effect */
|
/* Hover Effect */
|
||||||
.sidebar .nav-link:hover {
|
.sidebar-app .nav-link:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Halaman yang aktif */
|
/* Halaman yang aktif */
|
||||||
.sidebar .nav-link.active {
|
.sidebar-app .nav-link.active {
|
||||||
background-color:rgb(65, 157, 255); /* Warna biru saat aktif */
|
background-color:rgb(71, 71, 71); /* Warna biru saat aktif */
|
||||||
color: white !important;
|
color: white !important;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
22
src/App.jsx
22
src/App.jsx
@ -6,16 +6,28 @@ import Dashboard from './pages/Dashboard';
|
|||||||
import DevicesPage from './pages/DevicesPage';
|
import DevicesPage from './pages/DevicesPage';
|
||||||
import ReportPage from "./pages/ReportPage";
|
import ReportPage from "./pages/ReportPage";
|
||||||
import SettingsPage from "./pages/SettingsPage";
|
import SettingsPage from "./pages/SettingsPage";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
|
const [theme, setTheme] = useState(localStorage.getItem("theme") || "light");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.className = theme;
|
||||||
|
localStorage.setItem("theme", theme);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
setTheme(prevTheme => (prevTheme === "light" ? "dark" : "light"));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<div className="flex">
|
<div className={`app-container ${theme}`}>
|
||||||
|
<Navbar toggleTheme={toggleTheme} theme={theme} className={`${theme}`}/>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<div className="w-full">
|
<div className={`main-content ${theme}`}>
|
||||||
<Navbar />
|
|
||||||
<div className="content p-4">
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Navigate to="/dashboard" />}/>
|
<Route path="/" element={<Navigate to="/dashboard" />}/>
|
||||||
<Route path="/dashboard" element={<Dashboard />}/>
|
<Route path="/dashboard" element={<Dashboard />}/>
|
||||||
@ -25,10 +37,8 @@ function App() {
|
|||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
||||||
|
|||||||
@ -15,37 +15,37 @@ const DownloadChart = ({ data }) => {
|
|||||||
chart: {
|
chart: {
|
||||||
height: 250,
|
height: 250,
|
||||||
type: 'area',
|
type: 'area',
|
||||||
background: '#ececec',
|
background: '#1e1e1e',
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
},
|
},
|
||||||
dataLabels: { enabled: false },
|
dataLabels: { enabled: false },
|
||||||
stroke: {
|
stroke: {
|
||||||
curve: 'smooth',
|
curve: 'smooth',
|
||||||
colors: ['#28a745'],
|
colors: ['#4CAF50'],
|
||||||
},
|
},
|
||||||
xaxis: {
|
xaxis: {
|
||||||
type: 'datetime',
|
type: 'datetime',
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
axisBorder: { color: '#555555' },
|
axisBorder: { color: '#777777' },
|
||||||
axisTicks: { color: '#555555' },
|
axisTicks: { color: '#777777' },
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
borderColor: '#555555',
|
borderColor: '#777777',
|
||||||
strokeDashArray: 4,
|
strokeDashArray: 4,
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
theme: 'light',
|
theme: 'dark',
|
||||||
x: { format: 'dd/MM/yy HH:mm' },
|
x: { format: 'dd/MM/yy HH:mm' },
|
||||||
y: { formatter: (val) => `${val} Mbps` },
|
y: { formatter: (val) => `${val} Mbps` },
|
||||||
},
|
},
|
||||||
colors: ['#28a745'],
|
colors: ['#4CAF50'],
|
||||||
fill: {
|
fill: {
|
||||||
type: 'gradient',
|
type: 'gradient',
|
||||||
gradient: {
|
gradient: {
|
||||||
shade: 'light',
|
shade: 'dark',
|
||||||
type: 'vertical',
|
type: 'vertical',
|
||||||
gradientToColors: ['#28a745'],
|
gradientToColors: ['#28a745'],
|
||||||
stops: [0, 100],
|
stops: [0, 100],
|
||||||
|
|||||||
@ -16,7 +16,7 @@ const PingChart = ({ data }) => {
|
|||||||
chart: {
|
chart: {
|
||||||
height: 250,
|
height: 250,
|
||||||
type: 'area',
|
type: 'area',
|
||||||
background: '#ececec',
|
background: '#1e1e1e',
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
},
|
},
|
||||||
dataLabels: { enabled: false },
|
dataLabels: { enabled: false },
|
||||||
@ -26,15 +26,15 @@ const PingChart = ({ data }) => {
|
|||||||
},
|
},
|
||||||
xaxis: {
|
xaxis: {
|
||||||
type: 'datetime',
|
type: 'datetime',
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
axisBorder: { color: '#555555' },
|
axisBorder: { color: '#777777' },
|
||||||
axisTicks: { color: '#555555' },
|
axisTicks: { color: '#777777' },
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
borderColor: '#555555',
|
borderColor: '#777777',
|
||||||
strokeDashArray: 4,
|
strokeDashArray: 4,
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const UploadChart = ({ data }) => {
|
|||||||
chart: {
|
chart: {
|
||||||
height: 250,
|
height: 250,
|
||||||
type: 'area',
|
type: 'area',
|
||||||
background: '#ececec',
|
background: '#1e1e1e',
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
},
|
},
|
||||||
dataLabels: { enabled: false },
|
dataLabels: { enabled: false },
|
||||||
@ -25,15 +25,15 @@ const UploadChart = ({ data }) => {
|
|||||||
},
|
},
|
||||||
xaxis: {
|
xaxis: {
|
||||||
type: 'datetime',
|
type: 'datetime',
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
axisBorder: { color: '#555555' },
|
axisBorder: { color: '#777777' },
|
||||||
axisTicks: { color: '#555555' },
|
axisTicks: { color: '#777777' },
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
labels: { style: { fontFamily: 'Poppins, sans-serif' } },
|
labels: { style: { fontFamily: 'Poppins, sans-serif', colors: '#ffffff' } },
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
borderColor: '#555555',
|
borderColor: '#777777',
|
||||||
strokeDashArray: 4,
|
strokeDashArray: 4,
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { FaCheckCircle, FaTimesCircle } from "react-icons/fa";
|
|||||||
const AppDevice = ({ devices }) => {
|
const AppDevice = ({ devices }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table striped bordered hover responsive style={{ fontFamily: 'Poppins, sans-serif' }}>
|
<Table striped bordered hover responsive>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>IP Address</th>
|
<th>IP Address</th>
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const AverageData = ({ data }) => {
|
|||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className="mb-4 shadow-sm bg-dark text-light">
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaDownload style={{ marginRight: '10px', width: '15px', color: '#28a745' }} />
|
<FaDownload style={{ marginRight: '10px', width: '15px', color: '#28a745' }} />
|
||||||
Average Download
|
Average Download
|
||||||
@ -35,7 +35,7 @@ const AverageData = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className="mb-4 shadow-sm bg-dark text-light">
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
||||||
Average Upload
|
Average Upload
|
||||||
@ -46,7 +46,7 @@ const AverageData = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className="mb-4 shadow-sm bg-dark text-light">
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
||||||
Average Ping
|
Average Ping
|
||||||
|
|||||||
@ -5,12 +5,12 @@ import UploadChart from '../charts/UploadChart';
|
|||||||
import PingChart from '../charts/PingChart';
|
import PingChart from '../charts/PingChart';
|
||||||
import { FaDownload, FaUpload, FaTachometerAlt } from 'react-icons/fa';
|
import { FaDownload, FaUpload, FaTachometerAlt } from 'react-icons/fa';
|
||||||
|
|
||||||
const Chart = ({ data }) => {
|
const Chart = ({ data, theme }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md="4">
|
<Col md="4">
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className={`mb-4 shadow-sm ${theme}`}>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Card.Title>
|
<Card.Title>
|
||||||
<FaDownload style={{ marginRight: '10px', color: '#28a745'}} />
|
<FaDownload style={{ marginRight: '10px', color: '#28a745'}} />
|
||||||
@ -21,7 +21,7 @@ const Chart = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md="4">
|
<Col md="4">
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className={`mb-4 shadow-sm ${theme}`}>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Card.Title>
|
<Card.Title>
|
||||||
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
||||||
@ -32,7 +32,7 @@ const Chart = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md="4">
|
<Col md="4">
|
||||||
<Card className="mb-4 shadow-sm">
|
<Card className={`mb-4 shadow-sm ${theme}`}>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Card.Title>
|
<Card.Title>
|
||||||
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
||||||
|
|||||||
@ -2,21 +2,21 @@
|
|||||||
import { FaDownload, FaUpload, FaTachometerAlt } from 'react-icons/fa';
|
import { FaDownload, FaUpload, FaTachometerAlt } from 'react-icons/fa';
|
||||||
import { Card, Col, Row } from 'react-bootstrap';
|
import { Card, Col, Row } from 'react-bootstrap';
|
||||||
|
|
||||||
const LatestData = ({ data }) => {
|
const LatestData = ({ data, theme }) => {
|
||||||
const latestData = data.length > 0 ? data[data.length - 20] : null;
|
const latestData = data.length > 0 ? data[data.length - 20] : null;
|
||||||
|
|
||||||
if (!latestData) return null;
|
if (!latestData) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Card className='mb-4 shadow-sm border-light bg-dark text-light'>
|
<Card className='mb-4 shadow-sm border-light'>
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<h3 style={{marginTop: '20px', marginBottom: '20px'}}>Latest Data</h3>
|
<h3 style={{marginTop: '20px', marginBottom: '20px'}}>Latest Data</h3>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm bg-dark text-light">
|
<Card className={`${theme} mb-4 shadow-sm`}>
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaDownload style={{ marginRight: '10px', width: '15px', color: '#28a745' }} />
|
<FaDownload style={{ marginRight: '10px', width: '15px', color: '#28a745' }} />
|
||||||
Latest Download
|
Latest Download
|
||||||
@ -27,7 +27,7 @@ const LatestData = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm bg-dark text-light">
|
<Card className={`${theme} mb-4 shadow-sm`}>
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
<FaUpload style={{ marginRight: '10px', width: '15px', color: '#00bcd4' }} />
|
||||||
Latest Upload
|
Latest Upload
|
||||||
@ -38,7 +38,7 @@ const LatestData = ({ data }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={4}>
|
<Col md={4}>
|
||||||
<Card className="mb-4 shadow-sm bg-dark text-light">
|
<Card className={`${theme} mb-4 shadow-sm`}>
|
||||||
<Card.Header as="h6">
|
<Card.Header as="h6">
|
||||||
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
<FaTachometerAlt style={{ marginRight: '10px', width: '15px', color: '#ffc107' }} />
|
||||||
Latest Ping
|
Latest Ping
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import Table from 'react-bootstrap/Table';
|
|||||||
|
|
||||||
const MetricsTable = ({ metrics = [] }) => {
|
const MetricsTable = ({ metrics = [] }) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ overflowX: "auto", maxHeight: "400px", overflowY: "auto", position: "relative", borderTop: "1px solid #ddd" }}>
|
<div style={{ overflowX: "auto", maxHeight: "450px", overflowY: "auto", position: "relative", borderTop: "1px solid #444", backgroundColor: "#1e1e1e" }}>
|
||||||
<Table striped bordered hover responsive style={{ fontFamily: 'Poppins, sans-serif', minWidth: "900px"}}>
|
<Table striped bordered hover responsive variant='dark' style={{ fontFamily: 'Poppins, sans-serif', minWidth: "900px", backgroundColor: "#1e1e1e", color: "#ffffff" }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr style={{ backgroundColor: "#333333", color: "#ffffff" }}>
|
||||||
<th className="py-3 text-center align-middle">Monitor Name</th>
|
<th className="py-3 text-center align-middle">Monitor Name</th>
|
||||||
<th className="py-3 text-center align-middle">URL</th>
|
<th className="py-3 text-center align-middle">URL</th>
|
||||||
<th className="py-3 text-center align-middle">Response Time (ms)</th>
|
<th className="py-3 text-center align-middle">Response Time (ms)</th>
|
||||||
@ -16,9 +16,9 @@ const MetricsTable = ({ metrics = [] }) => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{metrics.map((item, index) => (
|
{metrics.map((item, index) => (
|
||||||
<tr key={index}>
|
<tr key={index} style={{ backgroundColor: "#222222", color: "#ffffff" }}>
|
||||||
<td>{item.monitor_name}</td>
|
<td>{item.monitor_name}</td>
|
||||||
<td><a href={item.monitor_url} target="_blank" rel="noopener noreferrer">{item.monitor_url}</a></td>
|
<td><a href={item.monitor_url} target="_blank" rel="noopener noreferrer" style={{ color: "#4CAF50" }}>{item.monitor_url}</a></td>
|
||||||
<td>{item.response_time} ms</td>
|
<td>{item.response_time} ms</td>
|
||||||
<td>
|
<td>
|
||||||
{item.status === 1 ? 'UP' :
|
{item.status === 1 ? 'UP' :
|
||||||
|
|||||||
@ -3,11 +3,11 @@ import { Table } from 'react-bootstrap';
|
|||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { FaDownload, FaUpload, FaTachometerAlt } from "react-icons/fa";
|
import { FaDownload, FaUpload, FaTachometerAlt } from "react-icons/fa";
|
||||||
|
|
||||||
const DataTable = ({ data = [] }) => {
|
const DataTable = ({ data = [], theme }) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ overflowX: "auto", maxHeight: "400px", overflowY: "auto", position: "relative", borderTop: "1px solid #ddd", marginBottom: "20px"}}>
|
<div style={{ overflowX: "auto", maxHeight: "400px", overflowY: "auto", position: "relative", marginBottom: "20px"}}>
|
||||||
<Table striped bordered hover responsive style={{ fontFamily: 'Poppins, sans-serif', minWidth: "900px"}}>
|
<Table striped bordered hover responsive style={{ fontFamily: 'Poppins, sans-serif', minWidth: "900px"}} className={`${theme}`}>
|
||||||
<thead className="bg-secondary text-center" style={{ position: "sticky", top: 0, zIndex: 10, backgroundColor: "#6c757d" }}>
|
<thead className="bg-secondary text-center" style={{ position: "sticky", top: 0, zIndex: 10, backgroundColor: "#343a40" }}>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="py-3 text-center align-middle">No</th>
|
<th className="py-3 text-center align-middle">No</th>
|
||||||
<th className="py-3 text-center align-middle" style={{ color: '#28a745' }}>
|
<th className="py-3 text-center align-middle" style={{ color: '#28a745' }}>
|
||||||
|
|||||||
@ -1,30 +1,20 @@
|
|||||||
import { Navbar, Nav } from 'react-bootstrap';
|
import { Navbar, Nav } from 'react-bootstrap';
|
||||||
import { FaChartLine } from 'react-icons/fa';
|
import { FaChartLine, FaSun, FaMoon } from 'react-icons/fa';
|
||||||
|
|
||||||
const AppNavbar = () => {
|
const AppNavbar = ({ toggleTheme, theme }) => {
|
||||||
return (
|
return (
|
||||||
<Navbar
|
<Navbar
|
||||||
className="fixed-top w-100 shadow-sm d-flex justify-content-between"
|
className={`${theme} navbar-app fixed-top w-100 shadow-sm d-flex justify-content-between`}
|
||||||
style={{ zIndex: 1030, padding: '15px 20px' }}
|
style={{ zIndex: 1030, padding: '15px 20px' }}
|
||||||
>
|
>
|
||||||
<Navbar.Brand href="#home" style={{ marginLeft: '20px', fontWeight: 'bold'}}>
|
<Navbar.Brand className={`${theme}`} href="#home" style={{ marginLeft: '20px'}}>
|
||||||
<FaChartLine style={{ marginRight: '10px', color: '#b31e1e' }} />
|
<FaChartLine style={{ marginRight: '10px', color: '#b31e1e' }} />
|
||||||
Speedtest Tracker
|
Speedtest Tracker
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
<Nav>
|
<Nav className="ml-auto" style={{ marginRight: '20px' }}>
|
||||||
<Nav.Item className="d-flex align-items-center" style={{ fontWeight: 'bold' }}>
|
<button onClick={toggleTheme} className="theme-toggle-btn">
|
||||||
Damar
|
{theme === 'light' ? <FaMoon size={20} /> : <FaSun size={20} />}
|
||||||
<img
|
</button>
|
||||||
src="/src/assets/react.svg"
|
|
||||||
alt="Profile"
|
|
||||||
style={{
|
|
||||||
width: '30px',
|
|
||||||
height: '30px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
marginLeft: '10px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Nav.Item>
|
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,13 +2,12 @@ import { Navbar, Nav } from 'react-bootstrap';
|
|||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import { FaTachometerAlt, FaDesktop, FaChartBar, FaCog } from "react-icons/fa";
|
import { FaTachometerAlt, FaDesktop, FaChartBar, FaCog } from "react-icons/fa";
|
||||||
|
|
||||||
const Sidebar = () => {
|
const Sidebar = ({theme}) => {
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='sidebar'>
|
<Navbar expand="lg" className={`sidebar-app flex-column ${theme}`}>
|
||||||
<Navbar expand="lg" className="flex-column">
|
|
||||||
<Nav className="flex-column w-100">
|
<Nav className="flex-column w-100">
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
as={Link}
|
as={Link}
|
||||||
@ -43,7 +42,6 @@ const Sidebar = () => {
|
|||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ const Dashboard = () => {
|
|||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<Container fluid className="text-center mt-5">
|
<Container fluid className="text-center mt-5">
|
||||||
<Spinner animation="border" variant="danger" />
|
<Spinner animation="border" variant="info" />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ const Dashboard = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container fluid className='d-flex' style={{ fontFamily: 'Poppins, sans-serif'}}>
|
<Container fluid className='flex'>
|
||||||
<Col className="p-3 ms-auto">
|
<Col className="p-3 ms-auto">
|
||||||
<h4 className='my-3'>Dashboard</h4>
|
<h4 className='my-3'>Dashboard</h4>
|
||||||
<Row>
|
<Row>
|
||||||
|
|||||||
@ -35,9 +35,8 @@ function DevicesPage() {
|
|||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<Container fluid className="text-center mt-5 text-light">
|
<Container fluid className="text-center mt-5">
|
||||||
<Spinner animation="border" variant="light" />
|
<Spinner animation="border" variant="info"/>
|
||||||
<p>Loading...</p>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const API_URL = import.meta.env.VITE_API_URL;
|
const API_SPEED_URL = import.meta.env.VITE_API_SPEED_URL;
|
||||||
const API_JSON_URL = import.meta.env.VITE_API_JSON_URL;
|
const API_PING_URL = import.meta.env.VITE_API_PING_URL;
|
||||||
const API_METRICS_URL = import.meta.env.VITE_API_METRICS_URL;
|
const API_METRICS_URL = import.meta.env.VITE_API_METRICS_URL;
|
||||||
|
|
||||||
// console.log(import.meta.env.VITE_API_URL)
|
// console.log(import.meta.env.VITE_API_URL)
|
||||||
|
|
||||||
export const fetchSpeedTestData = async () => {
|
export const fetchSpeedTestData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(API_URL, {
|
const response = await axios.get(API_SPEED_URL, {
|
||||||
headers: {
|
headers: {
|
||||||
'Author': 'vedeom',
|
'Author': 'vedeom',
|
||||||
},
|
},
|
||||||
@ -26,7 +26,7 @@ export const fetchSpeedTestData = async () => {
|
|||||||
|
|
||||||
export const fetchActiveDevices = async () => {
|
export const fetchActiveDevices = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(API_JSON_URL);
|
const response = await axios.get(API_PING_URL);
|
||||||
|
|
||||||
// console.log('Devices API Response:', response.data);
|
// console.log('Devices API Response:', response.data);
|
||||||
|
|
||||||
|
|||||||
@ -2,5 +2,9 @@ import { defineConfig } from 'vite'
|
|||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()]
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 5173,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user