add detail history transaction
This commit is contained in:
11
package-lock.json
generated
11
package-lock.json
generated
@ -71,6 +71,7 @@
|
||||
"styled-components": "^6.1.13",
|
||||
"stylis": "^4.3.4",
|
||||
"stylis-plugin-rtl": "^2.1.1",
|
||||
"tabs": "^0.2.0",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vite-plugin-windicss": "^1.9.3",
|
||||
@ -8025,6 +8026,10 @@
|
||||
"version": "5.4.3",
|
||||
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz",
|
||||
"integrity": "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ==",
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
"license": "MIT",
|
||||
>>>>>>> Stashed changes
|
||||
"peerDependencies": {
|
||||
"react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
@ -8777,6 +8782,12 @@
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/tabs": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tabs/-/tabs-0.2.0.tgz",
|
||||
"integrity": "sha512-q6mo8KWq/Zi+zGR3ZvGq6S6ckc3JNbGRGtAwIhtnp2GlS1goTqFnWX3MkyDKYSQuzwBqBAy2fYGHQI+3HMnXZQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
|
||||
|
||||
@ -77,6 +77,7 @@
|
||||
"styled-components": "^6.1.13",
|
||||
"stylis": "^4.3.4",
|
||||
"stylis-plugin-rtl": "^2.1.1",
|
||||
"tabs": "^0.2.0",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vite-plugin-windicss": "^1.9.3",
|
||||
|
||||
149
src/pages/transaction/blocks/DetailTransaction.tsx
Normal file
149
src/pages/transaction/blocks/DetailTransaction.tsx
Normal file
@ -0,0 +1,149 @@
|
||||
import { useTransactionContext } from '../hooks/useTransactionContext';
|
||||
import { useCallApi } from '@/hooks';
|
||||
import { apiConfig } from '@/config/api.config';
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogBody,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
const API_URL = apiConfig.transaction;
|
||||
|
||||
const DetailTransaction = () => {
|
||||
const { GetData } = useCallApi();
|
||||
const {
|
||||
showDetailDialog,
|
||||
setShowDetailDialog,
|
||||
selectedTransactionId
|
||||
} = useTransactionContext();
|
||||
|
||||
const [transactionDetails, setTransactionDetails] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTransactionDetails = async () => {
|
||||
if (selectedTransactionId) {
|
||||
try {
|
||||
const response = await GetData(`${API_URL}/transaction/history/detail/${selectedTransactionId}`, {
|
||||
id: selectedTransactionId
|
||||
});
|
||||
// console.log(response?.data);
|
||||
setTransactionDetails(response?.data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching transaction', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (showDetailDialog && selectedTransactionId) {
|
||||
fetchTransactionDetails();
|
||||
}
|
||||
}, [showDetailDialog, selectedTransactionId, GetData]);
|
||||
|
||||
const [activeTab, setActiveTab] = useState('detail'); // 'detail', 'log', 'approve'
|
||||
|
||||
return (
|
||||
<Dialog open={showDetailDialog} onOpenChange={setShowDetailDialog}>
|
||||
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5 overflow-hidden">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Transaction Details</DialogTitle>
|
||||
{/* <DialogDescription>
|
||||
Viewing details for transaction ID: {selectedTransactionId}
|
||||
</DialogDescription> */}
|
||||
</DialogHeader>
|
||||
<DialogBody>
|
||||
{/* Tabs Navigation */}
|
||||
<div className="flex border-b border-gray-200">
|
||||
<button
|
||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'detail' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||
onClick={() => setActiveTab('detail')}
|
||||
>
|
||||
Detail Transaction
|
||||
</button>
|
||||
<button
|
||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'log' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||
onClick={() => setActiveTab('log')}
|
||||
>
|
||||
Transaction Log
|
||||
</button>
|
||||
<button
|
||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'approve' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||
onClick={() => setActiveTab('approve')}
|
||||
>
|
||||
Log Approve
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Tab Content */}
|
||||
<div className="py-4">
|
||||
{activeTab === 'detail' && (
|
||||
<div className="space-y-4">
|
||||
<h3 className="font-semibold">Transaction Information</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">Transaction Date</p>
|
||||
<p className="font-medium">2023-11-15 14:30:22</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">Amount</p>
|
||||
<p className="font-medium">$1,250.00</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">Status</p>
|
||||
<p className="font-medium">COMPLETED</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">Fee</p>
|
||||
<p className="font-medium">$5.00</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'log' && (
|
||||
<div className="space-y-4">
|
||||
<h3 className="font-semibold">Transaction Logs</h3>
|
||||
<div className="border rounded-lg divide-y">
|
||||
<div className="p-3">
|
||||
<div className="flex justify-between">
|
||||
<span className="font-medium">Status changed to COMPLETED</span>
|
||||
<span className="text-sm text-gray-500">2023-11-15 14:35:22</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mt-1">System processed the transaction successfully</p>
|
||||
</div>
|
||||
<div className="p-3">
|
||||
<div className="flex justify-between">
|
||||
<span className="font-medium">Status changed to PROCESSING</span>
|
||||
<span className="text-sm text-gray-500">2023-11-15 14:31:22</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mt-1">Transaction received by system</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'approve' && (
|
||||
<div className="space-y-4">
|
||||
<h3 className="font-semibold">Approval Logs</h3>
|
||||
<div className="border rounded-lg divide-y">
|
||||
<div className="p-3">
|
||||
<div className="flex justify-between">
|
||||
<span className="font-medium">Approved by Admin</span>
|
||||
<span className="text-sm text-gray-500">2023-11-15 14:32:22</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mt-1">Transaction approved automatically by system</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</DialogBody>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailTransaction;
|
||||
@ -8,6 +8,7 @@ import { useCallApi } from '@/hooks';
|
||||
import ListToolbar from '../blocks/ListToolbar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useNavigate } from 'react-router';
|
||||
import DetailTransaction from '../blocks/DetailTransaction';
|
||||
|
||||
interface TransactionProps {
|
||||
id: number;
|
||||
@ -23,16 +24,26 @@ interface ContextProps {
|
||||
order_direction: any,
|
||||
filter: any
|
||||
) => Promise<{ data: TransactionProps[]; totalCount: number } | undefined>;
|
||||
showDetailDialog: boolean;
|
||||
setShowDetailDialog: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
selectedTransactionId: number | null;
|
||||
setSelectedTransactionId: React.Dispatch<React.SetStateAction<number | null>>;
|
||||
}
|
||||
|
||||
const initialProps: ContextProps = {
|
||||
getTransactionLists: async () => ({ data: [], totalCount: 0 })
|
||||
getTransactionLists: async () => ({ data: [], totalCount: 0 }),
|
||||
showDetailDialog: false,
|
||||
setShowDetailDialog: () => { },
|
||||
selectedTransactionId: null,
|
||||
setSelectedTransactionId: () => { }
|
||||
};
|
||||
|
||||
const ManageTransactionContext = createContext<ContextProps>(initialProps);
|
||||
const API_URL = apiConfig.transaction;
|
||||
|
||||
const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const [showDetailDialog, setShowDetailDialog] = useState(false);
|
||||
const [selectedTransactionId, setSelectedTransactionId] = useState<number | null>(null);
|
||||
const [transaction, setTransaction] = useState<TransactionProps[]>([]);
|
||||
const { GetData } = useCallApi();
|
||||
const navigate = useNavigate();
|
||||
@ -97,9 +108,9 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
let status;
|
||||
if (row.status === 'C') {
|
||||
status = 'COMPLETE';
|
||||
} else if(row.status === 'F') {
|
||||
} else if (row.status === 'F') {
|
||||
status = 'FAILED';
|
||||
} else if(row.status === 'O') {
|
||||
} else if (row.status === 'O') {
|
||||
status = 'ON PROCESS';
|
||||
} else {
|
||||
status = 'PENDING';
|
||||
@ -138,13 +149,19 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
cell: (data) => {
|
||||
const row = data.row.original.id;
|
||||
const row = data.row.original;
|
||||
return (
|
||||
<>
|
||||
<button className="btn btn-sm btn-icon btn-clear btn-light">
|
||||
<div key={`actions-${row.id}`}>
|
||||
<button
|
||||
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||
onClick={() => {
|
||||
setSelectedTransactionId(row.id);
|
||||
setShowDetailDialog(true);
|
||||
}}
|
||||
>
|
||||
<KeenIcon icon="eye" />
|
||||
</button>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
meta: {
|
||||
@ -161,25 +178,25 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
let enddate;
|
||||
let formattedFilter;
|
||||
|
||||
if (filter == undefined || filter.length==0) {
|
||||
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];
|
||||
|
||||
startdate = today.toISOString().split('T')[0];
|
||||
enddate = nextWeek.toISOString().split('T')[0];
|
||||
}else if (filter != undefined || filter.length!=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"
|
||||
from: startdate + " 00:00:00",
|
||||
to: enddate + " 23:59:59"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const response = await GetData(`${API_URL}/transaction/history`, {
|
||||
limit,
|
||||
page: page + 1,
|
||||
@ -199,10 +216,15 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<ManageTransactionContext.Provider
|
||||
value={{
|
||||
getTransactionLists
|
||||
getTransactionLists,
|
||||
showDetailDialog,
|
||||
setShowDetailDialog,
|
||||
selectedTransactionId,
|
||||
setSelectedTransactionId
|
||||
}}
|
||||
>
|
||||
<Toaster expand visibleToasts={9} duration={3000} />
|
||||
<DetailTransaction />
|
||||
|
||||
<DataGridProvider
|
||||
columns={columns}
|
||||
|
||||
13
yarn.lock
13
yarn.lock
@ -3713,7 +3713,11 @@ react-day-picker@^8.10.1:
|
||||
resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz"
|
||||
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
react-dom@^18.3.1:
|
||||
=======
|
||||
"react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19 || ^19.0.0-rc", react-dom@^18.0.0, "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react-dom@^18.3.1, "react-dom@>= 16.8.0", react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0:
|
||||
>>>>>>> Stashed changes
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
|
||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||
@ -3887,7 +3891,11 @@ react-transition-group@^4.4.5:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
react@^18.3.1:
|
||||
=======
|
||||
"react@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.3.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.6.0 || 17 || 18", "react@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18 || ^19 || ^19.0.0-rc", react@^18.0.0, "react@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react@^18.3.1, "react@>= 16.8.0", react@>=0.13, react@>=16.3.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, "react@16.8 - 18":
|
||||
>>>>>>> Stashed changes
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||
@ -4237,6 +4245,11 @@ synckit@^0.9.1:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
tabs@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/tabs/-/tabs-0.2.0.tgz"
|
||||
integrity sha512-q6mo8KWq/Zi+zGR3ZvGq6S6ckc3JNbGRGtAwIhtnp2GlS1goTqFnWX3MkyDKYSQuzwBqBAy2fYGHQI+3HMnXZQ==
|
||||
|
||||
tailwind-merge@^2.5.4:
|
||||
version "2.5.4"
|
||||
resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz"
|
||||
|
||||
Reference in New Issue
Block a user