mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-30 05:18:13 +00:00
feat: integrate AmharicDatePicker component across multiple pages and update translations
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ActionIcon, Button, Group, Popover, TextInput } from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Button,
|
||||
Group,
|
||||
MantineSize,
|
||||
Popover,
|
||||
TextInput,
|
||||
} from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { DayPicker as EthiopicDayPicker } from '@daypicker/ethiopic';
|
||||
import { DayPicker as GregorianDayPicker } from '@daypicker/react';
|
||||
@@ -52,23 +59,48 @@ const ETH_FORMATTERS = {
|
||||
formatMonthDropdown: (month: Date) => ethMonthName(month),
|
||||
};
|
||||
|
||||
export function toEthiopicDateLabel(date: Date): string {
|
||||
// Local-date parse/format for the "YYYY-MM-DD" wire format (matches native
|
||||
// <input type="date"> semantics). Deliberately NOT `new Date(iso)` (parses as
|
||||
// UTC midnight, off-by-one in negative-offset zones) and NOT
|
||||
// `.toISOString()` (shifts by the local offset when formatting) — same class
|
||||
// of bug the UTC-noon workaround above already had to fix once in this file.
|
||||
function parseISO(value?: string | null): Date | null {
|
||||
if (!value) return null;
|
||||
const [y, m, d] = value.split('-').map(Number);
|
||||
return y && m && d ? new Date(y, m - 1, d) : null;
|
||||
}
|
||||
|
||||
function formatISO(date: Date): string {
|
||||
const y = date.getFullYear();
|
||||
const m = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const d = String(date.getDate()).padStart(2, '0');
|
||||
return `${y}-${m}-${d}`;
|
||||
}
|
||||
|
||||
export function toEthiopicDateLabel(date: Date | string): string {
|
||||
const d = typeof date === 'string' ? parseISO(date) : date;
|
||||
if (!d) return '';
|
||||
try {
|
||||
const eth = toEthDateTime(date);
|
||||
const eth = toEthDateTime(d);
|
||||
return `EC ${eth.year}-${String(eth.month).padStart(2, '0')}-${String(eth.date).padStart(2, '0')}`;
|
||||
} catch {
|
||||
return date.toLocaleDateString('en-US');
|
||||
return d.toLocaleDateString('en-US');
|
||||
}
|
||||
}
|
||||
|
||||
const YEAR_DROPDOWN_END = new Date(new Date().getFullYear() + 50, 11, 31);
|
||||
|
||||
export interface AmharicDatePickerProps {
|
||||
label?: string;
|
||||
value?: Date | null;
|
||||
onChange?: (date: Date | null) => void;
|
||||
label?: React.ReactNode;
|
||||
value?: string | null;
|
||||
onChange?: (value: string) => void;
|
||||
required?: boolean;
|
||||
placeholder?: string;
|
||||
error?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
size?: MantineSize;
|
||||
name?: string;
|
||||
onBlur?: () => void;
|
||||
}
|
||||
|
||||
export function AmharicDatePicker({
|
||||
@@ -77,21 +109,28 @@ export function AmharicDatePicker({
|
||||
onChange,
|
||||
required,
|
||||
placeholder,
|
||||
error,
|
||||
disabled,
|
||||
size,
|
||||
name,
|
||||
onBlur,
|
||||
}: AmharicDatePickerProps) {
|
||||
const { i18n } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const [calendarType, setCalendarType] = useState<'EN' | 'AMH'>(() =>
|
||||
i18n.language?.startsWith('am') ? 'AMH' : 'EN',
|
||||
);
|
||||
const [opened, { close, toggle }] = useDisclosure(false);
|
||||
|
||||
const displayValue = value
|
||||
const selected = parseISO(value);
|
||||
|
||||
const displayValue = selected
|
||||
? calendarType === 'EN'
|
||||
? value.toLocaleDateString('en-US', {
|
||||
? selected.toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})
|
||||
: toAmharicDisplay(value)
|
||||
: toAmharicDisplay(selected)
|
||||
: '';
|
||||
|
||||
return (
|
||||
@@ -109,24 +148,32 @@ export function AmharicDatePicker({
|
||||
required={required}
|
||||
value={displayValue}
|
||||
readOnly
|
||||
disabled={disabled}
|
||||
size={size}
|
||||
name={name}
|
||||
error={error}
|
||||
placeholder={placeholder}
|
||||
onClick={toggle}
|
||||
onClick={() => !disabled && toggle()}
|
||||
onBlur={onBlur}
|
||||
leftSection={
|
||||
<Button
|
||||
type="button"
|
||||
variant="light"
|
||||
size="compact-xs"
|
||||
tabIndex={0}
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setCalendarType((prev) => (prev === 'EN' ? 'AMH' : 'EN'));
|
||||
}}
|
||||
aria-label="Switch calendar type"
|
||||
aria-label={t('common.switchCalendar')}
|
||||
>
|
||||
{calendarType}
|
||||
</Button>
|
||||
}
|
||||
leftSectionWidth="calc(4.375rem * var(--mantine-scale))"
|
||||
rightSection={
|
||||
<ActionIcon size="md" variant="transparent" onClick={toggle}>
|
||||
<ActionIcon size="md" variant="transparent" disabled={disabled} onClick={() => toggle()}>
|
||||
<IconCalendarEvent size={20} />
|
||||
</ActionIcon>
|
||||
}
|
||||
@@ -138,14 +185,14 @@ export function AmharicDatePicker({
|
||||
<EthiopicDayPicker
|
||||
className="amharic-daypicker"
|
||||
mode="single"
|
||||
selected={value ?? undefined}
|
||||
defaultMonth={value ?? undefined}
|
||||
selected={selected ?? undefined}
|
||||
defaultMonth={selected ?? undefined}
|
||||
endMonth={YEAR_DROPDOWN_END}
|
||||
numerals="latn"
|
||||
captionLayout="dropdown"
|
||||
formatters={ETH_FORMATTERS}
|
||||
onSelect={(date: Date | undefined) => {
|
||||
onChange?.(date ?? null);
|
||||
onChange?.(date ? formatISO(date) : '');
|
||||
close();
|
||||
}}
|
||||
/>
|
||||
@@ -153,12 +200,12 @@ export function AmharicDatePicker({
|
||||
<GregorianDayPicker
|
||||
className="amharic-daypicker"
|
||||
mode="single"
|
||||
selected={value ?? undefined}
|
||||
defaultMonth={value ?? undefined}
|
||||
selected={selected ?? undefined}
|
||||
defaultMonth={selected ?? undefined}
|
||||
endMonth={YEAR_DROPDOWN_END}
|
||||
captionLayout="dropdown"
|
||||
onSelect={(date: Date | undefined) => {
|
||||
onChange?.(date ?? null);
|
||||
onChange?.(date ? formatISO(date) : '');
|
||||
close();
|
||||
}}
|
||||
/>
|
||||
@@ -169,7 +216,7 @@ export function AmharicDatePicker({
|
||||
variant="subtle"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
onChange?.(null);
|
||||
onChange?.('');
|
||||
close();
|
||||
}}
|
||||
>
|
||||
@@ -179,7 +226,7 @@ export function AmharicDatePicker({
|
||||
variant="light"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
onChange?.(new Date());
|
||||
onChange?.(formatISO(new Date()));
|
||||
close();
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user