From 03e670ef096c266bb511de4928dd68a393dbd773 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 4 Mar 2025 16:16:10 +0700 Subject: [PATCH 01/53] Form transfertype + transactionFee --- .gitignore | 2 + src/pages/transfer/blocks/AddDialog.tsx | 120 +++++++- .../transfer/blocks/TransactionFeeDialog.tsx | 281 ++++++++++++++++++ 3 files changed, 395 insertions(+), 8 deletions(-) create mode 100644 src/pages/transfer/blocks/TransactionFeeDialog.tsx diff --git a/.gitignore b/.gitignore index 4e80c27..5a3db31 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* +yarn.lock + node_modules dist diff --git a/src/pages/transfer/blocks/AddDialog.tsx b/src/pages/transfer/blocks/AddDialog.tsx index 300425e..a7abdf1 100644 --- a/src/pages/transfer/blocks/AddDialog.tsx +++ b/src/pages/transfer/blocks/AddDialog.tsx @@ -1,5 +1,5 @@ import { apiConfig } from '@/config/api.config'; -import { useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; import { Alert, KeenIcon, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; @@ -20,6 +20,10 @@ import { SelectValue } from '@/components/ui/select'; import { Button } from '@/components/ui/button'; +import TransactionFeeDialog from './TransactionFeeDialog'; +import { toast } from 'sonner'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; interface CreateTransferTypeParams { transfer_type_name: string; @@ -30,6 +34,9 @@ interface CreateTransferTypeParams { maximum_amount: number; otp_threshold: number; maximum_transaction_perDay: number; + status: string; + created_by: string; + created_at: string; } const API_URL = apiConfig.service_dashboard; @@ -52,14 +59,21 @@ const AddDialog = () => { minimal_amount: 0, maximum_amount: 0, otp_threshold: 0, - maximum_transaction_perDay: 0 + maximum_transaction_perDay: 0, + status: '', + created_by: '', + created_at: '' }; const [formField, setFormField] = useState(initialState); + const resetForm = () => { setFormField(initialState); }; + const [isSubmitting, setIsSubmitting] = useState(false); + const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false); + const parsedUser = getAuth()?.user; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -76,16 +90,72 @@ const AddDialog = () => { }; console.log(payload); }; + useEffect(() => { + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showAddDialog) { + setFormField({ + ...formField, + created_by: parsedUser?.username, + created_at: formattedTime + }); + } + }, [showAddDialog]); + const doCreateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + console.log(formField); + + for (const key in formField) { + if ( + formField[key as keyof typeof formField] === '' || + formField[key as keyof typeof formField] === 0 + ) { + setAlert({ show: true, message: 'All fields must be filled out' }); + return; + } + } + + setAlert({ show: false, message: '' }); + const response = await PostData(`${API_URL}/transactiontype/create`, formField); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleAddDialog(false); + toast.success('Success Create Transfer Type'); + reload(); + resetForm(); + + const createActivity = { + module: 'Manage Transfer Type', + description: `Create New Transfer Type => ${formField.transfer_type_name}`, + action: 'C' + }; + + doSaveLogActivity(createActivity); + } else { + setAlert({ show: true, message: response?.message || 'Failed to create transfer type' }); + } + + handleAddDialog(false); + }, + [formField] + ); + const handleTransactionFeeSubmit = (data: any) => { + // console.log('Transaction Fee Data Submitted:', data); + setShowTransactionFeeDialog(false); + }; return ( handleAddDialog(open)}> + +
-

- Create Transfer Type -

+

Transfer Type

{

{alert.message}

)} -
+
@@ -273,17 +343,51 @@ const AddDialog = () => { />
+
+
+ + +
+ +
+
+
+ -
+ setShowTransactionFeeDialog(false)} + onSubmit={handleTransactionFeeSubmit} + />
diff --git a/src/pages/transfer/blocks/TransactionFeeDialog.tsx b/src/pages/transfer/blocks/TransactionFeeDialog.tsx new file mode 100644 index 0000000..cccf165 --- /dev/null +++ b/src/pages/transfer/blocks/TransactionFeeDialog.tsx @@ -0,0 +1,281 @@ +import { useState, useCallback, useEffect } from 'react'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import Typography from '@mui/material/Typography'; +import { toast } from 'sonner'; +import { apiConfig } from '@/config/api.config'; +import { useCallApi } from '@/hooks'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { get } from 'http'; +import { getAuth } from '@/auth'; +import { useDataGrid } from '@/components'; +import { set } from 'date-fns'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { + Select, + SelectTrigger, + SelectValue, + SelectContent, + SelectItem +} from '@/components/ui/select'; + +interface TransactionFeeDialogProps { + open: boolean; + onClose: () => void; + onSubmit: (data: TransactionFeeForm) => void; +} + +interface TransactionFeeForm { + name: string; + description: string; + minimum_amount: number; + maximum_amount: number; + period_start: string; + period_end: string; + deduct_amount: number; + deduct_percentage: number; + priority: string; + status: string; + transactionTypeId: string; + created_by: string; + created_at: string; +} + +const API_URL = apiConfig.service_dashboard; + +const TransactionFeeDialog: React.FC = ({ open, onClose, onSubmit }) => { + const { showAddDialog, handleAddDialog } = useManageTransferTypeContext(); + const parsedUser = getAuth()?.user; + const [formField, setFormField] = useState({ + name: '', + description: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: '', + status: '', + transactionTypeId: '', + created_by: '', + created_at: '' + }); + const { PostData, PutData } = useCallApi(); + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormField((prev) => ({ + ...prev, + [name]: value + })); + }; + const [isSubmitting, setIsSubmitting] = useState(false); + const { reload } = useDataGrid(); + const resetForm = () => { + setFormField(formField); + }; + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + useEffect(() => { + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showAddDialog) { + setFormField({ + ...formField, + created_by: parsedUser?.username, + created_at: formattedTime + }); + } + }, [showAddDialog]); + const doCreateTransactionFee = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + console.log(formField); + const response = await PostData(`${API_URL}/transactionfees/create`, formField); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleAddDialog(false); + toast.success('Success Create Transfer Type'); + reload(); + resetForm(); + + const createActivity = { + module: 'Manage Transfer Fee', + description: `Create New Transfer Fee => ${formField.name}`, + action: 'C' + }; + + doSaveLogActivity(createActivity); + } else { + setAlert({ show: true, message: response?.message || 'Failed to create transfer fee' }); + } + + onSubmit(formField); + }, + [formField] + ); + + return ( + + + + Transaction Fee + + + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + { + const value = e.target.value; + if (/^\d*$/.test(value)) { + handleChange(e); + } + }} + required + type="text" + inputMode="numeric" + placeholder="Masukkan angka" + /> +
+
+ + +
+ +
+ + +
+
+
+
+
+
+ ); +}; + +export default TransactionFeeDialog; From e1ff9d03ecfdfa6b614d3e1fbd015336e86327fd Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Sat, 22 Mar 2025 11:29:03 +0700 Subject: [PATCH 02/53] fix remove display id on table --- .../aldeias/hooks/ManageAldeiasContext.tsx | 10 ---------- .../hooks/ManageConversionContext.tsx | 10 ---------- .../hooks/ManageMunicipiosContext.tsx | 10 ---------- .../hooks/ManagePostoAdmsContext.tsx | 11 ---------- .../products/hooks/ManageProductsContext.tsx | 10 ---------- .../hooks/ManageProfessionContext.tsx | 10 ---------- .../provider/hooks/ManageProviderContext.tsx | 10 ---------- .../master/sucos/hooks/ManageSucosContext.tsx | 10 ---------- .../hooks/ManageWalletRuleContext.tsx | 20 ------------------- 9 files changed, 101 deletions(-) diff --git a/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx b/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx index f0b9aff..6dcce41 100644 --- a/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx +++ b/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx @@ -77,16 +77,6 @@ const ManageAldeiasContextProvider = ({ children }: { children: React.ReactNode const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.name, id: 'name', diff --git a/src/pages/master/conversion/hooks/ManageConversionContext.tsx b/src/pages/master/conversion/hooks/ManageConversionContext.tsx index fe96cb0..21f8c78 100644 --- a/src/pages/master/conversion/hooks/ManageConversionContext.tsx +++ b/src/pages/master/conversion/hooks/ManageConversionContext.tsx @@ -68,16 +68,6 @@ const ManageConversionContextProvider = ({ children }: { children: React.ReactNo const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.name, id: 'name', diff --git a/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx b/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx index 80c208a..5a95477 100644 --- a/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx +++ b/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx @@ -102,16 +102,6 @@ const ManageMunicipiosProvider = ({ children }: { children: React.ReactNode }) = const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { // accessorFn: (row) => row.name, // id: 'name', diff --git a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx index 5c2f500..ec68ee0 100644 --- a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx +++ b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx @@ -83,17 +83,6 @@ const ManagePostoAdmsContextProvider = ({ children }: { children: React.ReactNod const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.PostoAdms_id, - id: 'id', - // accessorKey: 'PostoAdms_id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.PostoAdms_name, id: 'name', diff --git a/src/pages/master/products/hooks/ManageProductsContext.tsx b/src/pages/master/products/hooks/ManageProductsContext.tsx index 8987177..0bc11bc 100644 --- a/src/pages/master/products/hooks/ManageProductsContext.tsx +++ b/src/pages/master/products/hooks/ManageProductsContext.tsx @@ -72,16 +72,6 @@ const ManageProductsContextProvider = ({ children }: { children: React.ReactNode const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.products_id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.products_name, id: 'name', diff --git a/src/pages/master/profession/hooks/ManageProfessionContext.tsx b/src/pages/master/profession/hooks/ManageProfessionContext.tsx index a9a0fc8..63d003c 100644 --- a/src/pages/master/profession/hooks/ManageProfessionContext.tsx +++ b/src/pages/master/profession/hooks/ManageProfessionContext.tsx @@ -67,16 +67,6 @@ const ManageProfessionContextProvider = ({ children }: { children: React.ReactNo const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.name, id: 'name', diff --git a/src/pages/master/provider/hooks/ManageProviderContext.tsx b/src/pages/master/provider/hooks/ManageProviderContext.tsx index ba92dda..b065f8b 100644 --- a/src/pages/master/provider/hooks/ManageProviderContext.tsx +++ b/src/pages/master/provider/hooks/ManageProviderContext.tsx @@ -73,16 +73,6 @@ const ManageProviderContextProvider = ({ children }: { children: React.ReactNode const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.provider_id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.provider_name, id: 'name', diff --git a/src/pages/master/sucos/hooks/ManageSucosContext.tsx b/src/pages/master/sucos/hooks/ManageSucosContext.tsx index ddcd6c6..8c53953 100644 --- a/src/pages/master/sucos/hooks/ManageSucosContext.tsx +++ b/src/pages/master/sucos/hooks/ManageSucosContext.tsx @@ -85,16 +85,6 @@ const ManageSucosContextProvider = ({ children }: { children: React.ReactNode }) const columns = useMemo[]>( () => [ - { - accessorKey: 'sucos_id', - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.sucos_name, id: 'sucos_name', diff --git a/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx b/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx index e196eaa..819785c 100644 --- a/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx +++ b/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx @@ -69,26 +69,6 @@ const ManageWalletRuleContextProvider = ({ children }: { children: React.ReactNo const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.ID, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, - { - accessorFn: (row) => row.IDWallet, - id: 'name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, { accessorFn: (row) => row.balance_minimum, id: 'balance_minimum', From 41f96416b3c7930f3c360940678923311a5a6560 Mon Sep 17 00:00:00 2001 From: Raja Oktafrianto Date: Sat, 22 Mar 2025 14:19:48 +0700 Subject: [PATCH 03/53] update list sucos --- src/components/data-grid/DataGridContext.tsx | 7 ++++++- src/layouts/demo2/footer/Footer.tsx | 7 ++++++- src/pages/master/sucos/blocks/AddDialog.tsx | 8 ++++---- src/pages/master/sucos/blocks/DeleteDialog.tsx | 11 ++++++++++- src/pages/master/sucos/blocks/EditDialog.tsx | 11 ++++++----- src/pages/master/sucos/blocks/ListToolbar.tsx | 10 +++++++++- .../master/sucos/hooks/ManageSucosContext.tsx | 17 +++++++++++++++-- 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/components/data-grid/DataGridContext.tsx b/src/components/data-grid/DataGridContext.tsx index a684184..d68006b 100644 --- a/src/components/data-grid/DataGridContext.tsx +++ b/src/components/data-grid/DataGridContext.tsx @@ -151,7 +151,10 @@ export const DataGridProvider = (props: TDataGridProps !loading && setSorting(newSorting), - onColumnFiltersChange: (newFilters) => !loading && setColumnFilters(newFilters), + onColumnFiltersChange: (newFilters) => { + console.log('New Filters:', newFilters); // Debugging + !loading && setColumnFilters(newFilters); + }, onColumnVisibilityChange: setColumnVisibility, onPaginationChange: (newPagination) => !loading && setPagination(newPagination), getCoreRowModel: getCoreRowModel(), @@ -165,6 +168,8 @@ export const DataGridProvider = (props: TDataGridProps {
{currentYear}© - + Brillian Dev.
diff --git a/src/pages/master/sucos/blocks/AddDialog.tsx b/src/pages/master/sucos/blocks/AddDialog.tsx index dd5ab57..ea31fe8 100644 --- a/src/pages/master/sucos/blocks/AddDialog.tsx +++ b/src/pages/master/sucos/blocks/AddDialog.tsx @@ -45,7 +45,7 @@ const AddDialog = () => { }); const initialState = { name: '', - posto_adm_id: 0, + postoId: 0, created_by: '', created_at: '' }; @@ -80,7 +80,7 @@ const AddDialog = () => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name.trim() === '' || formField.posto_adm_id === 0) { + if (formField.name.trim() === '' || formField.postoId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -166,7 +166,7 @@ const AddDialog = () => { @@ -183,7 +183,7 @@ const AddDialog = () => { onSelect={() => { setFormField({ ...formField, - posto_adm_id: posto.PostoAdms_id + postoId: posto.PostoAdms_id }); setOpen(false); }} diff --git a/src/pages/master/sucos/blocks/DeleteDialog.tsx b/src/pages/master/sucos/blocks/DeleteDialog.tsx index d5aa4ce..f1235f9 100644 --- a/src/pages/master/sucos/blocks/DeleteDialog.tsx +++ b/src/pages/master/sucos/blocks/DeleteDialog.tsx @@ -4,7 +4,14 @@ import { ChangeEvent, useCallback, useState } from 'react'; import { useCallApi } from '@/hooks'; import { Alert, useDataGrid } from '@/components'; import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; import { EnforceSwitch } from '@/components/switch'; import { Button } from '@/components/ui/button'; @@ -39,6 +46,8 @@ const DeleteDialog = () => { handleDeleteDialog(open, null)}> + +

Are you sure?

you will delete this data! diff --git a/src/pages/master/sucos/blocks/EditDialog.tsx b/src/pages/master/sucos/blocks/EditDialog.tsx index 0e08201..0bd2c9e 100644 --- a/src/pages/master/sucos/blocks/EditDialog.tsx +++ b/src/pages/master/sucos/blocks/EditDialog.tsx @@ -48,7 +48,7 @@ const EditDialog = () => { const initialState = { name: '', - posto_adm_id: 0, // Pastikan ini sesuai dengan PostoAdms_id + postoId: 0, // Pastikan ini sesuai dengan PostoAdms_id updated_by: '', updated_at: '' }; @@ -110,7 +110,8 @@ const EditDialog = () => { setFormField((prev) => ({ ...prev, name: response.data.name, - posto_adm_id: response.data.posto.id // Pastikan ini sesuai dengan PostoAdms_id + postoId: response.data.posto?.id || '' + // Pastikan ini sesuai dengan PostoAdms_id })); } else { setFormField((prev) => ({ @@ -123,7 +124,7 @@ const EditDialog = () => { const handleUpdate = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name.trim() === '' || formField.posto_adm_id === 0) { + if (formField.name.trim() === '' || formField.postoId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -203,7 +204,7 @@ const EditDialog = () => { @@ -220,7 +221,7 @@ const EditDialog = () => { onSelect={() => { setFormField({ ...formField, - posto_adm_id: posto.PostoAdms_id // Gunakan PostoAdms_id + postoId: posto.PostoAdms_id // Gunakan PostoAdms_id }); setOpen(false); }} diff --git a/src/pages/master/sucos/blocks/ListToolbar.tsx b/src/pages/master/sucos/blocks/ListToolbar.tsx index 313188e..7336ae2 100644 --- a/src/pages/master/sucos/blocks/ListToolbar.tsx +++ b/src/pages/master/sucos/blocks/ListToolbar.tsx @@ -16,11 +16,19 @@ const ListToolbar = () => { table.getColumn('sucos_name')?.setFilterValue(event.target.value) } /> + + table.getColumn('posto_name')?.setFilterValue(event.target.value) + } + /> + +
+
+ + + +
+
+ ); +}; + +export default AddFeeDialog; diff --git a/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx b/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx new file mode 100644 index 0000000..bf61c83 --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx @@ -0,0 +1,87 @@ +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Alert, useDataGrid } from '@/components'; +import { ChangeEvent, useCallback, useState } from 'react'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { EnforceSwitch } from '@/components/switch'; +import { useContext } from 'react'; +import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; +import { ManageTransferFeeContext } from '../hooks/ManageTransferFeeContext'; +import { DialogDescription } from '@radix-ui/react-dialog'; +import { useManageAccessTypeContext } from '@/pages/access/access-type/hooks/useManageAccessTypeContext'; + +const API_URL = apiConfig.service_transaction; + +const DeleteDialog = () => { + const { showDeleteFeeDialog, handleDeleteFeeDialog, selectedTransferFee } = useManageTransferFeeContext(); + const { reload } = useDataGrid(); + const { DeleteData } = useCallApi(); + const [enforce, setEnforce] = useState(false); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const doDeleteTransferFee = useCallback(async () => { + console.log("Selected Transfer Fee:", selectedTransferFee, "Type:", typeof selectedTransferFee); + const response = await DeleteData(`${API_URL}/transactionfees/delete/${selectedTransferFee}/${enforce}`, { + id: selectedTransferFee + }); + + if (response?.status) { + setAlert((prev) => ({ ...prev, show: false, message: '' })); + handleDeleteFeeDialog(false, null); + toast.success('Success Delete Product'); + reload(); + } else { + toast.error('Failed Delete Product'); + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + }, [selectedTransferFee, enforce]); + + // console.log(selectedTransferFee); + + return ( + handleDeleteFeeDialog(open, null)}> + + + Delete Transfer Type + Delete Transfer Type + +

Are you sure?

+ you will delete this data! +
+ + ) => { + setEnforce(e.target.checked); + }} + /> +
+
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); +}; + +export default DeleteDialog; + +export { DeleteDialog }; diff --git a/src/pages/transfer/transferfee/blocks/EditDialog.tsx b/src/pages/transfer/transferfee/blocks/EditDialog.tsx new file mode 100644 index 0000000..89ee86c --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/EditDialog.tsx @@ -0,0 +1,499 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { NumericFormat } from 'react-number-format'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; + +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { apiConfig } from '@/config/api.config'; +import { Alert, Container, DataGridInner, KeenIcon, useDataGrid } from '@/components'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; +import { ManageTransferFeeContextProvider } from '../../transferfee/hooks/ManageTransferFeeContext'; +import AddFeeDialog from '../../transferfee/blocks/AddDialog'; + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL_CUSTOMER = apiConfig.service_customer; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +interface TransactionTypeProps { + id: string; + name: string; +} + +const EditFeeDialog = () => { + const parentRef = useRef(null); + const { showEditFeeDialog, handleEditFeeDialog, selectedTransferFee } = + useManageTransferFeeContext(); + const { reload } = useDataGrid(); + const [wallets, setWallets] = useState([]); + const { GetData, PutData } = useCallApi(); + const [isSubmitting, setIsSubmitting] = useState(false); + const [transactionTypes, setTransactionTypes] = useState([]); + const parsedUser = getAuth()?.user; + const [customers, setCustomers] = useState([]); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const [formField, setFormField] = useState({ + name: '', + description: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: '', + status: '', + status_include: '', + transaction_type: '', + updated_by: '', + updated_at: '' + }); + useEffect(() => { + const updated_time = new Date(); + const formattedTime = updated_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showEditFeeDialog) { + setFormField({ + ...formField, + updated_by: parsedUser?.username, + updated_at: formattedTime + }); + } + }, [showEditFeeDialog]); + /* actions */ + const doUpdateTransferFee = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + const response = await PutData(`${API_URL}/transactionfees/update/${selectedTransferFee}`, { + ...formField + }); + if (response?.status) { + handleEditFeeDialog(false, null); + toast.success('Success Update User'); + reload(); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + console.log(formField); + }, + [formField, selectedTransferFee] + ); + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + }, []); + + useEffect(() => { + fetchWallets(); + }, [fetchWallets]); + + useEffect(() => { + if (!showEditFeeDialog) return; + + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + + // 🟡 Log daftar pelanggan saja (kalau respons pakai struktur {data: {list: [...]}}) + console.log('CUSTOMER LIST: ', response?.data?.list); + + setCustomers(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'msisdn', desc: false }]); + }, []); + useEffect(() => { + if (!showEditFeeDialog) return; + + const getTransactionTypeList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + + // 🟡 Log daftar pelanggan saja (kalau respons pakai struktur {data: {list: [...]}}) + console.log('TRANSACTION TYPE LIST: ', response?.data?.list); + + setTransactionTypes(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getTransactionTypeList([{ id: 'id', desc: false }]); + }, [showEditFeeDialog]); + + const fetchTransactionFee = useCallback(async (id: string) => { + const response = await GetData(`${API_URL}/transactionfees/getdata/${id}`, { id }); + // console.log("API Response:", response); + + if (response?.status) { + setFormField((prev) => ({ + ...prev, + name: response.data.name, + description: response.data.description, + minimum_amount: response.data.minimum_amount, + maximum_amount: response.data.maximum_amount, + period_start: response.data.period_start, + period_end: response.data.period_end, + deduct_amount: response.data.deduct_amount, + deduct_percentage: response.data.deduct_percentage, + priority: response.data.priority, + status: response.data.status, + status_include: response.data.status_include, + transaction_type: response.data.transaction_type.id + + // updated_by: parsedUser?.username , + // updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ') + })); + } else { + setFormField((prev) => ({ + ...prev, + name: '', + description: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: '', + status: '', + status_include: '', + transaction_type: '' + })); + } + }, []); + + useEffect(() => { + if (selectedTransferFee) { + fetchTransactionFee(selectedTransferFee); + } + }, [selectedTransferFee]); + + return ( + handleEditFeeDialog(open, null)}> + + + + +
+
+

+ Update Transaction Fee +

+
+
+
handleEditFeeDialog(false, null)} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + minimum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_start: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_end: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_percentage: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ {/*
+ + +
*/} + + {/*
+ + +
*/} +
+ + +
+
+
+
+
+
+
+
+ ); +}; + +export { EditFeeDialog }; diff --git a/src/pages/transfer/transferfee/blocks/ListToolBar.tsx b/src/pages/transfer/transferfee/blocks/ListToolBar.tsx new file mode 100644 index 0000000..9acdc39 --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/ListToolBar.tsx @@ -0,0 +1,44 @@ + import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; + import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; + import { Button } from '@/components/ui/button'; + + const ListToolbar = () => { + const { table, reload } = useDataGrid(); + const { handleAddFeeDialog, handleEditFeeDialog, selectedTransferFee} = useManageTransferFeeContext(); + + return ( +
+
+
+
+ +
+
+ + + + +
+
+
+
+ ); + }; + + export default ListToolbar; diff --git a/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx b/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx new file mode 100644 index 0000000..67d08ba --- /dev/null +++ b/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx @@ -0,0 +1,236 @@ +import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; +import { Toaster } from '@/components/ui/sonner'; +import { apiConfig } from '@/config/api.config'; +import { useCallApi } from '@/hooks'; +import { ColumnDef } from '@tanstack/react-table'; +import { createContext, useCallback, useEffect, useMemo, useState } from 'react'; +import ListToolbar from '../blocks/ListToolBar'; +import DeleteDialog from '../blocks/DeleteDialog'; +import { EditFeeDialog } from '../blocks/EditDialog'; + +interface ContextProps { + showEditFeeDialog: boolean; + handleEditFeeDialog: (show: boolean, selectedTransferFee: string | null) => void; + showAddFeeDialog: boolean; + handleAddFeeDialog: (show: boolean) => void; + handleDeleteFeeDialog: (show: boolean, selectedTransferFee: string | null) => void; + showDeleteFeeDialog: boolean; + selectedTransferFee: string | null; +} + +const initialProps: ContextProps = { + showEditFeeDialog: false, + handleEditFeeDialog: () => {}, + showAddFeeDialog: false, + handleAddFeeDialog: () => {}, + showDeleteFeeDialog: false, + handleDeleteFeeDialog: () => {}, + selectedTransferFee: null +}; + +const ManageTransferFeeContext = createContext(initialProps); +const API_URL = apiConfig.service_transaction; + +const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactNode }) => { + const [showEditFeeDialog, setShowEditFeeDialog] = useState(false); + const [showAddFeeDialog, setShowAddFeeDialog] = useState(false); + const [showDeleteFeeDialog, setShowDeleteFeeDialog] = useState(false); + + const [selectedTransferFee, setSelectedTransferFee] = useState(null); + const { GetData } = useCallApi(); + + const handleEditFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => { + setSelectedTransferFee(show ? selectedTransferFee : null); + setShowEditFeeDialog(show); + }, []); + + const handleAddFeeDialog = useCallback((show: boolean) => { + setShowAddFeeDialog(show); + }, []); + + const handleDeleteFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => { + setSelectedTransferFee(show ? selectedTransferFee : null); + setShowDeleteFeeDialog(show); + }, []); + const doGetTransferFeeListData = async ( + page: number, + limit: number, + sorting: any, + filter: any + ) => { + sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value.toLowerCase() }; + const response = await GetData(`${API_URL}/transactionfees/list`, { + limit: limit, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'ASC' : 'DESC', + filter: JSON.stringify(filter) + }); + console.log('hasilnya', response?.data.list); + console.log('transactiontype', response?.data); + + return { data: response?.data.list, totalCount: response?.data.total_count }; + }; + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => row.name, + id: 'name', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.description, + id: 'description', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.minimum_amount, + id: 'minimum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.maximum_amount, + id: 'maximum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.period_start?.split('T')[0], + id: 'period_start', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.period_end?.split('T')[0], + id: 'period_end', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.deduct_amount, + id: 'deduct_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.deduct_percentage, + id: 'deduct_percentage', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.priority, + id: 'priority', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[100px]' } + }, + { + accessorFn: (row) => row.transaction_type?.name, + id: 'transactionTypeId', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.status_include, + id: 'status_include', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + id: 'actions', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + cell: (data) => { + const row = data.row.original; + return ( + <> + + + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + } + ], + [handleEditFeeDialog, handleDeleteFeeDialog] + ); + + return ( +
+
+

Manage Transaction Fee

+
+ + + } + sorting={[{ id: 'id', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + doGetTransferFeeListData(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + + + +
+ ); +}; + +export { ManageTransferFeeContext, ManageTransferFeeContextProvider }; diff --git a/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx b/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx new file mode 100644 index 0000000..11873ba --- /dev/null +++ b/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageTransferFeeContext } from './ManageTransferFeeContext'; + +const useManageTransferFeeContext = () => { + const context = useContext(ManageTransferFeeContext); + + if (!context) throw new Error('useManageAccessTypeContext must be used within AuthProvider'); + + return context; +}; + +export { useManageTransferFeeContext }; diff --git a/src/pages/transfer/transfertype/TransferType.tsx b/src/pages/transfer/transfertype/TransferType.tsx new file mode 100644 index 0000000..de8effe --- /dev/null +++ b/src/pages/transfer/transfertype/TransferType.tsx @@ -0,0 +1,27 @@ +import { Container, DataGridInner } from '@/components'; +import { + ManageTransferTypeContext, + ManageTransferTypeContextProvider +} from './hooks/ManageTransferTypeContext'; +import AddDialog from './blocks/AddDialog'; +import { DeleteDialog } from './blocks/DeleteDialog'; +import { EditDialog } from './blocks/EditDialog'; + +const TransferType = () => { + + return ( + + +
+ +
+ + + + +
+
+ ); +}; + +export default TransferType; diff --git a/src/pages/transfer/transfertype/blocks/AddDialog.tsx b/src/pages/transfer/transfertype/blocks/AddDialog.tsx new file mode 100644 index 0000000..d0afb04 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/AddDialog.tsx @@ -0,0 +1,490 @@ +import { apiConfig } from '@/config/api.config'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { + Alert, + Container, + DataGridColumnHeader, + DataGridInner, + KeenIcon, + useDataGrid +} from '@/components'; +import { useCallApi } from '@/hooks'; +import { NumericFormat } from 'react-number-format'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; +import { Button } from '@/components/ui/button'; +import { toast } from 'sonner'; +import { getAuth } from '@/auth'; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL3_CUSTOMER = apiConfig.service_customer; + +const AddDialog = () => { + const parentRef = useRef(null); + const { GetData } = useCallApi(); + const { showAddDialog, handleAddDialog, selectedTransferType } = useManageTransferTypeContext(); + const [wallets, setWallets] = useState([]); + const [customers, setCustomers] = useState([]); + const { reload } = useDataGrid(); + const { PostData, PutData } = useCallApi(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const initialState = { + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + minimum_amount: 0, + maximum_amount: 0, + max_transaction_per_day: 0, + status: '', + status_approval: '', + created_by: '', + created_at: '' + }; + + const [formField, setFormField] = useState(initialState); + + const resetForm = () => { + setFormField(initialState); + }; + const [isSubmitting, setIsSubmitting] = useState(false); + + const parsedUser = getAuth()?.user; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + // setIsSubmitting(true); + const payload = { + name: formField.name, + description: formField.description, + wallet_origin: formField.wallet_origin, + wallet_destination: formField.wallet_destination, + minimum_amount: formField.minimum_amount, + maximum_amount: formField.maximum_amount, + max_transaction_per_day: formField.max_transaction_per_day, + wallet_fee_destination: formField.wallet_fee_destination, + customer_fee_destination: formField.customer_fee_destination, + status_approval: formField.status_approval, + status: formField.status + }; + }; + useEffect(() => { + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showAddDialog) { + setFormField({ + ...formField, + created_by: parsedUser?.username, + created_at: formattedTime + }); + } + }, [showAddDialog]); + + useEffect(() => { + if (!showAddDialog) return; + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + + const response = await GetData(`${API_URL3_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + console.log('CUSTOMER LIST: ', response?.data?.list); + + setCustomers(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'msisdn', desc: false }]); + }, [showAddDialog]); + + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + console.log('WALLET LIST: ', response?.data?.list); + }, []); + + useEffect(() => { + if (!showAddDialog) return; + fetchWallets(); + }, [showAddDialog]); + + const doCreateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + console.log(formField); + for (const key in formField) { + if ( + formField[key as keyof typeof formField] === '' || + formField[key as keyof typeof formField] === 0 + ) { + setAlert({ show: true, message: 'All fields must be filled out' }); + return; + } + } + + setAlert({ show: false, message: '' }); + + const response = await PostData(`${API_URL}/transactiontype/create`, formField); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleAddDialog(false); + toast.success('Success Create Transfer Type'); + reload(); + resetForm(); + + console.log('Berhasil nih, isinya gini:', formField); + } else { + setAlert({ show: true, message: response?.message || 'Failed to create transfer type' }); + } + handleAddDialog(false); + }, + [formField] + ); + + return ( + handleAddDialog(open)}> + + + + +
+
+

Transaction Type

+
+
+
{ + handleAddDialog(false); + resetForm(); + }} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + minimum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Maximum Amount" + /> +
+
+
+
+ + { + setFormField((prev) => ({ + ...prev, + max_transaction_per_day: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+
+
+
+
+ ); +}; + +export default AddDialog; diff --git a/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx new file mode 100644 index 0000000..52f9e25 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx @@ -0,0 +1,92 @@ +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Alert, useDataGrid } from '@/components'; +import { ChangeEvent, useCallback, useState } from 'react'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { EnforceSwitch } from '@/components/switch'; +import { useContext } from 'react'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { ManageTransferTypeContext } from '../hooks/ManageTransferTypeContext'; +import TransferType from '../TransferType'; +import { DialogDescription } from '@radix-ui/react-dialog'; +import { useManageAccessTypeContext } from '@/pages/access/access-type/hooks/useManageAccessTypeContext'; + +const API_URL = apiConfig.service_transaction; + +const DeleteDialog = () => { + const { showDeleteDialog, handleDeleteDialog, selectedTransferType } = useManageTransferTypeContext(); + const { reload } = useDataGrid(); + const { DeleteData } = useCallApi(); + const [enforce, setEnforce] = useState(false); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const doDeleteTransferType = useCallback(async () => { + if (!selectedTransferType) { + toast.error('No Transfer Type selected'); + return; + } + + const response = await DeleteData(`${API_URL}/transactiontype/delete/${selectedTransferType}/${enforce}`, { + id: selectedTransferType + }); + + if (response?.status) { + setAlert((prev) => ({ ...prev, show: false, message: '' })); + handleDeleteDialog(false, null); + reload(); + setTimeout(() => toast.success('Success Delete Product'), 0); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setTimeout(() => toast.error('Failed Delete Product'), 0); + } + }, [selectedTransferType, enforce, DeleteData, handleDeleteDialog, reload]); + + // console.log(selectedTransferType); + + return ( + handleDeleteDialog(open, null)}> + + + Delete Transfer Type + Delete Transfer Type + +

Are you sure?

+ you will delete this data! +
+ + ) => { + setEnforce(e.target.checked); + }} + /> +
+
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); +}; + +export default DeleteDialog; + +export { DeleteDialog }; diff --git a/src/pages/transfer/transfertype/blocks/EditDialog.tsx b/src/pages/transfer/transfertype/blocks/EditDialog.tsx new file mode 100644 index 0000000..7a27df0 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/EditDialog.tsx @@ -0,0 +1,525 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; +import { NumericFormat } from 'react-number-format'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { apiConfig } from '@/config/api.config'; +import { Alert, Container, DataGridInner, KeenIcon, useDataGrid } from '@/components'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; +import { ManageTransferFeeContextProvider } from '../../transferfee/hooks/ManageTransferFeeContext'; +import AddFeeDialog from '../../transferfee/blocks/AddDialog'; + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL_CUSTOMER = apiConfig.service_customer; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +interface TranssactionTypeProps { + name: string; + description: string; + minimum_amount: number; + maximum_amount: number; + max_transaction_per_day: number; + status_approval: string; + status: string; + wallet_origin: WalletProps; + wallet_destination: WalletProps; + wallet_fee_destination: WalletProps; + customer_fee_destination: CustomerProps; +} + +const EditDialog = () => { + const parentRef = useRef(null); + const { showEditDialog, handleEditDialog, selectedTransferType, accounts } = + useManageTransferTypeContext(); + const { reload } = useDataGrid(); + const [wallets, setWallets] = useState([]); + const { GetData, PutData } = useCallApi(); + const [isSubmitting, setIsSubmitting] = useState(false); + const parsedUser = getAuth()?.user; + const [customers, setCustomers] = useState([]); + const [transactiontypes, setTransactionTypes] = useState([]); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const resetForm = () => { + setFormField(formField); + }; + const [formField, setFormField] = useState({ + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + minimum_amount: 0, + maximum_amount: 0, + max_transaction_per_day: 0, + status_approval: '', + status: '', + updated_by: '', + updated_at: '' + }); + useEffect(() => { + const updated_time = new Date(); + const formattedTime = updated_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showEditDialog) { + setFormField({ + ...formField, + updated_by: parsedUser?.username, + updated_at: formattedTime + }); + } + }, [showEditDialog]); + /* actions */ + const doUpdateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + const response = await PutData(`${API_URL}/transactiontype/update/${selectedTransferType}`, { + ...formField + }); + if (response?.status) { + handleEditDialog(false, null); + toast.success('Success Update User'); + reload(); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + // console.log(formField); + }, + [formField, selectedTransferType] + ); + useEffect(() => { + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + // console.log('CUSTOMER LIST: ', response?.data?.list); + + setCustomers(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'id', desc: false }]); + }, [showEditDialog]); + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + }, []); + + useEffect(() => { + fetchWallets(); + }, [fetchWallets]); + + const fetchTransactionType = useCallback(async (id: string) => { + const response = await GetData(`${API_URL}/transactiontype/getdata/${id}`, { id }); + // console.log("API Response:", response); + + if (response?.status) { + const data = response.data; + console.log('Fetched customer_fee_destination:', response.data); + setFormField((prev) => ({ + ...prev, + name: response.data.name, + description: response.data.description, + wallet_origin: response.data.wallet_origin.id, + wallet_destination: response.data.wallet_destination.id, + wallet_fee_destination: response.data.wallet_fee_destination.id, + customer_fee_destination: response.data.customer_fee_destination.id, + minimum_amount: response.data.minimum_amount, + maximum_amount: response.data.maximum_amount, + max_transaction_per_day: response.data.max_transaction_per_day, + status_approval: response.data.status_approval, + status: response.data.status + // updated_by: parsedUser?.username , + // updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ') + })); + } else { + setFormField((prev) => ({ + ...prev, + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + maximum_amount: 0, + minimum_amount: 0, + max_transaction_per_day: 0, + status_approval: '', + status: '' + })); + } + }, []); + + useEffect(() => { + if (selectedTransferType) { + fetchTransactionType(selectedTransferType); + } + }, [selectedTransferType]); + // console.log('Form Field Data: ', formField); + // console.log('customer list:', customers); + return ( + handleEditDialog(open, null)}> + + + + +
+
+

+ Update Transaction Type +

+
+
+
{ + handleEditDialog(false, null); + resetForm(); + }} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Maximum Amount" + /> +
+
+
+
+ + { + setFormField((prev) => ({ + ...prev, + max_transaction_per_day: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ + {/*
+ +
*/} +
+ {/* */} + + + +
+
+
+ {/* Bagian Transaction Fee */} + + +
+ +
+ +
+
+
+
+
+
+ ); +}; + +export { EditDialog }; diff --git a/src/pages/transfer/transfertype/blocks/ListToolBar.tsx b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx new file mode 100644 index 0000000..7325816 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx @@ -0,0 +1,44 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { Button } from '@/components/ui/button'; + +const ListToolbar = () => { + const { table, reload } = useDataGrid(); + const { handleAddDialog, handleEditDialog } = useManageTransferTypeContext(); + + return ( +
+
+
+
+ +
+
+ + + + +
+
+
+
+ ); +}; + +export default ListToolbar; diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx new file mode 100644 index 0000000..5759d29 --- /dev/null +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -0,0 +1,254 @@ + import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; + import { Toaster } from '@/components/ui/sonner'; + import { apiConfig } from '@/config/api.config'; + import { useCallApi } from '@/hooks'; + import { ColumnDef } from '@tanstack/react-table'; + import { createContext, useCallback, useEffect, useMemo, useState } from 'react'; + import ListToolbar from '../blocks/ListToolBar'; + + + interface AccountProps { + id: string; + name: string; + } + + interface TransferType { + id: string; + name: string; + minimum_amount: number; + maximum_amount: number; + max_transaction_per_day: number; + walletOriginId: string; + walletDestinationId: string; + status: string; + } + + interface ContextProps { + showEditDialog: boolean; + handleEditDialog: (show: boolean, selected_user: string | null) => void; + showAddDialog: boolean; + handleAddDialog: (show: boolean) => void; + showDeleteDialog: boolean; + handleDeleteDialog: (show: boolean, selected_user: string | null) => void; + selectedTransferType: string | null; + transferType: string|null; + accounts: AccountProps[]; + } + + const initialProps: ContextProps = { + showEditDialog: false, + handleEditDialog: () => {}, + showAddDialog: false, + handleAddDialog: () => {}, + showDeleteDialog: false, + handleDeleteDialog: () => {}, + selectedTransferType: null, + accounts: [], + transferType: null + }; + + const ManageTransferTypeContext = createContext(initialProps); + const API_URL = apiConfig.service_transaction; + + const ManageTransferTypeContextProvider = ({ children }: { children: React.ReactNode }) => { + const [showEditDialog, setShowEditDialog] = useState(false); + const [showAddDialog, setShowAddDialog] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [selectedUser, setSelectedUser] = useState(null); + const [accounts, setAccount] = useState([]); + const { GetData } = useCallApi(); + const [selectedTransferType, setSelectedTransferType] = useState(null); + const [transferType, setTransferType] = useState(null); + + + const handleEditDialog = useCallback((show: boolean, selected_transfertype: string | null) => { + setSelectedTransferType(show ? selected_transfertype : null); + setShowEditDialog(show); + }, []); + + const handleAddDialog = useCallback((show: boolean) => { + setShowAddDialog(show); + }, []); + + const handleDeleteDialog = useCallback((show: boolean, selected_transfertype: string | null) => { + setShowDeleteDialog(show); + setSelectedTransferType(show ? selected_transfertype : null); + }, []); + + const columns = useMemo[]>( + () => [ + + { + accessorFn: (row) => row.name, + id: 'name', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.wallet_origin?.name || 'N/A', + id: 'wallet_origin', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.wallet_destination.name || 'N/A', + id: 'wallet_destination', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.maximum_amount, + id: 'maximum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.minimum_amount, + id: 'minimum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.max_transaction_per_day, + id: 'max_transaction_per_day', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.description, + id: 'description', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.wallet_fee_destination.name , + id: 'wallet_fee_destination', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.customer_fee_destination?.username || 'N/A', + id: 'customer_fee_destination', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.status_approval, + id: 'status_approval', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.status, + id: 'status', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + } +, + { + id: 'actions', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + cell: (data) => { + const row = data.row.original; + return ( + <> + + + + ); + }, + meta: { headerClassName: 'w-[100px]', cellClassName: 'text-center' } + } + ], + [handleEditDialog, handleDeleteDialog] + ); + const doGetTransferTypeListData = async (page: number, limit: number, sorting: any, filter: any) => { + + sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: limit, + page: page + 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'ASC' : 'DESC', + filter: JSON.stringify(filter) + }); + console.log("bismillah:",response?.data.list) + // setTransferType(response?.data.list); + return { data: response?.data.list, totalCount: response?.data.total_count }; + // console.log("test:",response) +   }; + + return ( +
+
+

Manage Transaction Type

+
+ + + + +
+ } + sorting={[{ id: 'id', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + doGetTransferTypeListData(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + +
+
+
+ ); + + }; + + export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; + export type { TransferType }; diff --git a/src/pages/transfer/transfertype/hooks/useManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/useManageTransferTypeContext.tsx new file mode 100644 index 0000000..b726a7c --- /dev/null +++ b/src/pages/transfer/transfertype/hooks/useManageTransferTypeContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageTransferTypeContext } from './ManageTransferTypeContext'; + +const useManageTransferTypeContext = () => { + const context = useContext(ManageTransferTypeContext); + + if (!context) throw new Error('useManageAccessTypeContext must be used within AuthProvider'); + + return context; +}; + +export { useManageTransferTypeContext }; From d9843d78487d522e189130c65a4163a7fa90f70b Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 24 Mar 2025 10:22:43 +0700 Subject: [PATCH 05/53] tambahan --- src/config/api.config.ts | 6 +- src/pages/transfer/TransferType.tsx | 21 - src/pages/transfer/blocks/AddDialog.tsx | 398 ------------------ src/pages/transfer/blocks/ListToolBar.tsx | 49 --- .../transfer/blocks/TransactionFeeDialog.tsx | 281 ------------- .../hooks/ManageTransferTypeContext.tsx | 178 -------- .../hooks/useManageTransferTypeContext.tsx | 12 - src/routing/AppRoutingSetup.tsx | 2 +- 8 files changed, 6 insertions(+), 941 deletions(-) delete mode 100644 src/pages/transfer/TransferType.tsx delete mode 100644 src/pages/transfer/blocks/AddDialog.tsx delete mode 100644 src/pages/transfer/blocks/ListToolBar.tsx delete mode 100644 src/pages/transfer/blocks/TransactionFeeDialog.tsx delete mode 100644 src/pages/transfer/hooks/ManageTransferTypeContext.tsx delete mode 100644 src/pages/transfer/hooks/useManageTransferTypeContext.tsx diff --git a/src/config/api.config.ts b/src/config/api.config.ts index 3087034..8896461 100644 --- a/src/config/api.config.ts +++ b/src/config/api.config.ts @@ -1,6 +1,8 @@ interface apiConfigProps { service_dashboard: string; service_master_data: string; + service_transaction: string; + service_customer: string; } const API_URL = import.meta.env.VITE_APP_API_URL; @@ -8,7 +10,9 @@ const apiConfig: apiConfigProps = { // service_dashboard: `${API_URL}${import.meta.env.VITE_ENV != 'development' ? '/d' : ''}`, service_dashboard: `${API_URL}/d`, // service_master_data: `${API_URL}/m` - service_master_data: `${API_URL}/t` + service_master_data: `${API_URL}/t`, + service_transaction: `${API_URL}/tt`, + service_customer: `${API_URL}/c`, }; export { apiConfig }; diff --git a/src/pages/transfer/TransferType.tsx b/src/pages/transfer/TransferType.tsx deleted file mode 100644 index 2e5d03e..0000000 --- a/src/pages/transfer/TransferType.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Container, DataGridInner } from '@/components'; -import { - ManageTransferTypeContext, - ManageTransferTypeContextProvider -} from './hooks/ManageTransferTypeContext'; -import AddDialog from './blocks/AddDialog'; - -const TransferType = () => { - return ( - - -
- -
- -
-
- ); -}; - -export default TransferType; diff --git a/src/pages/transfer/blocks/AddDialog.tsx b/src/pages/transfer/blocks/AddDialog.tsx deleted file mode 100644 index a7abdf1..0000000 --- a/src/pages/transfer/blocks/AddDialog.tsx +++ /dev/null @@ -1,398 +0,0 @@ -import { apiConfig } from '@/config/api.config'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; -import { Alert, KeenIcon, useDataGrid } from '@/components'; -import { useCallApi } from '@/hooks'; -import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue -} from '@/components/ui/select'; -import { Button } from '@/components/ui/button'; -import TransactionFeeDialog from './TransactionFeeDialog'; -import { toast } from 'sonner'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; -import { getAuth } from '@/auth'; - -interface CreateTransferTypeParams { - transfer_type_name: string; - description: string; - from_account: string; - to_account: string; - minimal_amount: number; - maximum_amount: number; - otp_threshold: number; - maximum_transaction_perDay: number; - status: string; - created_by: string; - created_at: string; -} - -const API_URL = apiConfig.service_dashboard; - -const AddDialog = () => { - const parentRef = useRef(null); - const { showAddDialog, handleAddDialog, accounts } = useManageTransferTypeContext(); - const { reload } = useDataGrid(); - const { PostData, PutData } = useCallApi(); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - - const initialState = { - transfer_type_name: '', - description: '', - from_account: '', - to_account: '', - minimal_amount: 0, - maximum_amount: 0, - otp_threshold: 0, - maximum_transaction_perDay: 0, - status: '', - created_by: '', - created_at: '' - }; - - const [formField, setFormField] = useState(initialState); - - const resetForm = () => { - setFormField(initialState); - }; - - const [isSubmitting, setIsSubmitting] = useState(false); - const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false); - const parsedUser = getAuth()?.user; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - // setIsSubmitting(true); - const payload = { - transfer_type_name: formField.transfer_type_name, - description: formField.description, - from_account: formField.from_account, - to_account: formField.to_account, - minimal_amount: formField.minimal_amount, - maximum_amount: formField.maximum_amount, - otp_threshold: formField.otp_threshold, - maximum_transaction_perDay: formField.maximum_transaction_perDay - }; - console.log(payload); - }; - useEffect(() => { - const created_time = new Date(); - const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); - - if (showAddDialog) { - setFormField({ - ...formField, - created_by: parsedUser?.username, - created_at: formattedTime - }); - } - }, [showAddDialog]); - const doCreateTransferType = useCallback( - async (e: React.FormEvent) => { - e.preventDefault(); - console.log(formField); - - for (const key in formField) { - if ( - formField[key as keyof typeof formField] === '' || - formField[key as keyof typeof formField] === 0 - ) { - setAlert({ show: true, message: 'All fields must be filled out' }); - return; - } - } - - setAlert({ show: false, message: '' }); - const response = await PostData(`${API_URL}/transactiontype/create`, formField); - - if (response?.status) { - setAlert({ show: false, message: '' }); - handleAddDialog(false); - toast.success('Success Create Transfer Type'); - reload(); - resetForm(); - - const createActivity = { - module: 'Manage Transfer Type', - description: `Create New Transfer Type => ${formField.transfer_type_name}`, - action: 'C' - }; - - doSaveLogActivity(createActivity); - } else { - setAlert({ show: true, message: response?.message || 'Failed to create transfer type' }); - } - - handleAddDialog(false); - }, - [formField] - ); - const handleTransactionFeeSubmit = (data: any) => { - // console.log('Transaction Fee Data Submitted:', data); - setShowTransactionFeeDialog(false); - }; - - return ( - handleAddDialog(open)}> - - - - -
-
-

