MaskedDateInput: dot pads date

This commit is contained in:
popovspiridon99
2025-07-23 14:26:39 +09:00
parent 65201ee646
commit 33ae1c56bc

View File

@ -14,8 +14,6 @@ interface MaskedDateInputProps {
maxDate?: Date | undefined
}
const currentYear = new Date().getFullYear()
function parseDDMMYYYY(input: string): Date | null {
const [dd, mm, yyyy] = input.split(".")
const day = parseInt(dd, 10)
@ -26,7 +24,7 @@ function parseDDMMYYYY(input: string): Date | null {
isNaN(day) || isNaN(month) || isNaN(year) ||
day < 1 || day > 31 ||
month < 1 || month > 12 ||
year < 1900 //|| year > currentYear
year < 1900
) {
return null
}
@ -62,20 +60,50 @@ export default function MaskedDateInput({
}, [value])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
let raw = e.target.value.replace(/[^\d]/g, '').slice(0, 8)
let day = raw.slice(0, 2)
let month = raw.slice(2, 4)
let year = raw.slice(4, 8)
const raw = e.target.value;
const digits = raw.replace(/\D/g, '').slice(0, 8);
if (day.length === 1 && parseInt(day) > 3) day = '0' + day
if (month.length === 1 && parseInt(month) > 1) month = '0' + month
let day = digits.slice(0, 2);
let month = digits.slice(2, 4);
let year = digits.slice(4, 8);
const newValue = [day, month, year].filter(Boolean).join('.')
// Validate day and month only if they are fully entered (2 digits)
if (day.length === 2) {
const dayNum = parseInt(day, 10);
if (dayNum < 1 || dayNum > 31) return; // Invalid day → block update
}
setInputValue(newValue)
if (month.length === 2) {
const monthNum = parseInt(month, 10);
if (monthNum < 1 || monthNum > 12) return; // Invalid month → block update
}
const parsed = parseDDMMYYYY(newValue)
if (parsed) onChange?.(parsed)
if (year.length === 4) {
const yearNum = parseInt(year, 10);
if (yearNum < 1900) return; // Invalid year → block update
}
// Format the input as DD.MM.YYYY
let formatted = day;
if (month.length) formatted += '.' + month;
if (year.length) formatted += '.' + year;
// Smart dot-padding (like "1." → "01.")
if (/^\d\.$/.test(raw)) {
formatted = '0' + raw;
}
if (/^\d{2}\.\d\.$/.test(raw)) {
formatted = raw.replace(/^(\d{2})\.(\d)\.$/, (_, d, m) => `${d}.0${m}.`);
}
setInputValue(formatted);
// Final parsing only if full date is entered
if (day.length === 2 && month.length === 2 && year.length === 4) {
const parsed = parseDDMMYYYY(formatted);
if (parsed) onChange?.(parsed);
}
};