diff --git a/src/pages/master/device/component/CardDevice.jsx b/src/pages/master/device/component/CardDevice.jsx
new file mode 100644
index 0000000..eb2ad74
--- /dev/null
+++ b/src/pages/master/device/component/CardDevice.jsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import { Card, Button, Row, Col, Typography, Space, Tag } from 'antd';
+import { EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
+
+const { Text } = Typography;
+
+const CardDevice = ({ data, showPreviewModal, showEditModal, showDeleteDialog }) => {
+ const getCardStyle = () => {
+ const color = '#FF8C42'; // Orange color
+ return {
+ border: `2px solid ${color}`,
+ borderRadius: '8px',
+ textAlign: 'center' // Center text
+ };
+ };
+
+ const getTitleStyle = () => {
+ const backgroundColor = '#FF8C42'; // Orange color
+ return {
+ backgroundColor,
+ color: '#fff',
+ padding: '2px 8px',
+ borderRadius: '4px',
+ display: 'inline-block',
+ };
+ };
+
+ return (
+
+ {data.map((item) => (
+
+
+ {item.device_name}
+
+ }
+ style={getCardStyle()}
+ actions={[
+
+ }
+ onClick={() => showPreviewModal(item)}
+ />
+ }
+ onClick={() => showEditModal(item)}
+ />
+ }
+ onClick={() => showDeleteDialog(item)}
+ />
+ ,
+ ]}
+ >
+
+ Code: {item.device_code}
+
+
+ Location: {item.device_location}
+
+
+ IP Address: {item.ip_address}
+
+
+ Status:{' '}
+
+ {item.device_status ? 'Running' : 'Offline'}
+
+
+
+
+ ))}
+
+ );
+};
+
+export default CardDevice;
diff --git a/src/pages/master/device/component/ListDevice.jsx b/src/pages/master/device/component/ListDevice.jsx
index 9861c89..b1bafa8 100644
--- a/src/pages/master/device/component/ListDevice.jsx
+++ b/src/pages/master/device/component/ListDevice.jsx
@@ -7,27 +7,23 @@ import {
Row,
Col,
Card,
- Divider,
- Form,
Input,
- Dropdown,
+ Segmented,
} from 'antd';
import {
PlusOutlined,
- FilterOutlined,
EditOutlined,
DeleteOutlined,
EyeOutlined,
SearchOutlined,
- FilePdfOutlined,
- FileExcelOutlined,
- EllipsisOutlined,
+ AppstoreOutlined,
+ TableOutlined,
} from '@ant-design/icons';
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../../components/Global/ToastNotif';
import { useNavigate } from 'react-router-dom';
-import { deleteApd, getAllApd } from '../../../../api/master-apd';
import { deleteDevice, getAllDevice } from '../../../../api/master-device';
import TableList from '../../../../components/Global/TableList';
+import CardDevice from './CardDevice';
import { getFilterData } from '../../../../components/Global/DataFilter';
import ExcelJS from 'exceljs';
import { saveAs } from 'file-saver';
@@ -119,6 +115,8 @@ const columns = (showPreviewModal, showEditModal, showDeleteDialog) => [
const ListDevice = memo(function ListDevice(props) {
const [showFilter, setShowFilter] = useState(false);
const [trigerFilter, setTrigerFilter] = useState(false);
+ const [viewMode, setViewMode] = useState('card');
+ const [deviceData, setDeviceData] = useState([]);
const defaultFilter = { criteria: '' };
const [formDataFilter, setFormDataFilter] = useState(defaultFilter);
@@ -126,10 +124,19 @@ const ListDevice = memo(function ListDevice(props) {
const navigate = useNavigate();
+ const fetchData = async () => {
+ try {
+ const response = await getAllDevice(formDataFilter);
+ setDeviceData(response.data.data);
+ } catch (error) {
+ console.error("Failed to fetch device data:", error);
+ }
+ };
+
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
- if (props.actionMode == 'list') {
+ if (props.actionMode === 'list') {
setFormDataFilter(defaultFilter);
doFilter();
}
@@ -138,6 +145,10 @@ const ListDevice = memo(function ListDevice(props) {
}
}, [props.actionMode]);
+ useEffect(() => {
+ fetchData();
+ }, [trigerFilter]);
+
const toggleFilter = () => {
setFormDataFilter(defaultFilter);
setShowFilter((prev) => !prev);
@@ -186,8 +197,7 @@ const ListDevice = memo(function ListDevice(props) {
const handleDelete = async (device_id) => {
const response = await deleteDevice(device_id);
- // Backend returns: { statusCode: 200, message: "Device deleted successfully", rows: null, data: true }
- if (response.statusCode == 200 && response.data === true) {
+ if (response.statusCode === 200 && response.data === true) {
NotifAlert({
icon: 'success',
title: 'Berhasil',
@@ -213,7 +223,6 @@ const ListDevice = memo(function ListDevice(props) {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('Data APD');
let rowCursor = 1;
- // Kop Logo PIE
if (logoPiEnergi) {
const response = await fetch(logoPiEnergi);
const blob = await response.blob();
@@ -224,24 +233,21 @@ const ListDevice = memo(function ListDevice(props) {
extension: 'png',
});
- // Tempatkan gambar di pojok atas
sheet.addImage(imageId, {
tl: { col: 0.2, row: 0.8 },
ext: { width: 163, height: 80 },
});
- sheet.getRow(5).height = 15; // biar ada jarak ke tabel
+ sheet.getRow(5).height = 15;
rowCursor = 3;
}
- // Tambah Judul
const titleCell = sheet.getCell(`C${rowCursor}`);
titleCell.value = 'Data APD';
titleCell.font = { size: 20, bold: true, color: { argb: 'FF00AEEF' } };
titleCell.alignment = { vertical: 'middle', horizontal: 'center' };
sheet.mergeCells(`C${rowCursor}:F${rowCursor}`);
- // Header tabel
const headers = [
'ID APD',
'Nama APD',
@@ -256,12 +262,11 @@ const ListDevice = memo(function ListDevice(props) {
headerRow.font = { bold: true, size: 12 };
headerRow.eachCell((cell) => {
cell.alignment = {
- horizontal: 'center', // rata tengah kiri-kanan
- vertical: 'middle', // rata tengah atas-bawah
+ horizontal: 'center',
+ vertical: 'middle',
};
});
- // Tambahkan data
data.forEach((item) => {
sheet.addRow([
item.id_apd,
@@ -274,7 +279,6 @@ const ListDevice = memo(function ListDevice(props) {
]);
});
- // Auto width
sheet.columns.forEach((col) => {
let maxLength = 10;
col.eachCell({ includeEmpty: true }, (cell) => {
@@ -284,7 +288,6 @@ const ListDevice = memo(function ListDevice(props) {
col.width = maxLength + 2;
});
- // Export
const buffer = await workbook.xlsx.writeBuffer();
saveAs(new Blob([buffer]), 'Data_APD.xlsx');
};
@@ -302,7 +305,6 @@ const ListDevice = memo(function ListDevice(props) {
onChange={(e) => {
const value = e.target.value;
setSearchValue(value);
- // Auto search when clearing by backspace/delete
if (value === '') {
setFormDataFilter({ criteria: '' });
setTrigerFilter((prev) => !prev);
@@ -329,6 +331,14 @@ const ListDevice = memo(function ListDevice(props) {
+ },
+ { value: 'table', icon: },
+ ]}
+ value={viewMode}
+ onChange={setViewMode}
+ />
-
+ {viewMode === 'card' ? (
+
+ ) : (
+
+ )}