Skip to content

Commit

Permalink
Merge pull request #131 from Tekum-Emmanuella/Implement-the-frontend-…
Browse files Browse the repository at this point in the history
…page-for-recipient's-data-input-using-PPA-#26

Implement the frontend page for recipient's data input using ppa #26
  • Loading branch information
Motouom authored Jun 12, 2024
2 parents 8314af3 + d36a452 commit df6551c
Show file tree
Hide file tree
Showing 9 changed files with 761 additions and 403 deletions.
907 changes: 508 additions & 399 deletions power-pay-frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions power-pay-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"preview": "vite preview"
},
"dependencies": {
"@yudiel/react-qr-scanner": "^2.0.0-beta.3",
"axios": "^1.6.8",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0",
Expand Down
69 changes: 69 additions & 0 deletions power-pay-frontend/src/components/RecipientInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { useFormik } from 'formik';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faMoneyBill } from '@fortawesome/free-solid-svg-icons';
import { faPhone } from '@fortawesome/free-solid-svg-icons';
interface FormValues {
phone: string;
amount: string;
}

const RecipientInfo: React.FC = () => {
const formik = useFormik<FormValues>({
initialValues: {
phone: '',
amount: ''
},
onSubmit: (values) => {
// Handle form submission
console.log(values);
}
});

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
// Allow only numbers in the input fields
const newValue = value.replace(/[^\d]/g, '');
formik.setFieldValue(name, newValue);
};

return (
<div className="flex flex-col items-center justify-center h-screen bg-800 text-black text-sm">
<form onSubmit={formik.handleSubmit} className="max-w-sm mx-auto w-80 mb-12">
<div className="flex pb-4 flex-col items-center">
<div className="input-group">
<input
type="text"
id="phone"
name="phone"
placeholder='Phone Number'
onChange={handleChange}
value={formik.values.phone}
style={{ color: 'black' }}
className="text-lg px-12 rounded-full w-80 p-2.5 bg-red-50 dark:placeholder-gray-400 dark:text-black required"
/>
<FontAwesomeIcon icon={faPhone} size="1x" className="absolute text-red-500 left-10 top-1/2 transform -translate-y-1/2 color-red-100" />
</div>
</div>
<div className="flex flex-col items-center">
<div className="input-group">
<input
type="text"
id="amount"
name="amount"
placeholder="Amount"
onChange={handleChange}
value={formik.values.amount}
className="text-lg px-12 rounded-full w-80 p-2.5 bg-red-50 dark:placeholder-gray-400 dark:text-black required"
/>
<FontAwesomeIcon icon={faMoneyBill} size="1x" className="absolute text-red-500 left-2 top-1/2 transform -translate-y-1/2 color-red-100" />
</div>
</div>
<button type="submit" className="rounded-full bg-blue-950 hover:bg-blue-950 w-80 m-auto px-4 py-2 text-white text-lg absolute inset-x-0 bottom-12">Submit</button>
</form>
</div>
);
}

export default RecipientInfo;
63 changes: 63 additions & 0 deletions power-pay-frontend/src/components/fake_api.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useState } from 'react';
import axios from 'axios';

const FakeApi: React.FC = () => {
const baseURL = 'http://localhost:5000';
const api = axios.create({
baseURL,
timeout: 5000,
});

const [recipientPhoneNumber, setRecipientPhoneNumber] = useState('');
const [amount, setAmount] = useState('');
const [errorMessage, setErrorMessage] = useState('');

const mockSend_MoneyAPI = async (
recipientPhoneNumber: string,
amount: number
) => {
try {
if (!recipientPhoneNumber || !amount) {
setErrorMessage("Please fill in all fields");
} else {
console.log("Transaction Successful");
console.log("Recipient Phone Number:", recipientPhoneNumber);
console.log("Amount:", amount);
setErrorMessage('');
await api.post('/UserInfo', {
recipientPhoneNumber,
amount
});
}
} catch (error) {
setErrorMessage("An error occurred while processing the transaction.");
console.error("Error:", error);
}
}

const handleSendMoney = () => {
mockSend_MoneyAPI(recipientPhoneNumber, parseInt(amount));
}

return (
<div>
<p>FAKED API</p>
<input
type="text"
value={recipientPhoneNumber}
onChange={(e) => setRecipientPhoneNumber(e.target.value)}
placeholder="Recipient Phone Number"
/>
<input
type="text"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Amount"
/>
<button onClick={handleSendMoney}>Send Money</button>
{errorMessage && <p>{errorMessage}</p>}
</div>
);
};

