update page transaction
This commit is contained in:
@ -10,12 +10,37 @@ interface Props {
|
|||||||
enddate: string;
|
enddate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const polarToCartesian = (cx: number, cy: number, radius: number, angleInDegrees: number) => {
|
||||||
|
const angleInRadians = (angleInDegrees * Math.PI) / 180.0;
|
||||||
|
return {
|
||||||
|
x: cx + radius * Math.cos(angleInRadians),
|
||||||
|
y: cy + radius * Math.sin(angleInRadians),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const describeArc = (
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
radius: number,
|
||||||
|
startAngle: number,
|
||||||
|
endAngle: number
|
||||||
|
) => {
|
||||||
|
const start = polarToCartesian(x, y, radius, endAngle);
|
||||||
|
const end = polarToCartesian(x, y, radius, startAngle);
|
||||||
|
const largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
|
||||||
|
|
||||||
|
return [
|
||||||
|
"M", start.x, start.y,
|
||||||
|
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y,
|
||||||
|
].join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
const MemberActivity = ({ startdate, enddate }: Props) => {
|
const MemberActivity = ({ startdate, enddate }: Props) => {
|
||||||
const { GetData } = useCallApi();
|
const { GetData } = useCallApi();
|
||||||
const [responseTransactionValue, setResponseTransactionValue] = useState<any>(null);
|
const [responseTransactionValue, setResponseTransactionValue] = useState<any>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchDataTransactionValue = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await GetData(`${API_URL}/active-user`, {
|
const res = await GetData(`${API_URL}/active-user`, {
|
||||||
date_from: startdate,
|
date_from: startdate,
|
||||||
@ -23,43 +48,33 @@ const MemberActivity = ({ startdate, enddate }: Props) => {
|
|||||||
});
|
});
|
||||||
setResponseTransactionValue(res);
|
setResponseTransactionValue(res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching transaction value:', error);
|
console.error('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchDataTransactionValue();
|
fetchData();
|
||||||
}, [startdate, enddate, GetData]);
|
}, [startdate, enddate, GetData]);
|
||||||
|
|
||||||
const percentage = parseFloat((responseTransactionValue?.data?.total_customer_active_percentage ?? 0).toFixed(2)) ?? 0;
|
const percentage = parseFloat((responseTransactionValue?.data?.total_customer_active_percentage ?? 0).toFixed(2));
|
||||||
const totalCustomer = responseTransactionValue?.data?.total_customer ?? 0;
|
const totalCustomer = responseTransactionValue?.data?.total_customer ?? 0;
|
||||||
const activeCustomer = responseTransactionValue?.data?.total_customer_active ?? 0;
|
const activeCustomer = responseTransactionValue?.data?.total_customer_active ?? 0;
|
||||||
const reguler = responseTransactionValue?.data?.reguler ?? 0;
|
const reguler = responseTransactionValue?.data?.reguler ?? 0;
|
||||||
const premium = responseTransactionValue?.data?.premium ?? 0;
|
const premium = responseTransactionValue?.data?.premium ?? 0;
|
||||||
const agent = responseTransactionValue?.data?.agent ?? 0;
|
const agent = responseTransactionValue?.data?.agent ?? 0;
|
||||||
|
|
||||||
// Hitung sudut pointer
|
// Calculate pointer angle
|
||||||
const angle = (percentage / 100) * 180; // 0° (kiri) ke 180° (kanan)
|
const angle = (percentage / 100) * 180;
|
||||||
const radians = (angle * Math.PI) / 180;
|
const pointerX = 50 + 25 * Math.cos((angle - 180) * Math.PI / 180);
|
||||||
const radius = 40; // Radius dari setengah lingkaran
|
const pointerY = 50 + 25 * Math.sin((angle - 180) * Math.PI / 180);
|
||||||
const center = 50; // Titik pusat lingkaran
|
|
||||||
const pointerLength = 25; // Panjang pointer
|
|
||||||
|
|
||||||
const x = center + pointerLength * Math.cos(radians - Math.PI); // offset agar mulai dari kiri
|
|
||||||
const y = center + pointerLength * Math.sin(radians - Math.PI);
|
|
||||||
|
|
||||||
// Hitung titik akhir untuk arc aktif
|
|
||||||
const arcAngle = (Math.PI * percentage) / 100;
|
|
||||||
const arcX = 50 + radius * Math.cos(Math.PI - arcAngle);
|
|
||||||
const arcY = 50 - radius * Math.sin(arcAngle);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 bg-white rounded-lg shadow-md w-1/3">
|
<div className="p-6 bg-white rounded-lg shadow-md w-full max-w-md">
|
||||||
<div className="flex justify-between items-center pb-3 mb-4">
|
<div className="pb-3 mb-4">
|
||||||
<h2 className="text-lg font-semibold text-gray-700">Member Activity</h2>
|
<h2 className="text-lg font-semibold text-gray-700">Member Activity</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-6">
|
<div className="flex gap-6">
|
||||||
{/* Sidebar */}
|
{/* Sidebar Info */}
|
||||||
<ul className="space-y-4 w-1/2 text-gray-700 text-sm">
|
<ul className="space-y-4 w-1/2 text-gray-700 text-sm">
|
||||||
<li className="flex items-center gap-2">
|
<li className="flex items-center gap-2">
|
||||||
<UsersIcon className="w-4 h-4" />
|
<UsersIcon className="w-4 h-4" />
|
||||||
@ -70,15 +85,15 @@ const MemberActivity = ({ startdate, enddate }: Props) => {
|
|||||||
<span>Active Customer: {activeCustomer}</span>
|
<span>Active Customer: {activeCustomer}</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center gap-2">
|
<li className="flex items-center gap-2">
|
||||||
<UserCheckIcon className="w-4 h-4" color='blue'/>
|
<UserCheckIcon className="w-4 h-4" color='blue' />
|
||||||
<span>Reguler: {reguler}</span>
|
<span>Reguler: {reguler}</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center gap-2">
|
<li className="flex items-center gap-2">
|
||||||
<UserCheckIcon className="w-4 h-4" color='green'/>
|
<UserCheckIcon className="w-4 h-4" color='green' />
|
||||||
<span>Premium: {premium}</span>
|
<span>Premium: {premium}</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center gap-2">
|
<li className="flex items-center gap-2">
|
||||||
<UserCheckIcon className="w-4 h-4" color='orange'/>
|
<UserCheckIcon className="w-4 h-4" color='orange' />
|
||||||
<span>Agent: {agent}</span>
|
<span>Agent: {agent}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -88,7 +103,7 @@ const MemberActivity = ({ startdate, enddate }: Props) => {
|
|||||||
<div className="border border-gray-200 rounded-md p-4 text-center">
|
<div className="border border-gray-200 rounded-md p-4 text-center">
|
||||||
<h3 className="text-sm text-gray-600 font-medium mb-2">Active User</h3>
|
<h3 className="text-sm text-gray-600 font-medium mb-2">Active User</h3>
|
||||||
<div className="relative h-24 w-full">
|
<div className="relative h-24 w-full">
|
||||||
<svg className="w-full h-full" viewBox="0 0 100 50">
|
<svg viewBox="0 0 100 50" className="w-full h-full">
|
||||||
{/* Background arc */}
|
{/* Background arc */}
|
||||||
<path
|
<path
|
||||||
d="M 10 50 A 40 40 0 0 1 90 50"
|
d="M 10 50 A 40 40 0 0 1 90 50"
|
||||||
@ -97,24 +112,27 @@ const MemberActivity = ({ startdate, enddate }: Props) => {
|
|||||||
strokeWidth="10"
|
strokeWidth="10"
|
||||||
/>
|
/>
|
||||||
{/* Active arc */}
|
{/* Active arc */}
|
||||||
<path
|
{percentage > 0 && (
|
||||||
d={`M 10 50 A 40 40 0 ${percentage > 50 ? 1 : 0} 1 ${arcX} ${arcY}`}
|
<path
|
||||||
fill="none"
|
d={describeArc(50, 50, 40, 180, 180 + (percentage * 180 / 100))}
|
||||||
stroke="#34d399"
|
fill="none"
|
||||||
strokeWidth="10"
|
stroke="#34d399"
|
||||||
/>
|
strokeWidth="10"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{/* Pointer */}
|
{/* Pointer */}
|
||||||
<line
|
<line
|
||||||
x1="50"
|
x1="50"
|
||||||
y1="50"
|
y1="50"
|
||||||
x2={x}
|
x2={pointerX}
|
||||||
y2={y}
|
y2={pointerY}
|
||||||
stroke="#111827"
|
stroke="#111827"
|
||||||
strokeWidth="4"
|
strokeWidth="4"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<div className="flex justify-between text-xs text-gray-500 px-1">
|
<div className="flex justify-between text-xs text-gray-500 px-1 mt-1">
|
||||||
<span>{percentage}%</span>
|
<span>{percentage}%</span>
|
||||||
<span>100%</span>
|
<span>100%</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -43,7 +43,11 @@ const TransactionPieChart = ({ startdate, enddate }: Props) => {
|
|||||||
{ name: 'Purchase', value: parseFloat((responseTransactionValue?.data?.P ?? 0).toFixed(2)), color: '#baf7c5' },
|
{ name: 'Purchase', value: parseFloat((responseTransactionValue?.data?.P ?? 0).toFixed(2)), color: '#baf7c5' },
|
||||||
{ name: 'Withdraw', value: parseFloat((responseTransactionValue?.data?.W ?? 0).toFixed(2)), color: '#f56565' },
|
{ name: 'Withdraw', value: parseFloat((responseTransactionValue?.data?.W ?? 0).toFixed(2)), color: '#f56565' },
|
||||||
{ name: 'Top Up Partner', value: parseFloat((responseTransactionValue?.data?.N ?? 0).toFixed(2)), color: '#f7fa52' },
|
{ name: 'Top Up Partner', value: parseFloat((responseTransactionValue?.data?.N ?? 0).toFixed(2)), color: '#f7fa52' },
|
||||||
{ name: 'Reward', value: parseFloat((responseTransactionValue?.data?.E ?? 0).toFixed(2)), color: '#f7fa52' },
|
{ name: 'Reward', value: parseFloat((responseTransactionValue?.data?.E ?? 0).toFixed(2)), color: '#f50a19' },
|
||||||
|
{ name: 'Purchase Loja', value: parseFloat((responseTransactionValue?.data?.L ?? 0).toFixed(2)), color: '#F0A04B' },
|
||||||
|
{ name: 'Top Up P24', value: parseFloat((responseTransactionValue?.data?.B ?? 0).toFixed(2)), color: '#FADA7A' },
|
||||||
|
{ name: 'Transfer Agent', value: parseFloat((responseTransactionValue?.data?.A ?? 0).toFixed(2)), color: '#B1C29E' },
|
||||||
|
{ name: 'Withdrawal Agent', value: parseFloat((responseTransactionValue?.data?.M ?? 0).toFixed(2)), color: '#FCE7C8' },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -67,6 +67,18 @@ const TransactionValue = ({ startdate, enddate }: Props) => {
|
|||||||
case "E":
|
case "E":
|
||||||
type = "Reward";
|
type = "Reward";
|
||||||
break;
|
break;
|
||||||
|
case "L":
|
||||||
|
type = "Purchase Loja"
|
||||||
|
break;
|
||||||
|
case "B":
|
||||||
|
type ="Top Up P24";
|
||||||
|
break;
|
||||||
|
case "A":
|
||||||
|
type = " Transfer Agent";
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
type = "Withdrawal Agent";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
type = "Unknown";
|
type = "Unknown";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -118,12 +118,12 @@ const DetailApprovalTransaction = () => {
|
|||||||
<DialogBody>
|
<DialogBody>
|
||||||
{/* Tabs Navigation */}
|
{/* Tabs Navigation */}
|
||||||
<div className="flex border-b border-gray-200">
|
<div className="flex border-b border-gray-200">
|
||||||
<button
|
{/* <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'}`}
|
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')}
|
onClick={() => setActiveTab('detail')}
|
||||||
>
|
>
|
||||||
Detail Transaction
|
Detail Transaction
|
||||||
</button>
|
</button> */}
|
||||||
<button
|
<button
|
||||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'origincustomer' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'origincustomer' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
onClick={() => setActiveTab('origincustomer')}
|
onClick={() => setActiveTab('origincustomer')}
|
||||||
|
|||||||
@ -49,7 +49,6 @@ const DetailTransaction = () => {
|
|||||||
id: selectedTransactionId
|
id: selectedTransactionId
|
||||||
});
|
});
|
||||||
setTransactionDetails(response?.data);
|
setTransactionDetails(response?.data);
|
||||||
// console.log(response?.data);
|
|
||||||
// console.log(selectedTransactionId);
|
// console.log(selectedTransactionId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching transaction', error);
|
console.error('Error fetching transaction', error);
|
||||||
@ -127,6 +126,35 @@ const DetailTransaction = () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [formattedJson, setFormattedJson] = useState('');
|
||||||
|
const [highlightedJson, setHighlightedJson] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const obj = { a: 1, 'b': 'foo', c: [false, 'false', null, 'null', { d: { e: 1.3e5, f: '1.3e5' } }] };
|
||||||
|
const str = JSON.stringify(obj, undefined, 4);
|
||||||
|
setFormattedJson(str);
|
||||||
|
setHighlightedJson(syntaxHighlight(str));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function syntaxHighlight(json: any) {
|
||||||
|
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])"(\s:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match: any) {
|
||||||
|
let cls = 'number';
|
||||||
|
if (/^"/.test(match)) {
|
||||||
|
if (/:$/.test(match)) {
|
||||||
|
cls = 'key';
|
||||||
|
} else {
|
||||||
|
cls = 'string';
|
||||||
|
}
|
||||||
|
} else if (/true|false/.test(match)) {
|
||||||
|
cls = 'boolean';
|
||||||
|
} else if (/null/.test(match)) {
|
||||||
|
cls = 'null';
|
||||||
|
}
|
||||||
|
return '<span className="' + cls + '">' + match + '</span>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={showDetailDialog} onOpenChange={setShowDetailDialog}>
|
<Dialog open={showDetailDialog} onOpenChange={setShowDetailDialog}>
|
||||||
<DialogContent className="container-fixed max-w-[1024px] flex flex-col p-5 overflow-hidden">
|
<DialogContent className="container-fixed max-w-[1024px] flex flex-col p-5 overflow-hidden">
|
||||||
@ -137,12 +165,15 @@ const DetailTransaction = () => {
|
|||||||
<DialogBody>
|
<DialogBody>
|
||||||
{/* Tabs Navigation */}
|
{/* Tabs Navigation */}
|
||||||
<div className="flex border-b border-gray-200">
|
<div className="flex border-b border-gray-200">
|
||||||
<button
|
{transactionDetails?.kind == 'P' && (
|
||||||
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'}`}
|
<button
|
||||||
onClick={() => setActiveTab('detail')}
|
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>
|
Detail Transaction
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'origincustomer' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'origincustomer' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
onClick={() => setActiveTab('origincustomer')}
|
onClick={() => setActiveTab('origincustomer')}
|
||||||
@ -161,30 +192,39 @@ const DetailTransaction = () => {
|
|||||||
>
|
>
|
||||||
Origin Wallet
|
Origin Wallet
|
||||||
</button>
|
</button>
|
||||||
<button
|
{transactionDetails?.kind !== 'P' && (
|
||||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'destinationwallet' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
<button
|
||||||
onClick={() => setActiveTab('destinationwallet')}
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'destinationwallet' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
>
|
onClick={() => setActiveTab('destinationwallet')}
|
||||||
Destination Wallet
|
>
|
||||||
</button>
|
Destination Wallet
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<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'}`}
|
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')}
|
onClick={() => setActiveTab('log')}
|
||||||
>
|
>
|
||||||
Transaction Log
|
Transaction Log
|
||||||
</button>
|
</button>
|
||||||
<button
|
{transactionDetails?.kind !== 'P' && (
|
||||||
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'}`}
|
<button
|
||||||
onClick={() => setActiveTab('approve')}
|
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')}
|
||||||
Approval Log
|
>
|
||||||
</button>
|
Approval Log
|
||||||
<button
|
</button>
|
||||||
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'p24' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
)}
|
||||||
onClick={() => setActiveTab('p24')}
|
|
||||||
>
|
{transactionDetails?.kind !== 'P' && (
|
||||||
Log P24
|
<button
|
||||||
</button>
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'p24' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('p24')}
|
||||||
|
>
|
||||||
|
Log P24
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tab Content */}
|
{/* Tab Content */}
|
||||||
@ -281,8 +321,16 @@ const DetailTransaction = () => {
|
|||||||
kind = 'TOP UP';
|
kind = 'TOP UP';
|
||||||
} else if (transactionDetails?.kind === 'R') {
|
} else if (transactionDetails?.kind === 'R') {
|
||||||
kind = 'RETURN';
|
kind = 'RETURN';
|
||||||
}else if (transactionDetails?.kind === 'E') {
|
} else if (transactionDetails?.kind === 'E') {
|
||||||
kind = 'REWARD';
|
kind = 'REWARD';
|
||||||
|
} else if (transactionDetails?.kind === 'L') {
|
||||||
|
kind = 'PURCHASE LOJA';
|
||||||
|
} else if (transactionDetails?.kind === 'B') {
|
||||||
|
kind = 'TOP UP P24';
|
||||||
|
} else if (transactionDetails?.kind === 'A') {
|
||||||
|
kind = 'TRANSFER AGENT';
|
||||||
|
} else if (transactionDetails?.kind === 'M') {
|
||||||
|
kind = 'WITHDRAWAL AGENT';
|
||||||
}
|
}
|
||||||
return kind;
|
return kind;
|
||||||
})()}
|
})()}
|
||||||
@ -338,59 +386,60 @@ const DetailTransaction = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{activeTab === 'detail' && (
|
|
||||||
<div className="space-y-4">
|
{activeTab === 'detail' && transactionDetails?.kind == 'P' && (
|
||||||
<h3 className="font-semibold flex items-center">
|
<div className="space-y-4">
|
||||||
Product Information
|
<h3 className="font-semibold flex items-center">
|
||||||
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
Product Information
|
||||||
Product Info
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
</span>
|
Product Info
|
||||||
</h3>
|
</span>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
</h3>
|
||||||
<div>
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<p className="text-sm text-gray-500">Product Name</p>
|
<div>
|
||||||
<p className="font-medium">
|
<p className="text-sm text-gray-500">Product Name</p>
|
||||||
{transactionDetails?.purchase?.product?.name ?? "-"}
|
<p className="font-medium">
|
||||||
</p>
|
{transactionDetails?.purchase?.product?.name ?? "-"}
|
||||||
</div>
|
</p>
|
||||||
<div>
|
</div>
|
||||||
<p className="text-sm text-gray-500">Price Cash</p>
|
<div>
|
||||||
<p className="font-medium">
|
<p className="text-sm text-gray-500">Price Cash</p>
|
||||||
{transactionDetails?.purchase?.product?.price_cash != null
|
<p className="font-medium">
|
||||||
? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash)
|
{transactionDetails?.purchase?.product?.price_cash != null
|
||||||
: "-"}
|
? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash)
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Price Point</p>
|
|
||||||
<p className="font-medium">
|
|
||||||
{transactionDetails?.purchase?.product?.price_point ?? "-"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Product Type</p>
|
|
||||||
<p className="font-medium">
|
|
||||||
{transactionDetails?.purchase?.product?.type ?? "-"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Provider Name</p>
|
|
||||||
<p className="font-medium">
|
|
||||||
{transactionDetails?.purchase?.product?.provider?.description ?? "-"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Provider Type</p>
|
|
||||||
<p className="font-medium">
|
|
||||||
{transactionDetails?.purchase?.product?.provider?.type === "h2h"
|
|
||||||
? "HOST TO HOST"
|
|
||||||
: transactionDetails?.purchase?.product?.provider?.type === "agent"
|
|
||||||
? "AGENT"
|
|
||||||
: "-"}
|
: "-"}
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Price Point</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.purchase?.product?.price_point ?? "-"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Product Type</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.purchase?.product?.type ?? "-"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Provider Name</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.purchase?.product?.provider?.description ?? "-"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Provider Type</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.purchase?.product?.provider?.type === "h2h"
|
||||||
|
? "HOST TO HOST"
|
||||||
|
: transactionDetails?.purchase?.product?.provider?.type === "agent"
|
||||||
|
? "AGENT"
|
||||||
|
: "-"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'detail' && transactionDetails?.kind != 'P' && transactionDetails?.transfer != null && (
|
{activeTab === 'detail' && transactionDetails?.kind != 'P' && transactionDetails?.transfer != null && (
|
||||||
@ -463,7 +512,7 @@ const DetailTransaction = () => {
|
|||||||
kind = 'TOP UP';
|
kind = 'TOP UP';
|
||||||
} else if (transactionDetails?.kind === 'R') {
|
} else if (transactionDetails?.kind === 'R') {
|
||||||
kind = 'RETURN';
|
kind = 'RETURN';
|
||||||
}else if (transactionDetails?.kind === 'E') {
|
} else if (transactionDetails?.kind === 'E') {
|
||||||
kind = 'REWARD';
|
kind = 'REWARD';
|
||||||
}
|
}
|
||||||
return kind;
|
return kind;
|
||||||
@ -592,7 +641,7 @@ const DetailTransaction = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'destinationwallet' && (
|
{activeTab === 'destinationwallet' && transactionDetails?.kind?.trim()?.toUpperCase() !== 'P' && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h3 className="font-semibold">Destination Wallet</h3>
|
<h3 className="font-semibold">Destination Wallet</h3>
|
||||||
|
|
||||||
@ -651,7 +700,7 @@ const DetailTransaction = () => {
|
|||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Type</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Type</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Date</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Date</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th>
|
{/* <th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th> */}
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Endpoint</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Endpoint</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -683,8 +732,18 @@ const DetailTransaction = () => {
|
|||||||
hour12: false
|
hour12: false
|
||||||
})
|
})
|
||||||
: ''}</td>
|
: ''}</td>
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.request_body}</td>
|
{/* <td className="px-4 py-2 text-sm text-gray-500">{log.request_body}</td> */}
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.response_body}</td>
|
<td className="px-4 py-2 text-sm text-gray-500">
|
||||||
|
<pre
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: syntaxHighlight(
|
||||||
|
typeof log.response_body === 'string'
|
||||||
|
? log.response_body
|
||||||
|
: JSON.stringify(log.response_body, null, 4)
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint}</td>
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
@ -701,7 +760,7 @@ const DetailTransaction = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'approve' && (
|
{activeTab === 'approve' && transactionDetails?.kind == "P" && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h3 className="font-semibold">Approval Logs</h3>
|
<h3 className="font-semibold">Approval Logs</h3>
|
||||||
{transactionDetails?.log_approve.length === 0 ? (
|
{transactionDetails?.log_approve.length === 0 ? (
|
||||||
@ -777,7 +836,7 @@ const DetailTransaction = () => {
|
|||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Type</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Type</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Date</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Date</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th>
|
{/* <th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th> */}
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
||||||
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Endpoint</th>
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Endpoint</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -810,8 +869,18 @@ const DetailTransaction = () => {
|
|||||||
hour12: false
|
hour12: false
|
||||||
})
|
})
|
||||||
: ''}</td>
|
: ''}</td>
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.request_body}</td>
|
{/* <td className="px-4 py-2 text-sm text-gray-500">{log.request_body}</td> */}
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.response_body}</td>
|
<td className="px-4 py-2 text-sm text-gray-500">
|
||||||
|
<pre
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: syntaxHighlight(
|
||||||
|
typeof log.response_body === 'string'
|
||||||
|
? log.response_body
|
||||||
|
: JSON.stringify(log.response_body, null, 4)
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint ?? '-'}</td>
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint ?? '-'}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
|
|||||||
@ -178,6 +178,10 @@ const ListToolbar = () => {
|
|||||||
<SelectItem value="R">RETURN</SelectItem>
|
<SelectItem value="R">RETURN</SelectItem>
|
||||||
<SelectItem value="N">TOP UP PARTNER</SelectItem>
|
<SelectItem value="N">TOP UP PARTNER</SelectItem>
|
||||||
<SelectItem value="E">REWARD</SelectItem>
|
<SelectItem value="E">REWARD</SelectItem>
|
||||||
|
<SelectItem value="L">PURCHASE LOJA</SelectItem>
|
||||||
|
<SelectItem value="B">TOP UP P24</SelectItem>
|
||||||
|
<SelectItem value="A">TRANSFER AGENT</SelectItem>
|
||||||
|
<SelectItem value="M">WITHDRAWAL AGENT</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
|||||||
@ -78,6 +78,10 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
case 'R': return 'RETURN';
|
case 'R': return 'RETURN';
|
||||||
case 'N': return 'TOP UP PARTNER';
|
case 'N': return 'TOP UP PARTNER';
|
||||||
case 'E': return 'REWARD';
|
case 'E': return 'REWARD';
|
||||||
|
case 'L': return 'PURCHASE LOJA';
|
||||||
|
case 'B': return 'TOP UP P24';
|
||||||
|
case 'A': return 'TRANSFER AGENT';
|
||||||
|
case 'M': return 'WITHDRAWAL AGENT';
|
||||||
default: return '_';
|
default: return '_';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user