mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 13:02:50 +00:00
feat: add minDate and maxDate constraints to AmharicDatePicker and restrict form inputs to prevent future and invalid dates
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
import { TimeInput } from '@mantine/dates';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { DayPicker as EthiopicDayPicker } from '@daypicker/ethiopic';
|
||||
import { DayPicker as GregorianDayPicker } from '@daypicker/react';
|
||||
import { DayPicker as GregorianDayPicker, type Matcher } from '@daypicker/react';
|
||||
import { IconCalendarEvent } from '@tabler/icons-react';
|
||||
import '@daypicker/react/dist/style.css';
|
||||
import './AmharicDatePicker.css';
|
||||
@@ -131,6 +131,11 @@ export interface AmharicDatePickerProps {
|
||||
/** Show a time-of-day field alongside the calendar. Off by default —
|
||||
* most callers only need a calendar day. */
|
||||
withTime?: boolean;
|
||||
/** Earliest/latest selectable day. Accepts a Date or a value in the same
|
||||
* wire format as `value`. Days outside the range are disabled in both
|
||||
* calendars. */
|
||||
minDate?: Date | string;
|
||||
maxDate?: Date | string;
|
||||
/** Wire format for `value`/`onChange`: a full ISO-8601 instant (default,
|
||||
* what most backend date fields expect) or a bare `yyyy-mm-dd` calendar
|
||||
* date (what filter query params and plain `date: string` DTO fields
|
||||
@@ -151,6 +156,8 @@ export function AmharicDatePicker({
|
||||
onBlur,
|
||||
w,
|
||||
withTime = false,
|
||||
minDate,
|
||||
maxDate,
|
||||
dateFormat = 'iso',
|
||||
}: AmharicDatePickerProps) {
|
||||
const { t, i18n } = useTranslation();
|
||||
@@ -161,6 +168,21 @@ export function AmharicDatePicker({
|
||||
|
||||
const selected = parseWireValue(value, dateFormat, withTime);
|
||||
|
||||
const asDate = (limit: Date | string | undefined) =>
|
||||
limit instanceof Date ? limit : parseWireValue(limit, dateFormat, withTime);
|
||||
const min = asDate(minDate);
|
||||
const max = asDate(maxDate);
|
||||
const outOfRange: Matcher[] = [
|
||||
...(min ? [{ before: min }] : []),
|
||||
...(max ? [{ after: max }] : []),
|
||||
];
|
||||
// Compared as calendar days — the limits carry a midnight time-of-day, so
|
||||
// an instant comparison would call today "after" a max of today.
|
||||
const todayKey = formatPlainDate(new Date());
|
||||
const todayOutOfRange =
|
||||
(!!min && todayKey < formatPlainDate(min)) ||
|
||||
(!!max && todayKey > formatPlainDate(max));
|
||||
|
||||
const dateLabel = selected
|
||||
? calendarType === 'EN'
|
||||
? selected.toLocaleDateString('en-US', {
|
||||
@@ -266,6 +288,7 @@ export function AmharicDatePicker({
|
||||
endMonth={YEAR_DROPDOWN_END}
|
||||
numerals="latn"
|
||||
captionLayout="dropdown"
|
||||
disabled={outOfRange}
|
||||
formatters={ETH_FORMATTERS}
|
||||
onSelect={(date: Date | undefined) => {
|
||||
onChange?.(date ? formatWireValue(mergeDateTime(selected, date), dateFormat, withTime) : '');
|
||||
@@ -281,6 +304,7 @@ export function AmharicDatePicker({
|
||||
startMonth={YEAR_DROPDOWN_START}
|
||||
endMonth={YEAR_DROPDOWN_END}
|
||||
captionLayout="dropdown"
|
||||
disabled={outOfRange}
|
||||
onSelect={(date: Date | undefined) => {
|
||||
onChange?.(date ? formatWireValue(mergeDateTime(selected, date), dateFormat, withTime) : '');
|
||||
if (!withTime) close();
|
||||
@@ -389,6 +413,7 @@ export function AmharicDatePicker({
|
||||
<Button
|
||||
variant="light"
|
||||
size="xs"
|
||||
disabled={todayOutOfRange}
|
||||
onClick={() => {
|
||||
onChange?.(formatWireValue(new Date(), dateFormat, withTime));
|
||||
close();
|
||||
|
||||
Reference in New Issue
Block a user