UNPKG

@availity/mui-datepicker

Version:

Availity MUI Datepicker Component - part of the @availity/element design system

295 lines (259 loc) 8.1 kB
# DateRangePicker Docs The `element` library has a `Datepicker` component that can be used to create your own `DateRangePicker`. There is not a `DateRangePicker` exported from the library. ## Example The following code block shows an example `DateRangePicker` using the `Datepicker` and `Grid` components. ```tsx import { Datepicker, Grid } from '@availity/element'; import type { Dayjs } from 'dayjs'; type DateRangePickerProps = { startDate: Dayjs | null; endDate: Dayjs | null; onStartDateChange: (date: Dayjs | null) => void; onEndDateChange: (date: Dayjs | null) => void; startFieldProps?: { label?: string; helperText?: string; helpTopicId?: string; fullWidth?: boolean; }; endFieldProps?: { label?: string; helperText?: string; helpTopicId?: string; fullWidth?: boolean; }; }; const DateRangePicker = ({ startDate, endDate, onStartDateChange, onEndDateChange, startFieldProps = { label: 'Start Date', helperText: 'Select start date', }, endFieldProps = { label: 'End Date', helperText: 'Select end date', }, }: DateRangePickerProps) => { return ( <> <Grid container spacing={2}> <Grid size={{xs: 12, sm: 6}}> <Datepicker value={startDate} onChange={onStartDateChange} FieldProps={startFieldProps} maxDate={endDate ?? undefined} // Prevent selecting start date after end date views={['day', 'month', 'year']} /> </Grid> <Grid size={{xs: 12, sm: 6}}> <Datepicker value={endDate} onChange={onEndDateChange} FieldProps={endFieldProps} minDate={startDate ?? undefined} // Prevent selecting end date before start date views={['day', 'month', 'year']} /> </Grid> </Grid> </> ); }; ``` ### Simple Usage Below is an example of the `DateRangePicker` component we made above. <Source /> ```tsx import { useState } from 'react'; import { Dayjs } from 'dayjs'; import { DateRangePicker } from './DateRangePicker'; const MyComponent = () => { const [startDate, setStartDate] = useState<Dayjs | null>(null); const [endDate, setEndDate] = useState<Dayjs | null>(null); return ( <DateRangePicker // Required props startDate={startDate} endDate={endDate} onStartDateChange={setStartDate} onEndDateChange={setEndDate} // Optional props with default values shown startFieldProps={{ label: 'Start Date', helperText: 'Select start date', helpTopicId: '1234', // Optional help topic ID fullWidth: false, // Optional width control }} endFieldProps={{ label: 'End Date', helperText: 'Select end date', helpTopicId: '1234', // Optional help topic ID fullWidth: false, // Optional width control }} /> ); }; ``` ### Validation The recommended way to validate the `DateRangePicker` is to use `yup`. Below we have an example of validating that the `endDate` is after the `startDate`. ```tsx import * as yup from 'yup'; import { Dayjs } from 'dayjs'; const dateRangeSchema = yup.object().shape({ startDate: yup.mixed<Dayjs | null>().nullable().required('Start date is required'), endDate: yup .mixed<Dayjs | null>() .nullable() .required('End date is required') .test('is-after-start', 'End date must be after start date', function (endDate, context) { const { startDate } = context.parent; if (!startDate || !endDate) { return true; } return endDate.isAfter(startDate) || endDate.isSame(startDate); }), }); ``` You can then use the created component and validation schema in a form with `react-hook-form`. ```tsx import { useForm, Controller } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; import { Dayjs } from 'dayjs'; import { DateRangePicker } from './DateRangePicker'; interface DateRangeForm { startDate: Dayjs | null; endDate: Dayjs | null; } const dateRangeSchema = yup.object().shape({ startDate: yup.mixed<Dayjs | null>().nullable().required('Start date is required'), endDate: yup .mixed<Dayjs | null>() .nullable() .required('End date is required') .test('is-after-start', 'End date must be after start date', function (endDate, context) { const { startDate } = context.parent; if (!startDate || !endDate) { return true; } return endDate.isAfter(startDate) || endDate.isSame(startDate); }), }); const DateRangeForm = () => { const { control, handleSubmit, formState: { errors }, } = useForm<DateRangeForm>({ resolver: yupResolver(dateRangeSchema), defaultValues: { startDate: null, endDate: null, }, }); const DateRangeForm = () => { const { control, handleSubmit, formState: { errors }, watch, } = useForm<DateRangeForm>({ resolver: yupResolver(dateRangeSchema), defaultValues: { startDate: null, endDate: null, }, mode: 'onChange', // Enable real-time validation }); // Watch for changes in dates const startDate = watch('startDate'); const endDate = watch('endDate'); // Optional: Add side effects when dates change useEffect(() => { if (startDate && endDate) { // Perform any additional validation or business logic console.log('Date range changed:', { startDate, endDate }); } }, [startDate, endDate]); const onSubmit = (data: DateRangeForm) => { console.log('Form submitted:', data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="startDate" control={control} render={({ field: { onChange, value } }) => ( <Controller name="endDate" control={control} render={({ field: { onChange: onEndChange, value: endValue } }) => ( <DateRangePicker startDate={value} endDate={endValue} onStartDateChange={onChange} onEndDateChange={onEndChange} startFieldProps={{ helperText: errors.startDate?.message, error: Boolean(errors.startDate), label: 'Start Date', fullWidth: true, }} endFieldProps={{ helperText: errors.endDate?.message, error: Boolean(errors.endDate), label: 'End Date', fullWidth: true, }} /> )} /> )} /> <button type="submit" style={{ marginTop: '16px' }}> Submit </button> </form> ); }; const onSubmit = (data: DateRangeForm) => { console.log(data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="startDate" control={control} render={({ field: { onChange, value } }) => ( <Controller name="endDate" control={control} render={({ field: { onChange: onEndChange, value: endValue } }) => ( <DateRangePicker startDate={value} endDate={endValue} onStartDateChange={onChange} onEndDateChange={onEndChange} startFieldProps={{ helperText: errors.startDate?.message, error: Boolean(errors.startDate), label: 'Start Date', }} endFieldProps={{ helperText: errors.endDate?.message, error: Boolean(errors.endDate), label: 'End Date', }} /> )} /> )} /> <button type="submit">Submit</button> </form> ); }; ```