add menu dashboard svg

This commit is contained in:
2025-10-21 13:01:37 +07:00
parent fb3e500139
commit f7f11907dc
15 changed files with 968 additions and 5 deletions

View File

@@ -35,6 +35,13 @@ import IndexUser from './pages/user/IndexUser';
import IndexMember from './pages/shiftManagement/member/IndexMember';
import SvgTest from './pages/home/SvgTest';
import SvgOverview from './pages/home/SvgOverview';
import SvgCompressorA from './pages/home/SvgCompressorA';
import SvgCompressorB from './pages/home/SvgCompressorB';
import SvgCompressorC from './pages/home/SvgCompressorC';
import SvgAirDryerA from './pages/home/SvgAirDryerA';
import SvgAirDryerB from './pages/home/SvgAirDryerB';
import SvgAirDryerC from './pages/home/SvgAirDryerC';
const App = () => {
return (
@@ -52,6 +59,16 @@ const App = () => {
<Route path="blank" element={<Blank />} />
</Route>
<Route path="/dashboard-svg" element={<ProtectedRoute />}>
<Route path="overview" element={<SvgOverview />} />
<Route path="compressor-a" element={<SvgCompressorA />} />
<Route path="compressor-b" element={<SvgCompressorB />} />
<Route path="compressor-c" element={<SvgCompressorC />} />
<Route path="airdryer-a" element={<SvgAirDryerA />} />
<Route path="airdryer-b" element={<SvgAirDryerB />} />
<Route path="airdryer-c" element={<SvgAirDryerC />} />
</Route>
<Route path="/master" element={<ProtectedRoute />}>
<Route path="device" element={<IndexDevice />} />
<Route path="tag" element={<IndexTag />} />

View File

@@ -26,6 +26,9 @@ import {
TeamOutlined,
ClockCircleOutlined,
CalendarOutlined,
DesktopOutlined,
NodeExpandOutlined,
GroupOutlined,
} from '@ant-design/icons';
const { Text } = Typography;
@@ -40,6 +43,48 @@ const allItems = [
</Link>
),
},
{
key: 'dashboard-svg',
icon: <GroupOutlined style={{ fontSize: '19px' }} />,
label: 'Dashboard',
children: [
{
key: 'dashboard-svg-overview',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/overview">Overview</Link>,
},
{
key: 'dashboard-svg-compressor-a',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-a">Compressor A</Link>,
},
{
key: 'dashboard-svg-compressor-b',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-b">Compressor B</Link>,
},
{
key: 'dashboard-svg-compressor-c',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/compressor-c">Compressor C</Link>,
},
{
key: 'dashboard-svg-airdryer-a',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-a">Air Dryer A</Link>,
},
{
key: 'dashboard-svg-airdryer-b',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-b">Air Dryer B</Link>,
},
{
key: 'dashboard-svg-airdryer-c',
icon: <NodeExpandOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/dashboard-svg/airdryer-c">Air Dryer C</Link>,
},
],
},
{
key: 'master',
icon: <DatabaseOutlined style={{ fontSize: '19px' }} />,
@@ -60,16 +105,16 @@ const allItems = [
icon: <MobileOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/device">Device</Link>,
},
{
key: 'master-tag',
icon: <TagOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/tag">Tag</Link>,
},
{
key: 'master-unit',
icon: <AppstoreOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/unit">Unit</Link>,
},
{
key: 'master-tag',
icon: <TagOutlined style={{ fontSize: '19px' }} />,
label: <Link to="/master/tag">Tag</Link>,
},
{
key: 'master-status',
icon: <SafetyOutlined style={{ fontSize: '19px' }} />,
@@ -163,6 +208,7 @@ const LayoutMenu = () => {
if (pathname === '/notification') return 'notification';
if (pathname === '/event-alarm') return 'event-alarm';
if (pathname === '/jadwal-shift') return 'jadwal-shift';
if (pathname === '/dashboard-svg') return 'dashboard-svg';
// Handle master routes
if (pathname.startsWith('/master/')) {
@@ -170,6 +216,12 @@ const LayoutMenu = () => {
return `master-${subPath}`;
}
// Handle master routes
if (pathname.startsWith('/dashboard-svg/')) {
const subPath = pathParts[1];
return `dashboard-svg-${subPath}`;
}
// Handle history routes
if (pathname.startsWith('/history/')) {
const subPath = pathParts[1];
@@ -188,6 +240,7 @@ const LayoutMenu = () => {
// Function to get parent key from menu key
const getParentKey = (key) => {
if (key.startsWith('master-')) return 'master';
if (key.startsWith('dashboard-svg-')) return 'dashboard-svg';
if (key.startsWith('history-')) return 'history';
if (key.startsWith('shift-')) return 'shift-management';
return null;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/air_dryer_A_rev.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgAirDryerA = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgAirDryerA;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/air_dryer_B_rev.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgAirDryerB = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgAirDryerB;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/air_dryer_C_rev.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgAirDryerC = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgAirDryerC;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/test-new.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgCompressorA = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgCompressorA;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/test-new.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgCompressorB = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgCompressorB;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/test-new.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgCompressorC = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgCompressorC;

View File

@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
import { setValSvg } from '../../components/Global/MqttConnection';
import SvgTemplate from './SvgTemplate';
import SvgViewer from './SvgViewer';
const { Text } = Typography;
const filePathSvg = '/svg/test-new.svg';
const topicMqtt = 'PIU_GGCP/Devices/PB';
const SvgOverview = () => {
return (
<SvgTemplate>
<SvgViewer filePathSvg={filePathSvg} topicMqtt={topicMqtt} setValSvg={setValSvg} />
</SvgTemplate>
);
};
export default SvgOverview;

View File

@@ -0,0 +1,19 @@
const SvgTemplate = ({ children }) => {
return (
<div
style={{
height: '80vh', // penuh 1 layar
width: '80vw', // penuh 1 layar lebar
overflow: 'hidden', // hilangkan scroll
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff', // opsional
}}
>
{children}
</div>
);
};
export default SvgTemplate;

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { Card, Typography, Flex } from 'antd';
// import { ReactSVG } from 'react-svg';
import { setValSvg } from '../../components/Global/MqttConnection';
import { ReactSVG } from 'react-svg';
const { Text } = Typography;

View File

@@ -0,0 +1,19 @@
// SvgViewer.jsx
import { ReactSVG } from 'react-svg';
const SvgViewer = ({ filePathSvg, topicMqtt, setValSvg }) => {
return (
<ReactSVG
src={filePathSvg}
beforeInjection={(svg) => {
svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%');
svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
if (setValSvg) setValSvg(topicMqtt, svg);
}}
style={{ width: '100%', height: '100%' }}
/>
);
};
export default SvgViewer;