From e13539618b816b1c532c534e73f8a941c5f7b335 Mon Sep 17 00:00:00 2001 From: Iqbal Rizqi Kurniawan Date: Thu, 9 Oct 2025 10:50:27 +0700 Subject: [PATCH] add plant section management with list and detail views --- src/App.jsx | 1 + src/layout/LayoutMenu.jsx | 5 + .../master/plantSection/IndexPlantSection.jsx | 215 ++++++++++++++++++ .../component/DetailPlantSection.jsx | 106 +++++++++ .../component/ListPlantSection.jsx | 139 +++++++++++ 5 files changed, 466 insertions(+) create mode 100644 src/pages/master/plantSection/IndexPlantSection.jsx create mode 100644 src/pages/master/plantSection/component/DetailPlantSection.jsx create mode 100644 src/pages/master/plantSection/component/ListPlantSection.jsx diff --git a/src/App.jsx b/src/App.jsx index 91b534b..66657b0 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -14,6 +14,7 @@ import IndexDevice from './pages/master/device/IndexDevice'; import IndexTag from './pages/master/tag/IndexTag'; import IndexBrandDevice from './pages/master/brandDevice/IndexBrandDevice'; import IndexErrorCode from './pages/master/errorCode/IndexErrorCode'; +import IndexPlantSection from './pages/master/plantSection/IndexPlantSection'; // History import IndexTrending from './pages/history/trending/IndexTrending'; diff --git a/src/layout/LayoutMenu.jsx b/src/layout/LayoutMenu.jsx index f813883..382a1dc 100644 --- a/src/layout/LayoutMenu.jsx +++ b/src/layout/LayoutMenu.jsx @@ -41,6 +41,11 @@ const allItems = [ icon: , label: 'Master', children: [ + { + key: 'master-plant-section', + icon: , + label: Plant Section, + }, { key: 'master-device', icon: , diff --git a/src/pages/master/plantSection/IndexPlantSection.jsx b/src/pages/master/plantSection/IndexPlantSection.jsx new file mode 100644 index 0000000..73671bb --- /dev/null +++ b/src/pages/master/plantSection/IndexPlantSection.jsx @@ -0,0 +1,215 @@ + +import React, { memo, useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb'; +import { Form, Typography } from 'antd'; +import ListPlantSection from './component/ListPlantSection'; +import DetailPlantSection from './component/DetailPlantSection'; + +import { NotifConfirmDialog, NotifAlert } from '../../../components/Global/ToastNotif'; + +const { Text } = Typography; + +// Mock Data +const initialData = [ + { + key: '1', + kode_plant: 'PL-001', + nama_plant: 'Seksi Produksi A', + lokasi_plant: 'Gedung 1, Lantai 2', + deskripsi: 'Seksi yang bertanggung jawab untuk lini produksi A.', + }, + { + key: '2', + kode_plant: 'PL-002', + nama_plant: 'Seksi Pengepakan', + lokasi_plant: 'Gedung 1, Lantai 1', + deskripsi: 'Area pengepakan dan persiapan pengiriman.', + }, + { + key: '3', + kode_plant: 'PL-003', + nama_plant: 'Gudang Bahan Baku', + lokasi_plant: 'Gudang A', + deskripsi: 'Penyimpanan bahan baku utama.', + }, + { + key: '4', + kode_plant: 'PL-004', + nama_plant: 'Seksi Kualitas', + lokasi_plant: 'Laboratorium QC', + deskripsi: 'Pemeriksaan dan kontrol kualitas produk.', + }, + { + key: '5', + kode_plant: 'PL-005', + nama_plant: 'Seksi Perawatan', + lokasi_plant: 'Workshop', + deskripsi: 'Perawatan dan perbaikan mesin produksi.', + }, + { + key: '6', + kode_plant: 'PL-006', + nama_plant: 'Gudang Jadi', + lokasi_plant: 'Gudang B', + deskripsi: 'Penyimpanan produk yang siap dikirim.', + }, +]; + +const IndexPlantSection = memo(function IndexPlantSection() { + const navigate = useNavigate(); + const { setBreadcrumbItems } = useBreadcrumb(); + const [form] = Form.useForm(); + + const [data, setData] = useState(initialData); + const [actionMode, setActionMode] = useState('list'); + const [editingKey, setEditingKey] = useState(''); + const [isModalVisible, setIsModalVisible] = useState(false); + const [readOnly, setReadOnly] = useState(false); + + // Mock API function + const getAllPlantSection = async (params) => { + const { page = 1, limit = 10, search = '' } = Object.fromEntries(params.entries()); + + let filteredData = data; + if (search) { + filteredData = data.filter(item => + item.nama_plant.toLowerCase().includes(search.toLowerCase()) || + item.kode_plant.toLowerCase().includes(search.toLowerCase()) || + item.lokasi_plant.toLowerCase().includes(search.toLowerCase()) + ); + } + + const start = (page - 1) * limit; + const end = start + limit; + const paginatedData = filteredData.slice(start, end); + + return new Promise(resolve => { + setTimeout(() => { + resolve({ + status: 200, + data: { + data: paginatedData, + total: filteredData.length, + paging: { + page: parseInt(page), + limit: parseInt(limit), + total: filteredData.length, + }, + }, + }); + }, 500); + }); + }; + + useEffect(() => { + const token = localStorage.getItem('token'); + if (token) { + setBreadcrumbItems([ + { title: • Master }, + { title: Plant Section } + ]); + } else { + navigate('/signin'); + } + }, [navigate, setBreadcrumbItems]); + + useEffect(() => { + if (actionMode === 'add' || actionMode === 'edit' || actionMode === 'preview') { + setIsModalVisible(true); + setReadOnly(actionMode === 'preview'); + } else { + setIsModalVisible(false); + } + }, [actionMode]); + + const handleCancel = () => { + setActionMode('list'); + setEditingKey(''); + form.resetFields(); + }; + + const handleOk = () => { + if (readOnly) { + handleCancel(); + return; + } + form.validateFields() + .then((values) => { + let newData = [...data]; + if (editingKey) { + // Editing existing data + const index = newData.findIndex((item) => editingKey === item.key); + if (index > -1) { + const item = newData[index]; + newData.splice(index, 1, { ...item, ...values }); + } + } else { + // Adding new data + const newKey = (Math.max(...data.map(item => parseInt(item.key))) + 1).toString(); + newData = [{ key: newKey, ...values }, ...newData]; + } + setData(newData); + NotifAlert({ + icon: 'success', + title: 'Berhasil', + message: 'Data Plant Section berhasil disimpan.', + }); + handleCancel(); + }) + .catch((info) => { + console.log('Validate Failed:', info); + }); + }; + + const handleEdit = (record) => { + form.setFieldsValue(record); + setEditingKey(record.key); + setActionMode('edit'); + }; + + const handlePreview = (record) => { + form.setFieldsValue(record); + setEditingKey(record.key); + setActionMode('preview'); + }; + + const handleDelete = (record) => { + NotifConfirmDialog({ + icon: 'question', + title: 'Konfirmasi', + message: `Apakah anda yakin ingin menghapus plant section "${record.nama_plant}"?`, + onConfirm: () => { + const newData = data.filter((item) => item.key !== record.key); + setData(newData); + NotifAlert({ + icon: 'success', + title: 'Berhasil', + message: `Plant section "${record.nama_plant}" berhasil dihapus.`, + }); + }, + }); + }; + + return ( + + + + + ); +}); + +export default IndexPlantSection; diff --git a/src/pages/master/plantSection/component/DetailPlantSection.jsx b/src/pages/master/plantSection/component/DetailPlantSection.jsx new file mode 100644 index 0000000..cef0416 --- /dev/null +++ b/src/pages/master/plantSection/component/DetailPlantSection.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { Modal, Form, Input, ConfigProvider, Button, Typography } from 'antd'; + +const { Text } = Typography; + +const DetailPlantSection = ({ visible, onCancel, onOk, form, editingKey, readOnly }) => { + const modalTitle = readOnly ? 'Preview Plant Section' : (editingKey ? 'Edit Plant Section' : 'Tambah Plant Section'); + + return ( + + + + + + {!readOnly && ( + + )} + + , + ]} + destroyOnClose + > +
+
+ Kode Plant + * + + + +
+
+ Nama Plant + * + + + +
+
+ Lokasi Plant + * + + + +
+
+ Deskripsi + + + +
+
+
+ ); +}; + +export default DetailPlantSection; \ No newline at end of file diff --git a/src/pages/master/plantSection/component/ListPlantSection.jsx b/src/pages/master/plantSection/component/ListPlantSection.jsx new file mode 100644 index 0000000..dfb7c3f --- /dev/null +++ b/src/pages/master/plantSection/component/ListPlantSection.jsx @@ -0,0 +1,139 @@ +import React, { useState } from 'react'; +import { Button, Col, Row, Space, Input, ConfigProvider, Card } from 'antd'; +import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined, EyeOutlined } from '@ant-design/icons'; +import TableList from '../../../../components/Global/TableList'; + +const ListPlantSection = ({ + setActionMode, + handleEdit, + handleDelete, + handlePreview, + getAllPlantSection +}) => { + const [searchValue, setSearchValue] = useState(''); + const [formDataFilter, setFormDataFilter] = useState({ search: '' }); + const [trigerFilter, setTrigerFilter] = useState(false); + + const columns = [ + { + title: 'No', + dataIndex: 'key', + key: 'key', + width: '5%', + render: (text, record, index) => index + 1, + }, + { + title: 'Kode Plant', + dataIndex: 'kode_plant', + key: 'kode_plant', + }, + { + title: 'Nama Plant', + dataIndex: 'nama_plant', + key: 'nama_plant', + }, + { + title: 'Lokasi Plant', + dataIndex: 'lokasi_plant', + key: 'lokasi_plant', + }, + { + title: 'Deskripsi', + dataIndex: 'deskripsi', + key: 'deskripsi', + }, + { + title: 'Aksi', + key: 'action', + render: (_, record) => ( + + + } + size="large" + /> + + + + + + + + + + + + ); +}; + +export default ListPlantSection; \ No newline at end of file