mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-07-10 12:37:16 +02:00
web: fix day picker to allow selecting all months within min/max range (#9879)
* web: fix day picker to allow selecting all months within min/max range Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> * web: disable month nav buttons if they exceed min/max range in DayPicker Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,7 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useDatePicker } from "@rehookify/datepicker";
|
||||
import { Box, Button, Flex, Text } from "@theme-ui/components";
|
||||
import { useState } from "react";
|
||||
@@ -31,6 +32,7 @@ type DayPickerProps = {
|
||||
export function DayPicker(props: DayPickerProps) {
|
||||
const { selected, sx, maxDate, minDate, onSelect } = props;
|
||||
const [selectedDates, onDatesChange] = useState<Date[]>([selected]);
|
||||
|
||||
const {
|
||||
data: { weekDays, months, years, calendars },
|
||||
propGetters: { dayButton, addOffset, subtractOffset, setOffset }
|
||||
@@ -52,6 +54,24 @@ export function DayPicker(props: DayPickerProps) {
|
||||
|
||||
const { month, year, days } = calendars[0];
|
||||
|
||||
const currentMonthDate = months.find((m) => m.month === month)?.$date;
|
||||
const isNextMonthBeyondMax =
|
||||
maxDate && currentMonthDate
|
||||
? new Date(
|
||||
currentMonthDate.getFullYear(),
|
||||
currentMonthDate.getMonth() + 1,
|
||||
1
|
||||
) > stripTime(maxDate)
|
||||
: false;
|
||||
const isPrevMonthBeforeMin =
|
||||
minDate && currentMonthDate
|
||||
? new Date(
|
||||
currentMonthDate.getFullYear(),
|
||||
currentMonthDate.getMonth(),
|
||||
1
|
||||
) <= stripTime(minDate)
|
||||
: false;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
@@ -66,7 +86,7 @@ export function DayPicker(props: DayPickerProps) {
|
||||
<Button
|
||||
variant="icon"
|
||||
sx={{ p: 0 }}
|
||||
{...subtractOffset({ months: 1 })}
|
||||
{...subtractOffset({ months: 1 }, { disabled: isPrevMonthBeforeMin })}
|
||||
>
|
||||
<ChevronLeft />
|
||||
</Button>
|
||||
@@ -83,9 +103,12 @@ export function DayPicker(props: DayPickerProps) {
|
||||
value={month}
|
||||
onChange={(e) => {
|
||||
const selectedOption = e.target.selectedOptions[0];
|
||||
setOffset(new Date(selectedOption.dataset.date || ""))?.onClick?.(
|
||||
e
|
||||
const d = clampDate(
|
||||
new Date(selectedOption.dataset.date || ""),
|
||||
minDate,
|
||||
maxDate
|
||||
);
|
||||
setOffset(d)?.onClick?.(e as any);
|
||||
}}
|
||||
>
|
||||
{months.map((month) => (
|
||||
@@ -112,9 +135,12 @@ export function DayPicker(props: DayPickerProps) {
|
||||
value={year}
|
||||
onChange={(e) => {
|
||||
const selectedOption = e.target.selectedOptions[0];
|
||||
setOffset(new Date(selectedOption.dataset.date || ""))?.onClick?.(
|
||||
e
|
||||
const d = clampDate(
|
||||
new Date(selectedOption.dataset.date || ""),
|
||||
minDate,
|
||||
maxDate
|
||||
);
|
||||
setOffset(d)?.onClick?.(e as any);
|
||||
}}
|
||||
>
|
||||
{years.map((year) => (
|
||||
@@ -129,7 +155,16 @@ export function DayPicker(props: DayPickerProps) {
|
||||
))}
|
||||
</select>
|
||||
</Flex>
|
||||
<Button variant="icon" sx={{ p: 0 }} {...addOffset({ months: 1 })}>
|
||||
<Button
|
||||
variant="icon"
|
||||
sx={{ p: 0 }}
|
||||
{...addOffset(
|
||||
{ months: 1 },
|
||||
{
|
||||
disabled: isNextMonthBeyondMax
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChevronRight />
|
||||
</Button>
|
||||
</Flex>
|
||||
@@ -195,3 +230,24 @@ export function DayPicker(props: DayPickerProps) {
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
function clampDate(d: Date, minDate?: Date, maxDate?: Date) {
|
||||
/**
|
||||
* Strip time for accurate comparison
|
||||
*/
|
||||
const normalizedMaxDate = maxDate ? stripTime(maxDate) : null;
|
||||
const normalizedMinDate = minDate ? stripTime(minDate) : null;
|
||||
|
||||
if (normalizedMaxDate && d > normalizedMaxDate) {
|
||||
return normalizedMaxDate;
|
||||
}
|
||||
if (normalizedMinDate && d < normalizedMinDate) {
|
||||
return normalizedMinDate;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
function stripTime(date: Date) {
|
||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user