lavoce #42

Merged
bragaz_rexita merged 18 commits from lavoce into main 2026-04-10 05:35:38 +00:00
15 changed files with 1546 additions and 1188 deletions

View File

@@ -4,3 +4,7 @@ VITE_MQTT_SERVER=ws://localhost:1884
VITE_MQTT_USERNAME=
VITE_MQTT_PASSWORD=
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek
# VITE_WHATSAPP_URL=http://192.168.1.10:9531/qrview
VITE_WHATSAPP_URL=http://localhost:9531/qrview
# VITE_WHATSAPP_URL=https://117.102.231.130:9531/qrview

View File

@@ -1,48 +1,48 @@
{
"name": "antd-vite-react-sypiu",
"homepage": "/dashboard/home",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^6.0.0",
"@nivo/line": "^0.88.0",
"@nivo/pie": "^0.88.0",
"antd": "^5.15.2",
"axios": "^1.8.4",
"browser-image-compression": "^2.0.2",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"jspdf": "^3.0.4",
"jspdf-autotable": "^5.0.2",
"mqtt": "^5.14.0",
"qrcode": "^1.5.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"react-router-dom": "^6.22.3",
"react-svg": "^16.3.0",
"recharts": "^3.6.0",
"sweetalert2": "^11.17.2"
},
"devDependencies": {
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"vite": "^5.1.6"
},
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
"name": "antd-vite-react-call-of-duty",
"homepage": "/dashboard/home",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0 --port 8592",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^6.0.0",
"@nivo/line": "^0.88.0",
"@nivo/pie": "^0.88.0",
"antd": "^5.15.2",
"axios": "^1.8.4",
"browser-image-compression": "^2.0.2",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"jspdf": "^3.0.4",
"jspdf-autotable": "^5.0.2",
"mqtt": "^5.14.0",
"qrcode": "^1.5.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"react-router-dom": "^6.22.3",
"react-svg": "^16.3.0",
"recharts": "^3.6.0",
"sweetalert2": "^11.17.2"
},
"devDependencies": {
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"vite": "^5.1.6"
},
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
}

View File

