diff --git a/src/pages/master/brandDevice/IndexBrandDevice.jsx b/src/pages/master/brandDevice/IndexBrandDevice.jsx index aa60fc3..a8aac49 100644 --- a/src/pages/master/brandDevice/IndexBrandDevice.jsx +++ b/src/pages/master/brandDevice/IndexBrandDevice.jsx @@ -1,13 +1,97 @@ -import React, { memo, useEffect } from 'react'; + +import React, { memo, useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb'; -import { Typography } from 'antd'; +import { Form, Modal, Typography } from 'antd'; +import ListBrandDevice from './component/ListBrandDevice'; +import DetailBrandDevice from './component/DetailBrandDevice'; + +import { NotifConfirmDialog, NotifAlert } from '../../../components/Global/ToastNotif'; const { Text } = Typography; +// Mock Data +const initialData = [ + { + key: '1', + brandCode: 'HTC-01', + brandName: 'Brand A', + brandType: 'Type X', + deviceName: 'Device 1', + description: 'Description for Brand A', + }, + { + key: '2', + brandCode: 'HTC-02', + brandName: 'Brand B', + brandType: 'Type Y', + deviceName: 'Device 2', + description: 'Description for Brand B', + }, + { + key: '3', + brandCode: 'HTC-03', + brandName: 'Brand C', + brandType: 'Type Z', + deviceName: 'Device 3', + description: 'Description for Brand C', + }, + // Add more data for pagination testing + ...Array.from({ length: 20 }, (_, i) => ({ + key: `${i + 4}`, + brandCode: `HTC-${String(i + 4).padStart(2, '0')}`, + brandName: `Brand ${String.fromCharCode(68 + i)}`, + brandType: `Type ${String.fromCharCode(88 + i)}`, + deviceName: `Device ${i + 4}`, + description: `Description for Brand ${String.fromCharCode(68 + i)}`, + })), +]; + const IndexBrandDevice = memo(function IndexBrandDevice() { 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 getAllBrandDevice = async (params) => { + const { page = 1, limit = 10, search = '' } = Object.fromEntries(params.entries()); + + let filteredData = data; + if (search) { + filteredData = data.filter(item => + item.brandName.toLowerCase().includes(search.toLowerCase()) || + item.brandType.toLowerCase().includes(search.toLowerCase()) || + item.deviceName.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'); @@ -19,12 +103,98 @@ const IndexBrandDevice = memo(function IndexBrandDevice() { } 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); + 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 brand "${record.brandName}"?`, + onConfirm: () => { + const newData = data.filter((item) => item.key !== record.key); + setData(newData); + NotifAlert({ + icon: 'success', + title: 'Berhasil', + message: `Brand "${record.brandName}" berhasil dihapus.`, + }); + }, + }); + }; return ( -
-

Brand Device Page

-
+ + + + ); }); diff --git a/src/pages/master/brandDevice/component/DetailBrandDevice.jsx b/src/pages/master/brandDevice/component/DetailBrandDevice.jsx new file mode 100644 index 0000000..f2a4a3a --- /dev/null +++ b/src/pages/master/brandDevice/component/DetailBrandDevice.jsx @@ -0,0 +1,117 @@ +import React from 'react'; +import { Modal, Form, Input, ConfigProvider, Button, Typography } from 'antd'; + +const { Text } = Typography; + +const DetailBrandDevice = ({ visible, onCancel, onOk, form, editingKey, readOnly }) => { + const modalTitle = readOnly ? 'Preview Brand' : (editingKey ? 'Edit Brand' : 'Tambah Brand'); + + return ( + + + + + + {!readOnly && ( + + )} + + , + ]} + destroyOnClose + > +
+
+ Kode Brand + * + + + +
+
+ Brand Name + * + + + +
+
+ Brand Type + * + + + +
+
+ Device Name + * + + + +
+
+ Description + + + +
+
+
+ ); +}; + +export default DetailBrandDevice; \ No newline at end of file diff --git a/src/pages/master/brandDevice/component/ListBrandDevice.jsx b/src/pages/master/brandDevice/component/ListBrandDevice.jsx new file mode 100644 index 0000000..b015d6c --- /dev/null +++ b/src/pages/master/brandDevice/component/ListBrandDevice.jsx @@ -0,0 +1,137 @@ +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 ListBrandDevice = ({ + setActionMode, + handleEdit, + handleDelete, + handlePreview, + getAllBrandDevice // Mock API function +}) => { + const [searchValue, setSearchValue] = useState(''); + const [formDataFilter, setFormDataFilter] = useState({ search: '' }); + const [trigerFilter, setTrigerFilter] = useState(false); + + const columns = [ + { + title: 'Kode Brand', + dataIndex: 'brandCode', + key: 'brandCode', + }, + { + title: 'Brand Name', + dataIndex: 'brandName', + key: 'brandName', + }, + { + title: 'Brand Type', + dataIndex: 'brandType', + key: 'brandType', + }, + { + title: 'Device Name', + dataIndex: 'deviceName', + key: 'deviceName', + }, + { + title: 'Description', + dataIndex: 'description', + key: 'description', + }, + { + title: 'Aksi', + key: 'action', + render: (_, record) => ( + + + } + size="large" + /> + + + + + + + + + + + + ); +}; + +export default ListBrandDevice; \ No newline at end of file