From a60dcd104befe65d1f2c5ba78c9d00ceffea870e Mon Sep 17 00:00:00 2001 From: zain94rif Date: Tue, 24 Feb 2026 15:41:31 +0700 Subject: [PATCH 01/18] feat: add buttom for Daftar Error Code --- .../brandDevice/component/ListErrorCode.jsx | 132 ++++++++++++------ 1 file changed, 91 insertions(+), 41 deletions(-) diff --git a/src/pages/master/brandDevice/component/ListErrorCode.jsx b/src/pages/master/brandDevice/component/ListErrorCode.jsx index 6fbba65..170b6f6 100644 --- a/src/pages/master/brandDevice/component/ListErrorCode.jsx +++ b/src/pages/master/brandDevice/component/ListErrorCode.jsx @@ -1,6 +1,12 @@ import React, { useState, useEffect, useMemo } from 'react'; import { Card, Input, Button, Row, Col, Empty } from 'antd'; -import { PlusOutlined, SearchOutlined, DeleteOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons'; +import { + PlusOutlined, + SearchOutlined, + DeleteOutlined, + LeftOutlined, + RightOutlined, +} from '@ant-design/icons'; import { getErrorCodesByBrandId, deleteErrorCode } from '../../../../api/master-brand'; import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../../components/Global/ToastNotif'; @@ -16,7 +22,7 @@ const ListErrorCode = ({ onSearch, onSearchClear, isReadOnly = false, - errorCodes: propErrorCodes = null + errorCodes: propErrorCodes = null, }) => { const [errorCodes, setErrorCodes] = useState([]); const [loading, setLoading] = useState(false); @@ -52,12 +58,12 @@ const ListErrorCode = ({ if (response && response.statusCode === 200) { const apiErrorData = response.data || []; const allErrorCodes = [ - ...apiErrorData.map(ec => ({ + ...apiErrorData.map((ec) => ({ ...ec, tempId: `existing_${ec.error_code_id}`, - status: 'existing' + status: 'existing', })), - ...tempErrorCodes.filter(ec => ec.status !== 'deleted') + ...tempErrorCodes.filter((ec) => ec.status !== 'deleted'), ]; setErrorCodes(allErrorCodes); @@ -82,11 +88,9 @@ const ListErrorCode = ({ useEffect(() => { if (isReadOnly && propErrorCodes) { - setErrorCodes(propErrorCodes); setLoading(false); } else { - fetchErrorCodes(); } }, [brandId, queryParams, tempErrorCodes, trigerFilter, isReadOnly, propErrorCodes]); @@ -126,20 +130,19 @@ const ListErrorCode = ({ title: 'Hapus Error Code', message: `Apakah Anda yakin ingin menghapus error code ${item.error_code}?`, onConfirm: () => performDelete(item), - onCancel: () => { }, - confirmButtonText: 'Hapus' + onCancel: () => {}, + confirmButtonText: 'Hapus', }); } }; const performDelete = async (item) => { try { - if (!item.error_code_id || item.error_code_id === 'undefined') { NotifAlert({ icon: 'error', title: 'Error', - message: 'Error code ID tidak valid' + message: 'Error code ID tidak valid', }); return; } @@ -148,7 +151,7 @@ const ListErrorCode = ({ NotifAlert({ icon: 'error', title: 'Error', - message: 'Brand ID tidak valid' + message: 'Brand ID tidak valid', }); return; } @@ -159,30 +162,61 @@ const ListErrorCode = ({ NotifOk({ icon: 'success', title: 'Berhasil', - message: 'Error code berhasil dihapus' + message: 'Error code berhasil dihapus', }); fetchErrorCodes(); } else { NotifAlert({ icon: 'error', title: 'Gagal', - message: 'Gagal menghapus error code' + message: 'Gagal menghapus error code', }); } } catch (error) { NotifAlert({ icon: 'error', title: 'Error', - message: 'Terjadi kesalahan saat menghapus error code' + message: 'Terjadi kesalahan saat menghapus error code', }); } }; + const handleAddNew = () => { + if (onAddNew) { + onAddNew(); + } + }; + return ( + Daftar Error Code + + + } + style={{ width: '100%', minWidth: '300px' }} + bodyStyle={{ padding: '12px' }} > Search @@ -217,19 +251,18 @@ const ListErrorCode = ({ }} /> -
+
{errorCodes.length === 0 ? ( - + ) : (
{errorCodes.map((item) => ( @@ -240,13 +273,25 @@ const ListErrorCode = ({ padding: '8px 12px', borderRadius: '6px', marginBottom: '4px', - border: selectedErrorCode?.tempId === item.tempId ? '2px solid #23A55A' : '1px solid #d9d9d9', - backgroundColor: selectedErrorCode?.tempId === item.tempId ? '#f6ffed' : '#fff', - transition: 'all 0.2s ease' + border: + selectedErrorCode?.tempId === item.tempId + ? '2px solid #23A55A' + : '1px solid #d9d9d9', + backgroundColor: + selectedErrorCode?.tempId === item.tempId + ? '#f6ffed' + : '#fff', + transition: 'all 0.2s ease', }} onClick={() => onErrorCodeSelect(item)} > -
+
{item.error_code} @@ -266,7 +311,7 @@ const ListErrorCode = ({ padding: '2px 6px', height: '24px', fontSize: '11px', - border: '1px solid #ff4d4f' + border: '1px solid #ff4d4f', }} /> )} @@ -292,9 +337,15 @@ const ListErrorCode = ({ onClick={handlePrevious} disabled={pagination.current_page <= 1} size="small" + > + - - {pagination.current_page} / {pagination.total_page} + >
@@ -312,4 +362,4 @@ const ListErrorCode = ({ ); }; -export default ListErrorCode; \ No newline at end of file +export default ListErrorCode; -- 2.49.1 From 10824d4207716985e943b05b01c82efc91ace6fa Mon Sep 17 00:00:00 2001 From: zain94rif Date: Mon, 2 Mar 2026 15:52:44 +0700 Subject: [PATCH 02/18] fix: back to old view, no add buttom --- .../brandDevice/component/ListErrorCode.jsx | 33 +------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/src/pages/master/brandDevice/component/ListErrorCode.jsx b/src/pages/master/brandDevice/component/ListErrorCode.jsx index 170b6f6..207eac7 100644 --- a/src/pages/master/brandDevice/component/ListErrorCode.jsx +++ b/src/pages/master/brandDevice/component/ListErrorCode.jsx @@ -181,40 +181,9 @@ const ListErrorCode = ({ } }; - const handleAddNew = () => { - if (onAddNew) { - onAddNew(); - } - }; - return ( - Daftar Error Code - -
- } + title="Daftar Error Code" style={{ width: '100%', minWidth: '300px' }} bodyStyle={{ padding: '12px' }} > -- 2.49.1 From df0901a9b3422dafd3e8d950ee6d1601cc751aaf Mon Sep 17 00:00:00 2001 From: zain94rif Date: Tue, 3 Mar 2026 12:40:51 +0700 Subject: [PATCH 03/18] fix(svg): change the SVG image compressor B --- src/assets/svg/compressorB_rev.svg | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/assets/svg/compressorB_rev.svg b/src/assets/svg/compressorB_rev.svg index 9b7867d..61b601b 100644 --- a/src/assets/svg/compressorB_rev.svg +++ b/src/assets/svg/compressorB_rev.svg @@ -931,7 +931,7 @@ COMMUNICATION - + @@ -1851,7 +1851,7 @@ START/STOP - + UNLOAD/LOAD @@ -1980,4 +1980,11 @@ #### #### Plant Air Reciever + + + + + + + \ No newline at end of file -- 2.49.1 From b1d8d8bc9aa31a6aa3114bf5832a65418c2df9d4 Mon Sep 17 00:00:00 2001 From: zain94rif Date: Tue, 3 Mar 2026 14:34:27 +0700 Subject: [PATCH 04/18] fix(color): changer color in compressor ABC - start/stop --- src/components/Global/MqttConnection.jsx | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/components/Global/MqttConnection.jsx b/src/components/Global/MqttConnection.jsx index e2be3aa..def0648 100644 --- a/src/components/Global/MqttConnection.jsx +++ b/src/components/Global/MqttConnection.jsx @@ -74,6 +74,21 @@ const listenMessage = (callback) => { }); }; +function StatusColor(el, num) { + switch (num) { + case 1: + el.style.fill = 'orange'; + break; + case 2: + el.style.fill = 'green'; + break; + default: + el.style.fill = 'rgb(216,216,216)'; + } +} + +const colorIds = ['c_1023', 'c_2023', 'c_2023']; + const setValSvg = (listenTopic, svg) => { client.on('message', (topic, message) => { // console.log(topic ,' = ', listenTopic); @@ -89,7 +104,13 @@ const setValSvg = (listenTopic, svg) => { } else if (value === false) { el.style.display = 'none'; } else if (!isNaN(value)) { - el.textContent = Number(value ?? 0.0).toFixed(2); + const num = Number(value); + // el.textContent = Number(value ?? 0.0).toFixed(2); + if (colorIds.includes(el.id)) { + StatusColor(el, num); + } else { + el.textContent = num.toFixed(2); + } } else { el.textContent = value; } -- 2.49.1 From 986026c3af2a64531cc32e91dc6192ed645ec2df Mon Sep 17 00:00:00 2001 From: zain_arif Date: Mon, 16 Mar 2026 11:09:22 +0700 Subject: [PATCH 05/18] feat(menu): add new menu web control --- src/App.jsx | 5 ++ src/layout/LayoutMenu.jsx | 11 +++ src/pages/webControl/IndexWebControl.jsx | 90 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/pages/webControl/IndexWebControl.jsx diff --git a/src/App.jsx b/src/App.jsx index b0fbd5f..1cbda33 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -36,6 +36,7 @@ import IndexNotification from './pages/notification/IndexNotification'; import IndexRole from './pages/role/IndexRole'; import IndexUser from './pages/user/IndexUser'; import IndexContact from './pages/contact/IndexContact'; +import IndexWebControl from './pages/webControl/IndexWebControl'; import DetailNotificationTab from './pages/notificationDetail/IndexNotificationDetail'; import IndexVerificationSparepart from './pages/verificationSparepart/IndexVerificationSparepart'; @@ -144,6 +145,10 @@ const App = () => { } /> + }> + } /> + + }> } /> diff --git a/src/layout/LayoutMenu.jsx b/src/layout/LayoutMenu.jsx index 607bc2f..bfbc70d 100644 --- a/src/layout/LayoutMenu.jsx +++ b/src/layout/LayoutMenu.jsx @@ -7,6 +7,7 @@ import { DatabaseOutlined, SettingOutlined, UserOutlined, + GlobalOutlined, AntDesignOutlined, ShoppingCartOutlined, ShoppingOutlined, @@ -225,6 +226,15 @@ const allItems = [ ), }, + { + key: 'web-control', + icon: , + label: ( + + Web Control + + ), + }, // { // key: 'jadwal-shift', // icon: , @@ -250,6 +260,7 @@ const LayoutMenu = () => { if (pathname === '/dashboard/home') return 'home'; if (pathname === '/user') return 'user'; if (pathname === '/role') return 'role'; + if (pathname === '/web-control') return 'web-control'; if (pathname === '/notification') return 'notification'; if (pathname === '/jadwal-shift') return 'jadwal-shift'; if (pathname === '/contact') return 'contact'; diff --git a/src/pages/webControl/IndexWebControl.jsx b/src/pages/webControl/IndexWebControl.jsx new file mode 100644 index 0000000..93a72fb --- /dev/null +++ b/src/pages/webControl/IndexWebControl.jsx @@ -0,0 +1,90 @@ +import React, { useState, useEffect, memo } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { Button, Typography } from 'antd'; +import { useBreadcrumb } from '../../layout/LayoutBreadcrumb'; + +const { Text } = Typography; + +const IndexWebControl = memo(function IndexWebControl() { + const navigate = useNavigate(); + const { setBreadcrumbItems } = useBreadcrumb(); + + const [isPlaying, setIsPlaying] = useState(false); + + const url = "https://117.102.231.130:9529"; + + const handlePlay = () => { + setIsPlaying(true); + }; + + const handleReset = () => { + setIsPlaying(false); + }; + + useEffect(() => { + const token = localStorage.getItem('token'); + + if (token) { + setBreadcrumbItems([ + { + title: ( + + • Web Control Panel + + ), + }, + ]); + } else { + navigate('/signin'); + } + }, []); + + return ( +
+ +
+ + + +
+ +
+ {isPlaying ? ( +