60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { useState } from "react";
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
const IbanInput = ({ onValidIban }: { onValidIban?: (iban: string) => void }) => {
|
|
const [iban, setIban] = useState("");
|
|
const [error, setError] = useState("");
|
|
|
|
const formatIban = (value: string) => {
|
|
const alphanumeric = value.replace(/[^a-zA-Z0-9]/g, "").toUpperCase();
|
|
const formatted = alphanumeric.replace(/(.{4})/g, "$1 ").trim();
|
|
return formatted;
|
|
};
|
|
|
|
const validateIban = (rawIban: string) => {
|
|
// IBAN Validierung nach Mod-97-10 Regel
|
|
const rearranged = rawIban.slice(4) + rawIban.slice(0, 4);
|
|
const converted = rearranged.replace(/[A-Z]/g, (char) => (char.charCodeAt(0) - 55).toString());
|
|
const mod97 = BigInt(converted) % 97n;
|
|
return mod97 === 1n;
|
|
};
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const input = e.target.value;
|
|
if (input.length <= 27) {
|
|
setIban(formatIban(input));
|
|
setError(""); // Fehler zurücksetzen während der Eingabe
|
|
}
|
|
};
|
|
|
|
const handleBlur = () => {
|
|
const rawIban = iban.replace(/\s/g, ""); // Leerzeichen entfernen
|
|
if (rawIban.length >= 15) { // Minimum Länge einer IBAN
|
|
if (!validateIban(rawIban)) {
|
|
setError("Ungültige IBAN");
|
|
} else {
|
|
setError("");
|
|
if (onValidIban) {
|
|
onValidIban(rawIban);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col space-y-1">
|
|
<Input
|
|
placeholder="IBAN"
|
|
value={iban}
|
|
onChange={handleChange}
|
|
onBlur={handleBlur}
|
|
maxLength={27}
|
|
required
|
|
/>
|
|
{error && <span className="text-sm text-red-500">{error}</span>}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default IbanInput;
|