Compare commits
19 Commits
d02d7d87da
...
lavoce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9000d5da71 | ||
|
|
bd2dade932 | ||
|
|
da1adce118 | ||
|
|
b64fa47a38 | ||
|
|
4cca3fb95a | ||
|
|
13fcc126a2 | ||
|
|
75db6eb209 | ||
|
|
9c664cd9a3 | ||
|
|
34beee4975 | ||
| 8becbc2a6b | |||
| ea3e748684 | |||
| 517661a237 | |||
| 9c405fa0de | |||
| 9e3ad19591 | |||
| 986026c3af | |||
|
|
b1d8d8bc9a | ||
|
|
df0901a9b3 | ||
|
|
10824d4207 | ||
|
|
a60dcd104b |
@@ -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
|
||||
92
package.json
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
12
src/api/whatsapp-control.jsx
Normal 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 };
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 177 KiB |
@@ -74,27 +74,77 @@ 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();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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>
|
||||
|
||||
85
src/pages/whatsAppControl/IndexWhatsAppControl.jsx
Normal 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;
|
||||
172
src/pages/whatsAppControl/WebControlBackup.jsx
Normal 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;
|
||||