lavoce #42
92
package.json
92
package.json
@@ -1,48 +1,48 @@
|
|||||||
{
|
{
|
||||||
"name": "antd-vite-react-call-of-duty",
|
"name": "antd-vite-react-call-of-duty",
|
||||||
"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",
|
"dev": "vite --host 0.0.0.0 --port 8592",
|
||||||
"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"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^6.0.0",
|
"@ant-design/icons": "^6.0.0",
|
||||||
"@nivo/line": "^0.88.0",
|
"@nivo/line": "^0.88.0",
|
||||||
"@nivo/pie": "^0.88.0",
|
"@nivo/pie": "^0.88.0",
|
||||||
"antd": "^5.15.2",
|
"antd": "^5.15.2",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"browser-image-compression": "^2.0.2",
|
"browser-image-compression": "^2.0.2",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"jspdf": "^3.0.4",
|
"jspdf": "^3.0.4",
|
||||||
"jspdf-autotable": "^5.0.2",
|
"jspdf-autotable": "^5.0.2",
|
||||||
"mqtt": "^5.14.0",
|
"mqtt": "^5.14.0",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"react-svg": "^16.3.0",
|
"react-svg": "^16.3.0",
|
||||||
"recharts": "^3.6.0",
|
"recharts": "^3.6.0",
|
||||||
"sweetalert2": "^11.17.2"
|
"sweetalert2": "^11.17.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.2.64",
|
"@types/react": "^18.2.64",
|
||||||
"@types/react-dom": "^18.2.21",
|
"@types/react-dom": "^18.2.21",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-react": "^7.34.0",
|
"eslint-plugin-react": "^7.34.0",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.5",
|
"eslint-plugin-react-refresh": "^0.4.5",
|
||||||
"vite": "^5.1.6"
|
"vite": "^5.1.6"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
|
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ 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 IndexWebControl from './pages/webControl/IndexWebControl';
|
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,8 +145,8 @@ const App = () => {
|
|||||||
<Route index element={<IndexUser />} />
|
<Route index element={<IndexUser />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="/web-control" element={<ProtectedRoute />}>
|
<Route path="/whatsapp-control" element={<ProtectedRoute />}>
|
||||||
<Route index element={<IndexWebControl />} />
|
<Route index element={<IndexWhatsAppControl />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="/contact" element={<ProtectedRoute />}>
|
<Route path="/contact" element={<ProtectedRoute />}>
|
||||||
|
|||||||
@@ -9,6 +9,4 @@ const resetWA = async () => {
|
|||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export { resetWA };
|
||||||
resetWA,
|
|
||||||
};
|
|
||||||
@@ -227,11 +227,11 @@ const allItems = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'web-control',
|
key: 'whatsapp-control',
|
||||||
icon: <GlobalOutlined style={{ fontSize: '19px' }} />,
|
icon: <GlobalOutlined style={{ fontSize: '19px' }} />,
|
||||||
label: (
|
label: (
|
||||||
<Link to="/web-control" className="fontMenus">
|
<Link to="/whatsapp-control" className="fontMenus">
|
||||||
Web Control
|
WhatsApp Control
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -260,7 +260,7 @@ 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 === '/web-control') return 'web-control';
|
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';
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import React, { useState, useEffect, memo } from 'react';
|
import React, { useState, useEffect, memo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Button, Typography } from 'antd';
|
import { Button, Typography } from 'antd';
|
||||||
import { resetWA } from '../../api/web-control';
|
import { resetWA } from '../../api/whatsapp-control';
|
||||||
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
|
import { useBreadcrumb } from '../../layout/LayoutBreadcrumb';
|
||||||
import { ReloadOutlined } from '@ant-design/icons';
|
import { ReloadOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
const IndexWebControl = memo(function IndexWebControl() {
|
const IndexWhatsAppControl = memo(function IndexWhatsAppControl() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { setBreadcrumbItems } = useBreadcrumb();
|
const { setBreadcrumbItems } = useBreadcrumb();
|
||||||
|
|
||||||
const [isPlaying, setIsPlaying] = useState(true);
|
const [isPlaying, setIsPlaying] = useState(true);
|
||||||
|
|
||||||
const url = "http://localhost:9531/qrview";
|
const url = import.meta.env.VITE_WHATSAPP_URL;
|
||||||
|
|
||||||
const handleReset = async() => {
|
const handleReset = async () => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
await resetWA();
|
await resetWA();
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
@@ -29,7 +29,7 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
{
|
{
|
||||||
title: (
|
title: (
|
||||||
<Text strong style={{ fontSize: '14px' }}>
|
<Text strong style={{ fontSize: '14px' }}>
|
||||||
• Web Control Panel
|
• WhatsApp Control Panel
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -41,10 +41,9 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '20px' }}>
|
<div style={{ padding: '20px' }}>
|
||||||
|
|
||||||
<div style={{ marginBottom: 20 }}>
|
<div style={{ marginBottom: 20 }}>
|
||||||
<Button type="primary" onClick={handleReset} style={{ marginRight: 10 }}>
|
<Button type="primary" onClick={handleReset} style={{ marginRight: 10 }}>
|
||||||
<ReloadOutlined/> Restart WhatsApp
|
<ReloadOutlined /> Restart WhatsApp
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
{isPlaying ? (
|
{isPlaying ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={url}
|
src={url}
|
||||||
title="Web Preview"
|
title="WhatsApp Preview"
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -83,4 +82,4 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IndexWebControl;
|
export default IndexWhatsAppControl;
|
||||||
@@ -12,27 +12,27 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
const { setBreadcrumbItems } = useBreadcrumb();
|
const { setBreadcrumbItems } = useBreadcrumb();
|
||||||
|
|
||||||
const [isPlaying, setIsPlaying] = useState(true);
|
const [isPlaying, setIsPlaying] = useState(true);
|
||||||
const [currentUrl, setCurrentUrl] = useState("http://localhost:9531");
|
const [currentUrl, setCurrentUrl] = useState('http://localhost:9531');
|
||||||
const iframeRef = useRef(null);
|
const iframeRef = useRef(null);
|
||||||
|
|
||||||
const handleReset = async() => {
|
const handleReset = async () => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
await resetWA();
|
await resetWA();
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
// Kembali ke halaman login setelah reset
|
// Kembali ke halaman login setelah reset
|
||||||
setCurrentUrl("https://localhost:9531");
|
setCurrentUrl('https://localhost:9531');
|
||||||
message.success('WhatsApp berhasil di-restart');
|
message.success('WhatsApp berhasil di-restart');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fungsi untuk redirect ke QR View
|
// Fungsi untuk redirect ke QR View
|
||||||
const redirectToQRView = () => {
|
const redirectToQRView = () => {
|
||||||
setCurrentUrl("https://localhost:9531/qrview");
|
setCurrentUrl('https://localhost:9531/qrview');
|
||||||
message.info('Redirecting to QR View...');
|
message.info('Redirecting to QR View...');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fungsi untuk kembali ke login
|
// Fungsi untuk kembali ke login
|
||||||
const backToLogin = () => {
|
const backToLogin = () => {
|
||||||
setCurrentUrl("https://localhost:9531");
|
setCurrentUrl('https://localhost:9531');
|
||||||
message.info('Back to login page');
|
message.info('Back to login page');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,10 +65,12 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
// Jika pesan adalah string
|
// Jika pesan adalah string
|
||||||
if (typeof event.data === 'string') {
|
if (typeof event.data === 'string') {
|
||||||
const lowerData = event.data.toLowerCase();
|
const lowerData = event.data.toLowerCase();
|
||||||
if (lowerData.includes('login') ||
|
if (
|
||||||
|
lowerData.includes('login') ||
|
||||||
lowerData.includes('success') ||
|
lowerData.includes('success') ||
|
||||||
lowerData.includes('authenticated') ||
|
lowerData.includes('authenticated') ||
|
||||||
lowerData.includes('qrview')) {
|
lowerData.includes('qrview')
|
||||||
|
) {
|
||||||
console.log('Login detected via string message');
|
console.log('Login detected via string message');
|
||||||
redirectToQRView();
|
redirectToQRView();
|
||||||
}
|
}
|
||||||
@@ -76,10 +78,12 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
|
|
||||||
// Jika pesan adalah object
|
// Jika pesan adalah object
|
||||||
if (typeof event.data === 'object') {
|
if (typeof event.data === 'object') {
|
||||||
if (event.data.type === 'LOGIN_SUCCESS' ||
|
if (
|
||||||
|
event.data.type === 'LOGIN_SUCCESS' ||
|
||||||
event.data.status === 'success' ||
|
event.data.status === 'success' ||
|
||||||
event.data.logged_in === true ||
|
event.data.logged_in === true ||
|
||||||
event.data.redirect === true) {
|
event.data.redirect === true
|
||||||
|
) {
|
||||||
console.log('Login detected via object message');
|
console.log('Login detected via object message');
|
||||||
redirectToQRView();
|
redirectToQRView();
|
||||||
}
|
}
|
||||||
@@ -99,7 +103,7 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
// Jika tidak ada pesan dari iframe, coba redirect otomatis setelah 10 detik
|
// Jika tidak ada pesan dari iframe, coba redirect otomatis setelah 10 detik
|
||||||
// Asumsi: login biasanya selesai dalam 10 detik
|
// Asumsi: login biasanya selesai dalam 10 detik
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
if (currentUrl === "https://localhost:9531") {
|
if (currentUrl === 'https://localhost:9531') {
|
||||||
console.log('Auto redirect after 10 seconds (fallback)');
|
console.log('Auto redirect after 10 seconds (fallback)');
|
||||||
redirectToQRView();
|
redirectToQRView();
|
||||||
}
|
}
|
||||||
@@ -112,7 +116,7 @@ const IndexWebControl = memo(function IndexWebControl() {
|
|||||||
<div style={{ padding: '20px' }}>
|
<div style={{ padding: '20px' }}>
|
||||||
<div style={{ marginBottom: 20, display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
<div style={{ marginBottom: 20, display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||||||
<Button type="primary" onClick={handleReset}>
|
<Button type="primary" onClick={handleReset}>
|
||||||
<ReloadOutlined/> Restart WhatsApp
|
<ReloadOutlined /> Restart WhatsApp
|
||||||
</Button>
|
</Button>
|
||||||
{/* <Button onClick={redirectToQRView} type="default">
|
{/* <Button onClick={redirectToQRView} type="default">
|
||||||
Redirect ke QR View
|
Redirect ke QR View
|
||||||
Reference in New Issue
Block a user