@@ -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 IndexWhatsAppControl from './pages/whatsAppControl/IndexWhatsAppControl';
import DetailNotificationTab from './pages/notificationDetail/IndexNotificationDetail';
import IndexVerificationSparepart from './pages/verificationSparepart/IndexVerificationSparepart';
@@ -144,6 +145,10 @@ const App = () => {
<Route index element={<IndexUser />} />
</Route>
<Route path="/whatsapp-control" element={<ProtectedRoute />}>
<Route index element={<IndexWhatsAppControl />} />
</Route>
<Route path="/contact" element={<ProtectedRoute />}>
<Route index element={<IndexContact />} />
</Route>

View File

@@ -0,0 +1,12 @@
import { SendRequest } from '../components/Global/ApiRequest';
const resetWA = async () => {
const response = await SendRequest({
method: 'post',
prefix: `notifikasi-wa/restart-wa`,
});
return response.data;
};
export { resetWA };

View File

@@ -186,7 +186,7 @@
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4501">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
@@ -217,14 +217,9 @@
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517" id="c_4021"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT A (01-CL-10532-A)</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4005">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4004">####.##</text>
@@ -237,11 +232,16 @@
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4008">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4007">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4006">##</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_4018"/>
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_4019"/>
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_4016"/>
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_4017"/>
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_4020"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.685" cy="322.259" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.031" cy="234.094" rx="13.582" ry="12.517" id="c_-3"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_4018"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_4018"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_4021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.772" cy="237.876" rx="13.582" ry="12.517" id="c_4021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id=""/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="320.687" rx="13.582" ry="12.517" id="-2"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.259" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="237.483" rx="13.582" ry="12.517" id="c_-3"/>
</svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -186,7 +186,7 @@
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5501">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
@@ -217,13 +217,9 @@
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT B (01-CL-10535-B)</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5005">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5004">####.##</text>
@@ -236,12 +232,16 @@
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5008">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5007">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5006">##</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_5018"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.517" rx="13.582" ry="12.517" id=""/>
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_5019"/>
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_5016"/>
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_5017"/>
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_5020"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517" id="c_5021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.685" cy="322.259" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.031" cy="234.094" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_5018"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_5018"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_5021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" rx="13.582" ry="12.517" id="c_5021"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="320.662" rx="13.582" ry="12.517" id=""/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.125" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="234.26" rx="13.582" ry="12.517" id="c_-3"/>
</svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -186,7 +186,7 @@
<rect x="43.65" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(248, 213, 14);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; font-weight: 700; white-space: pre; stroke-width: 1;" x="54.237" y="536.777" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Alarm Info</text>
<rect x="126.341" y="360.147" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="159.3" y="537.792" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6501">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<rect x="43.443" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="56.987" y="250.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT or LT Dry</text>
@@ -217,13 +217,9 @@
<rect x="870.356" y="344.9" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.702" cy="366.997" rx="20.673" ry="17.46"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="380.451" y="296.591" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="379.214" y="423.395" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="897.237" y="299.014" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">REGEN</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.772" cy="233.876" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="896" y="425.818" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">DRYING</text>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517"/>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 35px; stroke-width: 1; font-weight: bold;" x="348.875" y="78.242" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">AIR DRYER UNIT C (01-CL-10539-C)</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.447" y="617.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6005">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="522.446" y="567.288" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6004">####.##</text>
@@ -236,12 +232,16 @@
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177.05" y="323.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6008">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="168.775" y="365.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6007">####.##</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="92.151" y="325.554" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6006">##</text>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_6018"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.517" rx="13.582" ry="12.517" id=""/>
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(255, 172, 63);" cx="640.283" cy="271.689" rx="9.717" ry="7.689" id="c_6019"/>
<ellipse style="fill: rgb(63, 255, 69); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.254" cy="192.696" rx="20.673" ry="17.46" id="c_6016"/>
<ellipse style="fill: rgb(255, 159, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="279.12" rx="20.673" ry="17.46" id="c_6017"/>
<ellipse style="fill: rgb(255, 63, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="911.352" cy="366.862" rx="20.673" ry="17.46" id="c_6020"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.685" cy="322.259" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.623" cy="320.662" rx="13.582" ry="12.517" id="c_6021"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.031" cy="234.094" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="336.418" cy="237.483" rx="13.582" ry="12.517" id="c_6018"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="762.96" cy="322.354" rx="13.582" ry="12.517" id="c_6018"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.016" rx="13.582" ry="12.517" id="c_6021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="237.483" rx="13.582" ry="12.517" id="c_6021"/>
<ellipse style="fill: rgb(255, 204, 63); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="763.418" cy="322.692" rx="13.582" ry="12.517" id="c_-2"/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="335.418" cy="321.095" rx="13.582" ry="12.517" id=""/>
<ellipse style="fill: rgb(216, 216, 216); stroke: rgb(0, 0, 0); stroke-width: 0.763;" cx="761.418" cy="237.483" rx="13.582" ry="12.517" id="c_-3"/>
</svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 177 KiB

After

Width:  |  Height:  |  Size: 177 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 177 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -74,27 +74,78 @@ const listenMessage = (callback) => {
});
};
const colorIds = ['c_1023', 'c_2023', 'c_2023'];
const StatusColor = (el, num) => {
switch (num) {
case 1:
el.style.fill = 'orange';
break;
case 2:
el.style.fill = 'rgb(7,250,14)';
break;
default:
el.style.fill = 'rgb(216,216,216)';
}
};
const dryerIds = ['c_4018', 'c_4021', 'c_5018', 'c_5021', 'c_6018', 'c_6021'];
const handleBoolean = (svg, el, value) => {
if (!dryerIds.includes(el.id)) {
el.style.display = value ? '' : 'none';
return;
}
const i = dryerIds.indexOf(el.id);
const id1 = dryerIds[i - (i % 2)];
const id2 = dryerIds[i - (i % 2) + 1];
const el1 = svg.getElementById(id1);
const el2 = svg.getElementById(id2);
if (!el1 || !el2) return;
el1.style.fill = value ? 'rgb(216,216,216)' : 'yellow';
el2.style.fill = value ? 'yellow' : 'rgb(216,216,216)';
};
const handleNumber = (el, value) => {
const num = Number(value);
if (colorIds.includes(el.id)) {
StatusColor(el, num);
} else {
el.textContent = num.toFixed(2);
}
};
const handleOther = (el, value) => {
el.textContent = value;
};
const setValSvg = (listenTopic, svg) => {
client.on('message', (topic, message) => {
// console.log(topic ,' = ', listenTopic);
if (topic === listenTopic) {
const objChanel = JSON.parse(message);
Object.entries(objChanel).forEach(([key, value]) => {
// console.log(key, value);
const el = svg.getElementById(key);
if (el) {
if (value === true) {
el.style.display = ''; // sembunyikan
} else if (value === false) {
el.style.display = 'none';
} else if (!isNaN(value)) {
el.textContent = Number(value ?? 0.0).toFixed(2);
} else {
el.textContent = value;
}
if (!el) return;
// else if (el.id === 'c_2014' || el.id === 'c_2024') {
// el.setAttribute('text-anchor', 'middle');
// el.setAttribute('x', '10%');
// }
if (typeof value === 'boolean') {
handleBoolean(svg, el, value);
} else if (!isNaN(value)) {
handleNumber(el, value);
} else {
handleOther(el, value);
}
});
const target = svg.querySelector('text[x="225.25"][y="537.752"]');
if (target) target.remove();
}
});
};

View File

@@ -7,6 +7,7 @@ import {
DatabaseOutlined,
SettingOutlined,
UserOutlined,
GlobalOutlined,
AntDesignOutlined,
ShoppingCartOutlined,
ShoppingOutlined,
@@ -36,6 +37,14 @@ import {
} from '@ant-design/icons';
const { Text } = Typography;
const host = window.location.hostname;
const isLocal =
host === '127.0.0.1' ||
host === 'localhost' ||
host.startsWith('192.168.') ||
host.startsWith('10.') ||
host.startsWith('172.');
const allItems = [
{
@@ -225,6 +234,19 @@ const allItems = [
</Link>
),
},
...(isLocal
? [
{
key: 'whatsapp-control',
icon: <GlobalOutlined style={{ fontSize: '19px' }} />,
label: (
<Link to="/whatsapp-control" className="fontMenus">
WhatsApp Control
</Link>
),
},
]
: []),
// {
// key: 'jadwal-shift',
// icon: <CalendarOutlined style={{ fontSize: '19px' }} />,
@@ -250,6 +272,7 @@ const LayoutMenu = () => {
if (pathname === '/dashboard/home') return 'home';
if (pathname === '/user') return 'user';
if (pathname === '/role') return 'role';
if (pathname === '/whatsapp-control') return 'whatsapp-control';
if (pathname === '/notification') return 'notification';
if (pathname === '/jadwal-shift') return 'jadwal-shift';
if (pathname === '/contact') return 'contact';

View File

@@ -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,21 +162,21 @@ 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',
});
}
};
@@ -181,8 +184,8 @@ const ListErrorCode = ({
return (
<Card
title="Daftar Error Code"
style={{ width: '100%', minWidth: '472px' }}
styles={{ body: { padding: '12px' } }}
style={{ width: '100%', minWidth: '300px' }}
bodyStyle={{ padding: '12px' }}
>
<Input.Search
placeholder="Cari error code..."
@@ -203,7 +206,7 @@ const ListErrorCode = ({
style={{
backgroundColor: '#23A55A',
borderColor: '#23A55A',
height: '32px'
height: '32px',
}}
>
Search
@@ -217,19 +220,18 @@ const ListErrorCode = ({
}}
/>
<div style={{
height: '90vh',
border: '1px solid #d9d9d9',
borderRadius: '6px',
overflow: 'auto',
marginBottom: 12,
backgroundColor: '#fafafa'
}}>
<div
style={{
height: '90vh',
border: '1px solid #d9d9d9',
borderRadius: '6px',
overflow: 'auto',
marginBottom: 12,
backgroundColor: '#fafafa',
}}
>
{errorCodes.length === 0 ? (
<Empty
description="Belum ada error code"
style={{ marginTop: 50 }}
/>
<Empty description="Belum ada error code" style={{ marginTop: 50 }} />
) : (
<div style={{ padding: '8px' }}>
{errorCodes.map((item) => (
@@ -240,13 +242,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)}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div style={{ flex: 1 }}>
<div style={{ fontWeight: 'bold', fontSize: '12px' }}>
{item.error_code}
@@ -266,7 +280,7 @@ const ListErrorCode = ({
padding: '2px 6px',
height: '24px',
fontSize: '11px',
border: '1px solid #ff4d4f'
border: '1px solid #ff4d4f',
}}
/>
)}
@@ -292,9 +306,15 @@ const ListErrorCode = ({
onClick={handlePrevious}
disabled={pagination.current_page <= 1}
size="small"
></Button>
<span
style={{
fontSize: '12px',
color: '#666',
minWidth: '60px',
textAlign: 'center',
}}
>
</Button>
<span style={{ fontSize: '12px', color: '#666', minWidth: '60px', textAlign: 'center' }}>
{pagination.current_page} / {pagination.total_page}
</span>
<Button
@@ -302,8 +322,7 @@ const ListErrorCode = ({
onClick={handleNext}
disabled={pagination.current_page >= pagination.total_page}
size="small"
>
</Button>
></Button>
</div>
</Col>
</Row>

View File

@@ -0,0 +1,85 @@
import React, { useState, useEffect, memo } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button, Typography } from 'antd';
import { resetWA } from '../../api/whatsapp-control';
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
import { ReloadOutlined } from '@ant-design/icons';
const { Text } = Typography;
const IndexWhatsAppControl = memo(function IndexWhatsAppControl() {
const navigate = useNavigate();
const { setBreadcrumbItems } = useBreadcrumb();
const [isPlaying, setIsPlaying] = useState(true);
const url = import.meta.env.VITE_WHATSAPP_URL;
const handleReset = async () => {
setIsPlaying(false);
await resetWA();
setIsPlaying(true);
};
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
setBreadcrumbItems([
{
title: (
<Text strong style={{ fontSize: '14px' }}>
WhatsApp Control Panel
</Text>
),
},
]);
} else {
navigate('/signin');
}
}, []);
return (
<div style={{ padding: '20px' }}>
<div style={{ marginBottom: 20 }}>
<Button type="primary" onClick={handleReset} style={{ marginRight: 10 }}>
<ReloadOutlined /> Restart WhatsApp
</Button>
</div>
<div
style={{
border: '1px solid #ddd',
height: '700px',
background: '#fafafa',
}}
>
{isPlaying ? (
<iframe
src={url}
title="WhatsApp Preview"
style={{
width: '100%',
height: '100%',
border: 'none',
}}
/>
) : (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: '#888',
}}
>
Memuat Halaman WhatsApp QR Code
</div>
)}
</div>
</div>
);
});
export default IndexWhatsAppControl;

View File

@@ -0,0 +1,172 @@
import React, { useState, useEffect, useRef, memo } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button, Typography, message } from 'antd';
import { resetWA } from '../../api/web-control';
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
import { ReloadOutlined } from '@ant-design/icons';
const { Text } = Typography;
const IndexWebControl = memo(function IndexWebControl() {
const navigate = useNavigate();
const { setBreadcrumbItems } = useBreadcrumb();
const [isPlaying, setIsPlaying] = useState(true);
const [currentUrl, setCurrentUrl] = useState('http://localhost:9531');
const iframeRef = useRef(null);
const handleReset = async () => {
setIsPlaying(false);
await resetWA();
setIsPlaying(true);
// Kembali ke halaman login setelah reset
setCurrentUrl('https://localhost:9531');
message.success('WhatsApp berhasil di-restart');
};
// Fungsi untuk redirect ke QR View
const redirectToQRView = () => {
setCurrentUrl('https://localhost:9531/qrview');
message.info('Redirecting to QR View...');
};
// Fungsi untuk kembali ke login
const backToLogin = () => {
setCurrentUrl('https://localhost:9531');
message.info('Back to login page');
};
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
setBreadcrumbItems([
{
title: (
<Text strong style={{ fontSize: '14px' }}>
Web Control Panel
</Text>
),
},
]);
} else {
navigate('/signin');
}
}, [navigate, setBreadcrumbItems]);
// Mendengarkan pesan dari iframe
useEffect(() => {
const handleMessage = (event) => {
// Terima pesan dari domain manapun untuk testing
console.log('Message received from:', event.origin);
console.log('Message data:', event.data);
// Cek apakah ini pesan login success
if (event.data) {
// Jika pesan adalah string
if (typeof event.data === 'string') {
const lowerData = event.data.toLowerCase();
if (
lowerData.includes('login') ||
lowerData.includes('success') ||
lowerData.includes('authenticated') ||
lowerData.includes('qrview')
) {
console.log('Login detected via string message');
redirectToQRView();
}
}
// Jika pesan adalah object
if (typeof event.data === 'object') {
if (
event.data.type === 'LOGIN_SUCCESS' ||
event.data.status === 'success' ||
event.data.logged_in === true ||
event.data.redirect === true
) {
console.log('Login detected via object message');
redirectToQRView();
}
}
}
};
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
};
}, []);
// Alternative: Coba dengan timer (jika postMessage tidak berfungsi)
useEffect(() => {
// Jika tidak ada pesan dari iframe, coba redirect otomatis setelah 10 detik
// Asumsi: login biasanya selesai dalam 10 detik
const timer = setTimeout(() => {
if (currentUrl === 'https://localhost:9531') {
console.log('Auto redirect after 10 seconds (fallback)');
redirectToQRView();
}
}, 10000);
return () => clearTimeout(timer);
}, [currentUrl]);
return (
<div style={{ padding: '20px' }}>
<div style={{ marginBottom: 20, display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
<Button type="primary" onClick={handleReset}>
<ReloadOutlined /> Restart WhatsApp
</Button>
{/* <Button onClick={redirectToQRView} type="default">
Redirect ke QR View
</Button>
<Button onClick={backToLogin} type="default">
Kembali ke Login
</Button> */}
</div>
<div
style={{
border: '1px solid #ddd',
height: '700px',
background: '#fafafa',
position: 'relative',
}}
>
{isPlaying ? (
<iframe
key={currentUrl} // Force re-render saat URL berubah
ref={iframeRef}
src={currentUrl}
title="Web Preview"
style={{
width: '100%',
height: '100%',
border: 'none',
}}
onLoad={() => {
console.log('Iframe loaded with URL:', currentUrl);
// Hanya log, tidak mencoba mengakses URL untuk menghindari error CORS
}}
onError={(e) => console.error('Iframe error:', e)}
/>
) : (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: '#888',
}}
>
Memuat Halaman WhatsApp QR Code
</div>
)}
</div>
</div>
);
});
export default IndexWebControl;