From d3110cf440ce48c58859490b2c3e1916831c4092 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Mar 2025 02:44:19 +0700 Subject: [PATCH] menu crud --- src/pages/members/kyc/Kyc.tsx | 3 + .../members/manage-members/ManageMembers.tsx | 3 + .../menu/manage-menu/blocks/AddDIalog.tsx | 81 +++++++------ .../menu/manage-menu/blocks/DeleteDialog.tsx | 10 +- .../menu/manage-menu/blocks/EditDialog.tsx | 111 ++++++++++-------- .../manage-menu/hooks/ManageMenusContext.tsx | 63 ++++++---- 6 files changed, 160 insertions(+), 111 deletions(-) diff --git a/src/pages/members/kyc/Kyc.tsx b/src/pages/members/kyc/Kyc.tsx index 151eb71..e346889 100644 --- a/src/pages/members/kyc/Kyc.tsx +++ b/src/pages/members/kyc/Kyc.tsx @@ -8,6 +8,7 @@ import { useAuthContext } from '@/auth'; import { apiConfig } from '@/config/api.config'; import ConfirmDialog from '@/components/confirm'; import axios from 'axios'; +import { toast } from 'sonner'; const BASE_URL = apiConfig.service_customer; import CustomerDialog from '../manage-members/CustomerDetailModal'; @@ -128,10 +129,12 @@ const Kyc = () => { await fetchGroups(); setDialogOpen(false) setIsDialogOpen(false) + toast.success('Success Update Kyc Member'); } catch (error: any) { alert(error.message) setDialogOpen(false) setIsDialogOpen(false) + toast.error(error.message) } } diff --git a/src/pages/members/manage-members/ManageMembers.tsx b/src/pages/members/manage-members/ManageMembers.tsx index a0d1959..2258819 100644 --- a/src/pages/members/manage-members/ManageMembers.tsx +++ b/src/pages/members/manage-members/ManageMembers.tsx @@ -7,6 +7,7 @@ import CustomerDialog from './CustomerDetailModal'; import ConfirmDialog from '@/components/confirm'; import { useAuthContext } from '@/auth'; import { ScreenLoader } from '@/components'; +import { toast } from 'sonner'; const BASE_URL = apiConfig.service_customer; const ManageMembers = () => { @@ -99,10 +100,12 @@ const ManageMembers = () => { await fetchGroups(); setDialogOpen(false) setIsDialogOpen(false) + toast.success('Success Update Member'); } catch (error: any) { alert(error.message) setDialogOpen(false) setIsDialogOpen(false) + toast.error(error.message) } } diff --git a/src/pages/menu/manage-menu/blocks/AddDIalog.tsx b/src/pages/menu/manage-menu/blocks/AddDIalog.tsx index 72e4209..d79fe8a 100644 --- a/src/pages/menu/manage-menu/blocks/AddDIalog.tsx +++ b/src/pages/menu/manage-menu/blocks/AddDIalog.tsx @@ -12,13 +12,14 @@ import { DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { FormControl,NativeSelect } from "@mui/material"; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_dashboard; const AddDialog = () => { const parentRef = useRef(null); - const { showAddDialog, handleAddDialog } = useManageMenusContext(); + const { showAddDialog, handleAddDialog, parents } = useManageMenusContext(); const { reload } = useDataGrid(); const { PostData } = useCallApi(); const [alert, setAlert] = useState({ @@ -36,26 +37,7 @@ const AddDialog = () => { }; const [formField, setFormField] = useState(initialState); - const doCreateMenu = useCallback( - async (e: React.FormEvent) => { - e.preventDefault(); - - const response = await PostData(`${API_URL}/menus/create`, formField); - - if (response?.status) { - handleAddDialog(false); - resetForm(); - toast.success('Success Create Menu'); - reload(); - } else { - toast.error('Failed Create Menu'); - setAlert({ show: true, message: 'Failed Create Menu' }); - } - }, - [formField] - ); - - const handleSubmit = (e: React.FormEvent) => { + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if ( @@ -69,7 +51,17 @@ const AddDialog = () => { return; } - doCreateMenu(e); + const response = await PostData(`${API_URL}/menus/create`, formField); + + if (response?.status) { + handleAddDialog(false); + resetForm(); + toast.success('Success Create Menu'); + reload(); + } else { + toast.error('Failed Create Menu'); + setAlert({ show: true, message: 'Failed Create Menu' }); + } console.log(formField); setAlert({ show: false, message: '' }); }; @@ -140,13 +132,24 @@ const AddDialog = () => {
- - setFormField({ ...formField, id_parent: e.target.value })} - /> + + + setFormField({ ...formField, id_parent: e.target.value })} + inputProps={{ + name: 'id_parent', + id: 'uncontrolled-native', + }} + > + { + parents ? parents.map((el: any) => ( + + )) : '' + } + +
@@ -185,12 +188,20 @@ const AddDialog = () => { - setFormField({ ...formField, status: e.target.value })} - /> + + setFormField({ ...formField, status: e.target.value })} + inputProps={{ + name: 'status', + id: 'uncontrolled-native', + }} + > + + + + diff --git a/src/pages/menu/manage-menu/blocks/DeleteDialog.tsx b/src/pages/menu/manage-menu/blocks/DeleteDialog.tsx index f0baf0e..4f4818c 100644 --- a/src/pages/menu/manage-menu/blocks/DeleteDialog.tsx +++ b/src/pages/menu/manage-menu/blocks/DeleteDialog.tsx @@ -10,7 +10,7 @@ import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_dashboard; const DeleteDialog = () => { - const { showDeleteDialog, handleDeleteDialog, selectedMenu } = useManageMenusContext(); + const { showDeleteDialog, handleDeleteDialog, selectedMenu }: any = useManageMenusContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); const [enforce, setEnforce] = useState(false); @@ -19,9 +19,9 @@ const DeleteDialog = () => { message: '' }); - const doDeleteMenu = useCallback(async () => { - const response = await DeleteData(`${API_URL}/menus/delete/${selectedMenu}/${enforce}`, { - id: selectedMenu + const doDeleteMenu = async () => { + const response = await DeleteData(`${API_URL}/menus/delete/${selectedMenu.id}/${enforce}`, { + id: selectedMenu.id }); if (response?.status) { @@ -33,7 +33,7 @@ const DeleteDialog = () => { toast.error('Failed Delete Menu'); setAlert((prev) => ({ ...prev, show: true, message: response?.message })); } - }, [selectedMenu, enforce]); + }; return ( handleDeleteDialog(open, null)}> diff --git a/src/pages/menu/manage-menu/blocks/EditDialog.tsx b/src/pages/menu/manage-menu/blocks/EditDialog.tsx index 7dff544..78a5ea2 100644 --- a/src/pages/menu/manage-menu/blocks/EditDialog.tsx +++ b/src/pages/menu/manage-menu/blocks/EditDialog.tsx @@ -2,7 +2,7 @@ import { Alert, useDataGrid } from '@/components'; import { useManageMenusContext } from '../hooks/useManageMenusContext'; import { useCallApi } from '@/hooks'; import { apiConfig } from '@/config/api.config'; -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useState, useEffect } from 'react'; import { toast } from 'sonner'; import { Dialog, @@ -12,12 +12,13 @@ import { DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { FormControl,NativeSelect } from "@mui/material"; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; - const API_URL = apiConfig.service_dashboard; + const EditDialog = () => { - const { showEditDialog, handleEditDialog, selectedMenu } = useManageMenusContext(); + const { showEditDialog, handleEditDialog, selectedMenu, setSelectedMenu, parents }: any = useManageMenusContext(); const { reload } = useDataGrid(); const { PutData } = useCallApi(); const [alert, setAlert] = useState({ @@ -25,6 +26,7 @@ const EditDialog = () => { message: '' }); const initialState = { + id: '', module: '', name: '', link: '', @@ -33,13 +35,25 @@ const EditDialog = () => { icon: '', status: '' }; - const [formField, setFormField] = useState(initialState); - const doUpdateMenu = useCallback(async (e: React.FormEvent) => { + const handleUpdate = async (e: React.FormEvent) => { e.preventDefault(); + + if ( + selectedMenu.module === '' || + selectedMenu.name === '' || + selectedMenu.link === '' || + selectedMenu.order_number === 0 || + selectedMenu.status === '' + ) { + setAlert({ show: true, message: 'Please fill in all required fields.' }); + return; + } - const response = await PutData(`${API_URL}/menus/update/${selectedMenu}`, formField); - + const updateMenu = selectedMenu; + if (updateMenu.id_parent === null) updateMenu.id_parent = ""; + delete updateMenu.parentName + const response = await PutData(`${API_URL}/menus/update/${selectedMenu.id}`, selectedMenu); if (response?.status) { handleEditDialog(false, null); resetForm(); @@ -49,29 +63,11 @@ const EditDialog = () => { toast.error('Failed Update Menu'); setAlert({ show: true, message: 'Failed Update Menu' }); } - }, []); - - const handleUpdate = (e: React.FormEvent) => { - e.preventDefault(); - - if ( - formField.module === '' || - formField.name === '' || - formField.link === '' || - formField.order_number === 0 || - formField.status === '' - ) { - setAlert({ show: true, message: 'Please fill in all required fields.' }); - return; - } - - doUpdateMenu(e); - console.log(formField); setAlert({ show: false, message: '' }); }; const resetForm = () => { - setFormField(initialState); + setSelectedMenu(initialState) setAlert({ show: false, message: '' }); }; @@ -100,8 +96,8 @@ const EditDialog = () => { setFormField({ ...formField, module: e.target.value })} + value={selectedMenu.module} + onChange={(e) => setSelectedMenu({ ...selectedMenu, module: e.target.value })} /> @@ -114,8 +110,8 @@ const EditDialog = () => { setFormField({ ...formField, name: e.target.value })} + value={selectedMenu.name} + onChange={(e) => setSelectedMenu({ ...selectedMenu, name: e.target.value })} /> @@ -128,8 +124,8 @@ const EditDialog = () => { setFormField({ ...formField, link: e.target.value })} + value={selectedMenu.link} + onChange={(e) => setSelectedMenu({ ...selectedMenu, link: e.target.value })} /> @@ -137,12 +133,23 @@ const EditDialog = () => {
- setFormField({ ...formField, id_parent: e.target.value })} - /> + + setSelectedMenu({ ...selectedMenu, id_parent: e.target.value })} + inputProps={{ + name: 'id_parent', + id: 'uncontrolled-native', + }} + > + { + parents ? parents.map((el: any) => ( + + )) : '' + } + +
@@ -155,10 +162,10 @@ const EditDialog = () => { className="input" type="number" min={0} - value={formField.order_number === 0 ? '' : formField.order_number} + value={selectedMenu.order_number === 0 ? '' : selectedMenu.order_number} onChange={(e) => { const value = parseInt(e.target.value, 10); - setFormField({ ...formField, order_number: isNaN(value) ? 0 : value }); + setSelectedMenu({ ...selectedMenu, order_number: isNaN(value) ? 0 : value }); }} /> @@ -170,8 +177,8 @@ const EditDialog = () => { setFormField({ ...formField, name: e.target.value })} + value={selectedMenu.icon} + onChange={(e) => setSelectedMenu({ ...selectedMenu, icon: e.target.value })} /> @@ -181,12 +188,20 @@ const EditDialog = () => { - setFormField({ ...formField, status: e.target.value })} - /> + + setSelectedMenu({ ...selectedMenu, status: e.target.value })} + inputProps={{ + name: 'status', + id: 'uncontrolled-native', + }} + > + + + + diff --git a/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx b/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx index 69f43b1..96a82f0 100644 --- a/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx +++ b/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx @@ -27,15 +27,26 @@ interface MenuProps { status: string; } +const initialState = { + id: '', + module: '', + name: '', + link: '', + id_parent: '', + order_number: 0, + icon: '', + status: '' +}; + interface ContextProps { menus: MenuProps[]; showEditDialog: boolean; - handleEditDialog: (show: boolean, selected_postoAdms: string | null) => void; + handleEditDialog: (show: boolean, selected_postoAdms: object | null) => void; showAddDialog: boolean; handleAddDialog: (show: boolean) => void; showDeleteDialog: boolean; - handleDeleteDialog: (show: boolean, selected_postoAdms: string | null) => void; - selectedMenu: string | null; + handleDeleteDialog: (show: boolean, selected_postoAdms: object | null) => void; + selectedMenu: object | null; getMenusLists: ( limit: number, page: number, @@ -43,6 +54,8 @@ interface ContextProps { order_field: any, order_direction: any ) => Promise<{ data: MenuProps[]; totalCount: number } | undefined>; + setSelectedMenu: (data: object) => void; + parents: any; } const initialProps: ContextProps = { @@ -50,11 +63,13 @@ const initialProps: ContextProps = { showAddDialog: false, handleAddDialog: (show: boolean) => {}, showEditDialog: false, - handleEditDialog: (show: boolean, selected_menu: string | null) => {}, + handleEditDialog: (show: boolean, selected_menu: object | null) => {}, showDeleteDialog: false, - handleDeleteDialog: (show: boolean, selected_menu: string | null) => {}, - selectedMenu: null, - getMenusLists: async () => ({ data: [], totalCount: 0 }) + handleDeleteDialog: (show: boolean, selected_menu: object | null) => {}, + selectedMenu: initialState, + getMenusLists: async () => ({ data: [], totalCount: 0 }), + setSelectedMenu: (data: object) => {}, + parents: [] }; const ManageMenusContext = createContext(initialProps); @@ -65,21 +80,22 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) const [showAddDialog, setShowAddDialog] = useState(false); const [showEditDialog, setShowEditDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [selectedMenu, setSelectedMenu] = useState(null); + const [selectedMenu, setSelectedMenu] = useState(initialState); + const [parents, setParents] = useState([]); const { GetData } = useCallApi(); const handleAddDialog = useCallback((show: boolean) => { setShowAddDialog(show); }, []); - const handleEditDialog = useCallback((show: boolean, selected_menu: string | null) => { + const handleEditDialog = useCallback((show: boolean, selected_menu: object | null) => { + if (show) setSelectedMenu(selected_menu); setShowEditDialog(show); - setSelectedMenu(selected_menu); }, []); - const handleDeleteDialog = useCallback((show: boolean, selected_menu: string | null) => { + const handleDeleteDialog = useCallback((show: boolean, selected_menu: object | null) => { + if (show) setSelectedMenu(selected_menu); setShowDeleteDialog(show); - setSelectedMenu(selected_menu); }, []); const columns = useMemo[]>( @@ -135,13 +151,13 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) <> @@ -158,25 +174,27 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) ); const flattenChildren = (parent: any, parentIdx: number, depth = 0, parentName = '') => { + if (parent.link === '/') { + if (!parents.find((el: any) => el.id === parent.id)) setParents((el: any) => [...el, { id: parent.id, name: parent.name }]) // GET PARENTS + } if (!parent.children || parent.children.length === 0) { return []; // Jika tidak ada children, kembalikan array kosong } return parent.children.flatMap((child: any, childIdx: number) => { - // Jika child masih punya children, lakukan rekursi lebih dalam if (child.children && child.children.length > 0) { return flattenChildren(child, parentIdx * 100 + childIdx, depth + 1, child.name); } - // Jika ini adalah child terakhir (leaf node), masukkan ke array hasil return { - id: parentIdx * 100 + childIdx + 1, + id: child.id, module: parent.module, parentName: parentName || parent.name, name: child.name, link: child.link, - id_parent: parent.id_parent, - status: parent.status + id_parent: child.id_parent, + status: parent.status, + order_number: parent.order_number }; }); }; @@ -194,10 +212,8 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); - console.log(response?.data); if (!response?.data.list) return { data: [], totalCount: 0 }; - // Gunakan rekursi untuk mencari children paling dalam const transformedData = response.data.list.flatMap((row: any, parentIdx: number) => flattenChildren(row, parentIdx) ); @@ -205,7 +221,6 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) const total_count = transformedData.length; setMenus(transformedData); - console.log(menus); return { data: transformedData, totalCount: total_count }; } catch (error) { console.error('Error fetching Menus', error); @@ -224,7 +239,9 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) showDeleteDialog, handleDeleteDialog, selectedMenu, - getMenusLists + getMenusLists, + setSelectedMenu, + parents }} >