Transfer Type

-
-
-
{ - handleAddDialog(false); - resetForm(); - }} - > - -
-
-
- -
- {alert.show && ( - -

{alert.message}

-
- )} -
-
-
-
- - - setFormField((prev) => ({ ...prev, transfer_type_name: target.value })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ ...prev, description: target.value })) - } - /> -
-
- -
-
- - -
- -
-
-
- -
-
- - -
- -
-
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - minimal_amount: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - maximum_amount: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - otp_threshold: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - maximum_transaction_perDay: Number(target.value) - })) - } - /> -
-
-
-
- - -
- -
-
-
- -
- - - -
-
-
- setShowTransactionFeeDialog(false)} - onSubmit={handleTransactionFeeSubmit} - /> -
-
-
-
- ); -}; - -export default AddDialog; diff --git a/src/pages/transfer/blocks/ListToolBar.tsx b/src/pages/transfer/blocks/ListToolBar.tsx deleted file mode 100644 index a3af2c3..0000000 --- a/src/pages/transfer/blocks/ListToolBar.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; -import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; -import { Button } from '@/components/ui/button'; - -const ListToolbar = () => { - const { table, reload } = useDataGrid(); - const { handleAddDialog, handleEditDialog } = useManageTransferTypeContext(); - - return ( -
-
-
-
- - - - -
-
- - - - -
-
-
-
- ); -}; - -export default ListToolbar; diff --git a/src/pages/transfer/blocks/TransactionFeeDialog.tsx b/src/pages/transfer/blocks/TransactionFeeDialog.tsx deleted file mode 100644 index cccf165..0000000 --- a/src/pages/transfer/blocks/TransactionFeeDialog.tsx +++ /dev/null @@ -1,281 +0,0 @@ -import { useState, useCallback, useEffect } from 'react'; -import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import Typography from '@mui/material/Typography'; -import { toast } from 'sonner'; -import { apiConfig } from '@/config/api.config'; -import { useCallApi } from '@/hooks'; -import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; -import { get } from 'http'; -import { getAuth } from '@/auth'; -import { useDataGrid } from '@/components'; -import { set } from 'date-fns'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; -import { - Select, - SelectTrigger, - SelectValue, - SelectContent, - SelectItem -} from '@/components/ui/select'; - -interface TransactionFeeDialogProps { - open: boolean; - onClose: () => void; - onSubmit: (data: TransactionFeeForm) => void; -} - -interface TransactionFeeForm { - name: string; - description: string; - minimum_amount: number; - maximum_amount: number; - period_start: string; - period_end: string; - deduct_amount: number; - deduct_percentage: number; - priority: string; - status: string; - transactionTypeId: string; - created_by: string; - created_at: string; -} - -const API_URL = apiConfig.service_dashboard; - -const TransactionFeeDialog: React.FC = ({ open, onClose, onSubmit }) => { - const { showAddDialog, handleAddDialog } = useManageTransferTypeContext(); - const parsedUser = getAuth()?.user; - const [formField, setFormField] = useState({ - name: '', - description: '', - minimum_amount: 0, - maximum_amount: 0, - period_start: '', - period_end: '', - deduct_amount: 0, - deduct_percentage: 0, - priority: '', - status: '', - transactionTypeId: '', - created_by: '', - created_at: '' - }); - const { PostData, PutData } = useCallApi(); - const handleChange = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setFormField((prev) => ({ - ...prev, - [name]: value - })); - }; - const [isSubmitting, setIsSubmitting] = useState(false); - const { reload } = useDataGrid(); - const resetForm = () => { - setFormField(formField); - }; - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - useEffect(() => { - const created_time = new Date(); - const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); - - if (showAddDialog) { - setFormField({ - ...formField, - created_by: parsedUser?.username, - created_at: formattedTime - }); - } - }, [showAddDialog]); - const doCreateTransactionFee = useCallback( - async (e: React.FormEvent) => { - e.preventDefault(); - console.log(formField); - const response = await PostData(`${API_URL}/transactionfees/create`, formField); - - if (response?.status) { - setAlert({ show: false, message: '' }); - handleAddDialog(false); - toast.success('Success Create Transfer Type'); - reload(); - resetForm(); - - const createActivity = { - module: 'Manage Transfer Fee', - description: `Create New Transfer Fee => ${formField.name}`, - action: 'C' - }; - - doSaveLogActivity(createActivity); - } else { - setAlert({ show: true, message: response?.message || 'Failed to create transfer fee' }); - } - - onSubmit(formField); - }, - [formField] - ); - - return ( - - - - Transaction Fee - - - -
-
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - { - const value = e.target.value; - if (/^\d*$/.test(value)) { - handleChange(e); - } - }} - required - type="text" - inputMode="numeric" - placeholder="Masukkan angka" - /> -
-
- - -
- -
- - -
-
-
-
-
-
- ); -}; - -export default TransactionFeeDialog; diff --git a/src/pages/transfer/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/hooks/ManageTransferTypeContext.tsx deleted file mode 100644 index 5a3d5d3..0000000 --- a/src/pages/transfer/hooks/ManageTransferTypeContext.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { DataGridColumnHeader, DataGridProvider } from '@/components'; -import { Toaster } from '@/components/ui/sonner'; -import { apiConfig } from '@/config/api.config'; -import { useCallApi } from '@/hooks'; -import { ColumnDef } from '@tanstack/react-table'; -import { createContext, useCallback, useEffect, useMemo, useState } from 'react'; -import ListToolbar from '../blocks/ListToolBar'; - -interface SelectedUser { - id: string; - name: string; - internal_name: string; - description: string; -} - -interface AccountProps { - id: string; - name: string; -} - -const accounts: string[] = [ - 'eMoney Account', - 'Topup Account', - 'Merchant Account', - 'Deposit Account', - 'Cash out/in' -]; - -interface ContextProps { - showEditDialog: boolean; - handleEditDialog: (show: boolean, selected_user: string | null) => void; - showAddDialog: boolean; - handleAddDialog: (show: boolean) => void; - selectedUser: string | null; - accounts: AccountProps[]; -} - -const initialProps: ContextProps = { - showEditDialog: false, - handleEditDialog: () => {}, - showAddDialog: false, - handleAddDialog: () => {}, - selectedUser: null, - accounts: [] -}; - -const ManageTransferTypeContext = createContext(initialProps); -const API_URL = apiConfig.service_dashboard; - -const ManageTransferTypeContextProvider = ({ children }: { children: React.ReactNode }) => { - const [showEditDialog, setShowEditDialog] = useState(false); - const [showAddDialog, setShowAddDialog] = useState(false); - const [selectedUser, setSelectedUser] = useState(null); - const [accounts, setAccount] = useState([]); - const { GetData } = useCallApi(); - - useEffect(() => { - setAccount([ - { id: '1', name: 'eMoney Account' }, - { id: '2', name: 'Topup Account' }, - { id: '3', name: 'Merchant Account' }, - { id: '4', name: 'Deposit Account' }, - { id: '5', name: 'Cash in/out Account' } - ]); - }, []); - - const handleEditDialog = useCallback((show: boolean, selected_user: string | null) => { - setSelectedUser(show ? selected_user : null); - setShowEditDialog(show); - }, []); - - const handleAddDialog = useCallback((show: boolean) => { - setShowAddDialog(show); - }, []); - - const columns = useMemo[]>( - () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, - { - accessorFn: (row) => row.name, - id: 'name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - accessorFn: (row) => row.internal_name, - id: 'internal_name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - accessorFn: (row) => row.description, - id: 'description', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - id: 'actions', - enableSorting: false, - header: ({ column }) => , - cell: ({ row }) => { - return ( - <> - - - - ); - }, - meta: { - headerClassName: 'w-[100px]', - cellClassName: 'text-center' - } - } - ], - [handleAddDialog, handleEditDialog] - ); - - return ( -
-
-

Manage Access Type

-
- - - } - sorting={[{ id: 'id', desc: true }]} - serverSide={true} - > - {children} - - -
- ); -}; - -export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; -export type { SelectedUser }; diff --git a/src/pages/transfer/hooks/useManageTransferTypeContext.tsx b/src/pages/transfer/hooks/useManageTransferTypeContext.tsx deleted file mode 100644 index b726a7c..0000000 --- a/src/pages/transfer/hooks/useManageTransferTypeContext.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from 'react'; -import { ManageTransferTypeContext } from './ManageTransferTypeContext'; - -const useManageTransferTypeContext = () => { - const context = useContext(ManageTransferTypeContext); - - if (!context) throw new Error('useManageAccessTypeContext must be used within AuthProvider'); - - return context; -}; - -export { useManageTransferTypeContext }; diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index 971fbaa..1cf83ae 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -24,7 +24,7 @@ import ManageMenu from '@/pages/menu/manage-menu/ManageMenu'; import Welcome from '@/pages/menu/welcome/Welcome'; import Inbox from '@/pages/message/Inbox'; import ManageWebServices from '@/pages/webservice/ManageWebServices'; -import TransferType from '@/pages/transfer/TransferType'; +import TransferType from '@/pages/transfer/transfertype/TransferType'; import MasterData from '@/pages/master/MasterData'; import PostoAdmsMaster from '@/pages/master/postoadms/PostoAdmsMaster'; import SucosMaster from '@/pages/master/sucos/SucosMaster'; From 7a62945fd67a495d3e0b2b6fe18d4eb04d45146c Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 24 Mar 2025 10:46:46 +0700 Subject: [PATCH 06/53] +package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 29c3f8b..41cfe62 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "react-inlinesvg": "^4.1.4", "react-intl": "^6.8.7", "react-leaflet": "^4.2.1", + "react-number-format": "^5.4.3", "react-query": "^3.39.3", "react-router": "^6.28.0", "react-router-dom": "^6.28.0", From 6fc67b0b2da959e9ce597dc1c977d153bed1d3d2 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 24 Mar 2025 11:37:38 +0700 Subject: [PATCH 07/53] delete wrna background + h1 manage transfer type --- src/pages/transfer/transfertype/TransferType.tsx | 4 ++-- .../transfertype/hooks/ManageTransferTypeContext.tsx | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/pages/transfer/transfertype/TransferType.tsx b/src/pages/transfer/transfertype/TransferType.tsx index 01a6da5..daa87c6 100644 --- a/src/pages/transfer/transfertype/TransferType.tsx +++ b/src/pages/transfer/transfertype/TransferType.tsx @@ -13,7 +13,7 @@ const TransferType = () => { return ( -

Manage Access Type

+

Manage Transaction Type

Dashboard @@ -24,7 +24,7 @@ const TransferType = () => { - Manage Access Type + Manage Transfer Type
diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx index 5759d29..569d2a2 100644 --- a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -202,17 +202,11 @@ order_direction: sorting[0].desc ? 'ASC' : 'DESC', filter: JSON.stringify(filter) }); - console.log("bismillah:",response?.data.list) - // setTransferType(response?.data.list); return { data: response?.data.list, totalCount: response?.data.total_count }; - // console.log("test:",response)   }; return ( -
-
-

Manage Transaction Type

-
+
Date: Mon, 24 Mar 2025 11:45:22 +0700 Subject: [PATCH 08/53] fix search filter --- src/pages/menu/manage-menu/blocks/ListToolbar.tsx | 4 ++-- src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx index 784c705..b0364d8 100644 --- a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx +++ b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx @@ -16,8 +16,8 @@ const ListToolbar = () => { table.getColumn('subMenu')?.setFilterValue(event.target.value)} + value={(table.getColumn('name')?.getFilterValue() as string) ?? ''} + onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} /> diff --git a/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx b/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx index ab46533..fcdf17c 100644 --- a/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx +++ b/src/pages/menu/manage-menu/hooks/ManageMenusContext.tsx @@ -118,7 +118,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) }, { accessorFn: (row) => row.name, - id: 'subMenu', + id: 'name', header: ({ column }) => , enableSorting: false, enableHiding: false, @@ -210,7 +210,8 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) page: page + 1, with_deleted: false, order_field: sorting[0].id, - order_direction: sorting[0].desc ? 'DESC' : 'ASC' + order_direction: sorting[0].desc ? 'DESC' : 'ASC', + filter: JSON.stringify(filter) }); if (!response?.data.list) return { data: [], totalCount: 0 }; @@ -223,7 +224,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) console.log(response.data); setMenus(transformedData); - return { data: transformedData, totalCount: response.data.total_count }; + return { data: transformedData, totalCount: total_count }; } catch (error) { console.error('Error fetching Menus', error); return { data: [], totalCount: 0 }; @@ -250,7 +251,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode }) } layout={{ card: true }} sorting={[{ id: 'id', desc: false }]} From c96ab19450d285c9f6d0ca88b7fe1f19691f0fe5 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Mon, 24 Mar 2025 15:12:36 +0700 Subject: [PATCH 09/53] fix edit form fetch transaction type id --- src/pages/master/provider/blocks/EditDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/master/provider/blocks/EditDialog.tsx b/src/pages/master/provider/blocks/EditDialog.tsx index 93b487e..186698f 100644 --- a/src/pages/master/provider/blocks/EditDialog.tsx +++ b/src/pages/master/provider/blocks/EditDialog.tsx @@ -136,7 +136,7 @@ const EditDialog = () => { description: response?.data.description, type: response?.data.type, status: response?.data.status, - transactionTypeId: response?.data.transactionTypeId, + transactionTypeId: response?.data.transaction_type.id, agent: response?.data.agent })); } From 2960ed2b8ec90cd7add221d13f332cce6bd1c40e Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 24 Mar 2025 15:27:02 +0700 Subject: [PATCH 10/53] add resetform + change customer title --- .../transfer/transferfee/blocks/AddDialog.tsx | 16 ++++----- .../transferfee/blocks/DeleteDialog.tsx | 2 -- .../transferfee/blocks/EditDialog.tsx | 33 ++++++++++++------- .../hooks/ManageTransferFeeContext.tsx | 3 -- .../transfertype/blocks/AddDialog.tsx | 20 +++++------ .../transfertype/blocks/DeleteDialog.tsx | 1 - .../transfertype/blocks/EditDialog.tsx | 32 ++++++++++++------ 7 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx index dc7ecd7..da039ee 100644 --- a/src/pages/transfer/transferfee/blocks/AddDialog.tsx +++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx @@ -109,7 +109,6 @@ const AddFeeDialog = () => { status: formField.status, status_include: formField.status_include }; - console.log(payload); }; useEffect(() => { const created_time = new Date(); @@ -137,8 +136,6 @@ const AddFeeDialog = () => { order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); - console.log('TRANSACTION TYPE LIST: ', response?.data?.list); - setTransactionTypes(response?.data.list || []); } catch (error) { console.error('Error fetching customer', error); @@ -151,7 +148,6 @@ const AddFeeDialog = () => { const doCreateTransferType = useCallback( async (e: React.FormEvent) => { e.preventDefault(); - console.log(formField); for (const key in formField) { if ( formField[key as keyof typeof formField] === '' || @@ -167,7 +163,6 @@ const AddFeeDialog = () => { ...formField, priority: formField.priority ? 'Y' : 'N' }); - // console.log("coba coba:",response); if (response?.status) { toast.success('Success Create Transfer Fee'); @@ -177,7 +172,6 @@ const AddFeeDialog = () => { } else { setAlert({ show: true, message: response?.message || 'Failed to create transfer fee' }); } - console.log(response); }, [formField] ); @@ -190,7 +184,7 @@ const AddFeeDialog = () => {
-

AddTransfer Fee

+

Add Transfer Fee

{
-
*/}
- */} -
*/}
- */} - - @@ -190,24 +200,27 @@ ], [handleEditDialog, handleDeleteDialog] ); - const doGetTransferTypeListData = async (page: number, limit: number, sorting: any, filter: any) => { - - sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; - filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; - const response = await GetData(`${API_URL}/transactiontype/list`, { - limit: limit, - page: page + 1, - with_deleted: false, - order_field: sorting[0].id, - order_direction: sorting[0].desc ? 'ASC' : 'DESC', - filter: JSON.stringify(filter) - }); - return { data: response?.data.list, totalCount: response?.data.total_count }; -   }; + const doGetTransferTypeListData = async ( + page: number, + limit: number, + sorting: any, + filter: any + ) => { + sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: limit, + page: page + 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'ASC' : 'DESC', + filter: JSON.stringify(filter) + }); + return { data: response?.data.list, totalCount: response?.data.total_count }; + }; return (
- - +
); - - }; +}; - export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; - export type { TransferType }; +export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; +export type { TransferType }; From 2c9c11edf6d48e2f7b23b0551ec26d7baa99d99b Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Mon, 24 Mar 2025 15:34:24 +0700 Subject: [PATCH 12/53] fix clear history and hide filter icon --- .../menu/manage-menu/blocks/ListToolbar.tsx | 6 +++--- .../user/manage-user/blocks/EditDialog.tsx | 16 ++++++++++++++-- .../user/manage-user/blocks/ListToolBar.tsx | 6 +++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx index b0364d8..0e36ca9 100644 --- a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx +++ b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx @@ -20,17 +20,17 @@ const ListToolbar = () => { onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} /> - + {/* - + */}
- + */}
+ +
+
+ +
+ + + + ); +}; + +export default AddDialog; diff --git a/src/pages/transaction/blocks/DeleteDialog.tsx b/src/pages/transaction/blocks/DeleteDialog.tsx new file mode 100644 index 0000000..2e8f25d --- /dev/null +++ b/src/pages/transaction/blocks/DeleteDialog.tsx @@ -0,0 +1,87 @@ +import { Alert, useDataGrid } from '@/components'; +import { useTransactionContext } from '../hooks/useTransactionContext'; +import { ChangeEvent, useCallback, useState } from 'react'; +import axios from 'axios'; +import { apiConfig } from '@/config/api.config'; +import { useCallApi } from '@/hooks'; +import { toast } from 'sonner'; +import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; +import { EnforceSwitch } from '@/components/switch'; +import { Button } from '@/components/ui/button'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; + +const API_URL = apiConfig.service_master_data; + +const DeleteDialog = () => { + const { showDeleteDialog, handleDeleteDialog, selectedMunicipios, municipios } = + useTransactionContext(); + const { reload } = useDataGrid(); + const { DeleteData } = useCallApi(); + const [enforce, setEnforce] = useState(false); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const doDeleteMunicipio = useCallback(async () => { + const response = await DeleteData( + `${API_URL}/municipios/delete/${selectedMunicipios}/${enforce}`, + { + id: selectedMunicipios + } + ); + + if (response?.status) { + setAlert((prev) => ({ ...prev, show: false, message: '' })); + handleDeleteDialog(false, null); + toast.success('Success Delete Municipio'); + reload(); + // const createActivity = { + // module: 'Manage Municipio', + // description: `Delete Municipio => ${selectedMunicipios}`, + // action: 'D' + // }; + + // doSaveLogActivity(createActivity); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + }, [selectedMunicipios, enforce]); + + return ( + handleDeleteDialog(open, null)}> + + + +

Are you sure?

+ you will delete this data! +
+ + ) => { + setEnforce(e.target.checked); + }} + /> +
+
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); +}; + +export default DeleteDialog; diff --git a/src/pages/transaction/blocks/EditDialog.tsx b/src/pages/transaction/blocks/EditDialog.tsx new file mode 100644 index 0000000..0ab2a46 --- /dev/null +++ b/src/pages/transaction/blocks/EditDialog.tsx @@ -0,0 +1,173 @@ +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { useTransactionContext } from '../hooks/useTransactionContext'; +import { Alert, useDataGrid } from '@/components'; +import axios from 'axios'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { getAuth, useAuthContext } from '@/auth'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; + +const API_URL = apiConfig.service_master_data; + +const EditDialog = () => { + const parentRef = useRef(null); + const { showEditDialog, handleEditDialog, selectedMunicipios, municipios } = + useTransactionContext(); + const { reload } = useDataGrid(); + const { PutData, GetData } = useCallApi(); + const parsedUser = getAuth()?.user; + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const initialState = { + name: '', + updated_by: '', + updated_at: '' + }; + + const [formField, setFormField] = useState(initialState); + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + const resetForm = () => { + setFormField(initialState); + setAlert({ show: false, message: '' }); + }; + + const doUpdateMunicipios = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + const response = await PutData( + `${API_URL}/municipios/update/${selectedMunicipios}`, + formField + ); + + if (response?.status) { + handleEditDialog(false, null); + resetForm(); + toast.success('Success update municipio'); + reload(); + // const createActivity = { + // module: 'Manage Municipio', + // description: `Edit Municipio => ${selectedMunicipios}`, + // action: 'U' + // }; + + // doSaveLogActivity(createActivity); + } else { + toast.error('Failed update user'); + setAlert({ show: true, message: 'Failed to update municipio. Please try again.' }); + } + }, + [selectedMunicipios, formField] + ); + + const doFetchData = useCallback(async (id: string) => { + const response = await GetData(`${API_URL}/municipios/getdata/${id}`, { id }); + + if (response?.status) { + setFormField((prev) => ({ + ...prev, + name: response.data.name + })); + } else { + setFormField((prev) => ({ + ...prev, + name: '' + })); + } + }, []); + + const handleUpdate = (e: React.FormEvent) => { + e.preventDefault(); + + if (formField.name.trim() === '') { + setAlert({ show: true, message: 'Please fill name field.' }); + return; + } + + doUpdateMunicipios(e); + console.log(formField); + setAlert({ show: false, message: '' }); + }; + + useEffect(() => { + if (selectedMunicipios) { + doFetchData(selectedMunicipios); + } + }, [selectedMunicipios]); + + useEffect(() => { + if (showEditDialog === false) { + resetForm(); + } + }, [showEditDialog]); + + useEffect(() => { + if (selectedMunicipios) { + setFormField({ + name: formField.name, + updated_by: parsedUser.email, + updated_at: formattedTime + }); + } + }, [formattedTime]); + + // console.log(selectedMunicipios); + return ( + handleEditDialog(open, null)}> + + + Municipios - Update + + + +
+ {alert.show && ( + +

{alert.message}

+
+ )} + +
+
+
+
+ + setFormField({ ...formField, name: e.target.value })} + /> +
+
+ +
+ +
+
+
+
+
+
+
+ ); +}; + +export default EditDialog; diff --git a/src/pages/transaction/blocks/ListToolbar.tsx b/src/pages/transaction/blocks/ListToolbar.tsx new file mode 100644 index 0000000..cb71f6d --- /dev/null +++ b/src/pages/transaction/blocks/ListToolbar.tsx @@ -0,0 +1,90 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { useTransactionContext } from '../hooks/useTransactionContext'; +import { Button } from '@/components/ui/button'; +import { useCallback, useState, useEffect } from 'react'; +import { toast } from 'sonner'; + +const ListToolbar = () => { + const { table, reload } = useDataGrid(); + const { handleAddDialog, handleSearchDialog } = useTransactionContext(); + + // Set the initial state for trxDate + const [trxDate, settrxDate] = useState({ from: '', to: '' }); + + // Function to format date to YYYY-MM-DD + const formatDate = (date: Date): string => { + return date.toISOString().split('T')[0]; + }; + + // useEffect to set the default date values + useEffect(() => { + const today = new Date(); + const nextWeek = new Date(today); + nextWeek.setDate(today.getDate() + 7); + + settrxDate({ + from: formatDate(today), // Set 'from' to today + to: formatDate(nextWeek), // Set 'to' to 7 days later + }); + }, []); + + const handleFilterData = useCallback(() => { + try { + table.getColumn('transaction_date')?.setFilterValue(trxDate); + } catch (error) { + toast.error('Error applying filter'); + console.error('Error applying filter:', error); + } + }, [trxDate, table]); + + useEffect(() => { + if (trxDate.from && trxDate.to) { + handleFilterData(); + } + }, [trxDate]); + + return ( +
+
+
+
+ + + +
+
+ + + +
+
+
+
+ ); +}; + +export default ListToolbar; diff --git a/src/pages/transaction/blocks/SearchDialog.tsx b/src/pages/transaction/blocks/SearchDialog.tsx new file mode 100644 index 0000000..a5d84f7 --- /dev/null +++ b/src/pages/transaction/blocks/SearchDialog.tsx @@ -0,0 +1,178 @@ +import { useRef, useState } from 'react'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Alert, KeenIcon } from '@/components'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useTransactionContext } from '../hooks/useTransactionContext'; +import { apiConfig } from '@/config/api.config'; +import axios from 'axios'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; + +interface trxDate { + from: string; + to: string; +} + +const API_URL = apiConfig.service_master_data; + +const SearchDialog = () => { + const parentRef = useRef(null); + const { showSearchDialog, handleSearchDialog, municipios } = useTransactionContext(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const initialState = { + from: '', + to: '' + }; + + const [formField, setFormField] = useState(initialState); + const resetForm = () => { + setFormField(initialState); + }; + const [trxDate, settrxDate] = useState([]); + const [isFound, setIsFound] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + const from = String(formField.from); + const to = String(formField.to); + + // if (formField.id === 0) { + // setAlert({ show: true, message: 'Please fill name field.' }); + // return; + // } + + try { + // const response = await axios.get(`${API_URL}/municipios/postoadms/${id}`); + + // if (response.data.status) { + // setPostoadms(response.data.data); + // setIsFound(true); + // // console.log('Found postoadms: ', response.data.data); + // } else { + // setPostoadms([]); + // setIsFound(false); + // setAlert({ show: true, message: 'No postoadms found.' }); + // } + } catch (error) { + console.error('Error fetching postoadms', error); + setAlert({ show: true, message: 'Failed to fetch postoadms. Please try again.' }); + } + setAlert({ show: false, message: '' }); + }; + + const handleReset = () => { + setFormField(initialState); + setIsFound(false); + settrxDate([]); + }; + // console.log(municipios); + return ( + handleSearchDialog(open)}> + + + + +
+
+

+ Search Postoadms +

+
+
+
{ + handleSearchDialog(false); + resetForm(); + }} + > + +
+
+
+ +
+ {alert.show && ( + + {alert.message} + + )} +
+
+
+ + + {/* */} +
+ + {/* {isFound && postoadms.length > 0 && ( +
+

Postu Administravo:

+
+
+ + {postoadms.map((posto) => posto.name).join(', ')} + +
+
+ )} */} + +
+ + +
+
+
+
+
+
+
+ ); +}; + +export default SearchDialog; diff --git a/src/pages/transaction/hooks/TransactionContext.tsx b/src/pages/transaction/hooks/TransactionContext.tsx new file mode 100644 index 0000000..61a70d8 --- /dev/null +++ b/src/pages/transaction/hooks/TransactionContext.tsx @@ -0,0 +1,258 @@ +import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; +import { Toaster } from '@/components/ui/sonner'; +import { apiConfig } from '@/config/api.config'; +import { ColumnDef } from '@tanstack/react-table'; +import axios from 'axios'; +import React, { createContext, useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallApi } from '@/hooks'; +import ListToolbar from '../blocks/ListToolbar'; +import { Button } from '@/components/ui/button'; +import { useNavigate } from 'react-router'; + +interface TransactionProps { + id: number; + name: string; +} + +interface ContextProps { + municipios: TransactionProps[]; + showSearchDialog: boolean; + handleSearchDialog: (show: boolean) => void; + showEditDialog: boolean; + handleEditDialog: (show: boolean, selected_user: string | null) => void; + showAddDialog: boolean; + handleAddDialog: (show: boolean) => void; + showDeleteDialog: boolean; + handleDeleteDialog: (show: boolean, selected_user: string | null) => void; + selectedMunicipios: string | null; + getTransactionLists: ( + limit: number, + page: number, + with_deleted: boolean, + order_field: any, + order_direction: any, + filter: any + ) => Promise<{ data: TransactionProps[]; totalCount: number } | undefined>; +} + +const initialProps: ContextProps = { + municipios: [], + showSearchDialog: false, + handleSearchDialog: (show: boolean) => { }, + showEditDialog: false, + handleEditDialog: (show: boolean, selected_user: string | null) => { }, + showAddDialog: false, + handleAddDialog: (show: boolean) => { }, + showDeleteDialog: false, + handleDeleteDialog: (show: boolean, selected_user: string | null) => { }, + selectedMunicipios: null, + getTransactionLists: async () => ({ data: [], totalCount: 0 }) +}; + +const ManageTransactionContext = createContext(initialProps); +const API_URL = apiConfig.transaction; + +const TransactionProvider = ({ children }: { children: React.ReactNode }) => { + const [showSearchDialog, setShowSearchDialog] = useState(false); + const [showEditDialog, setShowEditDialog] = useState(false); + const [showAddDialog, setShowAddDialog] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [selectedMunicipios, setSelectedMunicipios] = useState(null); + const [municipios, setTransaction] = useState([]); + const { GetData } = useCallApi(); + const navigate = useNavigate(); + + const handleSearchDialog = useCallback((show: boolean) => { + setShowSearchDialog(show); + }, []); + + const handleAddDialog = useCallback((show: boolean) => { + setShowAddDialog(show); + }, []); + + const handleEditDialog = useCallback((show: boolean, selected_municipios: string | null) => { + setSelectedMunicipios(show ? selected_municipios : null); + setShowEditDialog(show); + }, []); + + const handleDeleteDialog = useCallback((show: boolean, selected_municipios: string | null) => { + setSelectedMunicipios(show ? selected_municipios : null); + setShowDeleteDialog(show); + }, []); + + const handleNavigate = (path: string) => { + const url = navigate(`${API_URL}/transaction/history/${path}`); + }; + + const columns = useMemo[]>( + () => [ + { + accessorKey: 'transaction_date', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorKey: 'origin_customer.fullname', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorFn: (row) => + new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(row.purchase.amount), + id: 'amount', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]', + }, + }, + { + accessorFn: (row) => { + let fee; + if (row.kind === 'P') { + fee = row.purchase.fee_amount; + } else { + fee = row.transfer.fee_amount; + } + return fee.toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + }); + }, + accessorKey: 'fee', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]', + }, + }, + { + accessorKey: 'description', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorKey: 'type.name', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + id: 'actions', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + cell: (data) => { + const row = data.row.original.id; + return ( + <> + + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + } + ], + [handleEditDialog, handleDeleteDialog] + ); + + const getTransactionLists = async (page: number, limit: number, sorting: any, filter: any) => { + try { + let startdate; + let enddate; + let formattedFilter; + + if (filter == undefined || filter.length==0) { + const today = new Date(); + const nextWeek = new Date(); + nextWeek.setDate(today.getDate() + 7); + + startdate = today.toISOString().split('T')[0]; + enddate = nextWeek.toISOString().split('T')[0]; + }else if (filter != undefined || filter.length!=0) { + startdate = filter[0].value.from; + enddate = filter[0].value.to; + } + + formattedFilter = { + "Transactions.transaction_date": { + from: startdate+" 00:00:00", + to: enddate+" 23:59:59" + } + }; + + const response = await GetData(`${API_URL}/transaction/history`, { + limit, + page: page + 1, + with_deleted: false, + order_field: "Transactions.created_at", + order_direction: 'DESC', + filter: JSON.stringify(formattedFilter) + }); + + setTransaction(response?.data.list); + return { data: response?.data.list, totalCount: response?.data.total_count }; + } catch (error) { + console.error('Error fetching transaction', error); + } + }; + + return ( + + + + } + layout={{ card: true }} + sorting={[{ id: 'id', desc: false }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + getTransactionLists(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + + ); +}; + +export { TransactionProvider, ManageTransactionContext }; +export type { TransactionProps }; diff --git a/src/pages/transaction/hooks/useTransactionContext.tsx b/src/pages/transaction/hooks/useTransactionContext.tsx new file mode 100644 index 0000000..4af7036 --- /dev/null +++ b/src/pages/transaction/hooks/useTransactionContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageTransactionContext } from './TransactionContext'; + +const useTransactionContext = () => { + const context = useContext(ManageTransactionContext); + + if (!context) throw new Error('useTransactionContext must be used within AuthProvider'); + + return context; +}; + +export { useTransactionContext }; diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx index 4fcba47..dda8418 100644 --- a/src/pages/transaction/transaction.tsx +++ b/src/pages/transaction/transaction.tsx @@ -1,12 +1,39 @@ +import { Container, DataGridInner } from '@/components'; +import { TransactionProvider } from './hooks/TransactionContext'; +import AddDialog from './blocks/AddDialog'; +import SearchDialog from './blocks/SearchDialog'; +import EditDialog from './blocks/EditDialog'; +import DeleteDialog from './blocks/DeleteDialog'; +import { Breadcrumbs, Link } from '@mui/material'; + const Transaction = () => { - return ( -
-
-

Transaction

+ return ( + + +

TRANSACTION

+ + + Dashboard + + + + Master Data + + + + Transaction + + +
+
-
- ); - }; - - export default Transaction; - \ No newline at end of file + + + + + + + ); +}; + +export default Transaction; diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index c3a165c..3c9ee50 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -19,7 +19,7 @@ import AccessType from '@/pages/access/access-type/AccessType'; import MemberCredential from '@/pages/access/member-credentials/MemberCredentials'; import ManageCurrency from '@/pages/account/manage-currency/ManageCurrency'; import ManageNotification from '@/pages/notification/ManageNotification'; -import MenuCategory from '@/pages/menu/menu-category/MenuCategory'; +import Transaction from '@/pages/transaction/Transaction'; import ManageMenu from '@/pages/menu/manage-menu/ManageMenu'; import Welcome from '@/pages/menu/welcome/Welcome'; import Inbox from '@/pages/message/Inbox'; @@ -76,7 +76,7 @@ const AppRoutingSetup = (): ReactElement => { } /> - } /> + } /> } /> } /> } /> diff --git a/yarn.lock b/yarn.lock index 644ce57..48c270d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -524,14 +524,14 @@ source-map "^0.5.7" stylis "4.2.0" -"@emotion/cache@^11.13.0", "@emotion/cache@^11.13.1": - version "11.13.1" - resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz" - integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw== +"@emotion/cache@^11.13.0", "@emotion/cache@^11.13.1", "@emotion/cache@^11.13.5": + version "11.14.0" + resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz" + integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== dependencies: "@emotion/memoize" "^0.9.0" "@emotion/sheet" "^1.4.0" - "@emotion/utils" "^1.4.0" + "@emotion/utils" "^1.4.2" "@emotion/weak-memoize" "^0.4.0" stylis "4.2.0" @@ -578,15 +578,15 @@ "@emotion/weak-memoize" "^0.4.0" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1", "@emotion/serialize@^1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz" - integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA== +"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1", "@emotion/serialize@^1.3.3": + version "1.3.3" + resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz" + integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== dependencies: "@emotion/hash" "^0.9.2" "@emotion/memoize" "^0.9.0" "@emotion/unitless" "^0.10.0" - "@emotion/utils" "^1.4.1" + "@emotion/utils" "^1.4.2" csstype "^3.0.2" "@emotion/sheet@^1.4.0": @@ -621,10 +621,10 @@ resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz" integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== -"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1": - version "1.4.1" - resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz" - integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA== +"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.2": + version "1.4.2" + resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz" + integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== "@emotion/weak-memoize@^0.4.0": version "0.4.0" @@ -979,68 +979,75 @@ clsx "^2.1.0" prop-types "^15.8.1" -"@mui/core-downloads-tracker@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.6.tgz" - integrity sha512-nz1SlR9TdBYYPz4qKoNasMPRiGb4PaIHFkzLzhju0YVYS5QSuFF2+n7CsiHMIDcHv3piPu/xDWI53ruhOqvZwQ== +"@mui/core-downloads-tracker@^6.4.8": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.8.tgz" + integrity sha512-vjP4+A1ybyCRhDZC7r5EPWu/gLseFZxaGyPdDl94vzVvk6Yj6gahdaqcjbhkaCrJjdZj90m3VioltWPAnWF/zw== -"@mui/material@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/material/-/material-6.1.6.tgz" - integrity sha512-1yvejiQ/601l5AK3uIdUlAVElyCxoqKnl7QA+2oFB/2qYPWfRwDgavW/MoywS5Y2gZEslcJKhe0s2F3IthgFgw== +"@mui/icons-material@^6.4.6": + version "6.4.6" + resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.6.tgz" + integrity sha512-rGJBvIQQbQAlyKYljHQ8wAQS/K2/uYwvemcpygnAmCizmCI4zSF9HQPuiG8Ql4YLZ6V/uKjA3WHIYmF/8sV+pQ== dependencies: "@babel/runtime" "^7.26.0" - "@mui/core-downloads-tracker" "^6.1.6" - "@mui/system" "^6.1.6" - "@mui/types" "^7.2.19" - "@mui/utils" "^6.1.6" + +"@mui/material@^6.1.6", "@mui/material@^6.4.6": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/material/-/material-6.4.8.tgz" + integrity sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q== + dependencies: + "@babel/runtime" "^7.26.0" + "@mui/core-downloads-tracker" "^6.4.8" + "@mui/system" "^6.4.8" + "@mui/types" "~7.2.24" + "@mui/utils" "^6.4.8" "@popperjs/core" "^2.11.8" - "@types/react-transition-group" "^4.4.11" + "@types/react-transition-group" "^4.4.12" clsx "^2.1.1" csstype "^3.1.3" prop-types "^15.8.1" - react-is "^18.3.1" + react-is "^19.0.0" react-transition-group "^4.4.5" -"@mui/private-theming@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.6.tgz" - integrity sha512-ioAiFckaD/fJSnTrUMWgjl9HYBWt7ixCh7zZw7gDZ+Tae7NuprNV6QJK95EidDT7K0GetR2rU3kAeIR61Myttw== +"@mui/private-theming@^6.4.8": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.8.tgz" + integrity sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ== dependencies: "@babel/runtime" "^7.26.0" - "@mui/utils" "^6.1.6" + "@mui/utils" "^6.4.8" prop-types "^15.8.1" -"@mui/styled-engine@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.6.tgz" - integrity sha512-I+yS1cSuSvHnZDBO7e7VHxTWpj+R7XlSZvTC4lS/OIbUNJOMMSd3UDP6V2sfwzAdmdDNBi7NGCRv2SZ6O9hGDA== +"@mui/styled-engine@^6.4.8": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.8.tgz" + integrity sha512-oyjx1b1FvUCI85ZMO4trrjNxGm90eLN3Ohy0AP/SqK5gWvRQg1677UjNf7t6iETOKAleHctJjuq0B3aXO2gtmw== dependencies: "@babel/runtime" "^7.26.0" - "@emotion/cache" "^11.13.1" - "@emotion/serialize" "^1.3.2" + "@emotion/cache" "^11.13.5" + "@emotion/serialize" "^1.3.3" "@emotion/sheet" "^1.4.0" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/system/-/system-6.1.6.tgz" - integrity sha512-qOf1VUE9wK8syiB0BBCp82oNBAVPYdj4Trh+G1s+L+ImYiKlubWhhqlnvWt3xqMevR+D2h1CXzA1vhX2FvA+VQ== +"@mui/system@^6.4.8": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/system/-/system-6.4.8.tgz" + integrity sha512-gV7iBHoqlsIenU2BP0wq14BefRoZcASZ/4LeyuQglayBl+DfLX5rEd3EYR3J409V2EZpR0NOM1LATAGlNk2cyA== dependencies: "@babel/runtime" "^7.26.0" - "@mui/private-theming" "^6.1.6" - "@mui/styled-engine" "^6.1.6" - "@mui/types" "^7.2.19" - "@mui/utils" "^6.1.6" + "@mui/private-theming" "^6.4.8" + "@mui/styled-engine" "^6.4.8" + "@mui/types" "~7.2.24" + "@mui/utils" "^6.4.8" clsx "^2.1.1" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/types@^7.2.14", "@mui/types@^7.2.15", "@mui/types@^7.2.19": - version "7.2.19" - resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz" - integrity sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA== +"@mui/types@^7.2.14", "@mui/types@^7.2.15", "@mui/types@~7.2.24": + version "7.2.24" + resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz" + integrity sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw== "@mui/utils@^5.15.14": version "5.16.6" @@ -1054,17 +1061,17 @@ prop-types "^15.8.1" react-is "^18.3.1" -"@mui/utils@^6.1.6": - version "6.1.6" - resolved "https://registry.npmjs.org/@mui/utils/-/utils-6.1.6.tgz" - integrity sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ== +"@mui/utils@^6.1.6", "@mui/utils@^6.4.8": + version "6.4.8" + resolved "https://registry.npmjs.org/@mui/utils/-/utils-6.4.8.tgz" + integrity sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ== dependencies: "@babel/runtime" "^7.26.0" - "@mui/types" "^7.2.19" - "@types/prop-types" "^15.7.13" + "@mui/types" "~7.2.24" + "@types/prop-types" "^15.7.14" clsx "^2.1.1" prop-types "^15.8.1" - react-is "^18.3.1" + react-is "^19.0.0" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1677,10 +1684,10 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== -"@types/prop-types@*", "@types/prop-types@^15.7.12", "@types/prop-types@^15.7.13": - version "15.7.13" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz" - integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== +"@types/prop-types@*", "@types/prop-types@^15.7.12", "@types/prop-types@^15.7.14": + version "15.7.14" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== "@types/react-dom@*", "@types/react-dom@^18.3.1": version "18.3.1" @@ -1696,12 +1703,10 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.11": - version "4.4.11" - resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz" - integrity sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA== - dependencies: - "@types/react" "*" +"@types/react-transition-group@^4.4.12": + version "4.4.12" + resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz" + integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== "@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.3.12", "@types/react@16 || 17 || 18": version "18.3.12" @@ -2624,6 +2629,8 @@ fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== @@ -3796,6 +3803,11 @@ react-is@^18.3.1: resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== +react-is@^19.0.0: + version "19.0.0" + resolved "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz" + integrity sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g== + react-leaflet@^4.2.1: version "4.2.1" resolved "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz" From f3b41ff3360a151aa782bd3ccc6f04855f6f845d Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Mon, 24 Mar 2025 15:52:01 +0700 Subject: [PATCH 19/53] update --- src/routing/AppRoutingSetup.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index 3c9ee50..9b076f5 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -33,7 +33,7 @@ import Municipios from '@/pages/master/municipios/Municipios'; import ProfessionMaster from '@/pages/master/profession/ProfessionMaster'; import ProductsMaster from '@/pages/master/products/ProductsMaster'; import ProviderMaster from '@/pages/master/provider/ProviderMaster'; -import Transaction from '@/pages/transaction/transaction'; +// import Transaction from '@/pages/transaction/transaction'; import ConversionMaster from '@/pages/master/conversion/ConversionMaster'; import WalletRuleMaster from '@/pages/master/walletRule/WalletRuleMaster'; From 884617ac3c8c7492b5f6d6cd9d5ef5338b5efebc Mon Sep 17 00:00:00 2001 From: Raja Oktafrianto Date: Mon, 24 Mar 2025 16:04:52 +0700 Subject: [PATCH 20/53] scroll bar add data postu, sucos, aldeias active. hide icon filter manage user & menu. message error in manage user done --- src/pages/master/aldeias/AldeiasMaster.tsx | 2 +- src/pages/master/aldeias/blocks/AddDialog.tsx | 5 ++++- src/pages/master/postoadms/blocks/AddDialog.tsx | 7 +++++-- src/pages/master/postoadms/blocks/ListToolbar.tsx | 4 +--- .../master/postoadms/hooks/ManagePostoAdmsContext.tsx | 2 +- src/pages/master/products/blocks/AddDialog.tsx | 8 +++++--- src/pages/master/sucos/SucosMaster.tsx | 2 +- src/pages/master/sucos/blocks/AddDialog.tsx | 5 ++++- src/pages/master/sucos/blocks/ListToolbar.tsx | 8 -------- src/pages/menu/manage-menu/blocks/ListToolbar.tsx | 6 +++--- .../settings/user/manage-user/blocks/ListToolBar.tsx | 6 +++--- src/partials/dropdowns/user/DropdownUser.tsx | 6 +++++- 12 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/pages/master/aldeias/AldeiasMaster.tsx b/src/pages/master/aldeias/AldeiasMaster.tsx index a3d0ad7..3ebb197 100644 --- a/src/pages/master/aldeias/AldeiasMaster.tsx +++ b/src/pages/master/aldeias/AldeiasMaster.tsx @@ -9,7 +9,7 @@ const AldeiasMaster = () => { return ( -

