14/02/2025

This commit is contained in:
damarrsyh 2025-02-14 16:45:12 +07:00
parent 1e135f763f
commit 760aec0638
18 changed files with 152 additions and 116 deletions

View File

@ -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",

View File

@ -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;
} }

View File

@ -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;

View File

@ -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],

View File

@ -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: {

View File

@ -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: {

View File

@ -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>

View File

@ -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

View File

@ -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' }} />

View File

@ -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

View File

@ -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' :

View File

@ -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' }}>

View File

@ -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>
); );

View File

@ -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>
); );
} }

View File

@ -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>

View File

@ -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>
); );
} }

View File

@ -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);

View File

@ -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,
}
}); });