diff --git a/bank-app/backend/main.py b/bank-app/backend/main.py index 29e86f1..48ca0ff 100644 --- a/bank-app/backend/main.py +++ b/bank-app/backend/main.py @@ -217,6 +217,18 @@ def get_account_id( return account +@app.get("/accounts/by-email/{email}") +def get_account_by_email(email: str, db: Session = Depends(get_db)): + accounts = db.query(Account).join(User).filter(User.email == email).all() + + if accounts is None: + raise HTTPException(status_code=404, detail="Recipient not found") + + return [ + {"account_id": acc.id, "account_type": acc.account_type} for acc in accounts + ] + + # IMPLEMENT TO ACCOUNTCARD @app.put("/accounts/{id}", response_model=AccountResponse) def update_account( @@ -335,7 +347,11 @@ def transfer_transaction( to_account = db.query(Account).filter(Account.id == transaction.to_account).first() return transfer( - db, from_account, to_account, transaction.amount, transaction.idempotency_key + db, + from_account.id, + to_account.id, + transaction.amount, + transaction.idempotency_key, ) diff --git a/bank-app/frontend/src/components/AccountCard.jsx b/bank-app/frontend/src/components/AccountCard.jsx index f24f181..bbdad44 100644 --- a/bank-app/frontend/src/components/AccountCard.jsx +++ b/bank-app/frontend/src/components/AccountCard.jsx @@ -4,14 +4,18 @@ import { authFetch } from "../utils/authFetch"; import TransactionList from "./TransactionList"; import { API_URL } from "../config"; -function AccountCard({ account, onDelete, onEdit, onDeposit, onWithdrawal}) { +function AccountCard({ account, onDelete, onEdit, onDeposit, onWithdrawal, onTransfer}) { const [editing, setEditing] = useState(false); const [ownerName, setOwnerName] = useState(account.owner_name); const [accountType, setAccountType] = useState(account.account_type); - + const [recipientAccounts, setRecipientAccounts] = useState([]); + const [selectedAccount, setSelectedAccount] = useState(""); + const [toEmail, setToEmail] = useState("") + const [amount, setAmount] = useState(""); const [showTransactions, setShowTransactions] = useState(false); + const [showTransfer, setShowTransfer] = useState(false); //above -> only use const [..., ...] = useState() when user is interacting with it (input fields, dropdowns checkboxes, temporary UI changes) // DO NOT USE IT when the backend owns it (e.g account.frozen, account.balance, account.account_type) @@ -88,6 +92,62 @@ function AccountCard({ account, onDelete, onEdit, onDeposit, onWithdrawal}) { } }; + const handleTransfer = async () => { //E-Transfer -> SHOW ACCOUNT'S USER NAMES INSTEAD OF account_type + try { + const idempotencyKey = crypto.randomUUID() + + const response = await authFetch( + `${API_URL}/accounts/${account.id}/transfer`, { + method : "PATCH", + headers : { + "Content-Type" : "application/json" + }, + body: JSON.stringify({ + from_account: account.id, + to_account: selectedAccount, + amount: Number(amount), + idempotency_key: idempotencyKey + }), + } + ); + + if (!response.ok) { + throw new Error("Transaction Failed"); + } + + const transactions = await response.json(); + + onTransfer(transactions); + setRecipientAccounts([]); + setSelectedAccount(""); + setAmount(""); + setShowTransfer(false); + + } catch (error) { + alert("Transaction Failed. Try again"); + console.error("TRANSFER ERROR:", error); + } + }; + + const findRecipient = async () => { + try { + const response = await authFetch( + `${API_URL}/accounts/by-email/${encodeURIComponent(toEmail)}` + ); + + if (!response.ok) { + throw new Error("Recipient not found"); + } + + const accounts = await response.json(); + + setRecipientAccounts(accounts); + } catch (error) { + alert("Recipient not found"); + console.error(error); + } + }; + //toggle button so that if your account is frozen then you can only unfreeze it vice versa const handleFreeze = async () => { try { @@ -224,6 +284,59 @@ function AccountCard({ account, onDelete, onEdit, onDeposit, onWithdrawal}) { + + {showTransfer && ( // show this if showTransfer is true (when "E-transfer is pressed") + <> + setToEmail(e.target.value)} + /> + + + > + )} + + {recipientAccounts.length > 0 && ( + + )} + + {showTransfer && ( + setAmount(e.target.value)} + + /> + )} + + + + {showTransfer && ( + + )} diff --git a/bank-app/frontend/src/components/AccountList.jsx b/bank-app/frontend/src/components/AccountList.jsx index 2c27516..d7a1452 100644 --- a/bank-app/frontend/src/components/AccountList.jsx +++ b/bank-app/frontend/src/components/AccountList.jsx @@ -71,6 +71,24 @@ function AccountList() { ); }; + const handleTransfer = (transactions) => { + setAccounts(prevAccounts => + prevAccounts.map(acc => { + const transaction = transactions.find( + transaction => transaction.account_id === acc.id + ); + + return transaction + ? { + ...acc, + balance: transaction.balance_after + } + : acc; + }) + ); + }; + + return (