Aldeias

+

Aldeias

Dashboard diff --git a/src/pages/master/aldeias/blocks/AddDialog.tsx b/src/pages/master/aldeias/blocks/AddDialog.tsx index af089ef..731ceba 100644 --- a/src/pages/master/aldeias/blocks/AddDialog.tsx +++ b/src/pages/master/aldeias/blocks/AddDialog.tsx @@ -172,7 +172,10 @@ const AddDialog = () => { 'Select Sucos'} - + e.stopPropagation()} + > diff --git a/src/pages/master/postoadms/blocks/AddDialog.tsx b/src/pages/master/postoadms/blocks/AddDialog.tsx index fa7c7dd..eaa8b1e 100644 --- a/src/pages/master/postoadms/blocks/AddDialog.tsx +++ b/src/pages/master/postoadms/blocks/AddDialog.tsx @@ -174,10 +174,13 @@ const AddDialog = () => { ?.name || 'Select Municipios'} - + e.stopPropagation()} + > - + No Municipio found. {municipios.map((municipio) => ( diff --git a/src/pages/master/postoadms/blocks/ListToolbar.tsx b/src/pages/master/postoadms/blocks/ListToolbar.tsx index 60ab7d2..04742a3 100644 --- a/src/pages/master/postoadms/blocks/ListToolbar.tsx +++ b/src/pages/master/postoadms/blocks/ListToolbar.tsx @@ -18,9 +18,7 @@ const ListToolbar = () => { type="text" placeholder="Search Postu" value={(table.getColumn('name')?.getFilterValue() as string) ?? ''} - onChange={(event) => - table.getColumn('name')?.setFilterValue(event.target.value) - } + onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} /> {/* diff --git a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx index ec68ee0..ef6f7b5 100644 --- a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx +++ b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx @@ -99,7 +99,7 @@ const ManagePostoAdmsContextProvider = ({ children }: { children: React.ReactNod { accessorFn: (row) => row.municipios_name, id: 'municipios_name', - header: ({ column }) => , + header: ({ column }) => , enableSorting: false, enableHiding: false, meta: { diff --git a/src/pages/master/products/blocks/AddDialog.tsx b/src/pages/master/products/blocks/AddDialog.tsx index 343e076..dc53b39 100644 --- a/src/pages/master/products/blocks/AddDialog.tsx +++ b/src/pages/master/products/blocks/AddDialog.tsx @@ -155,9 +155,11 @@ const AddDialog = () => {
{alert.show && ( - -

{alert.message}

-
+
+ +

{alert.message}

+
+
)}
diff --git a/src/pages/master/sucos/SucosMaster.tsx b/src/pages/master/sucos/SucosMaster.tsx index c698cfa..ac7b7e5 100644 --- a/src/pages/master/sucos/SucosMaster.tsx +++ b/src/pages/master/sucos/SucosMaster.tsx @@ -10,7 +10,7 @@ const SucosMaster = () => { return ( -

Sucos

+

Sucos

Dashboard diff --git a/src/pages/master/sucos/blocks/AddDialog.tsx b/src/pages/master/sucos/blocks/AddDialog.tsx index ea31fe8..822fe24 100644 --- a/src/pages/master/sucos/blocks/AddDialog.tsx +++ b/src/pages/master/sucos/blocks/AddDialog.tsx @@ -170,7 +170,10 @@ const AddDialog = () => { ?.PostoAdms_name || 'Select Posto Administrativo'} - + e.stopPropagation()} + > diff --git a/src/pages/master/sucos/blocks/ListToolbar.tsx b/src/pages/master/sucos/blocks/ListToolbar.tsx index 9e822bb..dcdf109 100644 --- a/src/pages/master/sucos/blocks/ListToolbar.tsx +++ b/src/pages/master/sucos/blocks/ListToolbar.tsx @@ -21,14 +21,6 @@ const ListToolbar = () => { table.getColumn('sucos_name')?.setFilterValue(event.target.value) } /> - - table.getColumn('posto_name')?.setFilterValue(event.target.value) - } - /> {/* - + */}
- + */}
@@ -186,9 +186,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_type: e.target.value }) + setFormField({ ...formField, type: e.target.value }) } />
@@ -202,9 +202,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_code: e.target.value }) + setFormField({ ...formField, code: e.target.value }) } />
@@ -218,9 +218,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_description: e.target.value }) + setFormField({ ...formField, description: e.target.value }) } />
@@ -236,12 +236,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_price_point} + value={formField.price_point} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_price_point: isNaN(value) ? 0 : value + price_point: isNaN(value) ? 0 : value }); }} /> @@ -258,12 +258,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_price_cash} + value={formField.price_cash} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_price_cash: isNaN(value) ? 0 : value + price_cash: isNaN(value) ? 0 : value }); }} /> @@ -280,12 +280,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_cashback_point} + value={formField.cashback_point} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_cashback_point: isNaN(value) ? 0 : value + cashback_point: isNaN(value) ? 0 : value }); }} /> @@ -302,12 +302,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_cashback_cash} + value={formField.cashback_cash} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_cashback_cash: isNaN(value) ? 0 : value + cashback_cash: isNaN(value) ? 0 : value }); }} /> @@ -320,9 +320,9 @@ const AddDialog = () => { Status* - setFormField({ ...formField, products_provider: value.toString() }) + setFormField({ ...formField, provider: value.toString() }) } > @@ -370,9 +370,9 @@ const AddDialog = () => { Process on Third Party* - setFormField({ ...formField, transactionTypeId: value }) + setFormField({ ...formField, transaction_type: value }) } > @@ -290,7 +290,7 @@ const AddDialog = () => { @@ -307,7 +307,7 @@ const AddDialog = () => { onSelect={() => { setFormField({ ...formField, - agentId: customer.msisdn + agent: customer.msisdn }); setOpen(false); }} From c559fa5d5d9475c3fae86c40261eb113347663d1 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Mar 2025 09:21:49 +0700 Subject: [PATCH 26/53] fix post profession --- src/pages/master/profession/blocks/AddDialog.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/master/profession/blocks/AddDialog.tsx b/src/pages/master/profession/blocks/AddDialog.tsx index f87c9f9..f3f0f34 100644 --- a/src/pages/master/profession/blocks/AddDialog.tsx +++ b/src/pages/master/profession/blocks/AddDialog.tsx @@ -48,7 +48,6 @@ const AddDialog = () => { const response = await PostData(`${API_URL}/profession/create`, formField); if (response?.status) { - resetForm(); handleAddDialog(false); toast.success('Success Create Profession'); reload(); From 3a0c01ca6529da6f0fb2afc5a3c6795a723a23f2 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Mar 2025 09:22:31 +0700 Subject: [PATCH 27/53] fix post profession --- src/pages/master/profession/hooks/ManageProfessionContext.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/master/profession/hooks/ManageProfessionContext.tsx b/src/pages/master/profession/hooks/ManageProfessionContext.tsx index 63d003c..1ec9abb 100644 --- a/src/pages/master/profession/hooks/ManageProfessionContext.tsx +++ b/src/pages/master/profession/hooks/ManageProfessionContext.tsx @@ -117,7 +117,7 @@ const ManageProfessionContextProvider = ({ children }: { children: React.ReactNo const response = await GetData(`${API_URL}/profession/list`, { limit, page: page + 1, - with_deleted: true, + with_deleted: false, order_field: sorting[0].id, order_direction: sorting[0].desc == false ? 'ASC' : 'DESC', filter: JSON.stringify(filter) From 50bd7980b23c7c2047f9706b92486b6482601eac Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Mar 2025 10:05:07 +0700 Subject: [PATCH 28/53] fix create and update - change posto_adm_id to postoId --- src/pages/master/sucos/blocks/AddDialog.tsx | 10 +++++----- src/pages/master/sucos/blocks/EditDialog.tsx | 16 ++++++++-------- src/pages/master/sucos/blocks/ListToolbar.tsx | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/pages/master/sucos/blocks/AddDialog.tsx b/src/pages/master/sucos/blocks/AddDialog.tsx index dd5ab57..67e9844 100644 --- a/src/pages/master/sucos/blocks/AddDialog.tsx +++ b/src/pages/master/sucos/blocks/AddDialog.tsx @@ -45,7 +45,7 @@ const AddDialog = () => { }); const initialState = { name: '', - posto_adm_id: 0, + postoId: 0, created_by: '', created_at: '' }; @@ -80,7 +80,7 @@ const AddDialog = () => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name.trim() === '' || formField.posto_adm_id === 0) { + if (formField.name.trim() === '' || formField.postoId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -117,7 +117,7 @@ const AddDialog = () => { order_field: sorting[0].id, order_direction: sorting[0].desc == false ? 'ASC' : 'DESC' }); - console.log('ini data posto :', response?.data); + // console.log('ini data posto :', response?.data); setPostoadms(response?.data.list || []); } catch (error) { console.log('Error fetching posto', error); @@ -166,7 +166,7 @@ const AddDialog = () => { @@ -183,7 +183,7 @@ const AddDialog = () => { onSelect={() => { setFormField({ ...formField, - posto_adm_id: posto.PostoAdms_id + postoId: posto.PostoAdms_id }); setOpen(false); }} diff --git a/src/pages/master/sucos/blocks/EditDialog.tsx b/src/pages/master/sucos/blocks/EditDialog.tsx index 0e08201..68b7bcd 100644 --- a/src/pages/master/sucos/blocks/EditDialog.tsx +++ b/src/pages/master/sucos/blocks/EditDialog.tsx @@ -48,7 +48,7 @@ const EditDialog = () => { const initialState = { name: '', - posto_adm_id: 0, // Pastikan ini sesuai dengan PostoAdms_id + postoId: 0, updated_by: '', updated_at: '' }; @@ -96,7 +96,7 @@ const EditDialog = () => { }); setPostoadms(response?.data.list); - console.log('Data Posto Adms:', response?.data.list); // Log data postoadms + // console.log('Data Posto Adms:', response?.data.list); } catch (error) { console.log('Error fetching postoadms', error); } @@ -104,13 +104,13 @@ const EditDialog = () => { const doFetchData = useCallback(async (id: string) => { const response = await GetData(`${API_URL}/sucos/getdata/${id}`, { id }); - console.log('Data Sucos:', response?.data); // Log data sucos + // console.log('Data Sucos:', response?.data); if (response?.status) { setFormField((prev) => ({ ...prev, name: response.data.name, - posto_adm_id: response.data.posto.id // Pastikan ini sesuai dengan PostoAdms_id + postoId: response.data.posto.id // Pastikan ini sesuai dengan PostoAdms_id })); } else { setFormField((prev) => ({ @@ -123,7 +123,7 @@ const EditDialog = () => { const handleUpdate = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name.trim() === '' || formField.posto_adm_id === 0) { + if (formField.name.trim() === '' || formField.postoId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -162,7 +162,7 @@ const EditDialog = () => { doFetchPostoAdms([{ id: 'name', desc: false }]); }, []); - console.log(selectedSucos); + // console.log(selectedSucos); return ( handleEditDialog(open, null)}> @@ -203,7 +203,7 @@ const EditDialog = () => { @@ -220,7 +220,7 @@ const EditDialog = () => { onSelect={() => { setFormField({ ...formField, - posto_adm_id: posto.PostoAdms_id // Gunakan PostoAdms_id + postoId: posto.PostoAdms_id // Gunakan PostoAdms_id }); setOpen(false); }} diff --git a/src/pages/master/sucos/blocks/ListToolbar.tsx b/src/pages/master/sucos/blocks/ListToolbar.tsx index 63cf889..334c9d1 100644 --- a/src/pages/master/sucos/blocks/ListToolbar.tsx +++ b/src/pages/master/sucos/blocks/ListToolbar.tsx @@ -16,7 +16,7 @@ const ListToolbar = () => { table.getColumn('sucos_name')?.setFilterValue(event.target.value) } From f7d0c77692ac521b912bdca152e8747b279368d3 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 12:56:13 +0700 Subject: [PATCH 29/53] update transaction issue --- src/routing/AppRoutingSetup.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index c7a50c6..b46c8a4 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -8,7 +8,7 @@ import { ErrorsRouting } from '@/errors'; import DashboardHomePage from '@/pages/dashboards/home/DashboardHomePage'; import ManageUserPage from '@/pages/settings/user/manage-user/ManageUserPage'; - +import Transaction from '@/pages/transaction/Transaction'; import LogActivityPage from '@/pages/settings/user/log-activity/LogActivityPage'; import ManagePositionPage from '@/pages/settings/user/manage-position/ManagePositionPage'; import ManageAccount from '@/pages/account/manage-account/ManageAccount'; @@ -19,7 +19,6 @@ import AccessType from '@/pages/access/access-type/AccessType'; import MemberCredential from '@/pages/access/member-credentials/MemberCredentials'; import ManageCurrency from '@/pages/account/manage-currency/ManageCurrency'; import ManageNotification from '@/pages/notification/ManageNotification'; -import Transaction from '@/pages/transaction/transaction'; import ManageMenu from '@/pages/menu/manage-menu/ManageMenu'; import Welcome from '@/pages/menu/welcome/Welcome'; import Inbox from '@/pages/message/Inbox'; From f11ace54c40be5270b39b3fca029e0b71a44124e Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 13:23:47 +0700 Subject: [PATCH 30/53] cleaning code --- src/pages/transaction/blocks/AddDialog.tsx | 172 ----------------- src/pages/transaction/blocks/DeleteDialog.tsx | 87 --------- src/pages/transaction/blocks/EditDialog.tsx | 173 ----------------- src/pages/transaction/blocks/ListToolbar.tsx | 8 - src/pages/transaction/blocks/SearchDialog.tsx | 178 ------------------ .../transaction/hooks/TransactionContext.tsx | 81 +++----- src/pages/transaction/transaction.tsx | 50 +++-- 7 files changed, 45 insertions(+), 704 deletions(-) delete mode 100644 src/pages/transaction/blocks/AddDialog.tsx delete mode 100644 src/pages/transaction/blocks/DeleteDialog.tsx delete mode 100644 src/pages/transaction/blocks/EditDialog.tsx delete mode 100644 src/pages/transaction/blocks/SearchDialog.tsx diff --git a/src/pages/transaction/blocks/AddDialog.tsx b/src/pages/transaction/blocks/AddDialog.tsx deleted file mode 100644 index 22cee5a..0000000 --- a/src/pages/transaction/blocks/AddDialog.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { useTransactionContext } from '../hooks/useTransactionContext'; -import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Alert, KeenIcon, useDataGrid } from '@/components'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import axios from 'axios'; -import { apiConfig } from '@/config/api.config'; -import { toast } from 'sonner'; -import { getAuth, useAuthContext } from '@/auth'; -import { useCallApi } from '@/hooks'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; - -const API_URL = apiConfig.service_master_data; - -const AddDialog = () => { - const parentRef = useRef(null); - const { reload } = useDataGrid(); - const { PostData } = useCallApi(); - const parsedUser = getAuth()?.user; - const { showAddDialog, handleAddDialog, selectedMunicipios } = useTransactionContext(); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - const initialState = { - name: '', - created_by: '', - created_at: '' - }; - - const [formField, setFormField] = useState(initialState); - const created_time = new Date(); - const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); - - const resetForm = () => { - setFormField(initialState); - setAlert({ show: false, message: '' }); - }; - - const doCreateMunicipio = useCallback( - async (e: React.FormEvent) => { - e.preventDefault(); - const response = await PostData(`${API_URL}/municipios/create`, formField); - - if (response?.status) { - handleAddDialog(false); - resetForm(); - reload(); - toast.success('Municipio created successfully!'); - // const createActivity = { - // module: 'Manage Municipio', - // description: `Create Municipio => ${selectedMunicipios}`, - // action: 'C' - // }; - - // doSaveLogActivity(createActivity); - } else { - toast.error('Failed to create municipio.'); - setAlert({ show: true, message: 'Failed to create municipio. Please try again.' }); - } - }, - [formField] - ); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - - if (formField.name.trim() === '') { - setAlert({ show: true, message: 'Please fill name field.' }); - return; - } - - doCreateMunicipio(e); - console.log(parsedUser.email); - console.log(formField); - setAlert({ show: false, message: '' }); - }; - - const handleReset = () => { - resetForm(); - setAlert({ show: false, message: '' }); - }; - - useEffect(() => { - if (showAddDialog) { - setFormField({ - name: formField.name, - created_by: parsedUser?.username, - created_at: formattedTime - }); - } - }, [formattedTime]); - - useEffect(() => { - if (showAddDialog === false) { - resetForm(); - } - }, [showAddDialog]); - - return ( - handleAddDialog(open)}> - - - - -
-
-

Add Municipios

-
-
-
{ - handleAddDialog(false); - resetForm(); - }} - > - -
-
-
- -
- {alert.show && ( - - {alert.message} - - )} - -
-
- - - - setFormField((prev) => ({ ...prev, name: target.value })) - } - /> -
- -
- - -
-
- -
-
-
-
- ); -}; - -export default AddDialog; diff --git a/src/pages/transaction/blocks/DeleteDialog.tsx b/src/pages/transaction/blocks/DeleteDialog.tsx deleted file mode 100644 index 2e8f25d..0000000 --- a/src/pages/transaction/blocks/DeleteDialog.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { Alert, useDataGrid } from '@/components'; -import { useTransactionContext } from '../hooks/useTransactionContext'; -import { ChangeEvent, useCallback, useState } from 'react'; -import axios from 'axios'; -import { apiConfig } from '@/config/api.config'; -import { useCallApi } from '@/hooks'; -import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; -import { Button } from '@/components/ui/button'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; - -const API_URL = apiConfig.service_master_data; - -const DeleteDialog = () => { - const { showDeleteDialog, handleDeleteDialog, selectedMunicipios, municipios } = - useTransactionContext(); - const { reload } = useDataGrid(); - const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - - const doDeleteMunicipio = useCallback(async () => { - const response = await DeleteData( - `${API_URL}/municipios/delete/${selectedMunicipios}/${enforce}`, - { - id: selectedMunicipios - } - ); - - if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); - handleDeleteDialog(false, null); - toast.success('Success Delete Municipio'); - reload(); - // const createActivity = { - // module: 'Manage Municipio', - // description: `Delete Municipio => ${selectedMunicipios}`, - // action: 'D' - // }; - - // doSaveLogActivity(createActivity); - } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); - } - }, [selectedMunicipios, enforce]); - - return ( - handleDeleteDialog(open, null)}> - - - -

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
-
- {alert.show && ( - -

{alert.message}

-
- )} -
- - - - -
-
- ); -}; - -export default DeleteDialog; diff --git a/src/pages/transaction/blocks/EditDialog.tsx b/src/pages/transaction/blocks/EditDialog.tsx deleted file mode 100644 index 0ab2a46..0000000 --- a/src/pages/transaction/blocks/EditDialog.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { useTransactionContext } from '../hooks/useTransactionContext'; -import { Alert, useDataGrid } from '@/components'; -import axios from 'axios'; -import { apiConfig } from '@/config/api.config'; -import { toast } from 'sonner'; -import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import { getAuth, useAuthContext } from '@/auth'; -import { useCallApi } from '@/hooks'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; - -const API_URL = apiConfig.service_master_data; - -const EditDialog = () => { - const parentRef = useRef(null); - const { showEditDialog, handleEditDialog, selectedMunicipios, municipios } = - useTransactionContext(); - const { reload } = useDataGrid(); - const { PutData, GetData } = useCallApi(); - const parsedUser = getAuth()?.user; - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - - const initialState = { - name: '', - updated_by: '', - updated_at: '' - }; - - const [formField, setFormField] = useState(initialState); - const created_time = new Date(); - const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); - - const resetForm = () => { - setFormField(initialState); - setAlert({ show: false, message: '' }); - }; - - const doUpdateMunicipios = useCallback( - async (e: React.FormEvent) => { - e.preventDefault(); - const response = await PutData( - `${API_URL}/municipios/update/${selectedMunicipios}`, - formField - ); - - if (response?.status) { - handleEditDialog(false, null); - resetForm(); - toast.success('Success update municipio'); - reload(); - // const createActivity = { - // module: 'Manage Municipio', - // description: `Edit Municipio => ${selectedMunicipios}`, - // action: 'U' - // }; - - // doSaveLogActivity(createActivity); - } else { - toast.error('Failed update user'); - setAlert({ show: true, message: 'Failed to update municipio. Please try again.' }); - } - }, - [selectedMunicipios, formField] - ); - - const doFetchData = useCallback(async (id: string) => { - const response = await GetData(`${API_URL}/municipios/getdata/${id}`, { id }); - - if (response?.status) { - setFormField((prev) => ({ - ...prev, - name: response.data.name - })); - } else { - setFormField((prev) => ({ - ...prev, - name: '' - })); - } - }, []); - - const handleUpdate = (e: React.FormEvent) => { - e.preventDefault(); - - if (formField.name.trim() === '') { - setAlert({ show: true, message: 'Please fill name field.' }); - return; - } - - doUpdateMunicipios(e); - console.log(formField); - setAlert({ show: false, message: '' }); - }; - - useEffect(() => { - if (selectedMunicipios) { - doFetchData(selectedMunicipios); - } - }, [selectedMunicipios]); - - useEffect(() => { - if (showEditDialog === false) { - resetForm(); - } - }, [showEditDialog]); - - useEffect(() => { - if (selectedMunicipios) { - setFormField({ - name: formField.name, - updated_by: parsedUser.email, - updated_at: formattedTime - }); - } - }, [formattedTime]); - - // console.log(selectedMunicipios); - return ( - handleEditDialog(open, null)}> - - - Municipios - Update - - - -
- {alert.show && ( - -

{alert.message}

-
- )} - -
-
-
-
- - setFormField({ ...formField, name: e.target.value })} - /> -
-
- -
- -
-
-
-
-
-
-
- ); -}; - -export default EditDialog; diff --git a/src/pages/transaction/blocks/ListToolbar.tsx b/src/pages/transaction/blocks/ListToolbar.tsx index cb71f6d..afc8ac5 100644 --- a/src/pages/transaction/blocks/ListToolbar.tsx +++ b/src/pages/transaction/blocks/ListToolbar.tsx @@ -6,7 +6,6 @@ import { toast } from 'sonner'; const ListToolbar = () => { const { table, reload } = useDataGrid(); - const { handleAddDialog, handleSearchDialog } = useTransactionContext(); // Set the initial state for trxDate const [trxDate, settrxDate] = useState({ from: '', to: '' }); @@ -74,13 +73,6 @@ const ListToolbar = () => { />
-
- - - -
diff --git a/src/pages/transaction/blocks/SearchDialog.tsx b/src/pages/transaction/blocks/SearchDialog.tsx deleted file mode 100644 index a5d84f7..0000000 --- a/src/pages/transaction/blocks/SearchDialog.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { useRef, useState } from 'react'; -import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Alert, KeenIcon } from '@/components'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import { useTransactionContext } from '../hooks/useTransactionContext'; -import { apiConfig } from '@/config/api.config'; -import axios from 'axios'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue -} from '@/components/ui/select'; - -interface trxDate { - from: string; - to: string; -} - -const API_URL = apiConfig.service_master_data; - -const SearchDialog = () => { - const parentRef = useRef(null); - const { showSearchDialog, handleSearchDialog, municipios } = useTransactionContext(); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - const initialState = { - from: '', - to: '' - }; - - const [formField, setFormField] = useState(initialState); - const resetForm = () => { - setFormField(initialState); - }; - const [trxDate, settrxDate] = useState([]); - const [isFound, setIsFound] = useState(false); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - const from = String(formField.from); - const to = String(formField.to); - - // if (formField.id === 0) { - // setAlert({ show: true, message: 'Please fill name field.' }); - // return; - // } - - try { - // const response = await axios.get(`${API_URL}/municipios/postoadms/${id}`); - - // if (response.data.status) { - // setPostoadms(response.data.data); - // setIsFound(true); - // // console.log('Found postoadms: ', response.data.data); - // } else { - // setPostoadms([]); - // setIsFound(false); - // setAlert({ show: true, message: 'No postoadms found.' }); - // } - } catch (error) { - console.error('Error fetching postoadms', error); - setAlert({ show: true, message: 'Failed to fetch postoadms. Please try again.' }); - } - setAlert({ show: false, message: '' }); - }; - - const handleReset = () => { - setFormField(initialState); - setIsFound(false); - settrxDate([]); - }; - // console.log(municipios); - return ( - handleSearchDialog(open)}> - - - - -
-
-

- Search Postoadms -

-
-
-
{ - handleSearchDialog(false); - resetForm(); - }} - > - -
-
-
- -
- {alert.show && ( - - {alert.message} - - )} -
-
-
- - - {/* */} -
- - {/* {isFound && postoadms.length > 0 && ( -
-

Postu Administravo:

-
-
- - {postoadms.map((posto) => posto.name).join(', ')} - -
-
- )} */} - -
- - -
-
-
-
-
-
-
- ); -}; - -export default SearchDialog; diff --git a/src/pages/transaction/hooks/TransactionContext.tsx b/src/pages/transaction/hooks/TransactionContext.tsx index 61a70d8..c8b4943 100644 --- a/src/pages/transaction/hooks/TransactionContext.tsx +++ b/src/pages/transaction/hooks/TransactionContext.tsx @@ -15,16 +15,6 @@ interface TransactionProps { } interface ContextProps { - municipios: TransactionProps[]; - showSearchDialog: boolean; - handleSearchDialog: (show: boolean) => void; - showEditDialog: boolean; - handleEditDialog: (show: boolean, selected_user: string | null) => void; - showAddDialog: boolean; - handleAddDialog: (show: boolean) => void; - showDeleteDialog: boolean; - handleDeleteDialog: (show: boolean, selected_user: string | null) => void; - selectedMunicipios: string | null; getTransactionLists: ( limit: number, page: number, @@ -36,16 +26,6 @@ interface ContextProps { } const initialProps: ContextProps = { - municipios: [], - showSearchDialog: false, - handleSearchDialog: (show: boolean) => { }, - showEditDialog: false, - handleEditDialog: (show: boolean, selected_user: string | null) => { }, - showAddDialog: false, - handleAddDialog: (show: boolean) => { }, - showDeleteDialog: false, - handleDeleteDialog: (show: boolean, selected_user: string | null) => { }, - selectedMunicipios: null, getTransactionLists: async () => ({ data: [], totalCount: 0 }) }; @@ -53,33 +33,9 @@ const ManageTransactionContext = createContext(initialProps); const API_URL = apiConfig.transaction; const TransactionProvider = ({ children }: { children: React.ReactNode }) => { - const [showSearchDialog, setShowSearchDialog] = useState(false); - const [showEditDialog, setShowEditDialog] = useState(false); - const [showAddDialog, setShowAddDialog] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [selectedMunicipios, setSelectedMunicipios] = useState(null); - const [municipios, setTransaction] = useState([]); + const [transaction, setTransaction] = useState([]); const { GetData } = useCallApi(); const navigate = useNavigate(); - - const handleSearchDialog = useCallback((show: boolean) => { - setShowSearchDialog(show); - }, []); - - const handleAddDialog = useCallback((show: boolean) => { - setShowAddDialog(show); - }, []); - - const handleEditDialog = useCallback((show: boolean, selected_municipios: string | null) => { - setSelectedMunicipios(show ? selected_municipios : null); - setShowEditDialog(show); - }, []); - - const handleDeleteDialog = useCallback((show: boolean, selected_municipios: string | null) => { - setSelectedMunicipios(show ? selected_municipios : null); - setShowDeleteDialog(show); - }, []); - const handleNavigate = (path: string) => { const url = navigate(`${API_URL}/transaction/history/${path}`); }; @@ -136,6 +92,28 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { headerClassName: 'w-[250px]', }, }, + { + accessorFn: (row) => { + let status; + if (row.status === 'C') { + status = 'COMPLETE'; + } else if(row.status === 'F') { + status = 'FAILED'; + } else if(row.status === 'O') { + status = 'ON PROCESS'; + } else { + status = 'PENDING'; + } + return status; + }, + accessorKey: 'status', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]', + }, + }, { accessorKey: 'description', header: ({ column }) => , @@ -175,8 +153,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { } } ], - [handleEditDialog, handleDeleteDialog] - ); + []); const getTransactionLists = async (page: number, limit: number, sorting: any, filter: any) => { try { @@ -222,16 +199,6 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { return ( diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx index dda8418..7466c60 100644 --- a/src/pages/transaction/transaction.tsx +++ b/src/pages/transaction/transaction.tsx @@ -1,39 +1,31 @@ import { Container, DataGridInner } from '@/components'; import { TransactionProvider } from './hooks/TransactionContext'; -import AddDialog from './blocks/AddDialog'; -import SearchDialog from './blocks/SearchDialog'; -import EditDialog from './blocks/EditDialog'; -import DeleteDialog from './blocks/DeleteDialog'; import { Breadcrumbs, Link } from '@mui/material'; const Transaction = () => { - return ( - - -

TRANSACTION

- - - Dashboard - + return ( + + +

TRANSACTION

+ + + Dashboard + - - Master Data - + + Master Data + - - Transaction - - -
- -
- - - - -
-
- ); + + Transaction + +
+
+ +
+
+
+ ); }; export default Transaction; From 9a36cbf4649e4850ae44ea203a95de0f72c04453 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 14:26:49 +0800 Subject: [PATCH 31/53] Delete src/pages/transaction/transaction.tsx --- src/pages/transaction/transaction.tsx | 31 --------------------------- 1 file changed, 31 deletions(-) delete mode 100644 src/pages/transaction/transaction.tsx diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx deleted file mode 100644 index 7466c60..0000000 --- a/src/pages/transaction/transaction.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Container, DataGridInner } from '@/components'; -import { TransactionProvider } from './hooks/TransactionContext'; -import { Breadcrumbs, Link } from '@mui/material'; - -const Transaction = () => { - return ( - - -

TRANSACTION

- - - Dashboard - - - - Master Data - - - - Transaction - - -
- -
-
-
- ); -}; - -export default Transaction; From 0518cf66bed24481e1e0d322a5115a813366e453 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 13:27:29 +0700 Subject: [PATCH 32/53] update --- src/pages/transaction/transaction.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx index 7466c60..7889919 100644 --- a/src/pages/transaction/transaction.tsx +++ b/src/pages/transaction/transaction.tsx @@ -23,6 +23,7 @@ const Transaction = () => {
+
); From 9e36ae96d101662cb751ccba9484fd72d15940ea Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 13:33:09 +0700 Subject: [PATCH 33/53] update --- src/pages/transaction/transaction.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx index 7889919..0aacee6 100644 --- a/src/pages/transaction/transaction.tsx +++ b/src/pages/transaction/transaction.tsx @@ -1,5 +1,6 @@ import { Container, DataGridInner } from '@/components'; import { TransactionProvider } from './hooks/TransactionContext'; + import { Breadcrumbs, Link } from '@mui/material'; const Transaction = () => { From b415220c5f635625d68cdecc9b7597a993ab7d62 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 14:34:14 +0800 Subject: [PATCH 34/53] revert 9a36cbf4649e4850ae44ea203a95de0f72c04453 revert Delete src/pages/transaction/transaction.tsx --- src/pages/transaction/transaction.tsx | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/pages/transaction/transaction.tsx diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx new file mode 100644 index 0000000..7466c60 --- /dev/null +++ b/src/pages/transaction/transaction.tsx @@ -0,0 +1,31 @@ +import { Container, DataGridInner } from '@/components'; +import { TransactionProvider } from './hooks/TransactionContext'; +import { Breadcrumbs, Link } from '@mui/material'; + +const Transaction = () => { + return ( + + +

TRANSACTION

+ + + Dashboard + + + + Master Data + + + + Transaction + + +
+ +
+
+
+ ); +}; + +export default Transaction; From 9bfeb6992c73452093ba534f0e3a7492f0d1de39 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 13:35:19 +0700 Subject: [PATCH 35/53] update --- src/pages/transaction/transaction.tsx | 44 +++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx index 0aacee6..cacee7f 100644 --- a/src/pages/transaction/transaction.tsx +++ b/src/pages/transaction/transaction.tsx @@ -1,33 +1,31 @@ import { Container, DataGridInner } from '@/components'; import { TransactionProvider } from './hooks/TransactionContext'; - import { Breadcrumbs, Link } from '@mui/material'; const Transaction = () => { - return ( - - -

TRANSACTION

- - - Dashboard - + return ( + + +

TRANSACTION

+ + + Dashboard + - - Master Data - + + Master Data + - - Transaction - - -
- -
- -
-
- ); + + Transaction + +
+
+ +
+
+
+ ); }; export default Transaction; From 24a8bf30545a18d421bf3369bb082e2227e95bcb Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 14:42:17 +0800 Subject: [PATCH 36/53] Update src/pages/transaction/Transaction.tsx --- src/pages/transaction/Transaction.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/pages/transaction/Transaction.tsx b/src/pages/transaction/Transaction.tsx index dda8418..cacee7f 100644 --- a/src/pages/transaction/Transaction.tsx +++ b/src/pages/transaction/Transaction.tsx @@ -1,9 +1,5 @@ import { Container, DataGridInner } from '@/components'; import { TransactionProvider } from './hooks/TransactionContext'; -import AddDialog from './blocks/AddDialog'; -import SearchDialog from './blocks/SearchDialog'; -import EditDialog from './blocks/EditDialog'; -import DeleteDialog from './blocks/DeleteDialog'; import { Breadcrumbs, Link } from '@mui/material'; const Transaction = () => { @@ -27,10 +23,6 @@ const Transaction = () => {
- - - - ); From bc9db45d86dd92a99ae2e16a981bc363153c5dd4 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 25 Mar 2025 14:42:38 +0800 Subject: [PATCH 37/53] Delete src/pages/transaction/transaction.tsx --- src/pages/transaction/transaction.tsx | 31 --------------------------- 1 file changed, 31 deletions(-) delete mode 100644 src/pages/transaction/transaction.tsx diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx deleted file mode 100644 index cacee7f..0000000 --- a/src/pages/transaction/transaction.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Container, DataGridInner } from '@/components'; -import { TransactionProvider } from './hooks/TransactionContext'; -import { Breadcrumbs, Link } from '@mui/material'; - -const Transaction = () => { - return ( - - -

TRANSACTION

- - - Dashboard - - - - Master Data - - - - Transaction - - -
- -
-
-
- ); -}; - -export default Transaction; From 20421f2d0080f13d55e75a505b0053164a8e6f8a Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Mar 2025 13:58:05 +0700 Subject: [PATCH 38/53] update provider --- src/components/ui/dialog.tsx | 2 +- .../master/provider/blocks/AddDialog.tsx | 83 ++++++++++--------- .../master/provider/blocks/EditDialog.tsx | 4 +- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index db2f34c..dcafbd0 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef< { const response = await PostData(`${API_URL_MASTERDATA}/provider/create`, formField); if (response?.status) { - resetForm(); + // resetForm(); handleAddDialog(false); toast.success('Success Create Provider'); reload(); @@ -116,6 +117,41 @@ const AddDialog = () => { setAlert({ show: false, message: '' }); }; + const getTransactionTypeList = async (sorting: any) => { + try { + const response = await GetData(`${API_URL_TRANSACTION}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc == false ? 'ASC' : 'DESC' + }); + + // console.log('TRANSACTION TYPE: ', response?.data); + setTransactions(response?.data.list); + } catch (error) { + console.error('Error fetching transaction type', error); + } + }; + + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc == false ? 'ASC' : 'DESC' + }); + + // console.log('CUSTOMER: ', response?.data); + setCustomers(response?.data.list); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + useEffect(() => { if (showAddDialog) { setFormField({ @@ -127,42 +163,7 @@ const AddDialog = () => { }, [formattedTime]); useEffect(() => { - const getCustomerList = async (sorting: any) => { - try { - sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting; - const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { - limit: 100, - page: 1, - with_deleted: false, - order_field: sorting[0].id, - order_direction: sorting[0].desc == false ? 'ASC' : 'DESC' - }); - - // console.log('CUSTOMER: ', response?.data); - setCustomers(response?.data.list); - } catch (error) { - console.error('Error fetching customer', error); - } - }; - - const getTransactionTypeList = async (sorting: any) => { - try { - const response = await GetData(`${API_URL_TRANSACTION}/transactiontype/list`, { - limit: 100, - page: 1, - with_deleted: false, - order_field: sorting[0].id, - order_direction: sorting[0].desc == false ? 'ASC' : 'DESC' - }); - - // console.log('TRANSACTION TYPE: ', response?.data); - setTransactions(response?.data.list); - } catch (error) { - console.error('Error fetching transaction type', error); - } - }; - - getCustomerList([{ id: 'msisdn', desc: false }]); + getCustomerList([{ id: 'id', desc: false }]); getTransactionTypeList([{ id: 'name', desc: false }]); }, []); @@ -290,7 +291,7 @@ const AddDialog = () => { @@ -302,12 +303,12 @@ const AddDialog = () => { {customers.map((customer) => ( { setFormField({ ...formField, - agent: customer.msisdn + agent: customer.id }); setOpen(false); }} diff --git a/src/pages/master/provider/blocks/EditDialog.tsx b/src/pages/master/provider/blocks/EditDialog.tsx index 186698f..574b827 100644 --- a/src/pages/master/provider/blocks/EditDialog.tsx +++ b/src/pages/master/provider/blocks/EditDialog.tsx @@ -128,7 +128,7 @@ const EditDialog = () => { const doFetchData = useCallback(async (id: string) => { const response = await GetData(`${API_URL_MASTERDATA}/provider/getdata/${id}`, { id }); - console.log(response); + // console.log(response); if (response?.status) { setFormField((prev) => ({ ...prev, @@ -185,7 +185,7 @@ const EditDialog = () => { }, [formattedTime]); useEffect(() => { - getCustomerList([{ id: 'msisdn', desc: false }]); + getCustomerList([{ id: 'id', desc: false }]); getTransactionTypeList([{ id: 'name', desc: false }]); }, []); From f1a7a839e8ff533ca17697b5b856f6f2843e0d76 Mon Sep 17 00:00:00 2001 From: Raja Oktafrianto Date: Tue, 25 Mar 2025 14:53:54 +0700 Subject: [PATCH 39/53] fixing add dialog manage user & manage position and edit dialog manage user --- .../user/manage-position/blocks/AddDialog.tsx | 24 +++++++++++--- .../user/manage-user/blocks/AddDialog.tsx | 10 ++++-- .../user/manage-user/blocks/EditDialog.tsx | 32 +++++++++++++------ 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/pages/settings/user/manage-position/blocks/AddDialog.tsx b/src/pages/settings/user/manage-position/blocks/AddDialog.tsx index 6c32480..b24a4b3 100644 --- a/src/pages/settings/user/manage-position/blocks/AddDialog.tsx +++ b/src/pages/settings/user/manage-position/blocks/AddDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { Dialog, @@ -59,6 +59,10 @@ const MenuItemComponent: React.FC<{ ); }; +const initialState = { + name: '' +}; + const AddDialog = () => { const parentRef = useRef(null); const { showAddDialog, handleAddDialog, menus } = useManagePositionContext(); @@ -69,9 +73,7 @@ const AddDialog = () => { message: '' }); const [selectMenus, setSelectMenus] = useState([]); - const [formField, setFormField] = useState({ - name: '' - }); + const [formField, setFormField] = useState(initialState); /* actions */ const handleCheckboxChange = useCallback((key: string) => { @@ -80,6 +82,12 @@ const AddDialog = () => { ); }, []); + const resetForm = () => { + setFormField(() => ({ name: '' })); + setAlert({ show: false, message: '' }); + setSelectMenus([]); + }; + const doCreatePosition = useCallback( async (e: React.FormEvent) => { e.preventDefault(); @@ -96,7 +104,7 @@ const AddDialog = () => { }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + resetForm(); handleAddDialog(false); toast.success('Success Create Position'); reload(); @@ -114,6 +122,12 @@ const AddDialog = () => { [formField, selectMenus] ); + useEffect(() => { + if (showAddDialog === false) { + resetForm(); + } + }, [showAddDialog]); + return ( handleAddDialog(open)}> diff --git a/src/pages/settings/user/manage-user/blocks/AddDialog.tsx b/src/pages/settings/user/manage-user/blocks/AddDialog.tsx index a7647cc..ac69750 100644 --- a/src/pages/settings/user/manage-user/blocks/AddDialog.tsx +++ b/src/pages/settings/user/manage-user/blocks/AddDialog.tsx @@ -59,6 +59,7 @@ const AddDialog = () => { const [formField, setFormField] = useState(initialState); const resetForm = () => { setFormField(initialState); + setAlert({ show: false, message: '' }); }; const [showPassword, setShowPassword] = useState({ password: false, @@ -104,6 +105,12 @@ const AddDialog = () => { const isButtonDisabled = !messagePassword || isSubmitting || passwordErrors.length > 0; + useEffect(() => { + if (showAddDialog === false) { + resetForm(); + } + }, [showAddDialog]); + /* actions */ const doCreateUser = useCallback( async (e: React.FormEvent) => { @@ -118,7 +125,7 @@ const AddDialog = () => { `${API_URL}/user/add_role/${response?.message?.id}/${formField.id_role}`, {} ); - setAlert((prev) => ({ ...prev, show: false, message: '' })); + resetForm(); handleAddDialog(false); toast.success('Success Create User'); reload(); @@ -336,7 +343,6 @@ const AddDialog = () => { -
@@ -313,7 +313,7 @@ const AddDialog = () => { setOpen(false); }} > - {customer.fullname} + {customer.username} ))} diff --git a/src/pages/master/provider/blocks/EditDialog.tsx b/src/pages/master/provider/blocks/EditDialog.tsx index 574b827..d60d4c2 100644 --- a/src/pages/master/provider/blocks/EditDialog.tsx +++ b/src/pages/master/provider/blocks/EditDialog.tsx @@ -55,7 +55,7 @@ const EditDialog = () => { description: '', type: '', status: '', - transactionTypeId: '', + transaction_type: '', agent: '', updated_by: '', updated_at: '' @@ -128,7 +128,7 @@ const EditDialog = () => { const doFetchData = useCallback(async (id: string) => { const response = await GetData(`${API_URL_MASTERDATA}/provider/getdata/${id}`, { id }); - // console.log(response); + console.log(response); if (response?.status) { setFormField((prev) => ({ ...prev, @@ -136,8 +136,8 @@ const EditDialog = () => { description: response?.data.description, type: response?.data.type, status: response?.data.status, - transactionTypeId: response?.data.transaction_type.id, - agent: response?.data.agent + transaction_type: response?.data.transaction_type.id, + agent: response?.data.agent.id })); } }, []); @@ -150,7 +150,7 @@ const EditDialog = () => { formField.description.trim() === '' || formField.type.trim() === '' || formField.status.trim() === '' || - formField.transactionTypeId.trim() === '' || + formField.transaction_type.trim() === '' || formField.agent.trim() === '' ) { setAlert({ show: true, message: 'Please fill in all required fields.' }); @@ -188,7 +188,7 @@ const EditDialog = () => { getCustomerList([{ id: 'id', desc: false }]); getTransactionTypeList([{ id: 'name', desc: false }]); }, []); - + // console.log(selectedProvider); return ( handleEditDialog(open, null)}> @@ -282,9 +282,9 @@ const EditDialog = () => { Transaction Type Id*
@@ -363,8 +362,8 @@ const AddFeeDialog = () => { - Y - N + Yes + No @@ -373,15 +372,15 @@ const AddFeeDialog = () => { diff --git a/src/pages/transfer/transferfee/blocks/EditDialog.tsx b/src/pages/transfer/transferfee/blocks/EditDialog.tsx index 87ee112..34e990e 100644 --- a/src/pages/transfer/transferfee/blocks/EditDialog.tsx +++ b/src/pages/transfer/transferfee/blocks/EditDialog.tsx @@ -72,7 +72,7 @@ const EditFeeDialog = () => { period_end: '', deduct_amount: 0, deduct_percentage: 0, - priority: '', + priority: false, status: '', status_include: '', transaction_type: '', @@ -96,7 +96,8 @@ const EditFeeDialog = () => { async (e: React.FormEvent) => { e.preventDefault(); const response = await PutData(`${API_URL}/transactionfees/update/${selectedTransferFee}`, { - ...formField + ...formField, + priority: formField.priority ? 'Y' : 'N' // Ubah ke "Y" atau "N" }); if (response?.status) { handleEditFeeDialog(false, null); @@ -165,9 +166,10 @@ const EditFeeDialog = () => { order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); - setTransactionTypes(response?.data.list || []); + // console.log('Transaction Type: ', response?.data.list); + setTransactionTypes(response?.data.list); } catch (error) { - console.error('Error fetching customer', error); + console.error('Error fetching Transaction Type', error); } }; @@ -188,29 +190,10 @@ const EditFeeDialog = () => { period_end: response.data.period_end, deduct_amount: response.data.deduct_amount, deduct_percentage: response.data.deduct_percentage, - priority: response.data.priority, + priority: response.data.priority === 'Y', status: response.data.status, status_include: response.data.status_include, transaction_type: response.data.transaction_type.id - - // updated_by: parsedUser?.username , - // updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ') - })); - } else { - setFormField((prev) => ({ - ...prev, - name: '', - description: '', - minimum_amount: 0, - maximum_amount: 0, - period_start: '', - period_end: '', - deduct_amount: 0, - deduct_percentage: 0, - priority: '', - status: '', - status_include: '', - transaction_type: '' })); } }, []); @@ -230,7 +213,7 @@ const EditFeeDialog = () => { period_end: '', deduct_amount: 0, deduct_percentage: 0, - priority: '', + priority: false, status: '', status_include: '', transaction_type: '', @@ -416,8 +399,8 @@ const EditFeeDialog = () => { - Y - N + Active + Inactive @@ -433,26 +416,29 @@ const EditFeeDialog = () => { - Y - N + Yes + No
+ {/*
{ order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); - - setCustomers(response?.data.list || []); + console.log('CUSTOMER: ', response?.data.list); + setCustomers(response?.data.list); } catch (error) { console.error('Error fetching customer', error); } }; getCustomerList([{ id: 'id', desc: false }]); - }, [showEditDialog]); + }, []); const fetchWallets = useCallback(async () => { const params = { limit: 100, @@ -177,9 +177,8 @@ const EditDialog = () => { const fetchTransactionType = useCallback(async (id: string) => { const response = await GetData(`${API_URL}/transactiontype/getdata/${id}`, { id }); - + console.log('Transaction Type: ', response?.data); if (response?.status) { - const data = response.data; setFormField((prev) => ({ ...prev, name: response.data.name, @@ -196,21 +195,7 @@ const EditDialog = () => { // updated_by: parsedUser?.username , // updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ') })); - } else { - setFormField((prev) => ({ - ...prev, - name: '', - description: '', - wallet_origin: '', - wallet_destination: '', - wallet_fee_destination: '', - customer_fee_destination: '', - maximum_amount: 0, - minimum_amount: 0, - max_transaction_per_day: 0, - status_approval: '', - status: '' - })); + console.log('Transaction Type: ', formField); } }, []); @@ -493,19 +478,7 @@ const EditDialog = () => {
- - {/*
- -
*/}
- {/* */} - @@ -184,11 +184,11 @@ const AddDialog = () => { {sucos.map((suco) => ( { setFormField({ ...formField, - sucos_id: suco.sucos_id + sucosId: suco.sucos_id }); setOpen(false); }} diff --git a/src/pages/master/aldeias/blocks/EditDialog.tsx b/src/pages/master/aldeias/blocks/EditDialog.tsx index d69981e..449197d 100644 --- a/src/pages/master/aldeias/blocks/EditDialog.tsx +++ b/src/pages/master/aldeias/blocks/EditDialog.tsx @@ -45,7 +45,7 @@ const EditDialog = () => { }); const initialState = { name: '', - sucos_id: 0, + sucosId: 0, updated_by: '', updated_at: '' }; @@ -102,13 +102,13 @@ const EditDialog = () => { setFormField((prev) => ({ ...prev, name: response.data.name, - sucos_id: response.data.sucos.id + sucosId: response.data.sucos.id })); } else { setFormField((prev) => ({ ...prev, name: '', - sucos_id: 0 + sucosId: 0 })); } }, []); @@ -116,7 +116,7 @@ const EditDialog = () => { const handleUpdate = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name === '' || formField.sucos_id === 0) { + if (formField.name === '' || formField.sucosId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -191,7 +191,7 @@ const EditDialog = () => { @@ -208,7 +208,7 @@ const EditDialog = () => { onSelect={() => { setFormField({ ...formField, - sucos_id: suco.sucos_id + sucosId: suco.sucos_id }); setOpen(false); }} From 8a956ea9508c8c3f67e56e29776d52660632192a Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Mar 2025 22:39:57 +0700 Subject: [PATCH 52/53] update --- src/pages/master/walletRule/blocks/ListToolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/master/walletRule/blocks/ListToolbar.tsx b/src/pages/master/walletRule/blocks/ListToolbar.tsx index fb78c55..2a2df4f 100644 --- a/src/pages/master/walletRule/blocks/ListToolbar.tsx +++ b/src/pages/master/walletRule/blocks/ListToolbar.tsx @@ -15,7 +15,7 @@ const ListToolbar = () => { table.getColumn('name')?.setFilterValue(event.target.value)} /> From 89dc164891ff2e2a8ecbab1517d6da18c78e6444 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 25 Mar 2025 23:10:41 +0700 Subject: [PATCH 53/53] applying soft delete on masterdata, except walletrule and conversion --- .../master/aldeias/blocks/DeleteDialog.tsx | 31 +++++------ .../master/municipios/blocks/DeleteDialog.tsx | 55 +++++++------------ .../master/postoadms/blocks/DeleteDialog.tsx | 41 ++++++-------- .../master/products/blocks/DeleteDialog.tsx | 44 ++++++--------- .../master/profession/blocks/DeleteDialog.tsx | 55 ++++++------------- .../master/provider/blocks/DeleteDialog.tsx | 49 ++++++----------- .../master/sucos/blocks/DeleteDialog.tsx | 50 ++++++----------- 7 files changed, 123 insertions(+), 202 deletions(-) diff --git a/src/pages/master/aldeias/blocks/DeleteDialog.tsx b/src/pages/master/aldeias/blocks/DeleteDialog.tsx index 44fc4c1..17c4954 100644 --- a/src/pages/master/aldeias/blocks/DeleteDialog.tsx +++ b/src/pages/master/aldeias/blocks/DeleteDialog.tsx @@ -2,38 +2,42 @@ import { apiConfig } from '@/config/api.config'; import { useManageAldeiasContext } from '../hooks/useManageAldeiasContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; + const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedAldeias } = useManageAldeiasContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' - }) + }); const doDeleteAldeias = useCallback(async () => { - const response = await DeleteData(`${API_URL}/aldeias/delete/${selectedAldeias}/${enforce}`, { + if (!selectedAldeias) { + toast.error('No Aldeias selected'); + return; + } + + const response = await DeleteData(`${API_URL}/aldeias/delete/${selectedAldeias}/false`, { id: selectedAldeias }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Aldeias'); reload(); } else { + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Aldeias'); - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); } - }, [selectedAldeias, enforce]); + }, [selectedAldeias, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> @@ -41,16 +45,7 @@ const DeleteDialog = () => {

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( diff --git a/src/pages/master/municipios/blocks/DeleteDialog.tsx b/src/pages/master/municipios/blocks/DeleteDialog.tsx index 0605ab5..f7e6f5d 100644 --- a/src/pages/master/municipios/blocks/DeleteDialog.tsx +++ b/src/pages/master/municipios/blocks/DeleteDialog.tsx @@ -1,69 +1,56 @@ import { Alert, useDataGrid } from '@/components'; import { useManageMunicipiosContext } from '../hooks/useManageMunicipiosContext'; -import { ChangeEvent, useCallback, useState } from 'react'; -import axios from 'axios'; +import { useCallback, useState } from 'react'; import { apiConfig } from '@/config/api.config'; import { useCallApi } from '@/hooks'; import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { DialogDescription } from '@radix-ui/react-dialog'; const API_URL = apiConfig.service_master_data; const DeleteDialog = () => { - const { showDeleteDialog, handleDeleteDialog, selectedMunicipios, municipios } = - useManageMunicipiosContext(); + const { showDeleteDialog, handleDeleteDialog, selectedMunicipios } = useManageMunicipiosContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteMunicipio = useCallback(async () => { + if (!selectedMunicipios) { + toast.error('No Municipio selected'); + return; + } + const response = await DeleteData( - `${API_URL}/municipios/delete/${selectedMunicipios}/${enforce}`, - { - id: selectedMunicipios - } + `${API_URL}/municipios/delete/${selectedMunicipios}/false`, + { id: selectedMunicipios } ); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Municipio'); reload(); - // const createActivity = { - // module: 'Manage Municipio', - // description: `Delete Municipio => ${selectedMunicipios}`, - // action: 'D' - // }; - - // doSaveLogActivity(createActivity); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); + toast.error('Failed Delete Municipio'); } - }, [selectedMunicipios, enforce]); + }, [selectedMunicipios, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> + + +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -72,10 +59,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/postoadms/blocks/DeleteDialog.tsx b/src/pages/master/postoadms/blocks/DeleteDialog.tsx index bc597ae..fca5448 100644 --- a/src/pages/master/postoadms/blocks/DeleteDialog.tsx +++ b/src/pages/master/postoadms/blocks/DeleteDialog.tsx @@ -1,11 +1,10 @@ import { Alert, useDataGrid } from '@/components'; import { useManagePostoAdmsContext } from '../hooks/useManagePostoAdmsContext'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { apiConfig } from '@/config/api.config'; import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; @@ -14,46 +13,42 @@ const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedPostoAdms } = useManagePostoAdmsContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' }); const doDeletePostoAdm = useCallback(async () => { + if (!selectedPostoAdms) { + toast.error('No Posto Adm selected'); + return; + } + const response = await DeleteData( - `${API_URL}/postoadms/delete/${selectedPostoAdms}/${enforce}`, - { - id: selectedPostoAdms - } + `${API_URL}/postoadms/delete/${selectedPostoAdms}/false`, + { id: selectedPostoAdms } ); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Posto Adm'); reload(); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); + toast.error('Failed Delete Posto Adm'); } - }, [selectedPostoAdms, enforce]); + }, [selectedPostoAdms, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> + +

Are you sure?

- you will delete this data! - {/*
- - ) => { - setEnforce(e.target.checked); - }} - /> -
*/} + You will delete this data!
{alert.show && ( @@ -62,10 +57,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/products/blocks/DeleteDialog.tsx b/src/pages/master/products/blocks/DeleteDialog.tsx index 39c3cb1..652f56b 100644 --- a/src/pages/master/products/blocks/DeleteDialog.tsx +++ b/src/pages/master/products/blocks/DeleteDialog.tsx @@ -2,57 +2,49 @@ import { apiConfig } from '@/config/api.config'; import { useManageProductsContext } from '../hooks/useManageProductsContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; + const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedProducts } = useManageProductsContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); + const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteProduct = useCallback(async () => { - const response = await DeleteData(`${API_URL}/product/delete/${selectedProducts}/${enforce}`, { + if (!selectedProducts) { + toast.error('No product selected'); + return; + } + + const response = await DeleteData(`${API_URL}/product/delete/${selectedProducts}/false`, { id: selectedProducts }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Product'); reload(); } else { + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Product'); - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); } - }, [selectedProducts, enforce]); + }, [selectedProducts, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> - + + + - -

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -61,10 +53,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/profession/blocks/DeleteDialog.tsx b/src/pages/master/profession/blocks/DeleteDialog.tsx index 0a74fc7..1f5f0f8 100644 --- a/src/pages/master/profession/blocks/DeleteDialog.tsx +++ b/src/pages/master/profession/blocks/DeleteDialog.tsx @@ -2,67 +2,48 @@ import { apiConfig } from '@/config/api.config'; import { useManageProfessionContext } from '../hooks/useManageProfessionContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; + const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedProfession } = useManageProfessionContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); + const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteProfession = useCallback(async () => { - const response = await DeleteData( - `${API_URL}/profession/delete/${selectedProfession}/${enforce}`, - { - id: selectedProfession - } - ); + if (!selectedProfession) { + toast.error('No profession selected'); + return; + } + const response = await DeleteData(`${API_URL}/profession/delete/${selectedProfession}/false`, { + id: selectedProfession + }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Profession'); reload(); } else { + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Profession'); - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); } - }, [selectedProfession, enforce]); + }, [selectedProfession, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> - +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -71,10 +52,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/provider/blocks/DeleteDialog.tsx b/src/pages/master/provider/blocks/DeleteDialog.tsx index 9be7895..41e0bef 100644 --- a/src/pages/master/provider/blocks/DeleteDialog.tsx +++ b/src/pages/master/provider/blocks/DeleteDialog.tsx @@ -2,64 +2,49 @@ import { apiConfig } from '@/config/api.config'; import { useManageProviderContext } from '../hooks/useManageProviderContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; + const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedProvider } = useManageProviderContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); + const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteProvider = useCallback(async () => { - const response = await DeleteData(`${API_URL}/provider/delete/${selectedProvider}/${enforce}`, { + if (!selectedProvider) { + toast.error('No provider selected'); + return; + } + + const response = await DeleteData(`${API_URL}/provider/delete/${selectedProvider}/false`, { id: selectedProvider }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Provider'); reload(); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Provider'); } - }, [selectedProvider, enforce]); + }, [selectedProvider, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> - +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -68,10 +53,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/sucos/blocks/DeleteDialog.tsx b/src/pages/master/sucos/blocks/DeleteDialog.tsx index f1235f9..440ee6a 100644 --- a/src/pages/master/sucos/blocks/DeleteDialog.tsx +++ b/src/pages/master/sucos/blocks/DeleteDialog.tsx @@ -1,18 +1,10 @@ import { apiConfig } from '@/config/api.config'; import { useManageSucosContext } from '../hooks/useManageSucosContext'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useCallApi } from '@/hooks'; import { Alert, useDataGrid } from '@/components'; import { toast } from 'sonner'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; @@ -21,45 +13,39 @@ const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedSucos } = useManageSucosContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); + const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteSucos = useCallback(async () => { - const response = await DeleteData(`${API_URL}/sucos/delete/${selectedSucos}/${enforce}`, { + if (!selectedSucos) { + toast.error('No sucos selected'); + return; + } + + // Hanya soft delete (tanpa enforce) + const response = await DeleteData(`${API_URL}/sucos/delete/${selectedSucos}/false`, { id: selectedSucos }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Sucos'); reload(); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); + toast.error('Failed Delete Sucos'); } - }, [selectedSucos, enforce]); + }, [selectedSucos, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> - +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -68,10 +54,10 @@ const DeleteDialog = () => { )}
- -