From 03aeb64d548ea7c1fd2ee5f3c3d85ac7a23d1409 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 25 Feb 2025 09:02:57 +0700 Subject: [PATCH] add the Manage Access Types page and handle the create transfer type form --- src/pages/access/access-type/AccessType.tsx | 20 +- .../access/access-type/blocks/AddDialog.tsx | 294 ++++++++++++++++++ .../access/access-type/blocks/ListToolBar.tsx | 49 +++ .../hooks/ManageAccessTypeContext.tsx | 178 +++++++++++ .../hooks/useManageAccessTypeContext.tsx | 12 + .../user/manage-user/blocks/AddDialog.tsx | 1 + 6 files changed, 549 insertions(+), 5 deletions(-) create mode 100644 src/pages/access/access-type/blocks/AddDialog.tsx create mode 100644 src/pages/access/access-type/blocks/ListToolBar.tsx create mode 100644 src/pages/access/access-type/hooks/ManageAccessTypeContext.tsx create mode 100644 src/pages/access/access-type/hooks/useManageAccessTypeContext.tsx diff --git a/src/pages/access/access-type/AccessType.tsx b/src/pages/access/access-type/AccessType.tsx index 185c37f..eaa656d 100644 --- a/src/pages/access/access-type/AccessType.tsx +++ b/src/pages/access/access-type/AccessType.tsx @@ -1,10 +1,20 @@ +import { Container, DataGridInner } from '@/components'; +import { + ManageAccessTypeContext, + ManageAccessTypeContextProvider +} from './hooks/ManageAccessTypeContext'; +import AddDialog from './blocks/AddDialog'; + const AccessType = () => { return ( -
-
-

Access Type

-
-
+ + +
+ +
+ +
+
); }; diff --git a/src/pages/access/access-type/blocks/AddDialog.tsx b/src/pages/access/access-type/blocks/AddDialog.tsx new file mode 100644 index 0000000..19189e0 --- /dev/null +++ b/src/pages/access/access-type/blocks/AddDialog.tsx @@ -0,0 +1,294 @@ +import { apiConfig } from '@/config/api.config'; +import { useRef, useState } from 'react'; +import { useManageAccessTypeContext } from '../hooks/useManageAccessTypeContext'; +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'; + +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; +} + +const API_URL = apiConfig.service_dashboard; + +const AddDialog = () => { + const parentRef = useRef(null); + const { showAddDialog, handleAddDialog, accounts } = useManageAccessTypeContext(); + 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 + }; + + const [formField, setFormField] = useState(initialState); + const resetForm = () => { + setFormField(initialState); + }; + const [isSubmitting, setIsSubmitting] = useState(false); + + 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); + }; + + return ( + handleAddDialog(open)}> + + +
+
+

+ Create 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) + })) + } + /> +
+
+ +
+ + +
+
+
+
+
+
+
+ ); +}; + +export default AddDialog; diff --git a/src/pages/access/access-type/blocks/ListToolBar.tsx b/src/pages/access/access-type/blocks/ListToolBar.tsx new file mode 100644 index 0000000..b99d8e1 --- /dev/null +++ b/src/pages/access/access-type/blocks/ListToolBar.tsx @@ -0,0 +1,49 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { useManageAccessTypeContext } from '../hooks/useManageAccessTypeContext'; +import { Button } from '@/components/ui/button'; + +const ListToolbar = () => { + const { table, reload } = useDataGrid(); + const { handleAddDialog, handleEditDialog } = useManageAccessTypeContext(); + + return ( +
+
+
+
+ + + + +
+
+ + + + +
+
+
+
+ ); +}; + +export default ListToolbar; diff --git a/src/pages/access/access-type/hooks/ManageAccessTypeContext.tsx b/src/pages/access/access-type/hooks/ManageAccessTypeContext.tsx new file mode 100644 index 0000000..1cf9649 --- /dev/null +++ b/src/pages/access/access-type/hooks/ManageAccessTypeContext.tsx @@ -0,0 +1,178 @@ +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 ManageAccessTypeContext = createContext(initialProps); +const API_URL = apiConfig.service_dashboard; + +const ManageAccessTypeContextProvider = ({ 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 { ManageAccessTypeContext, ManageAccessTypeContextProvider }; +export type { SelectedUser }; diff --git a/src/pages/access/access-type/hooks/useManageAccessTypeContext.tsx b/src/pages/access/access-type/hooks/useManageAccessTypeContext.tsx new file mode 100644 index 0000000..2113167 --- /dev/null +++ b/src/pages/access/access-type/hooks/useManageAccessTypeContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageAccessTypeContext } from './ManageAccessTypeContext'; + +const useManageAccessTypeContext = () => { + const context = useContext(ManageAccessTypeContext); + + if (!context) throw new Error('useManageAccessTypeContext must be used within AuthProvider'); + + return context; +}; + +export { useManageAccessTypeContext }; diff --git a/src/pages/settings/user/manage-user/blocks/AddDialog.tsx b/src/pages/settings/user/manage-user/blocks/AddDialog.tsx index 2b4ee68..a7647cc 100644 --- a/src/pages/settings/user/manage-user/blocks/AddDialog.tsx +++ b/src/pages/settings/user/manage-user/blocks/AddDialog.tsx @@ -336,6 +336,7 @@ const AddDialog = () => { +