diff --git a/src/api/master-device.jsx b/src/api/master-device.jsx index 15ffc23..4b1e84f 100644 --- a/src/api/master-device.jsx +++ b/src/api/master-device.jsx @@ -5,7 +5,39 @@ const getAllDevice = async (queryParams) => { method: 'get', prefix: `device?${queryParams.toString()}`, }); - return response; + console.log('getAllDevice response:', response); + console.log('Query params:', queryParams.toString()); + + // Parse query params to get page and limit + const params = Object.fromEntries(queryParams); + const currentPage = parseInt(params.page) || 1; + const currentLimit = parseInt(params.limit) || 10; + + // Backend returns all data, so we need to do client-side pagination + const allData = response.data || []; + const totalData = allData.length; + + // Calculate start and end index for current page + const startIndex = (currentPage - 1) * currentLimit; + const endIndex = startIndex + currentLimit; + + // Slice data for current page + const paginatedData = allData.slice(startIndex, endIndex); + + // Transform response to match TableList expected structure + return { + status: response.statusCode || 200, + data: { + data: paginatedData, + paging: { + page: currentPage, + limit: currentLimit, + total: totalData, + page_total: Math.ceil(totalData / currentLimit) + }, + total: totalData + } + }; }; const getDeviceById = async (id) => { @@ -22,7 +54,13 @@ const createDevice = async (queryParams) => { prefix: `device`, params: queryParams, }); - return response.data; + console.log('createDevice full response:', response); + // Return full response with statusCode + return { + statusCode: response.statusCode || 200, + data: response.data, + message: response.message + }; }; const updateDevice = async (device_id, queryParams) => { @@ -31,7 +69,13 @@ const updateDevice = async (device_id, queryParams) => { prefix: `device/${device_id}`, params: queryParams, }); - return response.data; + console.log('updateDevice full response:', response); + // Return full response with statusCode + return { + statusCode: response.statusCode || 200, + data: response.data, + message: response.message + }; }; const deleteDevice = async (queryParams) => { @@ -39,7 +83,13 @@ const deleteDevice = async (queryParams) => { method: 'delete', prefix: `device/${queryParams}`, }); - return response.data; + console.log('deleteDevice full response:', response); + // Return full response with statusCode + return { + statusCode: response.statusCode || 200, + data: response.data, + message: response.message + }; }; export { getAllDevice, getDeviceById, createDevice, updateDevice, deleteDevice }; diff --git a/src/pages/master/device/IndexDevice.jsx b/src/pages/master/device/IndexDevice.jsx index 0ea060c..1649089 100644 --- a/src/pages/master/device/IndexDevice.jsx +++ b/src/pages/master/device/IndexDevice.jsx @@ -66,7 +66,7 @@ const IndexDevice = memo(function IndexDevice() { setSelectedData={setSelectedData} readOnly={readOnly} showModal={showModal} - permitDefault={true} + permitDefault={false} actionMode={actionMode} /> {actionMode == 'generatepdf' && ( diff --git a/src/pages/master/device/component/DetailDevice.jsx b/src/pages/master/device/component/DetailDevice.jsx index 77ab15f..fe299dc 100644 --- a/src/pages/master/device/component/DetailDevice.jsx +++ b/src/pages/master/device/component/DetailDevice.jsx @@ -1,21 +1,25 @@ import React, { useEffect, useState } from 'react'; -import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, Radio } from 'antd'; +import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, Radio, Select } from 'antd'; import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif'; import { createApd, getJenisPermit, updateApd } from '../../../../api/master-apd'; +import { createDevice, updateDevice } from '../../../../api/master-device'; import { Checkbox } from 'antd'; const CheckboxGroup = Checkbox.Group; const { Text } = Typography; +const { TextArea } = Input; const DetailDevice = (props) => { const [confirmLoading, setConfirmLoading] = useState(false); const defaultData = { - id_apd: '', - nama_apd: '', - type_input: 1, - is_active: true, - jenis_permit_default: [], + device_id: '', + device_code: '', + device_name: '', + device_status: true, + device_location: 'Building A', + device_description: '', + ip_address: '', }; const [FormData, setFormData] = useState(defaultData); @@ -50,16 +54,62 @@ const DetailDevice = (props) => { props.setActionMode('list'); }; + const validateIPAddress = (ip) => { + const ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + return ipRegex.test(ip); + }; + const handleSave = async () => { setConfirmLoading(true); - if (!FormData.nama_apd) { + // Validasi required fields + if (!FormData.device_code) { NotifOk({ icon: 'warning', title: 'Peringatan', - message: 'Kolom Nama APD Tidak Boleh Kosong', + message: 'Kolom Device Code Tidak Boleh Kosong', }); + setConfirmLoading(false); + return; + } + if (!FormData.device_name) { + NotifOk({ + icon: 'warning', + title: 'Peringatan', + message: 'Kolom Device Name Tidak Boleh Kosong', + }); + setConfirmLoading(false); + return; + } + + if (!FormData.device_location) { + NotifOk({ + icon: 'warning', + title: 'Peringatan', + message: 'Kolom Device Location Tidak Boleh Kosong', + }); + setConfirmLoading(false); + return; + } + + if (!FormData.ip_address) { + NotifOk({ + icon: 'warning', + title: 'Peringatan', + message: 'Kolom IP Address Tidak Boleh Kosong', + }); + setConfirmLoading(false); + return; + } + + // Validasi format IP + if (!validateIPAddress(FormData.ip_address)) { + NotifOk({ + icon: 'warning', + title: 'Peringatan', + message: 'Format IP Address Tidak Valid', + }); setConfirmLoading(false); return; } @@ -76,52 +126,49 @@ const DetailDevice = (props) => { } const payload = { - nama_apd: FormData.nama_apd, - is_active: FormData.is_active, - type_input: FormData.type_input, - jenis_permit_default: checkedList, + device_code: FormData.device_code, + device_name: FormData.device_name, + device_status: FormData.device_status, + device_location: FormData.device_location, + device_description: FormData.device_description, + ip_address: FormData.ip_address, }; - if (props.permitDefault) { - try { - let response; - if (!FormData.id_apd) { - response = await createApd(payload); - } else { - response = await updateApd(FormData.id_apd, payload); - } + try { + let response; + if (!FormData.device_id) { + response = await createDevice(payload); + } else { + response = await updateDevice(FormData.device_id, payload); + } - if (response.statusCode === 200) { - NotifOk({ - icon: 'success', - title: 'Berhasil', - message: `Data "${response.data.nama_apd}" berhasil ${ - FormData.id_apd ? 'diubah' : 'ditambahkan' - }.`, - }); + console.log('Save Device Response:', response); - props.setActionMode('list'); - } else { - NotifAlert({ - icon: 'error', - title: 'Gagal', - message: response.message || 'Terjadi kesalahan saat menyimpan data.', - }); - } - } catch (error) { + // Check if response is successful + if (response && (response.statusCode === 200 || response.statusCode === 201)) { + NotifOk({ + icon: 'success', + title: 'Berhasil', + message: `Data Device "${response.data?.device_name || FormData.device_name}" berhasil ${ + FormData.device_id ? 'diubah' : 'ditambahkan' + }.`, + }); + + props.setActionMode('list'); + } else { NotifAlert({ icon: 'error', - title: 'Error', - message: 'Terjadi kesalahan pada server. Coba lagi nanti.', + title: 'Gagal', + message: response?.message || 'Terjadi kesalahan saat menyimpan data.', }); } - } else { - props.setData((prevData) => [ - ...prevData, - { nama_apd: payload.nama_apd, type_input: payload.type_input }, - ]); - - props.setActionMode('list'); + } catch (error) { + console.error('Save Device Error:', error); + NotifAlert({ + icon: 'error', + title: 'Error', + message: error.message || 'Terjadi kesalahan pada server. Coba lagi nanti.', + }); } setConfirmLoading(false); @@ -139,22 +186,35 @@ const DetailDevice = (props) => { const isChecked = event; setFormData({ ...FormData, - is_active: isChecked ? true : false, + device_status: isChecked ? true : false, + }); + }; + + const handleSelectChange = (value) => { + setFormData({ + ...FormData, + device_location: value, }); }; useEffect(() => { const token = localStorage.getItem('token'); if (token) { - getDataJenisPermit(); + // Only call getDataJenisPermit if permitDefault is enabled + if (props.permitDefault) { + getDataJenisPermit(); + } + if (props.selectedData != null) { setFormData(props.selectedData); - setCheckedList(props.selectedData.jenis_permit_default_arr); + if (props.permitDefault && props.selectedData.jenis_permit_default_arr) { + setCheckedList(props.selectedData.jenis_permit_default_arr); + } } else { setFormData(defaultData); } } else { - navigate('/signin'); + // navigate('/signin'); // Uncomment if useNavigate is imported } }, [props.showModal]); @@ -217,74 +277,103 @@ const DetailDevice = (props) => { > {FormData && (
- {props.permitDefault && ( - <> -
-
- Aktif -
-
+
+ Device Status +
+
+
+ -
- -
-
- - {FormData.is_active == 1 ? 'Aktif' : 'Non Aktif'} - -
-
+ checked={FormData.device_status === true} + onChange={handleStatusToggle} + />
- - - )} +
+ + {FormData.device_status === true ? 'Running' : 'Offline'} + +
+
+
+ -
- Device Name +
+ Device Code *
-
- Tipe Input - * -
- -
+
+ Device Name + * + +
+
+ Device Location + * + +
+
+ Device Description +