From 8d03a0a52e7ef2918f63cd81e6ea3523fc2408e0 Mon Sep 17 00:00:00 2001 From: bragaz_rexita Date: Thu, 23 Apr 2026 22:26:34 +0700 Subject: [PATCH] Add Checkbox and Input Scheduler Date --- src/components/Global/AppInput.jsx | 52 +++++++++++ .../master/device/component/DetailDevice.jsx | 76 ++++++++++----- .../sparepart/component/DetailSparepart.jsx | 93 ++++++++++++++++++- .../sparepart/component/ListSparepart.jsx | 4 +- 4 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 src/components/Global/AppInput.jsx diff --git a/src/components/Global/AppInput.jsx b/src/components/Global/AppInput.jsx new file mode 100644 index 0000000..620d0bd --- /dev/null +++ b/src/components/Global/AppInput.jsx @@ -0,0 +1,52 @@ +import { Input } from "antd"; +import { useEffect, useState, useRef } from "react"; + +const InputNumber = ({ + name, + value = 0, + onChange, + ...props +}) => { + const [inputValue, setInputValue] = useState( + value !== null && value !== undefined ? value.toString() : '' + ); + + useEffect(() => { + const newValue = value !== null && value !== undefined ? value.toString() : ''; + setInputValue(newValue); + }, [value]); + + const handleChange = (e) => { + const rawValue = e.target.value; + if (/^\d*$/.test(rawValue)) { + setInputValue(rawValue); + const numValue = rawValue === '' ? 0 : parseInt(rawValue, 10); + + // Kirim event object sintetis yang konsisten dengan handler biasa + onChange?.({ + target: { + name: name, + value: numValue + } + }); + } + }; + + const handleFocus = (e) => { + // Pilih semua teks saat fokus (opsional) + e.target.select(); + }; + + return ( + + ); +}; + +export { InputNumber }; diff --git a/src/pages/master/device/component/DetailDevice.jsx b/src/pages/master/device/component/DetailDevice.jsx index 3bd9c35..1015e74 100644 --- a/src/pages/master/device/component/DetailDevice.jsx +++ b/src/pages/master/device/component/DetailDevice.jsx @@ -1,9 +1,11 @@ import React, { useEffect, useState } from 'react'; -import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, Select } from 'antd'; +import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, Select, DatePicker } from 'antd'; import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif'; import { createDevice, updateDevice } from '../../../../api/master-device'; import { getAllBrands } from '../../../../api/master-brand'; import { validateRun } from '../../../../Utils/validate'; +import { toApiDateFormatter } from '../../../../components/Global/Formatter'; +import dayjs from 'dayjs'; const { Text } = Typography; const { TextArea } = Input; @@ -12,6 +14,8 @@ const DetailDevice = (props) => { const [confirmLoading, setConfirmLoading] = useState(false); const [brands, setBrands] = useState([]); const [loadingBrands, setLoadingBrands] = useState(false); + const dateNow = dayjs(); + const [schedulerDate, setSchedulerDate] = useState(dateNow); const defaultData = { device_id: '', @@ -23,6 +27,7 @@ const DetailDevice = (props) => { device_location: '', device_description: '', ip_address: '', + scheduler_date: '', listen_channel: '', }; @@ -41,6 +46,7 @@ const DetailDevice = (props) => { { field: 'device_name', label: 'Device Name', required: true }, { field: 'ip_address', label: 'Ip Address', required: true, ip: true }, { field: 'brand_id', label: 'Brand Device', required: true }, + { field: 'scheduler_date', label: 'Tanggaln(Scheduler)', required: true }, ]; if ( @@ -67,32 +73,35 @@ const DetailDevice = (props) => { ip_address: formData.ip_address, brand_id: formData.brand_id, listen_channel: formData.listen_channel, + scheduler_date: toApiDateFormatter(formData.scheduler_date) }; - const response = formData.device_id - ? await updateDevice(formData.device_id, payload) - : await createDevice(payload); + console.log(payload); - // Check if response is successful - if (response && (response.statusCode === 200 || response.statusCode === 201)) { - const deviceName = response.data?.device_name || formData.device_name; + // const response = formData.device_id + // ? await updateDevice(formData.device_id, payload) + // : await createDevice(payload); - NotifOk({ - icon: 'success', - title: 'Berhasil', - message: `Data Device "${deviceName}" berhasil ${ - formData.device_id ? 'diubah' : 'ditambahkan' - }.`, - }); + // // Check if response is successful + // if (response && (response.statusCode === 200 || response.statusCode === 201)) { + // const deviceName = response.data?.device_name || formData.device_name; - props.setActionMode('list'); - } else { - NotifAlert({ - icon: 'error', - title: 'Gagal', - message: response?.message || 'Terjadi kesalahan saat menyimpan data.', - }); - } + // NotifOk({ + // icon: 'success', + // title: 'Berhasil', + // message: `Data Device "${deviceName}" berhasil ${ + // formData.device_id ? 'diubah' : 'ditambahkan' + // }.`, + // }); + + // props.setActionMode('list'); + // } else { + // NotifAlert({ + // icon: 'error', + // title: 'Gagal', + // message: response?.message || 'Terjadi kesalahan saat menyimpan data.', + // }); + // } } catch (error) { console.error('Save Device Error:', error); NotifAlert({ @@ -128,6 +137,13 @@ const DetailDevice = (props) => { }); }; + const handleDateChange = (field, value) => { + setFormData({ + ...formData, + [field]: value, + }); + }; + // Fungsi untuk mengambil daftar brand const fetchBrands = async () => { setLoadingBrands(true); @@ -218,9 +234,10 @@ const DetailDevice = (props) => { , ]} > + {formData && (
-
+
Device Status
@@ -247,7 +264,7 @@ const DetailDevice = (props) => {
- + {/* */} +
+ Scheduler Date + + handleDateChange("scheduler_date", dateString) + } + format="DD-MM-YYYY" + style={{ width: '100%', marginTop: '4px' }} + /> +
Device Description