Files
CBS-Mobile-App/src/modules/payments/hooks/useTransferForm.ts
T

70 lines
2.3 KiB
TypeScript

import { useMemo, useState } from 'react';
import { useAccountSelection } from '../../home/hooks/useAccounts';
/**
* The half of a transfer form that is the same whichever way the money is
* addressed: which account it leaves, how much, and the note against it.
*
* The account list is read from `GET /accounts` on every mount — never from
* Redux, and never carried in from the previous screen.
*
* There is no balance check here, and that is not an omission. No endpoint in
* the CBS API returns a balance, so the app has nothing to compare an amount
* against; inventing a limit would be worse than having none, because a
* customer refused by the app has no way to find out they were refused
* wrongly. The bank rejects an overdrawn transfer on submission, and that
* refusal is the authoritative one.
*/
export const useTransferForm = () => {
const { accounts, selectedAccountNumber, setSelectedAccountNumber, selectedAccount, isLoading, refetch } =
useAccountSelection();
const [amount, setAmount] = useState('');
const [remarks, setRemarks] = useState('');
/** Grouping separators are allowed in, but never reach the parsed value. */
const parsedAmount = useMemo(() => Number.parseFloat(amount.replace(/,/g, '')), [amount]);
const amountError = useMemo(() => {
if (amount.length === 0) {
return undefined;
}
if (Number.isNaN(parsedAmount) || parsedAmount <= 0) {
return 'Enter a valid amount';
}
return undefined;
}, [amount, parsedAmount]);
const amountValid = !amountError && parsedAmount > 0;
const handleAmountChange = (value: string) => {
// One decimal point, digits either side, at most two paise. Filtering on
// the way in beats validating after the fact: the field cannot hold
// something the parser would then have to reject.
const cleaned = value.replace(/[^0-9.]/g, '');
const [rupees = '', ...rest] = cleaned.split('.');
const paise = rest.join('').slice(0, 2);
setAmount(rest.length ? `${rupees}.${paise}` : rupees);
};
return {
accounts,
selectedAccount,
sourceAccountNumber: selectedAccountNumber,
setSourceAccountNumber: setSelectedAccountNumber,
accountsLoading: isLoading,
refetchAccounts: refetch,
amount,
handleAmountChange,
parsedAmount,
amountError,
amountValid,
remarks,
setRemarks,
};
};