improvement: some improvement done for appointment and treatment shared components.
This commit is contained in:
@@ -6,6 +6,7 @@ import { CalendarDays } from 'lucide-react';
|
||||
import { parseDateInput, startOfLocalDay, toDateInputValue } from '@/components/appointments/appointmentTime';
|
||||
import { FORM_DATE_INPUT_CLASS } from '@/components/shared/formSelectStyles';
|
||||
import { CalendarDayPartsPanel } from '@/components/ui/shared/CalendarDayPartsPanel';
|
||||
import { useAnchoredPanelPosition } from '@/lib/hooks/useAnchoredPanelPosition';
|
||||
import {
|
||||
formatIsoAsGregorianDateInput,
|
||||
maskGregorianDateTyping,
|
||||
@@ -45,6 +46,11 @@ export function AppDateInput({
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const [text, setText] = useState('');
|
||||
const [panelOpen, setPanelOpen] = useState(false);
|
||||
const { panelRef, style: panelStyle } = useAnchoredPanelPosition({
|
||||
open: panelOpen && !disabled,
|
||||
anchorRef: rootRef,
|
||||
align: 'start',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setText(
|
||||
@@ -56,9 +62,11 @@ export function AppDateInput({
|
||||
if (!panelOpen) return;
|
||||
|
||||
function onPointerDown(event: MouseEvent) {
|
||||
if (!rootRef.current?.contains(event.target as Node)) {
|
||||
setPanelOpen(false);
|
||||
const target = event.target as Node;
|
||||
if (rootRef.current?.contains(target) || panelRef.current?.contains(target)) {
|
||||
return;
|
||||
}
|
||||
setPanelOpen(false);
|
||||
}
|
||||
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
@@ -73,7 +81,7 @@ export function AppDateInput({
|
||||
document.removeEventListener('mousedown', onPointerDown);
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
};
|
||||
}, [panelOpen]);
|
||||
}, [panelOpen, panelRef]);
|
||||
|
||||
const panelAnchorDate = value ? parseDateInput(value) : startOfLocalDay(new Date());
|
||||
const placeholder = persian ? '۱۴۰۴/۰۴/۲۲' : '2026-07-13';
|
||||
@@ -154,9 +162,19 @@ export function AppDateInput({
|
||||
|
||||
{panelOpen && !disabled ? (
|
||||
<div
|
||||
ref={panelRef}
|
||||
id={`${panelId}-parts`}
|
||||
role="dialog"
|
||||
className="absolute start-0 top-full z-50 mt-1 min-w-[17.5rem] w-max max-w-[calc(100vw-1.5rem)] rounded-[var(--radius-md)] border border-border bg-background-secondary p-3 shadow-lg"
|
||||
style={
|
||||
panelStyle ?? {
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
visibility: 'hidden',
|
||||
pointerEvents: 'none',
|
||||
}
|
||||
}
|
||||
className="min-w-[17.5rem] rounded-[var(--radius-md)] border border-border bg-background-secondary p-3 shadow-lg"
|
||||
>
|
||||
<CalendarDayPartsPanel
|
||||
panelId={panelId}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { formatAppPickerDateLabel } from '@/lib/i18n/format';
|
||||
import { CalendarDayPartsPanel } from '@/components/ui/shared/CalendarDayPartsPanel';
|
||||
import { addCalendarDays, compareLocalDayStart, startOfLocalDay } from '@/components/appointments/appointmentTime';
|
||||
import { Checkbox } from '@/components/ui/shared/Checkbox';
|
||||
import { useAnchoredPanelPosition } from '@/lib/hooks/useAnchoredPanelPosition';
|
||||
|
||||
export type CalendarDaySelectProps = {
|
||||
value: Date;
|
||||
@@ -50,6 +51,11 @@ export function CalendarDaySelect({
|
||||
const panelId = useId();
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const [panelOpen, setPanelOpen] = useState(false);
|
||||
const { panelRef, style: panelStyle } = useAnchoredPanelPosition({
|
||||
open: panelOpen && !disabled,
|
||||
anchorRef: rootRef,
|
||||
align: 'stretch',
|
||||
});
|
||||
|
||||
const normalizedValue = startOfLocalDay(value);
|
||||
const today = startOfLocalDay(new Date());
|
||||
@@ -63,10 +69,12 @@ export function CalendarDaySelect({
|
||||
if (!panelOpen) return;
|
||||
|
||||
function onPointerDown(event: MouseEvent) {
|
||||
if (!rootRef.current?.contains(event.target as Node)) {
|
||||
setPanelOpen(false);
|
||||
onBlur?.();
|
||||
const target = event.target as Node;
|
||||
if (rootRef.current?.contains(target) || panelRef.current?.contains(target)) {
|
||||
return;
|
||||
}
|
||||
setPanelOpen(false);
|
||||
onBlur?.();
|
||||
}
|
||||
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
@@ -82,7 +90,7 @@ export function CalendarDaySelect({
|
||||
document.removeEventListener('mousedown', onPointerDown);
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
};
|
||||
}, [onBlur, panelOpen]);
|
||||
}, [onBlur, panelOpen, panelRef]);
|
||||
|
||||
const triggerButton = (
|
||||
<button
|
||||
@@ -166,17 +174,27 @@ export function CalendarDaySelect({
|
||||
|
||||
{panelOpen && !disabled ? (
|
||||
<div
|
||||
ref={panelRef}
|
||||
id={panelId}
|
||||
role="dialog"
|
||||
aria-label={t('chooseDate')}
|
||||
className="absolute left-0 right-0 top-full z-50 mt-2 rounded-[var(--radius-md)] border border-border bg-background-secondary p-3 shadow-lg"
|
||||
style={
|
||||
panelStyle ?? {
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
visibility: 'hidden',
|
||||
pointerEvents: 'none',
|
||||
}
|
||||
}
|
||||
className="rounded-[var(--radius-md)] border border-border bg-background-secondary p-3 shadow-lg"
|
||||
>
|
||||
<CalendarDayPartsPanel
|
||||
panelId={panelId}
|
||||
value={normalizedValue}
|
||||
onChange={onChange}
|
||||
closePanelOnDaySelect={closePanelOnDaySelect}
|
||||
onAfterSelect={(day) => {
|
||||
onAfterSelect={() => {
|
||||
setPanelOpen(false);
|
||||
onBlur?.();
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user