From 5e355ea052f21413ca36c49e3848eb54d4f29478 Mon Sep 17 00:00:00 2001 From: Rifqi222 <mrifki193@gmail.com> Date: Mon, 13 Nov 2023 22:07:43 +0700 Subject: [PATCH] refactor: refactoring code for cleaning --- index.html | 2 +- .../AuthenticationForm/FormButton.tsx | 26 +- src/components/Navigation/Navbar.tsx | 2 +- .../WalletManagement/ButtonNumber.tsx | 14 ++ src/components/WalletManagement/History.tsx | 80 ------ .../WalletManagement/History/History.tsx | 59 +++++ .../History/HistorySingle.tsx | 40 +++ src/components/WalletManagement/TopUp.tsx | 236 ------------------ .../WalletManagement/TopUp/TopUp.tsx | 158 ++++++++++++ .../WalletManagement/TopUp/TopUpSingle.tsx | 51 ++++ src/components/WalletManagement/Transfer.tsx | 208 --------------- .../Transfer/ReceiptSingle.tsx | 75 ++++++ .../WalletManagement/Transfer/Transfer.tsx | 154 ++++++++++++ src/pages/History/HistoryPage.tsx | 2 +- src/pages/Home/Home.tsx | 14 +- src/pages/TopUp/TopUpPage.tsx | 2 +- src/pages/Transfer/TransferPage.tsx | 2 +- 17 files changed, 582 insertions(+), 543 deletions(-) create mode 100644 src/components/WalletManagement/ButtonNumber.tsx delete mode 100644 src/components/WalletManagement/History.tsx create mode 100644 src/components/WalletManagement/History/History.tsx create mode 100644 src/components/WalletManagement/History/HistorySingle.tsx delete mode 100644 src/components/WalletManagement/TopUp.tsx create mode 100644 src/components/WalletManagement/TopUp/TopUp.tsx create mode 100644 src/components/WalletManagement/TopUp/TopUpSingle.tsx delete mode 100644 src/components/WalletManagement/Transfer.tsx create mode 100644 src/components/WalletManagement/Transfer/ReceiptSingle.tsx create mode 100644 src/components/WalletManagement/Transfer/Transfer.tsx diff --git a/index.html b/index.html index 7c42e7a..18e5813 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="UTF-8" /> - <link rel="icon" type="image/png" href="/logo-color.png" /> + <link rel="icon" type="image/ico" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>iWalet App</title> </head> diff --git a/src/components/AuthenticationForm/FormButton.tsx b/src/components/AuthenticationForm/FormButton.tsx index 6231b1f..a25f962 100644 --- a/src/components/AuthenticationForm/FormButton.tsx +++ b/src/components/AuthenticationForm/FormButton.tsx @@ -1,19 +1,19 @@ import React from "react"; const FormButton = ({ - text, - onClickFunction, - disabled -}: { - text: string; - onClickFunction: (e: React.SyntheticEvent) => void; - disabled: boolean; -}) => { - return ( - <button className="py-2 px-4 text-base bg-darkgreen hover:bg-lightgreen text-white" type="submit" onClick={onClickFunction} disabled={disabled}> - {text} - </button> - ); + text, + onClickFunction, + disabled + }: { + text: string; + onClickFunction: (e: React.SyntheticEvent) => void; + disabled: boolean; + }) => { + return ( + <button className="py-2 px-4 text-base bg-darkgreen hover:bg-lightgreen text-white" type="submit" onClick={onClickFunction} disabled={disabled}> + {text} + </button> + ); }; export default FormButton; \ No newline at end of file diff --git a/src/components/Navigation/Navbar.tsx b/src/components/Navigation/Navbar.tsx index 5180855..e11c2a7 100644 --- a/src/components/Navigation/Navbar.tsx +++ b/src/components/Navigation/Navbar.tsx @@ -22,7 +22,7 @@ const Navbar= ({ navbarLinks } : { navbarLinks: InterfaceNavbar[] }) => { }, [isToggled]) return ( - <nav className="md:hidden sticky top-0"> + <nav className="md:hidden sticky top-0 z-10"> <div className="p-8 bg-darkgreen flex justify-between"> <img className="h-12" src={Logo} alt="iWalet Logo" title="iWalet Logo"/> <button diff --git a/src/components/WalletManagement/ButtonNumber.tsx b/src/components/WalletManagement/ButtonNumber.tsx new file mode 100644 index 0000000..86007ce --- /dev/null +++ b/src/components/WalletManagement/ButtonNumber.tsx @@ -0,0 +1,14 @@ +import React from 'react'; + +const ButtonNumber = ({ amount, onClickFunction }: { amount: number; onClickFunction: (amount: number) => void }) => { + return ( + <button + onClick={() => onClickFunction(amount)} + className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60" + > + {amount.toLocaleString()}{/* Menambahkan format uang */} + </button> + ); +}; + +export default ButtonNumber; diff --git a/src/components/WalletManagement/History.tsx b/src/components/WalletManagement/History.tsx deleted file mode 100644 index 177aec3..0000000 --- a/src/components/WalletManagement/History.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React from "react"; -import { ToastContainer } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import { FaWallet, FaPlus, FaDollarSign } from 'react-icons/fa6'; - -const History = () => { - return ( - <> - <ToastContainer /> - <div> - {/* Dark green banner */} - <div className="relative w-full md:h-40 h-52 bg-darkgreenhistory flex flex-row"> - <div className="p-4"> - <p className="text-white text-xl font-bold">Always use <i>iWalet</i> for all of your e-transactions~</p> - <p className="text-white text-xs">FREE REGISTRATION and get all of our services in just one click~</p> - <button className="mt-6 py-1 px-4 bg-none border border-white text-white rounded-3xl font-semibold text-sm">Try <i>iWalet</i> Transfer</button> - </div> - {/* Current balance at the bottom center of the dark green banner */} - <div className="absolute md:w-1/2 w-4/5 -bottom-12 left-1/2 transform -translate-x-1/2 bg-white text-black p-4 text-center shadow-lg rounded-lg"> - <div className="flex flex-col"> - <div className="flex flex-row justify-between"> - <div className="flex items-left flex-col"> - <div className="flex flex-row items-center"> - <span className="text-darkgreen mr-2"><FaWallet /></span> - <span className="text-greytext text-sm font-semibold">iWalet</span> - </div> - <span className="text-black font-bold text-2xl">Rp14.042</span> - </div> - <div className="ml-4 flex items-center"> {/* Add margin-left for spacing */} - <button className="py-1 px-4 flex items-center border border-darkgreen bg-verylightgreen text-white rounded-3xl"> - <span className="text-darkgreen mr-2"><FaPlus /></span> - <span className="text-darkgreen">Top-Up</span> - </button> - </div> - </div> - </div> - </div> - </div> - <div className="relative top-16 mb-4"> - <div className="flex flex-col bg-white text-black my-4 mx-2 md:mx-4 p-4 border border-lightgreen shadow-lg rounded-lg"> - <div className="flex flex-row items-center"> - <span className="text-darkgreen mr-1 text-6xl"><FaDollarSign /></span> - <div className="flex items-left flex-col justify-between w-full"> - <span className="text-black text-md font-semibold">Transfer ke</span> - <span className="text-black font-semibold text-xl">Rifqi Farhansyah</span> - <span className="text-darkgreen font-normal text-xl">Berhasil</span> - </div> - <div className="flex items-end flex-col justify-between w-full"> - <span className="text-black font-bold text-xl">Rp12.500</span> - <div className="flex flex-row items-center"> - <span className="text-darkgreen mr-4 text-md"><FaWallet /></span> - <span className="text-black text-md font-semibold">iWallet</span> - </div> - </div> - </div> - </div> - <div className="flex flex-col bg-white text-black my-4 mx-2 md:mx-4 p-4 border border-red shadow-lg rounded-lg"> - <div className="flex flex-row items-center"> - <span className="text-red mr-1 text-6xl"><FaDollarSign /></span> - <div className="flex items-left flex-col justify-between w-full"> - <span className="text-greytext text-md font-semibold">Top-Up</span> - <span className="text-greytext font-semibold text-xl">Michael Utama</span> - <span className="text-red font-normal text-xl">Gagal</span> - </div> - <div className="flex items-end flex-col justify-between w-full"> - <span className="text-greytext font-bold text-xl line-through">Rp12.500</span> - <div className="flex flex-row items-center"> - <span className="text-red mr-4 text-md"><FaWallet /></span> - <span className="text-greytext text-md font-semibold">iWallet</span> - </div> - </div> - </div> - </div> - </div> - </div> - </> - ); -}; - -export default History; diff --git a/src/components/WalletManagement/History/History.tsx b/src/components/WalletManagement/History/History.tsx new file mode 100644 index 0000000..dc6ef4a --- /dev/null +++ b/src/components/WalletManagement/History/History.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { FaWallet, FaPlus } from 'react-icons/fa6'; +import HistorySingle from './HistorySingle'; + +const History = () => { + return ( + <> + <ToastContainer /> + <div> + {/* Dark green banner */} + <div className="relative w-full md:h-40 h-52 bg-darkgreenhistory flex flex-row"> + <div className="p-4"> + <p className="text-white text-xl font-bold">Always use <i>iWalet</i> for all of your e-transactions~</p> + <p className="text-white text-xs">FREE REGISTRATION and get all of our services in just one click~</p> + <button className="mt-6 py-1 px-4 bg-none border border-white text-white rounded-3xl font-semibold text-sm">Try <i>iWalet</i> Transfer</button> + </div> + {/* Current balance at the bottom center of the dark green banner */} + <div className="absolute md:w-1/2 w-4/5 -bottom-12 left-1/2 transform -translate-x-1/2 bg-white text-black p-4 text-center shadow-lg rounded-lg"> + <div className="flex flex-col"> + <div className="flex flex-row justify-between"> + <div className="flex items-left flex-col"> + <div className="flex flex-row items-center"> + <span className="text-darkgreen mr-2"><FaWallet /></span> + <span className="text-greytext text-sm font-semibold">iWalet</span> + </div> + <span className="text-black font-bold text-2xl">Rp14.042</span> + </div> + <div className="ml-4 flex items-center"> {/* Add margin-left for spacing */} + <button className="py-1 px-4 flex items-center border border-darkgreen bg-verylightgreen text-white rounded-3xl"> + <span className="text-darkgreen mr-2"><FaPlus /></span> + <span className="text-darkgreen">Top-Up</span> + </button> + </div> + </div> + </div> + </div> + </div> + <div className="relative top-16 mb-4"> + <HistorySingle + status="Berhasil" + title="Transfer ke" + subtitle="Rifqi Farhansyah" + amount="Rp12.500" + /> + <HistorySingle + status="Gagal" + title="Top-Up" + subtitle="Michael Utama" + amount="Rp12.500" + /> + </div> + </div> + </> + ); +}; + +export default History; diff --git a/src/components/WalletManagement/History/HistorySingle.tsx b/src/components/WalletManagement/History/HistorySingle.tsx new file mode 100644 index 0000000..5b1d909 --- /dev/null +++ b/src/components/WalletManagement/History/HistorySingle.tsx @@ -0,0 +1,40 @@ +import { FaDollarSign, FaWallet } from 'react-icons/fa'; + +const HistorySingle = ({ + status, + title, + subtitle, + amount, +}: { + status: string; + title: string; + subtitle: string; + amount: string; +}) => { + const iconColor = status === 'Berhasil' ? 'text-darkgreen' : 'text-red'; + const textColor = status === 'Berhasil' ? 'text-black' : 'text-greytext'; + const walletIconColor = status === 'Berhasil' ? 'text-darkgreen' : 'text-red'; + const isLineThrough = status === 'Gagal'; + + return ( + <div className={`flex flex-col bg-white text-black my-4 mx-2 md:mx-4 p-4 border ${status === 'Berhasil' ? 'border-lightgreen' : 'border-red'} shadow-lg rounded-lg`}> + <div className="flex flex-row items-center"> + <span className={`${iconColor} mr-1 text-6xl`}><FaDollarSign /></span> + <div className="flex items-left flex-col justify-between w-full"> + <span className={`text-md font-semibold ${textColor}`}>{title}</span> + <span className={`font-semibold text-xl ${textColor}`}>{subtitle}</span> + <span className={`font-normal text-xl ${status === 'Berhasil' ? 'text-darkgreen' : 'text-red'}`}>{status}</span> + </div> + <div className="flex items-end flex-col justify-between w-full"> + <span className={`font-bold text-xl ${textColor} ${isLineThrough ? 'line-through' : ''}`}>{amount}</span> + <div className="flex flex-row items-center"> + <span className={`${walletIconColor} mr-4 text-md`}><FaWallet /></span> + <span className={`text-md font-semibold ${textColor}`}>iWallet</span> + </div> + </div> + </div> + </div> + ); +}; + +export default HistorySingle; diff --git a/src/components/WalletManagement/TopUp.tsx b/src/components/WalletManagement/TopUp.tsx deleted file mode 100644 index f33a3a2..0000000 --- a/src/components/WalletManagement/TopUp.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import React, { useState } from "react"; -import { ToastContainer, toast } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import { FaWallet } from 'react-icons/fa6'; -import BCA from '../../assets/bca.png'; -import Mandiri from '../../assets/mandiri.png'; -import BRI from '../../assets/briva.png'; -import BNI from '../../assets/bni.png'; -import BSI from '../../assets/bsi.png'; - -const TopUp = () => { - const [balance, setBalance] = useState(1000); // Initial balance - const [topUpAmount, setTopUpAmount] = useState(0); - const [selectedPaymentMethod, setSelectedPaymentMethod] = useState("credit-card"); - const [bankAccountNumber, setBankAccountNumber] = useState(""); - - // Function to format input value with thousands separators - const formatNumber = (value) => { - return Intl.NumberFormat().format(value); - }; - - const handleTopUp = (amount) => { - // Update the input value and the balance when the user tops up - setTopUpAmount(amount); - setBalance((prevBalance) => prevBalance + amount); - }; - - const handlePaymentMethodChange = (event) => { - setSelectedPaymentMethod(event.target.value); - }; - - const handleBankAccountChange = (event) => { - setBankAccountNumber(event.target.value); - }; - - const handleTopUpValid = () => { - if (isTopUpValid) { - // Simulasikan transaksi dengan proses validasi sederhana - if (Math.random() < 0.5) { - showToastSuccess(); // Transaksi berhasil - } else { - showToastFailure(); // Transaksi gagal - } - } - }; - - const showToastSuccess = () => { - toast.success("Transaksi berhasil!"); - }; - const showToastFailure = () => { - toast.error("Transaksi gagal. Silakan coba lagi."); - }; - - const isTopUpValid = topUpAmount > 0 && bankAccountNumber.length === 10; - - return ( - <> - <ToastContainer /> - <div> - <div className="text-sm mx-auto my-auto font-semibold border-2 border-darkgreen rounded-lg flex items-center justify-start p-5 max-w-screen-2xl"> - <FaWallet className="mr-2" /> Current Balance: <span className="font-normal">350.000</span> - </div> - <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> - <h1 className="text-4xl font-semibold mb-2">Top-Up Amount:</h1> - - <div className="mb-4"> - <label> - <input - type="text" - value={formatNumber(topUpAmount)} // Format the value with thousands separators - onChange={(e) => { - const inputValue = e.target.value.replace(/,/g, ''); - const newAmount = inputValue === "" ? 0 : parseInt(inputValue, 10); - setTopUpAmount(newAmount); - }} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - placeholder="Enter amount" - /> - </label> - </div> - - <div className="md:space-y-0 space-y-2"> - <button onClick={() => handleTopUp(500000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-8 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 500rb - </button> - <button onClick={() => handleTopUp(1000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 1jt - </button> - <button onClick={() => handleTopUp(2000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 2jt - </button> - <button onClick={() => handleTopUp(2500000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 2.5jt - </button> - <button onClick={() => handleTopUp(5000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 5jt - </button> - <button onClick={() => handleTopUp(10000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 10jt - </button> - </div> - </div> - <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> - <div> - <h1 className="text-4xl font-semibold mb-2">Payment Method:</h1> - <div className="space-y-2"> - <div className="flex flex-col"> - <div className="flex flex-row items-center"> - <input - type="radio" - id="bca" - name="paymentMethod" - value="bca" - checked={selectedPaymentMethod === "bca"} - onChange={handlePaymentMethodChange} - /> - <img src={BCA} alt="BCA Logo" className="w-16 h-auto m-2 mr-4" /> - <label className="font-semibold text-xl my-2" htmlFor="bca"> BCA Virtual Account</label> - </div> - {selectedPaymentMethod === "bca" && ( - <input - type="number" - placeholder="Enter your BCA Account Number" - value={bankAccountNumber} - onChange={handleBankAccountChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - )} - </div> - <div className="flex flex-col"> - <div className="flex flex-row items-center"> - <input - type="radio" - id="mandiri" - name="paymentMethod" - value="mandiri" - checked={selectedPaymentMethod === "mandiri"} - onChange={handlePaymentMethodChange} - /> - <img src={Mandiri} alt="Mandiri Logo" className="w-16 h-auto m-2 mr-4" /> - <label className="font-semibold text-xl my-2" htmlFor="mandiri"> Mandiri Virtual Account</label> - </div> - {selectedPaymentMethod === "mandiri" && ( - <input - type="number" - placeholder="Enter your Mandiri Account Number" - value={bankAccountNumber} - onChange={handleBankAccountChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - )} - </div> - <div className="flex flex-col"> - <div className="flex flex-row items-center"> - <input - type="radio" - id="bri" - name="paymentMethod" - value="bri" - checked={selectedPaymentMethod === "bri"} - onChange={handlePaymentMethodChange} - /> - <img src={BRI} alt="BRI Logo" className="w-16 h-auto m-2 mr-4" /> - <label className="font-semibold text-xl my-2" htmlFor="bri"> BRIVA</label> - </div> - {selectedPaymentMethod === "bri" && ( - <input - type="number" - placeholder="Enter your BRI Account" - value={bankAccountNumber} - onChange={handleBankAccountChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - )} - </div> - <div className="flex flex-col"> - <div className="flex flex-row items-center"> - <input - type="radio" - id="bni" - name="paymentMethod" - value="bni" - checked={selectedPaymentMethod === "bni"} - onChange={handlePaymentMethodChange} - /> - <img src={BNI} alt="BNI Logo" className="w-16 h-auto m-2 mr-4" /> - <label className="font-semibold text-xl my-2" htmlFor="bni"> BNI Virtual Account</label> - </div> - {selectedPaymentMethod === "bni" && ( - <input - type="number" - placeholder="Enter your BNI Account" - value={bankAccountNumber} - onChange={handleBankAccountChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - )} - </div> - <div className="flex flex-col"> - <div className="flex flex-row items-center"> - <input - type="radio" - id="bsi" - name="paymentMethod" - value="bsi" - checked={selectedPaymentMethod === "bsi"} - onChange={handlePaymentMethodChange} - /> - <img src={BSI} alt="BSI Logo" className="w-16 h-auto m-2 mr-4" /> - <label className="font-semibold text-xl my-2" htmlFor="bsi"> BSI Virtual Account</label> - </div> - {selectedPaymentMethod === "bsi" && ( - <input - type="number" - placeholder="Enter your BSI Account" - value={bankAccountNumber} - onChange={handleBankAccountChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - )} - </div> - - </div> - </div> - </div> - {isTopUpValid && ( - <div onClick={handleTopUpValid} className="cursor-pointer hover:bg-lightgreen text-sm mx-auto my-auto font-bold border-2 border-white text-white text-center items-center bg-darkgreen rounded-lg p-5 max-w-screen-sm"> - <button>TOP UP</button> - </div> - )} - </div> - </> - ); -}; - -export default TopUp; diff --git a/src/components/WalletManagement/TopUp/TopUp.tsx b/src/components/WalletManagement/TopUp/TopUp.tsx new file mode 100644 index 0000000..d34ed1b --- /dev/null +++ b/src/components/WalletManagement/TopUp/TopUp.tsx @@ -0,0 +1,158 @@ +import React, { useState } from "react"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { FaWallet } from 'react-icons/fa6'; +import TopUpSingle from "./TopUpSingle"; +import ButtonNumber from "../ButtonNumber"; +import BCA from '../../../assets/bca.png'; +import Mandiri from '../../../assets/mandiri.png'; +import BRI from '../../../assets/briva.png'; +import BNI from '../../../assets/bni.png'; +import BSI from '../../../assets/bsi.png'; + +const TopUp = () => { + const [balance, setBalance] = useState(1000); + const [topUpAmount, setTopUpAmount] = useState(0); + const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(''); + const [bankAccountNumber, setBankAccountNumber] = useState(''); + + const formatNumber = (value) => { + return Intl.NumberFormat().format(value); + }; + + const handleTopUp = (amount) => { + setTopUpAmount(amount); + setBalance((prevBalance) => prevBalance + amount); + }; + + const handlePaymentMethodChange = (event: React.ChangeEvent<HTMLInputElement>) => { + setSelectedPaymentMethod(event.target.value); + }; + + const handleBankAccountChange = (event: React.ChangeEvent<HTMLInputElement>) => { + setBankAccountNumber(event.target.value); + }; + + + const handleTopUpValid = () => { + if (isTopUpValid) { + if (Math.random() < 0.5) { + showToastSuccess(); + } else { + showToastFailure(); + } + } + }; + + const showToastSuccess = () => { + toast.success("Transaksi berhasil!"); + }; + const showToastFailure = () => { + toast.error("Transaksi gagal. Silakan coba lagi."); + }; + + const isTopUpValid = topUpAmount > 0 && bankAccountNumber.length === 10; + + return ( + <> + <ToastContainer /> + <div> + <div className="text-sm mx-auto my-auto font-semibold border-2 border-darkgreen rounded-lg flex items-center justify-start p-5 max-w-screen-2xl"> + <FaWallet className="mr-2" /> Current Balance: <span className="font-normal">350.000</span> + </div> + <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> + <h1 className="text-4xl font-semibold mb-2">Top-Up Amount:</h1> + + <div className="mb-4"> + <label> + <input + type="text" + value={formatNumber(topUpAmount)} + onChange={(e) => { + const inputValue = e.target.value.replace(/,/g, ''); + const newAmount = inputValue === "" ? 0 : parseInt(inputValue, 10); + setTopUpAmount(newAmount); + }} + className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" + placeholder="Enter amount" + /> + </label> + </div> + + <div className="md:space-y-0 space-y-2"> + <ButtonNumber amount={500000} onClickFunction={handleTopUp} /> + <ButtonNumber amount={1000000} onClickFunction={handleTopUp} /> + <ButtonNumber amount={2000000} onClickFunction={handleTopUp} /> + <ButtonNumber amount={2500000} onClickFunction={handleTopUp} /> + <ButtonNumber amount={5000000} onClickFunction={handleTopUp} /> + <ButtonNumber amount={10000000} onClickFunction={handleTopUp} /> + </div> + </div> + <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> + <div> + <h1 className="text-4xl font-semibold mb-2">Payment Method:</h1> + <div className="space-y-2"> + <TopUpSingle + id="bca" + logoSrc={BCA} + label="BCA Virtual Account" + paymentMethod="bca" + selectedPaymentMethod={selectedPaymentMethod} + handlePaymentMethodChange={handlePaymentMethodChange} + bankAccountNumber={bankAccountNumber} + handleBankAccountChange={handleBankAccountChange} + /> + <TopUpSingle + id="mandiri" + logoSrc={Mandiri} + label="Mandiri Virtual Account" + paymentMethod="mandiri" + selectedPaymentMethod={selectedPaymentMethod} + handlePaymentMethodChange={handlePaymentMethodChange} + bankAccountNumber={bankAccountNumber} + handleBankAccountChange={handleBankAccountChange} + /> + <TopUpSingle + id="bri" + logoSrc={BRI} + label="BRIVA" + paymentMethod="bri" + selectedPaymentMethod={selectedPaymentMethod} + handlePaymentMethodChange={handlePaymentMethodChange} + bankAccountNumber={bankAccountNumber} + handleBankAccountChange={handleBankAccountChange} + /> + <TopUpSingle + id="bni" + logoSrc={BNI} + label="BNI Virtual Account" + paymentMethod="bni" + selectedPaymentMethod={selectedPaymentMethod} + handlePaymentMethodChange={handlePaymentMethodChange} + bankAccountNumber={bankAccountNumber} + handleBankAccountChange={handleBankAccountChange} + /> + <TopUpSingle + id="bsi" + logoSrc={BSI} + label="BSI Mobile" + paymentMethod="bsi" + selectedPaymentMethod={selectedPaymentMethod} + handlePaymentMethodChange={handlePaymentMethodChange} + bankAccountNumber={bankAccountNumber} + handleBankAccountChange={handleBankAccountChange} + /> + </div> + </div> + </div> + {isTopUpValid && ( + <div onClick={handleTopUpValid} className="cursor-pointer hover:bg-lightgreen text-sm mx-auto my-auto font-bold border-2 border-white text-white text-center items-center bg-darkgreen rounded-lg p-5 max-w-screen-sm"> + <button>TOP UP</button> + </div> + )} + </div> + </> + ); +}; + +export default TopUp; diff --git a/src/components/WalletManagement/TopUp/TopUpSingle.tsx b/src/components/WalletManagement/TopUp/TopUpSingle.tsx new file mode 100644 index 0000000..89ec316 --- /dev/null +++ b/src/components/WalletManagement/TopUp/TopUpSingle.tsx @@ -0,0 +1,51 @@ +import React from 'react'; + +interface TopUpSingleProps { + id: string; + logoSrc: string; + label: string; + paymentMethod: string; + selectedPaymentMethod: string; + handlePaymentMethodChange: (event: React.ChangeEvent<HTMLInputElement>) => void; + bankAccountNumber: string; + handleBankAccountChange: (event: React.ChangeEvent<HTMLInputElement>) => void; +} + +const TopUpSingle: React.FC<TopUpSingleProps> = ({ + id, + logoSrc, + label, + paymentMethod, + selectedPaymentMethod, + handlePaymentMethodChange, + bankAccountNumber, + handleBankAccountChange, +}) => { + return ( + <div className="flex flex-col"> + <div className="flex flex-row items-center"> + <input + type="radio" + id={id} + name="paymentMethod" + value={paymentMethod} + checked={selectedPaymentMethod === paymentMethod} + onChange={handlePaymentMethodChange} + /> + <img src={logoSrc} alt={`${label} Logo`} className="w-16 h-auto m-2 mr-4" /> + <label className="font-semibold text-xl my-2" htmlFor={id}>{label}</label> + </div> + {selectedPaymentMethod === paymentMethod && ( + <input + type="number" + placeholder={`Enter your ${label} Account Number`} + value={bankAccountNumber} + onChange={handleBankAccountChange} + className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" + /> + )} + </div> + ); +}; + +export default TopUpSingle; diff --git a/src/components/WalletManagement/Transfer.tsx b/src/components/WalletManagement/Transfer.tsx deleted file mode 100644 index 9ad364c..0000000 --- a/src/components/WalletManagement/Transfer.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import QRCode from "qrcode.react"; -import React, { useState } from "react"; -import { ToastContainer, toast } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import { FaWallet } from 'react-icons/fa6'; -import Logo from '../../assets/logo-color.svg' - -const Transfer = () => { - const [balance, setBalance] = useState(1000); // Initial balance - const [transferAmount, setTransferAmount] = useState(0); - const [selectedPaymentMethod, setSelectedPaymentMethod] = useState("credit-card"); - const [iWaletNumber, setiWaletNumber] = useState(""); - const [transactionStatus, setTransactionStatus] = useState(""); // Transaksi berhasil atau gagal - const [receipt, setReceipt] = useState(""); // Receipt transaksi - const [senderName, setSenderName] = useState("John Doe"); // Nama pengirim - const [senderIwaletID, setSenderIwaletID] = useState("12345678"); // ID iwalet pengirim - const [receiverName, setReceiverName] = useState("Jane Smith"); // Nama penerima - const [receiverIwaletID, setReceiverIwaletID] = useState("87654321"); // ID iwalet penerima - const [transactionCode, setTransactionCode] = useState(""); // Hapus ini - const [receiptVisible, setReceiptVisible] = useState(false); - - const generateTransactionCode = () => { - const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - let code = ""; - for (let i = 0; i < 8; i++) { - const randomIndex = Math.floor(Math.random() * characters.length); - code += characters.charAt(randomIndex); - } - return code; - }; - - const trimReceiverName = (name) => { - const firstChar = name[0]; - const lastChar = name[name.length - 1]; - const stars = "*".repeat(name.length - 2); - return `${firstChar}${stars}${lastChar}`; - }; - - const showToastSuccess = () => { - toast.success("Transaksi berhasil!"); - }; - - const showToastFailure = () => { - toast.error("Transaksi gagal. Silakan coba lagi."); - }; - - - // Function to format input value with thousands separators - const formatNumber = (value) => { - return Intl.NumberFormat().format(value); - }; - - const handleTransfer = (amount) => { - // Update the input value and the balance when the user tops up - setTransferAmount(amount); - setBalance((prevBalance) => prevBalance + amount); - }; - - const handleiWaletChange = (event) => { - setiWaletNumber(event.target.value); - }; - - const handleTransferValid = () => { - if (isTransferValid) { - // Simulasikan transaksi dengan proses validasi sederhana - if (Math.random() < 0.5) { - showToastSuccess(); // Transaksi berhasil - setTransactionStatus("Transaksi berhasil"); - setReceipt(`${transferAmount}`); - setSenderIwaletID("12345678"); // ID iwalet pengirim - setReceiverIwaletID("87654321"); // ID iwalet penerima - setReceiverName(trimReceiverName(receiverName)); // Memangkas nama penerima - setTransactionCode(generateTransactionCode()); - setReceiptVisible(true); - } else { - showToastFailure(); // Transaksi gagal - setReceiptVisible(false); - } - } - }; - - const isTransferValid = transferAmount > 0 && iWaletNumber.length === 8; - - return ( - <> - <ToastContainer /> - <div> - <div className="text-sm mx-auto my-auto font-semibold border-2 border-darkgreen rounded-lg flex items-center justify-start p-5 max-w-screen-2xl"> - <FaWallet className="mr-2" /> Current Balance: <span className="font-normal">350.000</span> - </div> - <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> - <h1 className="text-4xl font-semibold mb-2">Transfer Amount:</h1> - - <div className="mb-4"> - <label> - <input - type="text" - value={formatNumber(transferAmount)} // Format the value with thousands separators - onChange={(e) => { - const inputValue = e.target.value.replace(/,/g, ''); - const newAmount = inputValue === "" ? 0 : parseInt(inputValue, 10); - setTransferAmount(newAmount); - }} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - placeholder="Enter amount" - /> - </label> - </div> - - <div className="md:space-y-0 space-y-2"> - <button onClick={() => handleTransfer(500000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-8 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 500rb - </button> - <button onClick={() => handleTransfer(1000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 1jt - </button> - <button onClick={() => handleTransfer(2000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 2jt - </button> - <button onClick={() => handleTransfer(2500000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 2.5jt - </button> - <button onClick={() => handleTransfer(5000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 5jt - </button> - <button onClick={() => handleTransfer(10000000)} className="bg-white border-2 border-borderoutline rounded-xl text-black px-4 py-1 rounded mr-2 focus:border-darkgreen focus:bg-lightgreen focus:bg-opacity-60 "> - 10jt - </button> - </div> - </div> - <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> - <div> - <h1 className="text-4xl font-semibold mb-2">Recipient Number:</h1> - <div className="space-y-2"> - <input - type="number" - placeholder="Enter Recepient iWalet Number" - value={iWaletNumber} - onChange={handleiWaletChange} - className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" - /> - </div> - </div> - </div> - {isTransferValid && ( - <div onClick={handleTransferValid} className="cursor-pointer hover:bg-lightgreen text-sm mx-auto my-auto font-bold border-2 border-white text-white text-center items-center bg-darkgreen rounded-lg p-5 max-w-screen-sm"> - <button >TRANSFER</button> - </div> - )} - <div className="text-center"> - {receiptVisible && ( - // RECEIPT - <div className="text-black p-4 rounded mt-4 receipt"> - <div className="flex h-screen w-full items-center justify-center"> - <div className="w-80 rounded bg-gray-50 px-6 pt-8 shadow-2xl shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]"> - <img src={Logo} alt="iWalet Logo" className="mx-auto w-16 py-2" /> - <div className="flex flex-col justify-center items-center gap-2"> - <h4 className="font-semibold">iWalet</h4> - <p className="text-xs">Jl. Ganesha No.10, Bandung, Jawa Barat</p> - </div> - <div className="flex flex-col gap-3 border-b py-6 text-xs"> - <p className="flex justify-between"> - <span className="text-gray-400">Transaction Code:</span> - <span>{transactionCode}</span> - </p> - <p className="flex justify-between"> - <span className="text-gray-400">Amount:</span> - <span>{receipt}</span> - </p> - <p className="flex justify-between"> - <span className="text-gray-400">Sender:</span> - <span>{senderName}</span> - </p> - <p className="flex justify-between"> - <span className="text-gray-400">Sender ID:</span> - <span>{senderIwaletID}</span> - </p> - </div> - <div className="flex flex-col gap-3 pb-6 pt-2 text-xs"> - <p className="flex justify-between"> - <span className="text-gray-400">Receiver:</span> - <span>{receiverName}</span> - </p> - <p className="flex justify-between"> - <span className="text-gray-400">Receiver ID:</span> - <span>{receiverIwaletID}</span> - </p> - <div className=" border-b border border-dashed"></div> - <br/> - <div className="flex items-center justify-center"> - <QRCode value={transactionCode} /> - </div> - <div className="py-4 justify-center items-center flex flex-col gap-2"> - <p className="flex gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M21.3 12.23h-3.48c-.98 0-1.85.54-2.29 1.42l-.84 1.66c-.2.4-.6.65-1.04.65h-3.28c-.31 0-.75-.07-1.04-.65l-.84-1.65a2.567 2.567 0 0 0-2.29-1.42H2.7c-.39 0-.7.31-.7.7v3.26C2 19.83 4.18 22 7.82 22h8.38c3.43 0 5.54-1.88 5.8-5.22v-3.85c0-.38-.31-.7-.7-.7ZM12.75 2c0-.41-.34-.75-.75-.75s-.75.34-.75.75v2h1.5V2Z" fill="#000"></path><path d="M22 9.81v1.04a2.06 2.06 0 0 0-.7-.12h-3.48c-1.55 0-2.94.86-3.63 2.24l-.75 1.48h-2.86l-.75-1.47a4.026 4.026 0 0 0-3.63-2.25H2.7c-.24 0-.48.04-.7.12V9.81C2 6.17 4.17 4 7.81 4h3.44v3.19l-.72-.72a.754.754 0 0 0-1.06 0c-.29.29-.29.77 0 1.06l2 2c.01.01.02.01.02.02a.753.753 0 0 0 .51.2c.1 0 .19-.02.28-.06.09-.03.18-.09.25-.16l2-2c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-.72.72V4h3.44C19.83 4 22 6.17 22 9.81Z" fill="#000"></path></svg> iWalet@shemale.com</p> - <p className="flex gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"><path fill="#000" d="M11.05 14.95L9.2 16.8c-.39.39-1.01.39-1.41.01-.11-.11-.22-.21-.33-.32a28.414 28.414 0 01-2.79-3.27c-.82-1.14-1.48-2.28-1.96-3.41C2.24 8.67 2 7.58 2 6.54c0-.68.12-1.33.36-1.93.24-.61.62-1.17 1.15-1.67C4.15 2.31 4.85 2 5.59 2c.28 0 .56.06.81.18.26.12.49.3.67.56l2.32 3.27c.18.25.31.48.4.7.09.21.14.42.14.61 0 .24-.07.48-.21.71-.13.23-.32.47-.56.71l-.76.79c-.11.11-.16.24-.16.4 0 .08.01.15.03.23.03.08.06.14.08.2.18.33.49.76.93 1.28.45.52.93 1.05 1.45 1.58.1.1.21.2.31.3.4.39.41 1.03.01 1.43zM21.97 18.33a2.54 2.54 0 01-.25 1.09c-.17.36-.39.7-.68 1.02-.49.54-1.03.93-1.64 1.18-.01 0-.02.01-.03.01-.59.24-1.23.37-1.92.37-1.02 0-2.11-.24-3.26-.73s-2.3-1.15-3.44-1.98c-.39-.29-.78-.58-1.15-.89l3.27-3.27c.28.21.53.37.74.48.05.02.11.05.18.08.08.03.16.04.25.04.17 0 .3-.06.41-.17l.76-.75c.25-.25.49-.44.72-.56.23-.14.46-.21.71-.21.19 0 .39.04.61.13.22.09.45.22.7.39l3.31 2.35c.26.18.44.39.55.64.1.25.16.5.16.78z"></path></svg> +62666XXXXX666</p> - </div> - </div> - </div> - </div> - </div> - )} - </div> - </div> - </> - ); -}; - -export default Transfer; diff --git a/src/components/WalletManagement/Transfer/ReceiptSingle.tsx b/src/components/WalletManagement/Transfer/ReceiptSingle.tsx new file mode 100644 index 0000000..4daf572 --- /dev/null +++ b/src/components/WalletManagement/Transfer/ReceiptSingle.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import QRCode from "qrcode.react"; + +interface ReceiptSingleProps { + LogoSrc: string, + transactionCode: string; + receipt: string; + senderName: string; + senderIwaletID: string; + receiverName: string; + receiverIwaletID: string; +} + +const ReceiptSingle: React.FC<ReceiptSingleProps> = ({ + LogoSrc, + transactionCode, + receipt, + senderName, + senderIwaletID, + receiverName, + receiverIwaletID, +}) => { + return ( + <div className="text-black p-4 rounded mt-4"> + <div className="flex h-screen w-full items-center justify-center"> + <div className="w-80 rounded bg-gray-50 px-6 pt-8 shadow-2xl shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]"> + <img src={LogoSrc} alt="iWalet LogoSrc" className="mx-auto w-16 py-2" /> + <div className="flex flex-col justify-center items-center gap-2"> + <h4 className="font-semibold">iWalet</h4> + <p className="text-xs">Jl. Ganesha No.10, Bandung, Jawa Barat</p> + </div> + <div className="flex flex-col gap-3 border-b py-6 text-xs"> + <p className="flex justify-between"> + <span className="text-gray-400">Transaction Code:</span> + <span>{transactionCode}</span> + </p> + <p className="flex justify-between"> + <span className="text-gray-400">Amount:</span> + <span>{receipt}</span> + </p> + <p className="flex justify-between"> + <span className="text-gray-400">Sender:</span> + <span>{senderName}</span> + </p> + <p className="flex justify-between"> + <span className="text-gray-400">Sender ID:</span> + <span>{senderIwaletID}</span> + </p> + </div> + <div className="flex flex-col gap-3 pb-6 pt-2 text-xs"> + <p className="flex justify-between"> + <span className="text-gray-400">Receiver:</span> + <span>{receiverName}</span> + </p> + <p className="flex justify-between"> + <span className="text-gray-400">Receiver ID:</span> + <span>{receiverIwaletID}</span> + </p> + <div className=" border-b border border-dashed"></div> + <br/> + <div className="flex items-center justify-center"> + <QRCode value={transactionCode} /> + </div> + <div className="py-4 justify-center items-center flex flex-col gap-2"> + <p className="flex gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M21.3 12.23h-3.48c-.98 0-1.85.54-2.29 1.42l-.84 1.66c-.2.4-.6.65-1.04.65h-3.28c-.31 0-.75-.07-1.04-.65l-.84-1.65a2.567 2.567 0 0 0-2.29-1.42H2.7c-.39 0-.7.31-.7.7v3.26C2 19.83 4.18 22 7.82 22h8.38c3.43 0 5.54-1.88 5.8-5.22v-3.85c0-.38-.31-.7-.7-.7ZM12.75 2c0-.41-.34-.75-.75-.75s-.75.34-.75.75v2h1.5V2Z" fill="#000"></path><path d="M22 9.81v1.04a2.06 2.06 0 0 0-.7-.12h-3.48c-1.55 0-2.94.86-3.63 2.24l-.75 1.48h-2.86l-.75-1.47a4.026 4.026 0 0 0-3.63-2.25H2.7c-.24 0-.48.04-.7.12V9.81C2 6.17 4.17 4 7.81 4h3.44v3.19l-.72-.72a.754.754 0 0 0-1.06 0c-.29.29-.29.77 0 1.06l2 2c.01.01.02.01.02.02a.753.753 0 0 0 .51.2c.1 0 .19-.02.28-.06.09-.03.18-.09.25-.16l2-2c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-.72.72V4h3.44C19.83 4 22 6.17 22 9.81Z" fill="#000"></path></svg> iWalet@shemale.com</p> + <p className="flex gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"><path fill="#000" d="M11.05 14.95L9.2 16.8c-.39.39-1.01.39-1.41.01-.11-.11-.22-.21-.33-.32a28.414 28.414 0 01-2.79-3.27c-.82-1.14-1.48-2.28-1.96-3.41C2.24 8.67 2 7.58 2 6.54c0-.68.12-1.33.36-1.93.24-.61.62-1.17 1.15-1.67C4.15 2.31 4.85 2 5.59 2c.28 0 .56.06.81.18.26.12.49.3.67.56l2.32 3.27c.18.25.31.48.4.7.09.21.14.42.14.61 0 .24-.07.48-.21.71-.13.23-.32.47-.56.71l-.76.79c-.11.11-.16.24-.16.4 0 .08.01.15.03.23.03.08.06.14.08.2.18.33.49.76.93 1.28.45.52.93 1.05 1.45 1.58.1.1.21.2.31.3.4.39.41 1.03.01 1.43zM21.97 18.33a2.54 2.54 0 01-.25 1.09c-.17.36-.39.7-.68 1.02-.49.54-1.03.93-1.64 1.18-.01 0-.02.01-.03.01-.59.24-1.23.37-1.92.37-1.02 0-2.11-.24-3.26-.73s-2.3-1.15-3.44-1.98c-.39-.29-.78-.58-1.15-.89l3.27-3.27c.28.21.53.37.74.48.05.02.11.05.18.08.08.03.16.04.25.04.17 0 .3-.06.41-.17l.76-.75c.25-.25.49-.44.72-.56.23-.14.46-.21.71-.21.19 0 .39.04.61.13.22.09.45.22.7.39l3.31 2.35c.26.18.44.39.55.64.1.25.16.5.16.78z"></path></svg> +62666XXXXX666</p> + </div> + </div> + </div> + </div> + </div> + ); +}; + +export default ReceiptSingle; diff --git a/src/components/WalletManagement/Transfer/Transfer.tsx b/src/components/WalletManagement/Transfer/Transfer.tsx new file mode 100644 index 0000000..3f46fab --- /dev/null +++ b/src/components/WalletManagement/Transfer/Transfer.tsx @@ -0,0 +1,154 @@ +import React, { useState } from "react"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { FaWallet } from 'react-icons/fa6'; +import Logo from '../../../assets/logo-color.svg' +import ButtonNumber from "../ButtonNumber"; +import ReceiptSingle from "./ReceiptSingle"; + +const Transfer = () => { + const [balance, setBalance] = useState(1000); + const [transferAmount, setTransferAmount] = useState(0); + const [selectedPaymentMethod, setSelectedPaymentMethod] = useState("credit-card"); + const [iWaletNumber, setiWaletNumber] = useState(""); + const [transactionStatus, setTransactionStatus] = useState(""); + const [receipt, setReceipt] = useState(""); + const [senderName, setSenderName] = useState("John Doe"); + const [senderIwaletID, setSenderIwaletID] = useState("12345678"); + const [receiverName, setReceiverName] = useState("Jane Smith"); + const [receiverIwaletID, setReceiverIwaletID] = useState("87654321"); + const [transactionCode, setTransactionCode] = useState(""); + const [receiptVisible, setReceiptVisible] = useState(false); + + const generateTransactionCode = () => { + const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + let code = ""; + for (let i = 0; i < 8; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + code += characters.charAt(randomIndex); + } + return code; + }; + + const trimReceiverName = (name) => { + const firstChar = name[0]; + const lastChar = name[name.length - 1]; + const stars = "*".repeat(name.length - 2); + return `${firstChar}${stars}${lastChar}`; + }; + + const showToastSuccess = () => { + toast.success("Transaksi berhasil!"); + }; + + const showToastFailure = () => { + toast.error("Transaksi gagal. Silakan coba lagi."); + }; + + const formatNumber = (value) => { + return Intl.NumberFormat().format(value); + }; + + const handleTransfer = (amount) => { + setTransferAmount(amount); + setBalance((prevBalance) => prevBalance + amount); + }; + + const handleiWaletChange = (event) => { + setiWaletNumber(event.target.value); + }; + + const handleTransferValid = () => { + if (isTransferValid) { + if (Math.random() < 0.5) { + showToastSuccess(); + setTransactionStatus("Transaksi berhasil"); + setReceipt(`${transferAmount}`); + setSenderIwaletID("12345678"); + setReceiverIwaletID("87654321"); + setReceiverName(trimReceiverName(receiverName)); + setTransactionCode(generateTransactionCode()); + setReceiptVisible(true); + } else { + showToastFailure(); + setReceiptVisible(false); + } + } + }; + + const isTransferValid = transferAmount > 0 && iWaletNumber.length === 8; + + return ( + <> + <ToastContainer /> + <div> + <div className="text-sm mx-auto my-auto font-semibold border-2 border-darkgreen rounded-lg flex items-center justify-start p-5 max-w-screen-2xl"> + <FaWallet className="mr-2" /> Current Balance: <span className="font-normal">350.000</span> + </div> + <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> + <h1 className="text-4xl font-semibold mb-2">Transfer Amount:</h1> + + <div className="mb-4"> + <label> + <input + type="text" + value={formatNumber(transferAmount)} // Format the value with thousands separators + onChange={(e) => { + const inputValue = e.target.value.replace(/,/g, ''); + const newAmount = inputValue === "" ? 0 : parseInt(inputValue, 10); + setTransferAmount(newAmount); + }} + className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" + placeholder="Enter amount" + /> + </label> + </div> + + <div className="md:space-y-0 space-y-2"> + <ButtonNumber amount={500000} onClickFunction={handleTransfer} /> + <ButtonNumber amount={1000000} onClickFunction={handleTransfer} /> + <ButtonNumber amount={2000000} onClickFunction={handleTransfer} /> + <ButtonNumber amount={2500000} onClickFunction={handleTransfer} /> + <ButtonNumber amount={5000000} onClickFunction={handleTransfer} /> + <ButtonNumber amount={10000000} onClickFunction={handleTransfer} /> + </div> + </div> + <div className=" flex wrap md:flex-col flex-col my-0 mx-auto p-5 max-w-screen-2xl"> + <div> + <h1 className="text-4xl font-semibold mb-2">Recipient Number:</h1> + <div className="space-y-2"> + <input + type="number" + placeholder="Enter Recepient iWalet Number" + value={iWaletNumber} + onChange={handleiWaletChange} + className="w-full p-2 border rounded outline-none focus:border-none focus:shadow-[0px_4px_16px_rgba(29,185,84,0.1),_0px_8px_24px_rgba(29,185,84,0.1),_0px_16px_56px_rgba(29,185,84,0.1)]" + /> + </div> + </div> + </div> + {isTransferValid && ( + <div onClick={handleTransferValid} className="cursor-pointer hover:bg-lightgreen text-sm mx-auto my-auto font-bold border-2 border-white text-white text-center items-center bg-darkgreen rounded-lg p-5 max-w-screen-sm"> + <button >TRANSFER</button> + </div> + )} + <div className="text-center"> + {receiptVisible && ( + // RECEIPT + <ReceiptSingle + LogoSrc={Logo} + transactionCode={transactionCode} + receipt={receipt} + senderName={senderName} + senderIwaletID={senderIwaletID} + receiverName={receiverName} + receiverIwaletID={receiverIwaletID} + /> + )} + </div> + </div> + </> + ); +}; + +export default Transfer; diff --git a/src/pages/History/HistoryPage.tsx b/src/pages/History/HistoryPage.tsx index e67bfab..578eb9e 100644 --- a/src/pages/History/HistoryPage.tsx +++ b/src/pages/History/HistoryPage.tsx @@ -6,7 +6,7 @@ import Navbar from "../../components/Navigation/Navbar"; import { useNavigate } from "react-router-dom"; import SubscriptionRequest from "@/components/SubscriptionRequest/SubscriptionRequest"; -import History from "@/components/WalletManagement/History"; +import History from "@/components/WalletManagement/History/History"; interface InterfaceLink { icon: ReactNode; diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 1eaf025..757b6e0 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -7,7 +7,7 @@ import Navbar from "../../components/Navigation/Navbar"; import { useNavigate } from "react-router-dom"; import SubscriptionRequest from "@/components/SubscriptionRequest/SubscriptionRequest"; // import Transfer from "@/components/WalletManagement/Transfer"; -import TopUp from "@/components/WalletManagement/TopUp"; +import TopUp from "@/components/WalletManagement/TopUp/TopUp"; interface InterfaceLink { icon: ReactNode; @@ -49,6 +49,18 @@ const Home = () => { text: "Transfer", url: "/transfer", }, + { + icon: ( + <> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> + <path + fill="#ffffff" + d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg> + </> + ), + text: "History", + url: "/history", + }, { icon: ( <> diff --git a/src/pages/TopUp/TopUpPage.tsx b/src/pages/TopUp/TopUpPage.tsx index 7c0234b..b84c023 100644 --- a/src/pages/TopUp/TopUpPage.tsx +++ b/src/pages/TopUp/TopUpPage.tsx @@ -6,7 +6,7 @@ import Navbar from "../../components/Navigation/Navbar"; import { useNavigate } from "react-router-dom"; import SubscriptionRequest from "@/components/SubscriptionRequest/SubscriptionRequest"; -import TopUp from "@/components/WalletManagement/TopUp"; +import TopUp from "@/components/WalletManagement/TopUp/TopUp"; interface InterfaceLink { icon: ReactNode; diff --git a/src/pages/Transfer/TransferPage.tsx b/src/pages/Transfer/TransferPage.tsx index 037393e..5abcebb 100644 --- a/src/pages/Transfer/TransferPage.tsx +++ b/src/pages/Transfer/TransferPage.tsx @@ -6,7 +6,7 @@ import Navbar from "../../components/Navigation/Navbar"; import { useNavigate } from "react-router-dom"; import SubscriptionRequest from "@/components/SubscriptionRequest/SubscriptionRequest"; -import Transfer from "@/components/WalletManagement/Transfer"; +import Transfer from "@/components/WalletManagement/Transfer/Transfer"; interface InterfaceLink { icon: ReactNode; -- GitLab