37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import { MaskedInput } from "./Input";
|
|
|
|
export type PreMaskedProps = Omit<React.ComponentPropsWithoutRef<typeof MaskedInput>, "mask" | "definitions">
|
|
|
|
export function IbanInput(props: PreMaskedProps) {
|
|
return <MaskedInput {...props}
|
|
mask="XXXX XXXX XXXX XXXX [XXXX] [XXXX] [XXXX] [XX]"
|
|
definitions={{ 'X': /[0-9A-Z]/ }}
|
|
prepare={(str: string) => str.toUpperCase()}
|
|
validate={(iban: string) => {
|
|
console.log(iban);
|
|
|
|
if (iban.length < 15 || iban.length > 34)
|
|
return "Invalid length";
|
|
|
|
// Rearranged IBAN
|
|
const rearranged = iban.slice(4) + iban.slice(0, 4);
|
|
|
|
// Convert letters to numbers (A=10 ... Z=35)
|
|
const converted = rearranged.replace(/[A-Z]/g, ch => (ch.charCodeAt(0) - 55).toString());
|
|
|
|
// Perform mod-97 check
|
|
let remainder = converted;
|
|
let block;
|
|
|
|
while (remainder.length > 2) {
|
|
block = remainder.slice(0, 9);
|
|
remainder = (parseInt(block, 10) % 97).toString() + remainder.slice(block.length);
|
|
}
|
|
|
|
if (parseInt(remainder, 10) % 97 !== 1)
|
|
return "Invalid checksum";
|
|
|
|
return null;
|
|
}}
|
|
/>
|
|
} |