Compare commits

..

38 Commits

Author SHA1 Message Date
e74b802a60 Merge pull request 'lavoce' (#33) from lavoce into main
Reviewed-on: #33
2026-01-06 11:30:27 +00:00
f436865b7f Merge pull request 'lavoce' (#32) from lavoce into main
Reviewed-on: #32
2026-01-05 03:41:39 +00:00
48437c3c50 Merge pull request 'lavoce' (#30) from lavoce into main
Reviewed-on: #30
2025-12-31 03:20:51 +00:00
a33c9b3b92 Merge pull request 'lavoce' (#29) from lavoce into main
Reviewed-on: #29
2025-12-23 05:22:06 +00:00
58d1f5c7ab Merge pull request 'Repair and replace svg' (#28) from lavoce into main
Reviewed-on: #28
2025-12-22 09:38:05 +00:00
c10a5bf62d Merge pull request 'lavoce' (#27) from lavoce into main
Reviewed-on: #27
2025-12-22 09:28:34 +00:00
6cc5042956 Merge pull request 'repair' (#26) from lavoce into main
Reviewed-on: #26
2025-11-28 07:17:06 +00:00
5079f8d316 Merge pull request 'lavoce' (#25) from lavoce into main
Reviewed-on: #25
2025-11-28 07:12:41 +00:00
7073390de7 Merge pull request 'lavoce' (#24) from lavoce into main
Reviewed-on: #24
2025-11-28 05:50:36 +00:00
4226a24e79 Merge pull request 'lavoce' (#23) from lavoce into main
Reviewed-on: #23
2025-11-28 05:10:26 +00:00
038009433f Merge pull request 'lavoce' (#22) from lavoce into main
Reviewed-on: #22
2025-11-25 03:50:54 +00:00
64ba51b17c Merge pull request 'lavoce' (#21) from lavoce into main
Reviewed-on: #21
2025-11-20 03:44:05 +00:00
47d0638a42 Merge pull request 'lavoce' (#20) from lavoce into main
Reviewed-on: #20
2025-11-19 01:05:19 +00:00
d8c5f3ed44 Merge pull request 'lavoce' (#19) from lavoce into main
Reviewed-on: #19
2025-11-18 00:26:36 +00:00
affd9146bb Merge pull request 'lavoce' (#18) from lavoce into main
Reviewed-on: #18
2025-11-17 08:27:39 +00:00
4022b3f8f4 Merge pull request 'lavoce' (#17) from lavoce into main
Reviewed-on: #17
2025-11-10 07:57:17 +00:00
446a4e2b95 Merge pull request 'lavoce' (#16) from lavoce into main
Reviewed-on: #16
2025-11-10 06:33:35 +00:00
83a475c708 Merge pull request 'Repair beautiful apps' (#15) from lavoce into main
Reviewed-on: #15
2025-11-04 10:01:47 +00:00
ab1c510a77 Merge pull request 'Repair bg-signin' (#14) from lavoce into main
Reviewed-on: #14
2025-11-04 08:48:59 +00:00
59859c6d18 Update public/web.config 2025-11-04 07:03:57 +00:00
2bd27937dc Update public/web.config 2025-11-04 07:02:55 +00:00
1058c660d6 Update public/web.config 2025-11-04 07:01:10 +00:00
35b2167791 Update public/web.config 2025-11-04 06:53:05 +00:00
ec676983d0 Update .gitignore 2025-11-04 06:51:39 +00:00
c07c5f8235 Update .gitignore 2025-11-04 06:47:31 +00:00
b32ad97034 Merge pull request 'Add side bar menus mobile mode' (#13) from lavoce into main
Reviewed-on: #13
2025-11-04 06:42:09 +00:00
76244f6f6e Merge pull request 'lavoce' (#12) from lavoce into main
Reviewed-on: #12
2025-11-04 06:23:15 +00:00
0a128cbb3c Merge pull request 'lavoce' (#11) from lavoce into main
Reviewed-on: #11
2025-10-28 09:47:36 +00:00
bd4ab26680 Merge pull request 'lavoce' (#10) from lavoce into main
Reviewed-on: #10
2025-10-28 04:48:54 +00:00
3e728a1ff5 Merge pull request 'lavoce' (#9) from lavoce into main
Reviewed-on: #9
2025-10-27 03:48:58 +00:00
9db143972e Merge pull request 'lavoce' (#8) from lavoce into main
Reviewed-on: #8
2025-10-25 09:19:36 +00:00
029ea269a7 Merge pull request 'lavoce' (#7) from lavoce into main
Reviewed-on: #7
2025-10-24 05:43:32 +00:00
4cdaa042da Merge pull request 'lavoce' (#6) from lavoce into main
Reviewed-on: #6
2025-10-23 07:28:11 +00:00
56af2a16c0 Merge pull request 'update file svg to src assets' (#5) from lavoce into main
Reviewed-on: #5
2025-10-23 04:52:13 +00:00
deadf2ffb4 Merge pull request 'lavoce' (#4) from lavoce into main
Reviewed-on: #4
2025-10-23 04:27:57 +00:00
4da80c7089 Merge pull request 'lavoce' (#3) from lavoce into main
Reviewed-on: #3
2025-10-22 05:59:57 +00:00
56e3ce78a6 Merge pull request 'lavoce' (#2) from lavoce into main
Reviewed-on: #2
2025-10-20 04:06:02 +00:00
7c2a019dd2 Merge pull request 'lavoce' (#1) from lavoce into main
Reviewed-on: #1
2025-09-17 08:39:35 +00:00
23 changed files with 1929 additions and 2373 deletions

View File

@@ -4,7 +4,3 @@ VITE_MQTT_SERVER=ws://localhost:1884
VITE_MQTT_USERNAME= VITE_MQTT_USERNAME=
VITE_MQTT_PASSWORD= VITE_MQTT_PASSWORD=
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek 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

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
*.config
node_modules node_modules
dist dist

View File

@@ -1,11 +1,11 @@
{ {
"name": "antd-vite-react-call-of-duty", "name": "antd-vite-react-sypiu",
"homepage": "/dashboard/home", "homepage": "/dashboard/home",
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host 0.0.0.0 --port 8592", "dev": "vite",
"build": "vite build", "build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview" "preview": "vite preview"

View File

@@ -3,7 +3,7 @@
<system.webServer> <system.webServer>
<rewrite> <rewrite>
<rules> <rules>
<rule name="reactViteSypiu"> <rule name="CallOfDuty">
<match url=".*" /> <match url=".*" />
<conditions logicalGrouping="MatchAll"> <conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />

View File

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

View File

@@ -82,15 +82,6 @@ const resendChatAllUser = async (notificationId) => {
return response.data; return response.data;
}; };
// Searching
const searchData = async (queryParams) => {
const response = await SendRequest({
method: 'get',
prefix: `notification?criteria=${queryParams}`,
});
return response.data;
};
export { export {
getAllNotification, getAllNotification,
getNotificationById, getNotificationById,
@@ -101,5 +92,4 @@ export {
resendNotificationToUser, resendNotificationToUser,
resendChatByUser, resendChatByUser,
resendChatAllUser, resendChatAllUser,
searchData,
}; };

View File

@@ -1,12 +0,0 @@
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

@@ -37,14 +37,17 @@
<rect x="461.861" y="211.956" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="461.861" y="211.956" width="62.018" height="9.968" 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: Arial, sans-serif; font-size: 9px;" x="561" y="309.954" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp SP</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px;" x="561" y="309.954" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp SP</text>
<rect x="461.861" y="221.924" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="461.861" y="221.924" width="62.018" height="17.46" 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: 12px; stroke-width: 1;" x="609.476" y="330.521" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="609.476" y="330.521" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
<rect x="461.424" y="242.149" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="461.424" y="242.149" width="62.018" height="9.968" 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: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="567.471" y="352.188" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="567.471" y="352.188" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
<rect x="461.424" y="252.117" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="461.424" y="252.117" width="62.018" height="17.46" 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: 12px; stroke-width: 1;" x="608.947" y="373.755" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="608.947" y="373.755" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
<rect x="535.456" y="242.272" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="535.456" y="242.272" width="62.018" height="9.968" 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: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="659" y="352.363" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="659" y="352.363" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Heater Temp</text>
<rect x="535.456" y="252.24" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="535.456" y="252.24" width="62.018" height="17.46" 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: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="698.476" y="373.93" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1; font-weight: bold;" x="748" y="347.676" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1; font-weight: bold;" x="748" y="347.676" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER</text>
<path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 678.512px 258.693px;" d="M 678.467 229.321 L 678.558 288.066" transform="matrix(0, 1.184039, -0.844567, 0, -0.000022, -0.000005)"/> <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 1.525; transform-origin: 678.512px 258.693px;" d="M 678.467 229.321 L 678.558 288.066" transform="matrix(0, 1.184039, -0.844567, 0, -0.000022, -0.000005)"/>
@@ -107,10 +110,12 @@
<rect x="427.269" y="377.282" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="427.269" y="377.282" width="62.018" height="9.968" 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: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.167" y="545.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.167" y="545.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
<rect x="427.269" y="387.25" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="427.269" y="387.25" width="62.018" height="17.46" 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: 12px; stroke-width: 1;" x="567.643" y="567.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.643" y="567.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°C</text>
<rect x="427.27" y="412.201" width="62.018" height="9.968" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="427.27" y="412.201" width="62.018" height="9.968" 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: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.168" y="595.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1;" x="532.168" y="595.681" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dew Temp</text>
<rect x="427.27" y="422.169" width="62.018" height="17.46" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="427.27" y="422.169" width="62.018" height="17.46" 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: 12px; stroke-width: 1;" x="567.644" y="617.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="567.644" y="617.248" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">°F</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1; text-anchor: middle; font-weight: bolder;" x="602.463" y="573.003" transform="matrix(0.826913, 0, 0, 0.698383, 24.207672, -7.192523)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>OUTLET</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 9px; stroke-width: 1; text-anchor: middle; font-weight: bolder;" x="602.463" y="573.003" transform="matrix(0.826913, 0, 0, 0.698383, 24.207672, -7.192523)">AIR<tspan x="602.4630126953125" dy="1em"></tspan>OUTLET</text>
<g transform="matrix(-0.387768, 0, 0, -0.200385, 743.634644, -199.991287)" style="transform-origin: 72.2405px 412.5px;"> <g transform="matrix(-0.387768, 0, 0, -0.200385, 743.634644, -199.991287)" style="transform-origin: 72.2405px 412.5px;">
@@ -174,36 +179,43 @@
<rect x="43.443" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="280.75" 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="53.987" y="423.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RUN HOUR</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="53.987" y="423.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RUN HOUR</text>
<rect x="126.135" y="280.75" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="280.75" 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="225" y="424.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="424.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<rect x="43.443" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="308.191" 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: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="461.382" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">PURGE HOUR</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="461.382" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">PURGE HOUR</text>
<rect x="126.135" y="308.191" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="308.191" 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="225" y="463.357" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="463.357" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<rect x="43.443" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; font-weight: 700; white-space: pre;" x="53.987" y="498.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER HOUR</text> <text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 12px; font-weight: 700; white-space: pre;" x="53.987" y="498.091" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HEATER HOUR</text>
<rect x="126.135" y="333.129" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="333.129" 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="225" y="499.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="225" y="499.066" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</text>
<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);"/> <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> <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);"/> <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)" 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="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="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</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;"/> <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> <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>
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="160.275" 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="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_4022">#######</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="187.715" 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: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="187.715" 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="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -0.902357, 3.138935)" id="c_4015">#####</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text> <text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
<rect x="43.443" y="241.422" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="241.422" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/>
<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="364.271" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Cycle Timer</text> <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="364.271" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Cycle Timer</text>
<rect x="126.341" y="241.068" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.341" y="241.068" 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="225.25" y="365.246" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</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="365.246" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="141.894" y="324.069" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Time</text> <text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="141.894" y="324.069" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Time</text>
<rect x="870.356" y="142.816" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="870.356" y="142.816" 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="1060.06" y="224.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dryer Status</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 14px; stroke-width: 1; font-weight: bold;" x="1060.06" y="224.103" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Dryer Status</text>
<rect x="870.356" y="170.304" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="870.356" y="170.304" width="82.691" height="42.35" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
@@ -217,10 +229,17 @@
<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);"/> <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"/> <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> <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> <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> <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> <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: 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -1.613663, 3.937793)">BLWR</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.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> <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>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4001">####.##</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_4001">####.##</text>
@@ -232,16 +251,11 @@
<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="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="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> <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="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(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, 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, 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(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(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_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(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_4021"/>
<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> </svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -186,16 +186,17 @@
<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);"/> <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> <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);"/> <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)" 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="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="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</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;"/> <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> <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>
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="160.275" 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="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_5022">#######</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="187.715" 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: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="187.715" 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="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 0.097643, 3.138935)" id="c_5015">#####</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text> <text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
@@ -217,10 +218,16 @@
<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);"/> <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"/> <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> <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> <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> <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> <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: 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -1.613663, 3.937793)">BLWR</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.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> <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>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5001">####.##</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_5001">####.##</text>
@@ -232,16 +239,12 @@
<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="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="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> <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.517" rx="13.582" ry="12.517" id=""/> <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="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="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(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, 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(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="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="335.623" cy="320.662" 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="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="762.685" cy="322.259" 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(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_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> </svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -186,16 +186,17 @@
<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);"/> <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> <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);"/> <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)" 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="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="225.25" y="537.752" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">H</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;"/> <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> <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>
<rect x="126.135" y="160.275" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="160.275" 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="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, -3.902357, 3.138935)" id="c_6022">#######</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="180.05" y="251.6" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">LT Dry</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="177" y="251.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">RT Dry</text>
<rect x="43.443" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); fill: rgb(120, 231, 228); stroke-width: 0.763;"/> <rect x="43.443" y="187.715" 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: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; stroke-width: 1; font-weight: bold;" x="53.987" y="288.876" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Opmode</text>
<rect x="126.135" y="187.715" width="82.691" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="126.135" y="187.715" 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="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -1.902357, 3.138935)" id="c_6015">#####</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">HTD</text>
<rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/> <rect x="43.443" y="214.051" width="165.383" height="27.103" style="stroke: rgb(0, 0, 0); stroke-width: 0.763; fill: rgb(244, 248, 248);"/>
<text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text> <text style="fill: rgb(51, 51, 51); font-family: Bahnschrift; font-size: 13px; font-weight: 700; white-space: pre; stroke-width: 1;" x="53.987" y="322.585" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">Step</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="233" y="323.56" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)">s</text>
@@ -217,10 +218,17 @@
<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);"/> <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"/> <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> <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> <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> <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> <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: 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: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, 1.386371, 4.000207)">HTLS</text>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 15px; stroke-width: 1;" x="183.349" y="288.807" transform="matrix(0.826913, 0, 0, 0.698383, -1.613663, 3.937793)">BLWR</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.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> <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>
<text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6001">####.##</text> <text style="white-space: pre; fill: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 12px; stroke-width: 1;" x="653.279" y="373.97" transform="matrix(0.826913, 0, 0, 0.698383, 2.097643, 3.138935)" id="c_6001">####.##</text>
@@ -232,16 +240,12 @@
<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="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="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> <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.517" rx="13.582" ry="12.517" id=""/> <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="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="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(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, 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, 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(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(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_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(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(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(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_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> </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: 177 KiB

After

Width:  |  Height:  |  Size: 177 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 177 KiB

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -10,8 +10,7 @@ const topics = [
'PIU_COD/COMPRESSOR/OVERVIEW', 'PIU_COD/COMPRESSOR/OVERVIEW',
'PIU_COD/COMPRESSOR/COMPRESSOR_A', 'PIU_COD/COMPRESSOR/COMPRESSOR_A',
'PIU_COD/COMPRESSOR/COMPRESSOR_B', 'PIU_COD/COMPRESSOR/COMPRESSOR_B',
'PIU_COD/COMPRESSOR/COMPRESSOR_C', 'PIU_COD/COMPRESSOR/COMPRESSOR_C'
'PIU_COD/ERROR_CODE/SIM',
]; ];
const options = { const options = {
keepalive: 30, keepalive: 30,
@@ -74,97 +73,29 @@ 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) => { const setValSvg = (listenTopic, svg) => {
client.on('message', (topic, message) => { client.on('message', (topic, message) => {
// console.log(topic ,' = ', listenTopic);
if (topic === listenTopic) { if (topic === listenTopic) {
const objChanel = JSON.parse(message); const objChanel = JSON.parse(message);
Object.entries(objChanel).forEach(([key, value]) => { Object.entries(objChanel).forEach(([key, value]) => {
// console.log(key, value);
const el = svg.getElementById(key); const el = svg.getElementById(key);
if (el) {
if (!el) return; if (value === true) {
// else if (el.id === 'c_2014' || el.id === 'c_2024') { el.style.display = ''; // sembunyikan
// el.setAttribute('text-anchor', 'middle'); } else if (value === false) {
// el.setAttribute('x', '10%'); el.style.display = 'none';
// }
if (typeof value === 'boolean') {
handleBoolean(svg, el, value);
} else if (!isNaN(value)) { } else if (!isNaN(value)) {
handleNumber(el, value); el.textContent = Number(value ?? 0.0).toFixed(2);
} else { } else {
handleOther(el, value); el.textContent = value;
}
} }
}); });
const target = svg.querySelector('text[x="225.25"][y="537.752"]');
if (target) target.remove();
} }
}); });
}; };
// === NOTIFICATION LISTENER === export { publishMessage, listenMessage, setValSvg };
const notifListeners = [];
const onNotifUpdate = (callback) => {
notifListeners.push(callback);
};
client.on('message', (topic, message) => {
if (topic === import.meta.env.VITE_MQTT_TOPIC_COD) {
try {
const payload = JSON.parse(message.toString());
notifListeners.forEach((cb) => cb(payload));
} catch (err) {
console.error('Invalid notif payload', err);
}
}
});
export { publishMessage, listenMessage, setValSvg, onNotifUpdate };

View File

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

View File

@@ -26,7 +26,7 @@ export default function RedirectWa() {
console.log('tes', response); console.log('tes', response);
const tokenResult = JSON.stringify(response.data?.data?.accessToken); const tokenResult = JSON.stringify(response.data?.accessToken);
sessionStorage.setItem('token_redirect', tokenResult); sessionStorage.setItem('token_redirect', tokenResult);
response.data.auth = true; response.data.auth = true;

View File

@@ -13,18 +13,13 @@ import {
Space, Space,
ConfigProvider, ConfigProvider,
} from 'antd'; } from 'antd';
import { EditOutlined, DeleteOutlined } from '@ant-design/icons'; import {
EditOutlined,
DeleteOutlined
} from '@ant-design/icons';
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif'; import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb'; import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
import { import { getBrandById, createBrand, createErrorCode, getErrorCodesByBrandId, updateErrorCode, deleteErrorCode, deleteBrand } from '../../../api/master-brand';
getBrandById,
createBrand,
createErrorCode,
getErrorCodesByBrandId,
updateErrorCode,
deleteErrorCode,
deleteBrand,
} from '../../../api/master-brand';
import BrandForm from './component/BrandForm'; import BrandForm from './component/BrandForm';
import ErrorCodeForm from './component/ErrorCodeForm'; import ErrorCodeForm from './component/ErrorCodeForm';
import SolutionForm from './component/SolutionForm'; import SolutionForm from './component/SolutionForm';
@@ -47,9 +42,7 @@ const AddBrandDevice = () => {
const [selectedSparepartIds, setSelectedSparepartIds] = useState([]); const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const tab = searchParams.get('tab'); const tab = searchParams.get('tab');
const [currentStep, setCurrentStep] = useState( const [currentStep, setCurrentStep] = useState(tab === 'error-codes' ? 1 : (location.state?.phase || 0));
tab === 'error-codes' ? 1 : location.state?.phase || 0
);
const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null); const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null);
const [isErrorCodeFormReadOnly, setIsErrorCodeFormReadOnly] = useState(false); const [isErrorCodeFormReadOnly, setIsErrorCodeFormReadOnly] = useState(false);
const [searchText, setSearchText] = useState(''); const [searchText, setSearchText] = useState('');
@@ -75,7 +68,7 @@ const AddBrandDevice = () => {
const values = solutionForm.getFieldsValue(true); const values = solutionForm.getFieldsValue(true);
const solutions = []; const solutions = [];
solutionFields.forEach((fieldKey) => { solutionFields.forEach(fieldKey => {
let solution = null; let solution = null;
if (values.solution_items && values.solution_items[fieldKey]) { if (values.solution_items && values.solution_items[fieldKey]) {
@@ -92,16 +85,9 @@ const AddBrandDevice = () => {
if (solutionType === 'text') { if (solutionType === 'text') {
isValid = solution.text && solution.text.trim() !== ''; isValid = solution.text && solution.text.trim() !== '';
} else if (solutionType === 'file') { } else if (solutionType === 'file') {
const hasPathSolution = const hasPathSolution = solution.path_solution && solution.path_solution.trim() !== '';
solution.path_solution && solution.path_solution.trim() !== ''; const hasFileUpload = (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0);
const hasFileUpload = const hasFile = (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0);
solution.fileUpload &&
typeof solution.fileUpload === 'object' &&
Object.keys(solution.fileUpload).length > 0;
const hasFile =
solution.file &&
typeof solution.file === 'object' &&
Object.keys(solution.file).length > 0;
isValid = hasPathSolution || hasFileUpload || hasFile; isValid = hasPathSolution || hasFileUpload || hasFile;
} }
@@ -132,9 +118,9 @@ const AddBrandDevice = () => {
text: '', text: '',
status: true, status: true,
file: null, file: null,
fileUpload: null, fileUpload: null
}, }
}, }
}); });
}, 100); }, 100);
} }
@@ -142,6 +128,7 @@ const AddBrandDevice = () => {
}; };
const setSolutionsForExistingRecord = (solutions, targetForm) => { const setSolutionsForExistingRecord = (solutions, targetForm) => {
if (!targetForm || !solutions || solutions.length === 0) { if (!targetForm || !solutions || solutions.length === 0) {
return; return;
} }
@@ -166,14 +153,11 @@ const AddBrandDevice = () => {
fileObject = { fileObject = {
uploadPath: solution.path_solution || solution.path_document, uploadPath: solution.path_solution || solution.path_document,
path_solution: solution.path_solution || solution.path_document, path_solution: solution.path_solution || solution.path_document,
name: name: solution.file_upload_name || (solution.path_solution || solution.path_document).split('/').pop() || 'File',
solution.file_upload_name ||
(solution.path_solution || solution.path_document).split('/').pop() ||
'File',
type_solution: solution.type_solution, type_solution: solution.type_solution,
isExisting: true, isExisting: true,
size: 0, size: 0,
url: solution.path_solution || solution.path_document, url: solution.path_solution || solution.path_document
}; };
} }
@@ -186,7 +170,7 @@ const AddBrandDevice = () => {
file: fileObject, file: fileObject,
fileUpload: fileObject, fileUpload: fileObject,
path_solution: solution.path_solution || solution.path_document || null, path_solution: solution.path_solution || solution.path_document || null,
fileName: solution.file_upload_name || null, fileName: solution.file_upload_name || null
}; };
}); });
@@ -196,35 +180,28 @@ const AddBrandDevice = () => {
setSolutionStatuses(newSolutionStatuses); setSolutionStatuses(newSolutionStatuses);
targetForm.resetFields(); targetForm.resetFields();
setTimeout(() => { setTimeout(() => {
targetForm.setFieldsValue({ targetForm.setFieldsValue({
solution_items: solutionItems, solution_items: solutionItems
}); });
setTimeout(() => { setTimeout(() => {
Object.keys(solutionItems).forEach((key) => { Object.keys(solutionItems).forEach(key => {
const solution = solutionItems[key]; const solution = solutionItems[key];
targetForm.setFieldValue(['solution_items', key, 'name'], solution.name); targetForm.setFieldValue(['solution_items', key, 'name'], solution.name);
targetForm.setFieldValue(['solution_items', key, 'type'], solution.type); targetForm.setFieldValue(['solution_items', key, 'type'], solution.type);
targetForm.setFieldValue(['solution_items', key, 'text'], solution.text); targetForm.setFieldValue(['solution_items', key, 'text'], solution.text);
targetForm.setFieldValue(['solution_items', key, 'file'], solution.file); targetForm.setFieldValue(['solution_items', key, 'file'], solution.file);
targetForm.setFieldValue( targetForm.setFieldValue(['solution_items', key, 'fileUpload'], solution.fileUpload);
['solution_items', key, 'fileUpload'],
solution.fileUpload
);
targetForm.setFieldValue(['solution_items', key, 'status'], solution.status); targetForm.setFieldValue(['solution_items', key, 'status'], solution.status);
targetForm.setFieldValue( targetForm.setFieldValue(['solution_items', key, 'path_solution'], solution.path_solution);
['solution_items', key, 'path_solution'], targetForm.setFieldValue(['solution_items', key, 'fileName'], solution.fileName);
solution.path_solution
);
targetForm.setFieldValue(
['solution_items', key, 'fileName'],
solution.fileName
);
}); });
const finalValues = targetForm.getFieldsValue(); const finalValues = targetForm.getFieldsValue();
}, 100); }, 100);
}, 100); }, 100);
@@ -232,14 +209,14 @@ const AddBrandDevice = () => {
const handleAddSolutionField = () => { const handleAddSolutionField = () => {
const newKey = Math.max(...solutionFields, 0) + 1; const newKey = Math.max(...solutionFields, 0) + 1;
setSolutionFields((prev) => [...prev, newKey]); setSolutionFields(prev => [...prev, newKey]);
setSolutionTypes((prev) => ({ ...prev, [newKey]: 'text' })); setSolutionTypes(prev => ({ ...prev, [newKey]: 'text' }));
setSolutionStatuses((prev) => ({ ...prev, [newKey]: true })); setSolutionStatuses(prev => ({ ...prev, [newKey]: true }));
}; };
const handleRemoveSolutionField = (fieldKey) => { const handleRemoveSolutionField = (fieldKey) => {
if (solutionFields.length > 1) { if (solutionFields.length > 1) {
setSolutionFields((prev) => prev.filter((key) => key !== fieldKey)); setSolutionFields(prev => prev.filter(key => key !== fieldKey));
const newTypes = { ...solutionTypes }; const newTypes = { ...solutionTypes };
const newStatuses = { ...solutionStatuses }; const newStatuses = { ...solutionStatuses };
delete newTypes[fieldKey]; delete newTypes[fieldKey];
@@ -256,7 +233,7 @@ const AddBrandDevice = () => {
}; };
const handleSolutionTypeChange = (fieldKey, type) => { const handleSolutionTypeChange = (fieldKey, type) => {
setSolutionTypes((prev) => ({ ...prev, [fieldKey]: type })); setSolutionTypes(prev => ({ ...prev, [fieldKey]: type }));
if (type === 'file') { if (type === 'file') {
solutionForm.setFieldValue(['solution_items', fieldKey, 'text'], ''); solutionForm.setFieldValue(['solution_items', fieldKey, 'text'], '');
@@ -269,7 +246,7 @@ const AddBrandDevice = () => {
}; };
const handleSolutionStatusChange = (fieldKey, status) => { const handleSolutionStatusChange = (fieldKey, status) => {
setSolutionStatuses((prev) => ({ ...prev, [fieldKey]: status })); setSolutionStatuses(prev => ({ ...prev, [fieldKey]: status }));
}; };
const handleNextStep = async () => { const handleNextStep = async () => {
@@ -282,7 +259,7 @@ const AddBrandDevice = () => {
brand_type: brandValues.brand_type || '', brand_type: brandValues.brand_type || '',
brand_manufacture: brandValues.brand_manufacture || '', brand_manufacture: brandValues.brand_manufacture || '',
brand_model: brandValues.brand_model || '', brand_model: brandValues.brand_model || '',
is_active: brandValues.is_active !== undefined ? brandValues.is_active : true, is_active: brandValues.is_active !== undefined ? brandValues.is_active : true
}; };
const response = await createBrand(brandApiData); const response = await createBrand(brandApiData);
@@ -291,7 +268,7 @@ const AddBrandDevice = () => {
const newBrandInfo = { const newBrandInfo = {
...brandValues, ...brandValues,
brand_id: response.data.brand_id, brand_id: response.data.brand_id,
brand_code: response.data.brand_code, brand_code: response.data.brand_code
}; };
setBrandInfo(newBrandInfo); setBrandInfo(newBrandInfo);
setTemporaryBrandId(response.data.brand_id); setTemporaryBrandId(response.data.brand_id);
@@ -330,7 +307,8 @@ const AddBrandDevice = () => {
if (isTemporaryBrand && temporaryBrandId) { if (isTemporaryBrand && temporaryBrandId) {
try { try {
await deleteBrand(temporaryBrandId); await deleteBrand(temporaryBrandId);
} catch (error) {} } catch (error) {
}
} }
navigate('/master/brand-device'); navigate('/master/brand-device');
}; };
@@ -382,6 +360,8 @@ const AddBrandDevice = () => {
setTrigerFilter((prev) => !prev); setTrigerFilter((prev) => !prev);
}; };
const resetErrorCodeForm = () => { const resetErrorCodeForm = () => {
errorCodeForm.resetFields(); errorCodeForm.resetFields();
errorCodeForm.setFieldsValue({ errorCodeForm.setFieldsValue({
@@ -411,16 +391,16 @@ const AddBrandDevice = () => {
return; return;
} }
// if (!solutionData || solutionData.length === 0) { if (!solutionData || solutionData.length === 0) {
// NotifAlert({ NotifAlert({
// icon: 'warning', icon: 'warning',
// title: 'Perhatian', title: 'Perhatian',
// message: 'Setiap error code harus memiliki minimal 1 solution!', message: 'Setiap error code harus memiliki minimal 1 solution!',
// }); });
// return; return;
// } }
const formattedSolutions = solutionData.map((solution) => { const formattedSolutions = solutionData.map(solution => {
const solutionType = solution.type || 'text'; const solutionType = solution.type || 'text';
let typeSolution = solutionType === 'text' ? 'text' : 'image'; let typeSolution = solutionType === 'text' ? 'text' : 'image';
@@ -442,11 +422,7 @@ const AddBrandDevice = () => {
} else { } else {
formattedSolution.text_solution = ''; formattedSolution.text_solution = '';
formattedSolution.path_solution = formattedSolution.path_solution = solution.path_solution || solution.file?.uploadPath || solution.fileUpload?.uploadPath || '';
solution.path_solution ||
solution.file?.uploadPath ||
solution.fileUpload?.uploadPath ||
'';
} }
if (formattedSolution.brand_code_solution_id) { if (formattedSolution.brand_code_solution_id) {
@@ -464,7 +440,7 @@ const AddBrandDevice = () => {
path_icon: errorCodeIcon?.uploadPath || '', path_icon: errorCodeIcon?.uploadPath || '',
is_active: errorCodeValues.status === undefined ? true : errorCodeValues.status, is_active: errorCodeValues.status === undefined ? true : errorCodeValues.status,
solution: formattedSolutions, solution: formattedSolutions,
spareparts: selectedSparepartIds || [], spareparts: selectedSparepartIds || []
}; };
let response; let response;
@@ -480,13 +456,11 @@ const AddBrandDevice = () => {
NotifOk({ NotifOk({
icon: 'success', icon: 'success',
title: 'Berhasil', title: 'Berhasil',
message: editingErrorCodeKey message: editingErrorCodeKey ? 'Error code berhasil diupdate!' : 'Error code berhasil ditambahkan!',
? 'Error code berhasil diupdate!'
: 'Error code berhasil ditambahkan!',
}); });
resetErrorCodeForm(); resetErrorCodeForm();
setTrigerFilter((prev) => !prev); setTrigerFilter(prev => !prev);
} else { } else {
NotifAlert({ NotifAlert({
icon: 'error', icon: 'error',
@@ -505,10 +479,12 @@ const AddBrandDevice = () => {
} }
}; };
const handleErrorCodeIconRemove = () => { const handleErrorCodeIconRemove = () => {
setErrorCodeIcon(null); setErrorCodeIcon(null);
}; };
const handleFinish = async () => { const handleFinish = async () => {
setConfirmLoading(true); setConfirmLoading(true);
try { try {
@@ -530,10 +506,10 @@ const AddBrandDevice = () => {
const response = await getErrorCodesByBrandId(brandInfo.brand_id, queryParams); const response = await getErrorCodesByBrandId(brandInfo.brand_id, queryParams);
if (response && response.statusCode === 200 && response.data) { if (response && response.statusCode === 200 && response.data) {
const freshErrorCodes = response.data.map((ec) => ({ const freshErrorCodes = response.data.map(ec => ({
...ec, ...ec,
tempId: `existing_${ec.error_code_id}`, tempId: `existing_${ec.error_code_id}`,
status: 'existing', status: 'existing'
})); }));
setApiErrorCodes(freshErrorCodes); setApiErrorCodes(freshErrorCodes);
@@ -541,8 +517,7 @@ const AddBrandDevice = () => {
NotifAlert({ NotifAlert({
icon: 'warning', icon: 'warning',
title: 'Perhatian', title: 'Perhatian',
message: message: 'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
}); });
return; return;
} }
@@ -551,8 +526,7 @@ const AddBrandDevice = () => {
NotifAlert({ NotifAlert({
icon: 'warning', icon: 'warning',
title: 'Perhatian', title: 'Perhatian',
message: message: 'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
'Harap tambahkan minimal 1 error code sebelum menyelesaikan.',
}); });
return; return;
} }
@@ -617,7 +591,11 @@ const AddBrandDevice = () => {
<Spin size="large" /> <Spin size="large" />
</div> </div>
)} )}
<BrandForm form={brandForm} isEdit={false} brandInfo={brandInfo} /> <BrandForm
form={brandForm}
isEdit={false}
brandInfo={brandInfo}
/>
</div> </div>
); );
} }
@@ -657,39 +635,31 @@ const AddBrandDevice = () => {
</Col> </Col>
<Col xs={24} md={16} lg={16}> <Col xs={24} md={16} lg={16}>
<div <div style={{
style={{ paddingLeft: '12px'
paddingLeft: '12px', }}>
}}
>
<Card <Card
title={ title={
<div <div style={{
style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
width: '100%', width: '100%'
}} }}>
> <span style={{
<span
style={{
fontSize: '16px', fontSize: '16px',
fontWeight: '600', fontWeight: '600',
color: '#262626', color: '#262626',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: '8px', gap: '8px'
}} }}>
> <span style={{
<span
style={{
width: '4px', width: '4px',
height: '20px', height: '20px',
backgroundColor: '#23A55A', backgroundColor: '#23A55A',
borderRadius: '2px', borderRadius: '2px'
}} }}></span>
></span>
Error Code Form Error Code Form
</span> </span>
<Button <Button
@@ -705,51 +675,43 @@ const AddBrandDevice = () => {
padding: '0 24px', padding: '0 24px',
fontWeight: '500', fontWeight: '500',
boxShadow: '0 2px 4px rgba(35, 165, 90, 0.2)', boxShadow: '0 2px 4px rgba(35, 165, 90, 0.2)',
transition: 'all 0.3s ease', transition: 'all 0.3s ease'
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.target.style.boxShadow = e.target.style.boxShadow = '0 4px 8px rgba(35, 165, 90, 0.3)';
'0 4px 8px rgba(35, 165, 90, 0.3)';
}} }}
onMouseLeave={(e) => { onMouseLeave={(e) => {
e.target.style.boxShadow = e.target.style.boxShadow = '0 2px 4px rgba(35, 165, 90, 0.2)';
'0 2px 4px rgba(35, 165, 90, 0.2)';
}} }}
> >
{editingErrorCodeKey {editingErrorCodeKey ? 'Update Error Code' : 'Save Error Code'}
? 'Update Error Code'
: 'Save Error Code'}
</Button> </Button>
</div> </div>
} }
style={{ style={{
width: '100%', width: '100%',
boxShadow: '0 2px 8px rgba(0,0,0,0.06)', boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
borderRadius: '12px', borderRadius: '12px'
}} }}
styles={{ styles={{
body: { padding: '16px 24px 12px 24px' }, body: { padding: '16px 24px 12px 24px' },
header: { header: {
padding: '16px 24px', padding: '16px 24px',
borderBottom: '1px solid #f0f0f0', borderBottom: '1px solid #f0f0f0',
backgroundColor: '#fafafa', backgroundColor: '#fafafa'
}, }
}} }}
> >
<div <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
style={{ display: 'flex', flexDirection: 'column', gap: '8px' }} <div style={{
>
<div
style={{
padding: '16px', padding: '16px',
border: '1px solid #f0f0f0', border: '1px solid #f0f0f0',
borderRadius: '10px', borderRadius: '10px',
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
marginBottom: '0', marginBottom: '0',
transition: 'all 0.3s ease', transition: 'all 0.3s ease',
boxShadow: '0 1px 3px rgba(0,0,0,0.04)', boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
}} }}>
>
<ErrorCodeForm <ErrorCodeForm
errorCodeForm={errorCodeForm} errorCodeForm={errorCodeForm}
isErrorCodeFormReadOnly={isErrorCodeFormReadOnly} isErrorCodeFormReadOnly={isErrorCodeFormReadOnly}
@@ -762,42 +724,29 @@ const AddBrandDevice = () => {
<Row gutter={[20, 0]} style={{ marginTop: '0' }}> <Row gutter={[20, 0]} style={{ marginTop: '0' }}>
<Col xs={24} md={12} lg={12}> <Col xs={24} md={12} lg={12}>
<div <div style={{
style={{
padding: '16px', padding: '16px',
border: '1px solid #f0f0f0', border: '1px solid #f0f0f0',
borderRadius: '10px', borderRadius: '10px',
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
transition: 'all 0.3s ease', transition: 'all 0.3s ease',
boxShadow: '0 1px 3px rgba(0,0,0,0.04)', boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
}} }}>
> <div style={{
<div
style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: '8px', gap: '8px',
marginBottom: '12px', marginBottom: '12px',
paddingBottom: '8px', paddingBottom: '8px',
borderBottom: '1px solid #f5f5f5', borderBottom: '1px solid #f5f5f5'
}} }}>
> <div style={{
<div
style={{
width: '3px', width: '3px',
height: '16px', height: '16px',
backgroundColor: '#1890ff', backgroundColor: '#1890ff',
borderRadius: '2px', borderRadius: '2px'
}} }}></div>
></div> <h4 style={{ margin: 0, color: '#262626', fontSize: '14px', fontWeight: '600' }}>
<h4
style={{
margin: 0,
color: '#262626',
fontSize: '14px',
fontWeight: '600',
}}
>
Solution Solution
</h4> </h4>
</div> </div>
@@ -807,23 +756,14 @@ const AddBrandDevice = () => {
solutionTypes={solutionTypes} solutionTypes={solutionTypes}
solutionStatuses={solutionStatuses} solutionStatuses={solutionStatuses}
onAddSolutionField={handleAddSolutionField} onAddSolutionField={handleAddSolutionField}
onRemoveSolutionField={ onRemoveSolutionField={handleRemoveSolutionField}
handleRemoveSolutionField
}
onSolutionTypeChange={handleSolutionTypeChange} onSolutionTypeChange={handleSolutionTypeChange}
onSolutionStatusChange={ onSolutionStatusChange={handleSolutionStatusChange}
handleSolutionStatusChange onSolutionFileUpload={(fileData) => {
} }}
onSolutionFileUpload={(fileData) => {}}
onFileView={(fileData) => { onFileView={(fileData) => {
if ( if (fileData && (fileData.url || fileData.uploadPath)) {
fileData && window.open(fileData.url || fileData.uploadPath, '_blank');
(fileData.url || fileData.uploadPath)
) {
window.open(
fileData.url || fileData.uploadPath,
'_blank'
);
} }
}} }}
isReadOnly={false} isReadOnly={false}
@@ -832,55 +772,40 @@ const AddBrandDevice = () => {
</div> </div>
</Col> </Col>
<Col xs={24} md={12} lg={12}> <Col xs={24} md={12} lg={12}>
<div <div style={{
style={{
padding: '16px', padding: '16px',
border: '1px solid #f0f0f0', border: '1px solid #f0f0f0',
borderRadius: '10px', borderRadius: '10px',
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
transition: 'all 0.3s ease', transition: 'all 0.3s ease',
boxShadow: '0 1px 3px rgba(0,0,0,0.04)', boxShadow: '0 1px 3px rgba(0,0,0,0.04)'
}} }}>
> <div style={{
<div
style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: '8px', gap: '8px',
marginBottom: '12px', marginBottom: '12px',
paddingBottom: '8px', paddingBottom: '8px',
borderBottom: '1px solid #f5f5f5', borderBottom: '1px solid #f5f5f5'
}} }}>
> <div style={{
<div
style={{
width: '3px', width: '3px',
height: '16px', height: '16px',
backgroundColor: '#faad14', backgroundColor: '#faad14',
borderRadius: '2px', borderRadius: '2px'
}} }}></div>
></div> <h4 style={{ margin: 0, color: '#262626', fontSize: '14px', fontWeight: '600' }}>
<h4
style={{
margin: 0,
color: '#262626',
fontSize: '14px',
fontWeight: '600',
}}
>
Sparepart Selection Sparepart Selection
</h4> </h4>
</div> </div>
<div <div style={{
style={{
maxHeight: '45vh', maxHeight: '45vh',
overflow: 'auto', overflow: 'auto',
border: '1px solid #e8e8e8', border: '1px solid #e8e8e8',
borderRadius: '8px', borderRadius: '8px',
padding: '12px', padding: '12px',
backgroundColor: '#fafafa', backgroundColor: '#fafafa'
}} }}>
>
<SparepartSelect <SparepartSelect
selectedSparepartIds={selectedSparepartIds} selectedSparepartIds={selectedSparepartIds}
onSparepartChange={setSelectedSparepartIds} onSparepartChange={setSelectedSparepartIds}
@@ -891,16 +816,15 @@ const AddBrandDevice = () => {
</Col> </Col>
</Row> </Row>
<div <div style={{
style={{
display: 'flex', display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
padding: '16px 0 0 0', padding: '16px 0 0 0',
borderTop: '1px solid #f0f0f0', borderTop: '1px solid #f0f0f0',
marginTop: '12px', marginTop: '12px'
}} }}>
>
{editingErrorCodeKey && ( {editingErrorCodeKey && (
<Button <Button
size="large" size="large"
@@ -913,7 +837,7 @@ const AddBrandDevice = () => {
height: '40px', height: '40px',
padding: '0 24px', padding: '0 24px',
fontWeight: '500', fontWeight: '500',
transition: 'all 0.3s ease', transition: 'all 0.3s ease'
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.target.style.borderColor = '#ff4d4f'; e.target.style.borderColor = '#ff4d4f';
@@ -947,7 +871,7 @@ const AddBrandDevice = () => {
setBreadcrumbItems([ setBreadcrumbItems([
{ {
title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}> Master</span>, title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}> Master</span>
}, },
{ {
title: ( title: (
@@ -971,11 +895,12 @@ const AddBrandDevice = () => {
if (location.state?.fromFileViewer && location.state.phase !== undefined) { if (location.state?.fromFileViewer && location.state.phase !== undefined) {
setCurrentStep(location.state.phase); setCurrentStep(location.state.phase);
} }
}, [setBreadcrumbItems, navigate, searchParams, location.state]); }, [setBreadcrumbItems, navigate, searchParams, location.state]);
useEffect(() => { useEffect(() => {
if (brandInfo.brand_id && currentStep === 1) { if (brandInfo.brand_id && currentStep === 1) {
setTrigerFilter((prev) => !prev); setTrigerFilter(prev => !prev);
} }
}, [brandInfo.brand_id, currentStep]); }, [brandInfo.brand_id, currentStep]);
@@ -988,7 +913,8 @@ const AddBrandDevice = () => {
const errorCodes = response.data || []; const errorCodes = response.data || [];
setApiErrorCodes(errorCodes); setApiErrorCodes(errorCodes);
} }
} catch (error) {} } catch (error) {
}
} }
}; };
fetchErrorCodes(); fetchErrorCodes();
@@ -999,7 +925,8 @@ const AddBrandDevice = () => {
if (isTemporaryBrand && temporaryBrandId && currentStep === 0) { if (isTemporaryBrand && temporaryBrandId && currentStep === 0) {
try { try {
await deleteBrand(temporaryBrandId); await deleteBrand(temporaryBrandId);
} catch (error) {} } catch (error) {
}
} }
}; };
@@ -1010,6 +937,7 @@ const AddBrandDevice = () => {
}; };
}, [isTemporaryBrand, temporaryBrandId, currentStep]); }, [isTemporaryBrand, temporaryBrandId, currentStep]);
return ( return (
<ConfigProvider <ConfigProvider
theme={{ theme={{
@@ -1060,9 +988,14 @@ const AddBrandDevice = () => {
<Divider /> <Divider />
<div style={{ display: 'flex', justifyContent: 'space-between' }}> <div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div> <div>
<Button onClick={handleCancel}>Cancel</Button> <Button onClick={handleCancel}>
Cancel
</Button>
{currentStep === 1 && ( {currentStep === 1 && (
<Button onClick={handlePrevStep} style={{ marginLeft: 8 }}> <Button
onClick={handlePrevStep}
style={{ marginLeft: 8 }}
>
Kembali ke Brand Info Kembali ke Brand Info
</Button> </Button>
)} )}

View File

@@ -479,14 +479,14 @@ const EditBrandDevice = () => {
return; return;
} }
// if (!solutionData || solutionData.length === 0) { if (!solutionData || solutionData.length === 0) {
// NotifAlert({ NotifAlert({
// icon: 'warning', icon: 'warning',
// title: 'Perhatian', title: 'Perhatian',
// message: 'Setiap error code harus memiliki minimal 1 solution!', message: 'Setiap error code harus memiliki minimal 1 solution!',
// }); });
// return; return;
// } }
const formattedSolutions = solutionData.map(solution => { const formattedSolutions = solutionData.map(solution => {
const solutionType = solution.type || 'text'; const solutionType = solution.type || 'text';

View File

@@ -1,12 +1,6 @@
import React, { useState, useEffect, useMemo } from 'react'; import React, { useState, useEffect, useMemo } from 'react';
import { Card, Input, Button, Row, Col, Empty } from 'antd'; import { Card, Input, Button, Row, Col, Empty } from 'antd';
import { import { PlusOutlined, SearchOutlined, DeleteOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
PlusOutlined,
SearchOutlined,
DeleteOutlined,
LeftOutlined,
RightOutlined,
} from '@ant-design/icons';
import { getErrorCodesByBrandId, deleteErrorCode } from '../../../../api/master-brand'; import { getErrorCodesByBrandId, deleteErrorCode } from '../../../../api/master-brand';
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../../components/Global/ToastNotif'; import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../../components/Global/ToastNotif';
@@ -22,7 +16,7 @@ const ListErrorCode = ({
onSearch, onSearch,
onSearchClear, onSearchClear,
isReadOnly = false, isReadOnly = false,
errorCodes: propErrorCodes = null, errorCodes: propErrorCodes = null
}) => { }) => {
const [errorCodes, setErrorCodes] = useState([]); const [errorCodes, setErrorCodes] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -58,12 +52,12 @@ const ListErrorCode = ({
if (response && response.statusCode === 200) { if (response && response.statusCode === 200) {
const apiErrorData = response.data || []; const apiErrorData = response.data || [];
const allErrorCodes = [ const allErrorCodes = [
...apiErrorData.map((ec) => ({ ...apiErrorData.map(ec => ({
...ec, ...ec,
tempId: `existing_${ec.error_code_id}`, tempId: `existing_${ec.error_code_id}`,
status: 'existing', status: 'existing'
})), })),
...tempErrorCodes.filter((ec) => ec.status !== 'deleted'), ...tempErrorCodes.filter(ec => ec.status !== 'deleted')
]; ];
setErrorCodes(allErrorCodes); setErrorCodes(allErrorCodes);
@@ -88,9 +82,11 @@ const ListErrorCode = ({
useEffect(() => { useEffect(() => {
if (isReadOnly && propErrorCodes) { if (isReadOnly && propErrorCodes) {
setErrorCodes(propErrorCodes); setErrorCodes(propErrorCodes);
setLoading(false); setLoading(false);
} else { } else {
fetchErrorCodes(); fetchErrorCodes();
} }
}, [brandId, queryParams, tempErrorCodes, trigerFilter, isReadOnly, propErrorCodes]); }, [brandId, queryParams, tempErrorCodes, trigerFilter, isReadOnly, propErrorCodes]);
@@ -130,19 +126,20 @@ const ListErrorCode = ({
title: 'Hapus Error Code', title: 'Hapus Error Code',
message: `Apakah Anda yakin ingin menghapus error code ${item.error_code}?`, message: `Apakah Anda yakin ingin menghapus error code ${item.error_code}?`,
onConfirm: () => performDelete(item), onConfirm: () => performDelete(item),
onCancel: () => {}, onCancel: () => { },
confirmButtonText: 'Hapus', confirmButtonText: 'Hapus'
}); });
} }
}; };
const performDelete = async (item) => { const performDelete = async (item) => {
try { try {
if (!item.error_code_id || item.error_code_id === 'undefined') { if (!item.error_code_id || item.error_code_id === 'undefined') {
NotifAlert({ NotifAlert({
icon: 'error', icon: 'error',
title: 'Error', title: 'Error',
message: 'Error code ID tidak valid', message: 'Error code ID tidak valid'
}); });
return; return;
} }
@@ -151,7 +148,7 @@ const ListErrorCode = ({
NotifAlert({ NotifAlert({
icon: 'error', icon: 'error',
title: 'Error', title: 'Error',
message: 'Brand ID tidak valid', message: 'Brand ID tidak valid'
}); });
return; return;
} }
@@ -162,21 +159,21 @@ const ListErrorCode = ({
NotifOk({ NotifOk({
icon: 'success', icon: 'success',
title: 'Berhasil', title: 'Berhasil',
message: 'Error code berhasil dihapus', message: 'Error code berhasil dihapus'
}); });
fetchErrorCodes(); fetchErrorCodes();
} else { } else {
NotifAlert({ NotifAlert({
icon: 'error', icon: 'error',
title: 'Gagal', title: 'Gagal',
message: 'Gagal menghapus error code', message: 'Gagal menghapus error code'
}); });
} }
} catch (error) { } catch (error) {
NotifAlert({ NotifAlert({
icon: 'error', icon: 'error',
title: 'Error', title: 'Error',
message: 'Terjadi kesalahan saat menghapus error code', message: 'Terjadi kesalahan saat menghapus error code'
}); });
} }
}; };
@@ -184,8 +181,8 @@ const ListErrorCode = ({
return ( return (
<Card <Card
title="Daftar Error Code" title="Daftar Error Code"
style={{ width: '100%', minWidth: '300px' }} style={{ width: '100%', minWidth: '472px' }}
bodyStyle={{ padding: '12px' }} styles={{ body: { padding: '12px' } }}
> >
<Input.Search <Input.Search
placeholder="Cari error code..." placeholder="Cari error code..."
@@ -206,7 +203,7 @@ const ListErrorCode = ({
style={{ style={{
backgroundColor: '#23A55A', backgroundColor: '#23A55A',
borderColor: '#23A55A', borderColor: '#23A55A',
height: '32px', height: '32px'
}} }}
> >
Search Search
@@ -220,18 +217,19 @@ const ListErrorCode = ({
}} }}
/> />
<div <div style={{
style={{
height: '90vh', height: '90vh',
border: '1px solid #d9d9d9', border: '1px solid #d9d9d9',
borderRadius: '6px', borderRadius: '6px',
overflow: 'auto', overflow: 'auto',
marginBottom: 12, marginBottom: 12,
backgroundColor: '#fafafa', backgroundColor: '#fafafa'
}} }}>
>
{errorCodes.length === 0 ? ( {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' }}> <div style={{ padding: '8px' }}>
{errorCodes.map((item) => ( {errorCodes.map((item) => (
@@ -242,25 +240,13 @@ const ListErrorCode = ({
padding: '8px 12px', padding: '8px 12px',
borderRadius: '6px', borderRadius: '6px',
marginBottom: '4px', marginBottom: '4px',
border: border: selectedErrorCode?.tempId === item.tempId ? '2px solid #23A55A' : '1px solid #d9d9d9',
selectedErrorCode?.tempId === item.tempId backgroundColor: selectedErrorCode?.tempId === item.tempId ? '#f6ffed' : '#fff',
? '2px solid #23A55A' transition: 'all 0.2s ease'
: '1px solid #d9d9d9',
backgroundColor:
selectedErrorCode?.tempId === item.tempId
? '#f6ffed'
: '#fff',
transition: 'all 0.2s ease',
}} }}
onClick={() => onErrorCodeSelect(item)} onClick={() => onErrorCodeSelect(item)}
> >
<div <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<div style={{ fontWeight: 'bold', fontSize: '12px' }}> <div style={{ fontWeight: 'bold', fontSize: '12px' }}>
{item.error_code} {item.error_code}
@@ -280,7 +266,7 @@ const ListErrorCode = ({
padding: '2px 6px', padding: '2px 6px',
height: '24px', height: '24px',
fontSize: '11px', fontSize: '11px',
border: '1px solid #ff4d4f', border: '1px solid #ff4d4f'
}} }}
/> />
)} )}
@@ -306,15 +292,9 @@ const ListErrorCode = ({
onClick={handlePrevious} onClick={handlePrevious}
disabled={pagination.current_page <= 1} disabled={pagination.current_page <= 1}
size="small" 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} {pagination.current_page} / {pagination.total_page}
</span> </span>
<Button <Button
@@ -322,7 +302,8 @@ const ListErrorCode = ({
onClick={handleNext} onClick={handleNext}
disabled={pagination.current_page >= pagination.total_page} disabled={pagination.current_page >= pagination.total_page}
size="small" size="small"
></Button> >
</Button>
</div> </div>
</Col> </Col>
</Row> </Row>

View File

@@ -44,29 +44,16 @@ import {
getNotificationDetail, getNotificationDetail,
resendChatByUser, resendChatByUser,
resendChatAllUser, resendChatAllUser,
searchData,
} from '../../../api/notification'; } from '../../../api/notification';
import { onNotifUpdate } from '../../../components/Global/MqttConnection';
const { Text, Paragraph, Link: AntdLink } = Typography; const { Text, Paragraph, Link: AntdLink } = Typography;
const OpenMail = ({ size = 22, color = 'black' }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 640"
width={size}
height={size}
fill={color}
>
<path d="M576 480C576 515.3 547.5 544 512.1 544L128 544C92.6 544 64 515.3 64 480L64 228C64.1 212.5 71.8 198 84.5 189.2L270 61.3C300.1 40.6 339.8 40.6 369.9 61.3L555.5 189.2C568.3 198 575.9 212.5 576 228L576 480zM128 496L512.1 496C520.9 496 528 488.9 528 480L528 288.3L373.2 405.7C341.8 429.6 298.3 429.6 266.8 405.7L112 288.3L112 480C112 488.9 119.2 496 128 496zM527.6 228.4L342.7 100.8C329 91.4 311 91.4 297.3 100.8L112.4 228.4L295.8 367.5C310.1 378.3 329.9 378.3 344.2 367.5L527.6 228.4z" />
</svg>
);
// Transform API response to component format // Transform API response to component format
const transformNotificationData = (apiData) => { const transformNotificationData = (apiData) => {
return apiData.map((item, index) => ({ return apiData.map((item, index) => ({
id: `notification-${item.notification_error_id}-${index}`, // Unique key prefix with array index id: `notification-${item.notification_error_id}-${index}`, // Unique key prefix with array index
type: item.is_read ? 'resolved' : item.is_delivered ? 'warning' : 'critical', type: item.is_read ? 'resolved' : item.is_delivered ? 'warning' : 'critical',
title: item.error_code_name || 'Unknown Error', title: item.error_code_name || 'Unknown Error',
color: item.error_code_color || 'Black',
issue: item.error_code || item.error_code_name || 'Unknown Error', issue: item.error_code || item.error_code_name || 'Unknown Error',
description: `${item.error_code} - ${item.error_code_name || ''}`, description: `${item.error_code} - ${item.error_code_name || ''}`,
timestamp: item.created_at timestamp: item.created_at
@@ -102,7 +89,6 @@ const ListNotification = memo(function ListNotification(props) {
const [activeTab, setActiveTab] = useState('all'); const [activeTab, setActiveTab] = useState('all');
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
const [notifTrigger, setNotifTrigger] = useState(0);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [modalContent, setModalContent] = useState(null); // 'user', 'log', 'details', or null const [modalContent, setModalContent] = useState(null); // 'user', 'log', 'details', or null
const [isAddingLog, setIsAddingLog] = useState(false); const [isAddingLog, setIsAddingLog] = useState(false);
@@ -180,12 +166,6 @@ const ListNotification = memo(function ListNotification(props) {
fetchNotifications(page, pageSize, isReadFilter); fetchNotifications(page, pageSize, isReadFilter);
}; };
useEffect(() => {
onNotifUpdate(() => {
setNotifTrigger((prev) => prev + 1);
});
}, []);
useEffect(() => { useEffect(() => {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (!token) { if (!token) {
@@ -196,18 +176,18 @@ const ListNotification = memo(function ListNotification(props) {
// Fetch notifications on component mount and when tab changes // Fetch notifications on component mount and when tab changes
const isReadFilter = activeTab === 'read' ? 1 : activeTab === 'unread' ? 0 : null; const isReadFilter = activeTab === 'read' ? 1 : activeTab === 'unread' ? 0 : null;
fetchNotifications(pagination.current_page, pagination.current_limit, isReadFilter); fetchNotifications(pagination.current_page, pagination.current_limit, isReadFilter);
}, [activeTab, notifTrigger]); }, [activeTab]);
const getIconAndColor = (type) => { const getIconAndColor = (type) => {
switch (type) { switch (type) {
case 'critical': case 'critical':
return { IconComponent: MailOutlined, color: '#faad14', bgColor: '#fff1f0' }; return { IconComponent: CloseCircleFilled, color: '#ff4d4f', bgColor: '#fff1f0' };
case 'warning': case 'warning':
return { IconComponent: MailOutlined, color: '#1890ff', bgColor: '#fffbe6' }; return { IconComponent: WarningFilled, color: '#faad14', bgColor: '#fffbe6' };
case 'resolved': case 'resolved':
return { IconComponent: MailOutlined, color: '#52c41a', bgColor: '#f6ffed' }; return { IconComponent: CheckCircleFilled, color: '#52c41a', bgColor: '#f6ffed' };
default: default:
return { IconComponent: MailOutlined, color: '#1890ff', bgColor: '#e6f7ff' }; return { IconComponent: InfoCircleFilled, color: '#1890ff', bgColor: '#e6f7ff' };
} }
}; };
@@ -239,49 +219,13 @@ const ListNotification = memo(function ListNotification(props) {
); );
}; };
const fetchSearch = async (data) => {
setLoading(true);
try {
const response = await searchData(data);
if (response && response.data) {
const transformedData = transformNotificationData(response.data);
setNotifications(transformedData);
// Update pagination with API response or calculate from data
if (response.paging) {
setPagination({
current_page: response.paging.current_page || page,
current_limit: response.paging.current_limit || limit,
total_limit: response.paging.total_limit || transformedData.length,
total_page:
response.paging.total_page || Math.ceil(transformedData.length / limit),
});
} else {
// Fallback: calculate pagination from data
const totalItems = transformedData.length;
setPagination((prev) => ({
...prev,
current_page: page,
current_limit: limit,
total_limit: totalItems,
total_page: Math.ceil(totalItems / limit),
}));
}
}
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
const handleSearch = () => { const handleSearch = () => {
fetchSearch(searchValue); setSearchTerm(searchValue);
}; };
const handleSearchClear = () => { const handleSearchClear = () => {
setSearchValue(''); setSearchValue('');
fetchSearch(''); setSearchTerm('');
}; };
const getUnreadCount = () => notifications.filter((n) => !n.isRead).length; const getUnreadCount = () => notifications.filter((n) => !n.isRead).length;
@@ -344,16 +288,14 @@ const ListNotification = memo(function ListNotification(props) {
name: user.contact_name, name: user.contact_name,
phone: user.contact_phone, phone: user.contact_phone,
status: user.is_send ? 'Delivered' : 'Pending', status: user.is_send ? 'Delivered' : 'Pending',
timestamp: user.updated_at timestamp: user.created_at
? new Date(user.updated_at) ? new Date(user.created_at).toLocaleString('id-ID', {
.toLocaleString('id-ID', {
day: '2-digit', day: '2-digit',
month: '2-digit', month: '2-digit',
year: 'numeric', year: 'numeric',
hour: '2-digit', hour: '2-digit',
minute: '2-digit', minute: '2-digit',
}) }) + ' WIB'
.replace('.', ':') + ' WIB'
: 'N/A', : 'N/A',
})); }));
setUserHistoryData(transformedUsers); setUserHistoryData(transformedUsers);
@@ -424,11 +366,7 @@ const ListNotification = memo(function ListNotification(props) {
flexShrink: 0, flexShrink: 0,
}} }}
> >
{notification.type === 'resolved' ? (
<OpenMail size={28.5} color={color} />
) : (
<IconComponent style={{ fontSize: '22px' }} /> <IconComponent style={{ fontSize: '22px' }} />
)}
</div> </div>
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<Row align="top"> <Row align="top">
@@ -443,12 +381,8 @@ const ListNotification = memo(function ListNotification(props) {
<div> <div>
<Text strong>{notification.title}</Text> <Text strong>{notification.title}</Text>
<div style={{ marginTop: '4px' }}> <div style={{ marginTop: '4px' }}>
<Text <Text style={{ color }}>
style={{ {notification.issue}
color: notification.color,
}}
>
Error Code {notification.issue}
</Text> </Text>
</div> </div>
</div> </div>
@@ -676,6 +610,9 @@ const ListNotification = memo(function ListNotification(props) {
icon={<SendOutlined />} icon={<SendOutlined />}
onClick={async () => { onClick={async () => {
await resendChatByUser(user.id, user.phone); await resendChatByUser(user.id, user.phone);
// message.info(
// 'Resend feature is not available yet. This feature is still under development.'
// );
}} }}
> >
Resend Resend
@@ -761,8 +698,8 @@ const ListNotification = memo(function ListNotification(props) {
{/* Kolom Kanan: Card */} {/* Kolom Kanan: Card */}
<Col flex="auto"> <Col flex="auto">
<Card size="small" style={{ borderColor: '#91d5ff' }}> <Card size="small" style={{ borderColor: '#91d5ff' }}>
<Row gutter={[16, 8]} align="top"> <Row gutter={[16, 8]} align="middle">
<Col xs={24} md={10}> <Col xs={24} md={12}>
<Space direction="vertical" size={4}> <Space direction="vertical" size={4}>
<Space> <Space>
<ClockCircleOutlined /> <ClockCircleOutlined />
@@ -773,14 +710,13 @@ const ListNotification = memo(function ListNotification(props) {
Added at {log.timestamp} Added at {log.timestamp}
</Text> </Text>
</Space> </Space>
<div>
<Text strong>{log.addedBy.name}</Text>
</div>
<div> <div>
<Text strong>
Added by: {log.addedBy.name}
</Text>
<span <span
style={{ style={{
marginLeft: '8px',
border: '1px solid #52c41a', border: '1px solid #52c41a',
color: '#52c41a', color: '#52c41a',
padding: '2px 6px', padding: '2px 6px',
@@ -793,8 +729,7 @@ const ListNotification = memo(function ListNotification(props) {
</div> </div>
</Space> </Space>
</Col> </Col>
<Col xs={24} md={14}> <Col xs={24} md={12}>
<Text strong>Description:</Text>
<Paragraph <Paragraph
style={{ style={{
color: '#595959', color: '#595959',

View File

@@ -14,8 +14,6 @@ import {
message, message,
Avatar, Avatar,
Tag, Tag,
Badge,
Divider,
} from 'antd'; } from 'antd';
import { import {
ArrowLeftOutlined, ArrowLeftOutlined,
@@ -35,8 +33,6 @@ import {
CheckCircleOutlined, CheckCircleOutlined,
SyncOutlined, SyncOutlined,
SendOutlined, SendOutlined,
MobileOutlined,
ClockCircleOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { import {
getNotificationDetail, getNotificationDetail,
@@ -44,7 +40,6 @@ import {
getNotificationLogByNotificationId, getNotificationLogByNotificationId,
updateIsRead, updateIsRead,
resendNotificationToUser, resendNotificationToUser,
resendChatByUser,
} from '../../api/notification'; } from '../../api/notification';
const { Content } = Layout; const { Content } = Layout;
@@ -113,19 +108,8 @@ const getUsersFromNotification = (notification) => {
id: user.notification_error_user_id.toString(), id: user.notification_error_user_id.toString(),
name: user.contact_name, name: user.contact_name,
phone: user.contact_phone, phone: user.contact_phone,
status: user.is_send ? 'Delivered' : 'Pending', status: user.is_send ? 'sent' : 'pending',
loading: user.loading || false, loading: user.loading || false,
timestamp: user.updated_at
? new Date(user.updated_at)
.toLocaleString('id-ID', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
})
.replace('.', ':') + ' WIB'
: 'N/A',
})); }));
}; };
@@ -251,6 +235,8 @@ const NotificationDetailTab = (props) => {
// Fetch using the actual API // Fetch using the actual API
const response = await getNotificationDetail(notificationId); const response = await getNotificationDetail(notificationId);
// Fetch using the actual API
const resUpdate = await updateIsRead(notificationId);
if (response && response.data) { if (response && response.data) {
const transformedData = transformNotificationData(response.data); const transformedData = transformNotificationData(response.data);
@@ -258,9 +244,6 @@ const NotificationDetailTab = (props) => {
// Fetch log history // Fetch log history
fetchLogHistory(notificationId); fetchLogHistory(notificationId);
// Fetch using the actual API
const resUpdate = await updateIsRead(notificationId);
} else { } else {
throw new Error('Notification not found'); throw new Error('Notification not found');
} }
@@ -394,7 +377,7 @@ const NotificationDetailTab = (props) => {
<Text>{notification.title}</Text> <Text>{notification.title}</Text>
<div style={{ marginTop: '2px' }}> <div style={{ marginTop: '2px' }}>
<Text strong style={{ fontSize: '16px' }}> <Text strong style={{ fontSize: '16px' }}>
Error Code {notification.issue} {notification.issue}
</Text> </Text>
</div> </div>
</Col> </Col>
@@ -482,56 +465,137 @@ const NotificationDetailTab = (props) => {
<Row align="middle" justify="space-between"> <Row align="middle" justify="space-between">
<Col> <Col>
<Space align="center"> <Space align="center">
<Avatar
size="large"
icon={<UserOutlined />}
/>
<div>
<Text strong>{user.name}</Text> <Text strong>{user.name}</Text>
<Text>|</Text> <div
<Text> style={{
<MobileOutlined /> {user.phone} display: 'flex',
</Text> alignItems: 'center',
<Text>|</Text> gap: '4px',
<Badge }}
status={ >
user.status === 'Delivered' <PhoneOutlined
? 'success' style={{
: 'default' color: '#8c8c8c',
} }}
text={user.status}
/> />
</Space>
<Divider style={{ margin: '8px 0' }} />
<Space align="center">
{user.status === 'Delivered' ? (
<CheckCircleFilled
style={{ color: '#52c41a' }}
/>
) : (
<ClockCircleOutlined
style={{ color: '#faad14' }}
/>
)}
<Text type="secondary"> <Text type="secondary">
{user.status === 'Delivered' {user.phone}
? 'Success Delivered at'
: 'Status '}{' '}
{user.timestamp}
</Text> </Text>
</div>
</div>
</Space> </Space>
</Col> </Col>
<Col> <Col>
<Col> <Space align="center" size="large">
{getStatusTag(user.status)}
<Button <Button
type="primary" type="primary"
ghost
icon={<SendOutlined />} icon={<SendOutlined />}
onClick={async () => { size="small"
await resendChatByUser( loading={user.loading}
user.id, onClick={async (e) => {
user.phone e.stopPropagation();
const userId = parseInt(
user.id
); );
try {
// Update user status to show loading
const updatedUsers =
notification.users.map(
(u) =>
u.notification_error_user_id ===
userId
? {
...u,
loading: true,
}
: u
);
setNotification({
...notification,
users: updatedUsers,
});
// Call the resend API
const response =
await resendNotificationToUser(
notification.notification_error_id,
userId
);
if (
response &&
response.statusCode ===
200
) {
message.success(
`Notification resent to ${user.name}`
);
// Update user status
const updatedUsersAfterSuccess =
notification.users.map(
(u) =>
u.notification_error_user_id ===
userId
? {
...u,
is_send: true,
status: 'sent',
loading: false,
}
: {
...u,
loading: false,
}
);
setNotification({
...notification,
users: updatedUsersAfterSuccess,
});
} else {
throw new Error(
response?.message ||
'Failed to resend notification'
);
}
} catch (error) {
console.error(
'Error resending notification:',
error
);
message.error(
error.message ||
'Failed to resend notification'
);
// Reset loading state
const resetUsers =
notification.users.map(
(u) =>
u.notification_error_user_id ===
userId
? {
...u,
loading: false,
}
: u
);
setNotification({
...notification,
users: resetUsers,
});
}
}} }}
> >
Resend Resend
</Button> </Button>
</Col> </Space>
</Col> </Col>
</Row> </Row>
</Card> </Card>
@@ -542,25 +606,58 @@ const NotificationDetailTab = (props) => {
</Col> </Col>
</Row> </Row>
<Row gutter={[8, 8]}> <Row gutter={[8, 8]} style={{ marginBottom: 'px' }}>
<Col xs={24} md={8}> <Col xs={24} md={8}>
<div>
<Card <Card
hoverable hoverable
bodyStyle={{ padding: '12px'}} bodyStyle={{ padding: '12px', textAlign: 'center' }}
> >
<Space> <Space>
<BookOutlined <BookOutlined
style={{ fontSize: '16px', color: '#1890ff' }} style={{ fontSize: '16px', color: '#1890ff' }}
/> />
<Text <Text strong style={{ fontSize: '16px', color: '#262626' }}>
strong
style={{ fontSize: '16px', color: '#262626' }}
>
Handling Guideline Handling Guideline
</Text> </Text>
</Space> </Space>
</Card>
</Col>
<Col xs={24} md={8}>
<Card
hoverable
bodyStyle={{ padding: '12px', textAlign: 'center' }}
>
<Space>
<ToolOutlined
style={{ fontSize: '16px', color: '#1890ff' }}
/>
<Text strong style={{ fontSize: '16px', color: '#262626' }}>
Spare Part
</Text>
</Space>
</Card>
</Col>
<Col xs={24} md={8}>
<Card bodyStyle={{ padding: '12px', textAlign: 'center' }}>
<Space>
<HistoryOutlined
style={{ fontSize: '16px', color: '#1890ff' }}
/>
<Text strong style={{ fontSize: '16px', color: '#262626' }}>
Log Activity
</Text>
</Space>
</Card>
</Col>
</Row>
<Row gutter={[8, 8]} style={{ marginTop: '-12px' }}>
<Col xs={24} md={8}>
<Card
size="small"
title="Guideline Documents"
style={{ height: '100%' }}
>
<Space <Space
direction="vertical" direction="vertical"
size="small" size="small"
@@ -574,8 +671,7 @@ const NotificationDetailTab = (props) => {
.map((sol, index) => ( .map((sol, index) => (
<div <div
key={ key={
sol.brand_code_solution_id || sol.brand_code_solution_id || index
index
} }
> >
{sol.path_document ? ( {sol.path_document ? (
@@ -590,8 +686,7 @@ const NotificationDetailTab = (props) => {
<Text <Text
type="secondary" type="secondary"
style={{ style={{
fontSize: fontSize: '10px',
'10px',
}} }}
> >
PDF PDF
@@ -603,8 +698,7 @@ const NotificationDetailTab = (props) => {
display: 'flex', display: 'flex',
justifyContent: justifyContent:
'space-between', 'space-between',
alignItems: alignItems: 'center',
'center',
}} }}
> >
<div> <div>
@@ -647,11 +741,6 @@ const NotificationDetailTab = (props) => {
sol.text_solution ? ( sol.text_solution ? (
<Card <Card
size="small" size="small"
title={
<Text strong>
{sol.solution_name}:
</Text>
}
bodyStyle={{ bodyStyle={{
padding: '8px 12px', padding: '8px 12px',
marginBottom: '4px', marginBottom: '4px',
@@ -660,8 +749,7 @@ const NotificationDetailTab = (props) => {
<Text <Text
type="secondary" type="secondary"
style={{ style={{
fontSize: fontSize: '10px',
'10px',
}} }}
> >
{sol.type_solution.toUpperCase()} {sol.type_solution.toUpperCase()}
@@ -669,10 +757,12 @@ const NotificationDetailTab = (props) => {
} }
> >
<div> <div>
<Text strong>
{sol.solution_name}:
</Text>
<div <div
style={{ style={{
marginTop: marginTop: '4px',
'4px',
}} }}
> >
{sol.text_solution} {sol.text_solution}
@@ -696,26 +786,13 @@ const NotificationDetailTab = (props) => {
)} )}
</Space> </Space>
</Card> </Card>
</div>
</Col> </Col>
<Col xs={24} md={8}> <Col xs={24} md={8}>
<div>
<Card <Card
hoverable size="small"
bodyStyle={{ padding: '12px'}} title="Required Spare Parts"
style={{ height: '100%' }}
> >
<Space>
<ToolOutlined
style={{ fontSize: '16px', color: '#1890ff' }}
/>
<Text
strong
style={{ fontSize: '16px', color: '#262626' }}
>
Spare Part
</Text>
</Space>
<Space <Space
direction="vertical" direction="vertical"
size="small" size="small"
@@ -799,11 +876,9 @@ const NotificationDetailTab = (props) => {
marginTop: '8px', marginTop: '8px',
}} }}
> >
Kode:{' '} Kode: {sparepart.sparepart_code}{' '}
{sparepart.sparepart_code} | | Qty: {sparepart.sparepart_qty}{' '}
Qty:{' '} | Unit:{' '}
{sparepart.sparepart_qty} |
Unit:{' '}
{sparepart.sparepart_unit} {sparepart.sparepart_unit}
</div> </div>
</Space> </Space>
@@ -824,23 +899,9 @@ const NotificationDetailTab = (props) => {
)} )}
</Space> </Space>
</Card> </Card>
</div>
</Col> </Col>
<Col xs={24} md={8}> <Col span={8}>
<div> <Card size="small" style={{ height: '100%' }}>
<Card bodyStyle={{ padding: '12px'}}>
<Space>
<HistoryOutlined
style={{ fontSize: '16px', color: '#1890ff' }}
/>
<Text
strong
style={{ fontSize: '16px', color: '#262626' }}
>
Log Activity
</Text>
</Space>
<Space <Space
direction="vertical" direction="vertical"
size="small" size="small"
@@ -850,9 +911,7 @@ const NotificationDetailTab = (props) => {
size="small" size="small"
bodyStyle={{ bodyStyle={{
padding: '8px 12px', padding: '8px 12px',
backgroundColor: isAddingLog backgroundColor: isAddingLog ? '#fafafa' : '#fff',
? '#fafafa'
: '#fff',
}} }}
> >
<Space <Space
@@ -862,10 +921,7 @@ const NotificationDetailTab = (props) => {
> >
{isAddingLog && ( {isAddingLog && (
<> <>
<Text <Text strong style={{ fontSize: '12px' }}>
strong
style={{ fontSize: '12px' }}
>
Add New Log / Update Progress Add New Log / Update Progress
</Text> </Text>
<Input.TextArea <Input.TextArea
@@ -873,9 +929,7 @@ const NotificationDetailTab = (props) => {
placeholder="Tuliskan update penanganan di sini..." placeholder="Tuliskan update penanganan di sini..."
value={newLogDescription} value={newLogDescription}
onChange={(e) => onChange={(e) =>
setNewLogDescription( setNewLogDescription(e.target.value)
e.target.value
)
} }
disabled={submitLoading} disabled={submitLoading}
/> />
@@ -927,22 +981,18 @@ const NotificationDetailTab = (props) => {
> >
<Paragraph <Paragraph
style={{ fontSize: '12px', margin: 0 }} style={{ fontSize: '12px', margin: 0 }}
// ellipsis={{ rows: 2 }} ellipsis={{ rows: 2 }}
> >
<Text strong>{log.addedBy.name}:</Text>{' '} <Text strong>{log.addedBy.name}:</Text>{' '}
{log.description} {log.description}
</Paragraph> </Paragraph>
<Text <Text type="secondary" style={{ fontSize: '11px' }}>
type="secondary"
style={{ fontSize: '11px' }}
>
{log.timestamp} {log.timestamp}
</Text> </Text>
</Card> </Card>
))} ))}
</Space> </Space>
</Card> </Card>
</div>
</Col> </Col>
</Row> </Row>
</Space> </Space>

View File

@@ -1,85 +0,0 @@
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

@@ -1,172 +0,0 @@
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;