export default FakeApi;
46 changes: 46 additions & 0 deletions power-pay-frontend/src/components/paymentoption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useState } from 'react';
import QRScannerComponent from './scan_rq';
import RecipientInfo from './RecipientInfo'; // Import the RecipientInfo component
import { Link } from "react-router-dom";

const PaymentOptions: React.FC = () => {
const [showQRScanner, setShowQRScanner] = useState<boolean>(false);
const [showInputManually, setShowInputManually] = useState<boolean>(false);

const handleScanQRClick = () => {
setShowQRScanner(true);
setShowInputManually(false); // Close InputManuallyComponent if open
};

const handleInputManuallyClick = () => {
setShowInputManually(true);
setShowQRScanner(false); // Close QRScannerComponent if open
};

return (
<div className="container">
<div className="bg-gray-100 absolute inset-x-6 top-12 h-40 rounded-lg">
<h5 className="h-auto text-center pt-9 mb-2 text-2xl font-bold tracking-tight text-black">Payment Option.</h5>
<h5 className="text-center pt-9 mb-2 text-black">Choose the option you wish to pay</h5>
</div>
<div className="pt-12">
<Link to={`RecipientInfo`}>
<button onClick={handleInputManuallyClick} className='bg-blue-950 rounded-full w-80 m-auto px-4 text-white text-lg absolute inset-x-0 mb-20 bottom-12'>Input Manually</button>
<br></br>
</Link>
<div className="pt-12">
<Link to={`QRScannerComponent`}>
<button onClick={handleScanQRClick} className="bg-blue-950 rounded-full w-80 m-auto px-4 text-white text-lg absolute inset-x-0 bottom-12"
type='button'>
QR Scan
</button>
</Link>
</div>
</div>
{showQRScanner && <QRScannerComponent />}
{showInputManually && <RecipientInfo />} {/* Render RecipientInfo component when showInputManually is true */}
</div>
);
};

export default PaymentOptions
23 changes: 23 additions & 0 deletions power-pay-frontend/src/components/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
createBrowserRouter
} from "react-router-dom"
;
import PaymentOptions from "./paymentoption";
import RecipientInfo from "./RecipientInfo";
import QRScannerComponent
from "./scan_rq";
const router = createBrowserRouter([
{
path: "/",
element: <PaymentOptions/>,
},
{
path: "/RecipientInfo",
element: <RecipientInfo.tsx/>,
},
{
path: "/qRScannerComponent",
element: <QRScannerComponent/>,
}
]);
export default router;
45 changes: 45 additions & 0 deletions power-pay-frontend/src/components/scan_rq.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useEffect, useRef as ref } from 'react';
import { Scanner as S } from '@yudiel/react-qr-scanner'; // Importing Scanner from @yudiel/react-qr-scanner
const Scanner: any = S;


const QRScannerComponent = () => {

const qrScannerRef = ref<any>(null);
useEffect(() => {
if (qrScannerRef.current) {
qrScannerRef.current.start();
}

return () => {
if (qrScannerRef.current) {
qrScannerRef.current.stop();
}
};
}, []);

const handleScan = (data: string | null) => {
if (data) {
console.log('Scanned data:', data);
}
};

const handleError = (err: any) => {
console.error('QR scanner error:', err);
};

return (
<div>
<Scanner
ref={qrScannerRef}
on={handleScan}
onError={handleError}
facingMode="environment"
style={{ width: '100%', height: 'auto' }}
/>
<button onClick={() => qrScannerRef.current?.start()} className="bg-blue-950 rounded-full w-80 m-auto px-4 text-white text-lg absolute p-2.5 inset-x-0 bottom-12">Start Scan</button>
</div>
);
};

export default QRScannerComponent;
8 changes: 4 additions & 4 deletions power-pay-frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
Expand Down
1 change: 1 addition & 0 deletions power-pay-frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"lib": ["ES2020", "DOM", "DOM.Iterable", "webworker"],
"module": "ESNext",
"skipLibCheck": true,
"noImplicitUseStrict": false,

/* Bundler mode */
"moduleResolution": "bundler",
Expand Down

0 comments on commit df6551c

Please sign in to comment.