Browse Source

fix: improve date string validation, parsing, and formatting logic in date components

master
mortezaei 1 week ago
parent
commit
ce49189a3b
  1. 19
      src/components/Componentes/question-date-sheet.tsx
  2. 66
      src/components/Componentes/question-date.tsx

19
src/components/Componentes/question-date-sheet.tsx

@ -156,12 +156,23 @@ export function QuestionDateSheet({
const { dictionary: t, locale } = useI18n(); const { dictionary: t, locale } = useI18n();
const [isClosing, setIsClosing] = useState(false); const [isClosing, setIsClosing] = useState(false);
const parts = value ? value.split("-") : [];
const [selectedYear, setSelectedYear] = useState(parts[0] || YEARS[0]);
const parts =
value && typeof value === "string" ? value.trim().split("-") : [];
const rawYear = parts.length === 3 ? parts[0] : "";
const rawMonth = parts.length === 3 ? parts[1]?.padStart(2, "0") : "";
const rawDay = parts.length === 3 ? parts[2]?.padStart(2, "0") : "";
const [selectedYear, setSelectedYear] = useState(
rawYear && YEARS.includes(rawYear) ? rawYear : YEARS[0],
);
const [selectedMonth, setSelectedMonth] = useState( const [selectedMonth, setSelectedMonth] = useState(
parts[1] || MONTH_VALUES[0],
rawMonth && MONTH_VALUES.includes(rawMonth) ? rawMonth : MONTH_VALUES[0],
);
const [selectedDay, setSelectedDay] = useState(
rawDay && Number.parseInt(rawDay, 10) >= 1 && Number.parseInt(rawDay, 10) <= 31
? rawDay
: "01",
); );
const [selectedDay, setSelectedDay] = useState(parts[2] || "01");
const dirtyRef = useRef(false); const dirtyRef = useRef(false);
const closeSheet = useCallback(() => { const closeSheet = useCallback(() => {

66
src/components/Componentes/question-date.tsx

@ -19,11 +19,33 @@ function parseDateParts(dateValue: string): {
month: string; month: string;
day: string; day: string;
} { } {
const parts = dateValue ? dateValue.split("-") : [];
if (typeof dateValue !== "string") {
return { year: "", month: "", day: "" };
}
const parts = dateValue.trim().split("-");
if (parts.length !== 3) {
return { year: "", month: "", day: "" };
}
const [y, m, d] = parts;
const yearNum = Number.parseInt(y, 10);
const monthNum = Number.parseInt(m, 10);
const dayNum = Number.parseInt(d, 10);
if (
Number.isNaN(yearNum) ||
Number.isNaN(monthNum) ||
Number.isNaN(dayNum) ||
yearNum <= 0 ||
monthNum < 1 ||
monthNum > 12 ||
dayNum < 1 ||
dayNum > 31
) {
return { year: "", month: "", day: "" };
}
return { return {
year: parts[0] || "",
month: parts[1] || "",
day: parts[2] || "",
year: y,
month: m.padStart(2, "0"),
day: d.padStart(2, "0"),
}; };
} }
@ -70,16 +92,32 @@ export function QuestionDate({ question, disabled }: QuestionDateProps) {
const displayDate = useMemo(() => { const displayDate = useMemo(() => {
if (!year || !month || !day) return ""; if (!year || !month || !day) return "";
const date = new Date(
Number.parseInt(year, 10),
Number.parseInt(month, 10) - 1,
Number.parseInt(day, 10),
);
return new Intl.DateTimeFormat(`${locale}-u-ca-gregory`, {
day: "numeric",
month: "long",
year: "numeric",
}).format(date);
const y = Number.parseInt(year, 10);
const m = Number.parseInt(month, 10);
const d = Number.parseInt(day, 10);
if (
!y ||
!m ||
!d ||
Number.isNaN(y) ||
Number.isNaN(m) ||
Number.isNaN(d)
) {
return "";
}
const date = new Date(y, m - 1, d);
if (Number.isNaN(date.getTime()) || !Number.isFinite(date.getTime())) {
return "";
}
try {
return new Intl.DateTimeFormat(`${locale}-u-ca-gregory`, {
day: "numeric",
month: "long",
year: "numeric",
}).format(date);
} catch {
return "";
}
}, [year, month, day, locale]); }, [year, month, day, locale]);
const openSheet = () => { const openSheet = () => {

Loading…
Cancel
Save