From 9ac2942ace432b74b759d949c3d1bff8ff1fcb45 Mon Sep 17 00:00:00 2001 From: Vinix Date: Thu, 23 Oct 2025 15:11:26 +0700 Subject: [PATCH 01/11] clean code role --- src/pages/role/IndexRole.jsx | 136 +++---------- src/pages/role/component/DetailRole.jsx | 259 ++++++++++++++++++------ src/pages/role/component/ListRole.jsx | 73 +++---- 3 files changed, 264 insertions(+), 204 deletions(-) diff --git a/src/pages/role/IndexRole.jsx b/src/pages/role/IndexRole.jsx index 0829656..c446522 100644 --- a/src/pages/role/IndexRole.jsx +++ b/src/pages/role/IndexRole.jsx @@ -1,144 +1,70 @@ import React, { memo, useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useBreadcrumb } from '../../layout/LayoutBreadcrumb'; -import { Form, Typography } from 'antd'; import ListRole from './component/ListRole'; import DetailRole from './component/DetailRole'; -import { createRole, updateRole } from '../../api/role'; -import { NotifAlert, NotifOk } from '../../components/Global/ToastNotif'; +import { useBreadcrumb } from '../../layout/LayoutBreadcrumb'; +import { Typography } from 'antd'; const { Text } = Typography; const IndexRole = memo(function IndexRole() { const navigate = useNavigate(); const { setBreadcrumbItems } = useBreadcrumb(); - const [form] = Form.useForm(); const [actionMode, setActionMode] = useState('list'); const [selectedData, setSelectedData] = useState(null); - const [isModalVisible, setIsModalVisible] = useState(false); const [readOnly, setReadOnly] = useState(false); + const [showModal, setShowModal] = useState(false); + + const setMode = (param) => { + setShowModal(true); + switch (param) { + case 'add': + setReadOnly(false); + break; + case 'edit': + setReadOnly(false); + break; + case 'preview': + setReadOnly(true); + break; + default: + setShowModal(false); + break; + } + setActionMode(param); + }; useEffect(() => { const token = localStorage.getItem('token'); if (token) { setBreadcrumbItems([ - { - title: ( - - • Role - - ), - }, + { title: • Role }, ]); } else { navigate('/signin'); } }, [navigate, setBreadcrumbItems]); - useEffect(() => { - if (actionMode === 'add' || actionMode === 'edit' || actionMode === 'preview') { - setIsModalVisible(true); - setReadOnly(actionMode === 'preview'); - - if (actionMode === 'add') { - form.resetFields(); - } else if (selectedData) { - form.setFieldsValue(selectedData); - } - } else { - setIsModalVisible(false); - form.resetFields(); - } - }, [actionMode, selectedData, form]); - - const handleCancel = () => { - setActionMode('list'); - setSelectedData(null); - form.resetFields(); - }; - - const handleOk = () => { - if (readOnly) { - handleCancel(); - return; - } - - form.validateFields() - .then(async (values) => { - try { - let response; - if (actionMode === 'edit') { - response = await updateRole(selectedData.role_id, values); - console.log('Update Response:', response); - - const isSuccess = response.statusCode === 200 || response.statusCode === 201; - if (isSuccess) { - NotifAlert({ - icon: 'success', - title: 'Berhasil', - message: `Data Role "${values.role_name}" berhasil diubah.`, - }); - handleCancel(); - } else { - NotifOk({ - icon: 'error', - title: 'Gagal', - message: response.message || 'Gagal mengubah data Role', - }); - } - } else if (actionMode === 'add') { - response = await createRole(values); - console.log('Create Response:', response); - - const isSuccess = response.statusCode === 200 || response.statusCode === 201; - if (isSuccess) { - NotifAlert({ - icon: 'success', - title: 'Berhasil', - message: `Data Role "${values.role_name}" berhasil ditambahkan.`, - }); - handleCancel(); - } else { - NotifOk({ - icon: 'error', - title: 'Gagal', - message: response.message || 'Gagal menambahkan data Role', - }); - } - } - } catch (error) { - console.error('Error:', error); - NotifOk({ - icon: 'error', - title: 'Error', - message: 'Terjadi kesalahan saat menyimpan data', - }); - } - }) - .catch((info) => { - console.log('Validate Failed:', info); - }); - }; - return ( ); }); -export default IndexRole; +export default IndexRole; \ No newline at end of file diff --git a/src/pages/role/component/DetailRole.jsx b/src/pages/role/component/DetailRole.jsx index 8d930a8..1c24dbf 100644 --- a/src/pages/role/component/DetailRole.jsx +++ b/src/pages/role/component/DetailRole.jsx @@ -1,72 +1,213 @@ -import React from 'react'; -import { Modal, Form, Input, InputNumber, Switch, Row, Col, Typography, Divider } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, InputNumber, Row, Col } from 'antd'; +import { NotifAlert, NotifOk } from '../../../components/Global/ToastNotif'; +import { validateRun } from '../../../Utils/validate'; +import { createRole, updateRole } from '../../../api/role'; const { Text } = Typography; +const { TextArea } = Input; -const DetailRole = ({ visible, onCancel, onOk, form, editingKey, readOnly }) => { - const modalTitle = editingKey ? (readOnly ? 'Preview Role' : 'Edit Role') : 'Tambah Role'; +const DetailRole = (props) => { + const [confirmLoading, setConfirmLoading] = useState(false); + + const defaultData = { + role_id: '', + role_name: '', + role_level: null, + role_description: '', + is_active: true, + }; + + const [formData, setFormData] = useState(defaultData); + + const handleInputChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const handleInputNumberChange = (value) => { + setFormData({ ...formData, role_level: value }); + }; + + const handleStatusToggle = (checked) => { + setFormData({ ...formData, is_active: checked }); + }; + + const handleCancel = () => { + props.setSelectedData(null); + props.setActionMode('list'); + }; + + const handleSave = async () => { + setConfirmLoading(true); + + const validationRules = [ + { field: 'role_name', label: 'Nama Role', required: true }, + { field: 'role_level', label: 'Level', required: true }, + ]; + + if ( + validateRun(formData, validationRules, (errorMessages) => { + NotifOk({ + icon: 'warning', + title: 'Peringatan', + message: errorMessages, + }); + setConfirmLoading(false); + }) + ) { + return; + } + + try { + const payload = { + role_name: formData.role_name, + role_level: formData.role_level, + role_description: formData.role_description, + is_active: formData.is_active, + }; + + const response = formData.role_id + ? await updateRole(formData.role_id, payload) + : await createRole(payload); + + if (response && (response.statusCode === 200 || response.statusCode === 201)) { + const action = formData.role_id ? 'diubah' : 'ditambahkan'; + NotifOk({ + icon: 'success', + title: 'Berhasil', + message: `Data Role "${payload.role_name}" berhasil ${action}.`, + }); + props.setActionMode('list'); + } else { + NotifAlert({ + icon: 'error', + title: 'Gagal', + message: response?.message || 'Gagal menyimpan data.', + }); + } + } catch (error) { + NotifAlert({ + icon: 'error', + title: 'Error', + message: error.message || 'Terjadi kesalahan pada server.', + }); + } finally { + setConfirmLoading(false); + } + }; + + useEffect(() => { + if (props.selectedData) { + setFormData({ ...defaultData, ...props.selectedData }); + } else { + setFormData(defaultData); + } + }, [props.showModal, props.selectedData]); return ( {modalTitle}} - open={visible} - onCancel={onCancel} - onOk={onOk} - okText="Simpan" - cancelText="Batal" - okButtonProps={{ disabled: readOnly }} - destroyOnClose - + title={ + + {props.actionMode === 'add' + ? 'Tambah Role' + : props.actionMode === 'preview' + ? 'Preview Role' + : 'Edit Role'} + + } + open={props.showModal} + onCancel={handleCancel} + footer={[ + + + + + + {!props.readOnly && ( + + )} + + , + ]} > -
- Status} - valuePropName="checked" - initialValue={true} - > - - - - - - Nama Role} - rules={[{ required: true, message: 'Nama Role wajib diisi!' }]} - > - - - - - Level} - rules={[{ required: true, message: 'Level wajib diisi!' }]} - > - - - - - - Deskripsi Role} - > - + Status +
+ - - + {formData.is_active ? 'Active' : 'Inactive'} +
+ + + +
+ Nama Role + * + +
+ + +
+ Level + * + +
+ +
+
+ Deskripsi Role +