-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
independent multiple calendars option #13
Comments
@JHSeo-git, thanks for reaching out with this proposal. |
@Feshchenko Thank you for your kind comment. You're right, it can look weird when selecting for the same month. The idea here is to remove the choice of the same month appearing in 2 calendars from the options. The maxMonth of the start-range calendar is always one month less than the end-range calendar, I think this is something you might want to consider, so here's a little suggestion! |
@JHSeo-git thanks for the reference. |
@Feshchenko Oh that's right, I hadn't thought about that a bit more. 🤔 |
@JHSeo-git I want create a date picker same as your. After working on it for several days, I was able to develop a date picker similar to what you wanted. However, I had to implement several workarounds to achieve the desired functionality. In order to make it work smoothly and better clean code, I ended up forking the repository and adding an Tab-1689058010605.webmThis is my changes of
|
@huongdevvn Wow That looks good! Similarly, I created a custom hook for a similar functionality Here's that code. /* -------------------------------------------------------------------------------------------------
* useRangeCalendarOffset
* -----------------------------------------------------------------------------------------------*/
type RangeType = 'start' | 'end';
interface UseRangeCalendarOffsetProps {
startDpState: DPState;
endDpState: DPState;
range: RangeType;
}
function useRangeCalendarOffset({ startDpState, endDpState, range }: UseRangeCalendarOffsetProps) {
const startCalendars = useCalendars(startDpState);
const endCalendars = useCalendars(endDpState);
const startCalendar = startCalendars.calendars[0];
const endCalendar = endCalendars.calendars[0];
const startRangeCalendar = React.useMemo(
() => ({
year: parseInt(getNumericText(startCalendar.year)),
month: parseInt(getNumericText(startCalendar.month)),
}),
[startCalendar]
);
const endRangeCalendar = React.useMemo(
() => ({
year: parseInt(getNumericText(endCalendar.year)),
month: parseInt(getNumericText(endCalendar.month)),
}),
[endCalendar]
);
const { dispatch: startDpDispatch } = startDpState;
const { dispatch: endDpDispatch } = endDpState;
const onCalculateDayOffset = React.useCallback(() => {
const startDate = new Date(startRangeCalendar.year, startRangeCalendar.month - 1, 1);
const endDate = new Date(endRangeCalendar.year, endRangeCalendar.month - 1, 1);
if (range === 'start') {
const nextDate = addMonths(startDate, 1);
if (endDate <= nextDate) {
endDpDispatch({
type: 'SET_OFFSET_DATE',
date: addMonths(nextDate, 1),
});
return;
}
}
if (range === 'end') {
const nextDate = subMonths(endDate, 1);
if (startDate >= nextDate) {
startDpDispatch({
type: 'SET_OFFSET_DATE',
date: subMonths(nextDate, 1),
});
return;
}
}
}, [startRangeCalendar, endRangeCalendar, startDpDispatch, endDpDispatch, range]);
const onCalculateMonthOffset = React.useCallback(
(m: CalendarMonth) => {
const startDate = new Date(startRangeCalendar.year, startRangeCalendar.month - 1, 1);
const endDate = new Date(endRangeCalendar.year, endRangeCalendar.month - 1, 1);
if (range === 'start') {
const nextDate = m.$date;
if (endDate <= nextDate) {
endDpDispatch({
type: 'SET_OFFSET_DATE',
date: addMonths(nextDate, 1),
});
return;
}
}
if (range === 'end') {
const nextDate = m.$date;
if (startDate >= nextDate) {
startDpDispatch({
type: 'SET_OFFSET_DATE',
date: subMonths(nextDate, 1),
});
return;
}
}
},
[startRangeCalendar, endRangeCalendar, startDpDispatch, endDpDispatch, range]
);
const onCalculateYearOffset = React.useCallback(
(y: CalendarYear) => {
const startDate = new Date(startRangeCalendar.year, startRangeCalendar.month - 1, 1);
const endDate = new Date(endRangeCalendar.year, endRangeCalendar.month - 1, 1);
if (range === 'start') {
const nextDate = y.$date;
if (endDate <= nextDate) {
endDpDispatch({
type: 'SET_OFFSET_DATE',
date: addMonths(nextDate, 1),
});
return;
}
}
if (range === 'end') {
const nextDate = y.$date;
if (startDate >= nextDate) {
startDpDispatch({
type: 'SET_OFFSET_DATE',
date: subMonths(nextDate, 1),
});
return;
}
}
},
[startRangeCalendar, endRangeCalendar, startDpDispatch, endDpDispatch, range]
);
return { onCalculateDayOffset, onCalculateMonthOffset, onCalculateYearOffset };
} |
Any update here @Feshchenko ? |
Hi @JHSeo-git are you able to provide an example of how you would actually use this hook. Thanks! |
@simontong Where I used that hook was to naturally change the start and end dates like a rsuit datepicker when an event occurs in day, month, and year mode, so here's what I used (not exactly the same, but closely) interface CalendarRangeProps {
startDpState: DPState;
endDpState: DPState;
range: 'start' | 'end';
}
const CalendarRange = ({ startDpState, endDpState, range }: CalendarRangeProps) => {
const targetDpState = range === 'start' ? startDpState : endDpState;
const [calendarViewMode, setCalendarViewMode] = useCalendarViewMode();
const { onCalculateDayOffset, onCalculateMonthOffset, onCalculateYearOffset } =
userRangeCalendarOffset({ startDpState, endDpState, range });
React.useLayoutEffect(() => {
const startDate = startDpState.selectedDates[0];
if (startDate) {
startDpState.dispatch({ type: 'SET_OFFSET_DATE', date: startDate });
}
if (!endDate) {
endDpState.dispatch({ type: 'SET_OFFSET_DATE', date: addMonths(startDate ?? today, 1) });
}
if (startDate?.getMonth() <= endDate?.getMonth()) {
endDpState.dispatch({ type: 'SET_OFFSET_DATE', date: addMonths(startDate ?? today, 1) });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div>
<CalendarHeader
dpState={range === 'start' ? startDpState : endDpState}
calendarViewMode={calendarViewMode}
setCalendarViewMode={setCalendarViewMode}
onPrevClick={range === 'end' ? onCalculateDayOffset : undefined}
onNextClick={range === 'start' ? onCalculateDayOffset : undefined}
/>
<div className="mt-2">
{calendarViewMode === 'days' && (
<CalendarRangeDays startDpState={startDpState} endDpState={endDpState} range={range} />
)}
{calendarViewMode === 'months' && (
<CalendarMonths
dpState={targetDpState}
setCalendarViewMode={setCalendarViewMode}
onMonthClick={onCalculateMonthOffset}
/>
)}
{calendarViewMode === 'years' && (
<CalendarYears
dpState={targetDpState}
setCalendarViewMode={setCalendarViewMode}
onYearClick={onCalculateYearOffset}
/>
)}
</div>
</div>
);
}; |
Is it possible to provide a more complete example that shows how the onCalculateDayOffset, onCalculateMonthOffset, onCalculateYearOffset are used, I was unable to get this to work. Thanks |
1 similar comment
Is it possible to provide a more complete example that shows how the onCalculateDayOffset, onCalculateMonthOffset, onCalculateYearOffset are used, I was unable to get this to work. Thanks |
First, I'd like to say that I'm enjoying using the library. 😄
I have a small question about additional functionality for range mode.
There is currently no method to select a date through multiple independent calendars when using range mode. We can use offset to show multiple calendars, but they are sequential and not independent.
(like
will-be-in-range
state when hover, days when move prev month / next month, ...)In order to use independent calendars in RANGE mode, I have personally implemented a few methods in my limited skills.
If you could provide this functionality in the library, I think it could be applied in many cases.
Once again, thank you for creating such an awesome library. 👍
Here is the sample code and application I did.
The text was updated successfully, but these errors were encountered: