Skip to content

Commit

Permalink
feat:Calendar:add disabledDate (#5602)
Browse files Browse the repository at this point in the history
* feat:Calendar:disabled logic

* fix:empty array

* fix:doc

* feat:undo new props

* feat:add test cases

* Refactor isDayDisabled

* feat:rename checkDateIsDisabled->isMonthYearDisabled

---------

Co-authored-by: Melloware <[email protected]>
  • Loading branch information
kl-nevermore and melloware authored Dec 16, 2023
1 parent f391c13 commit 05a83b4
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 25 deletions.
61 changes: 38 additions & 23 deletions components/lib/calendar/Calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -1841,11 +1841,7 @@ export const Calendar = React.memo(
}
}

if (props.disabledDates || props.enabledDates) {
validDate = !isDateDisabled(day, month, year);
}

if (props.disabledDays && currentView === 'date') {
if (props.disabledDates || props.enabledDates || props.disabledDays) {
validDay = !isDayDisabled(day, month, year);
}

Expand Down Expand Up @@ -1995,24 +1991,24 @@ export const Calendar = React.memo(
return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year;
};

const isDateDisabled = (day, month, year) => {
const isDayDisabled = (day, month, year) => {
if (props.disabledDates) {
return props.disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day);
}

if (props.enabledDates) {
return !props.enabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day);
if (props.disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day)) {
return true;
}
} else if (props.enabledDates) {
if (!props.enabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day)) {
return true;
}
}

return false;
};

const isDayDisabled = (day, month, year) => {
if (props.disabledDays) {
if (props.disabledDays && currentView === 'date') {
let weekday = new Date(year, month, day);
let weekdayNumber = weekday.getDay();

return props.disabledDays.indexOf(weekdayNumber) !== -1;
if (props.disabledDays.indexOf(weekdayNumber) !== -1) {
return true;
}
}

return false;
Expand Down Expand Up @@ -3656,17 +3652,17 @@ export const Calendar = React.memo(
{monthPickerValues().map((m, i) => {
const monthProps = mergeProps(
{
className: cx('month', { isMonthSelected, isSelectable, i, currentYear }),
className: cx('month', { isMonthSelected, isMonthYearDisabled, i, currentYear }),
onClick: (event) => onMonthSelect(event, i),
onKeyDown: (event) => onMonthCellKeydown(event, i),
'data-p-disabled': !isSelectable(0, i, currentYear),
'data-p-disabled': isMonthYearDisabled(i, currentYear),
'data-p-highlight': isMonthSelected(i)
},
ptm('month', {
context: {
month: m,
monthIndex: i,
disabled: !isSelectable(0, i, currentYear),
disabled: isMonthYearDisabled(i, currentYear),
selected: isMonthSelected(i)
}
})
Expand All @@ -3685,6 +3681,25 @@ export const Calendar = React.memo(
return null;
};

const isMonthYearDisabled = (month, year) => {
const daysCountInAllMonth = month === -1 ? new Array(12).fill(0).map((_, i) => getDaysCountInMonth(i, year)) : [getDaysCountInMonth(month, year)];

for (let i = 0; i < daysCountInAllMonth.length; i++) {
const monthDays = daysCountInAllMonth[i];
const _month = month === -1 ? i : month;

for (let day = 1; day <= monthDays; day++) {
let isDateSelectable = isSelectable(day, _month, year);

if (isDateSelectable) {
return false;
}
}
}

return true;
};

const createYearPicker = () => {
if (currentView === 'year') {
const yearPickerProps = mergeProps(
Expand All @@ -3699,17 +3714,17 @@ export const Calendar = React.memo(
{yearPickerValues().map((y, i) => {
const yearProps = mergeProps(
{
className: cx('year', { isYearSelected, isSelectable, y }),
className: cx('year', { isYearSelected, isSelectable, y, isMonthYearDisabled }),
onClick: (event) => onYearSelect(event, y),
'data-p-highlight': isYearSelected(y),
'data-p-disabled': !isSelectable(0, -1, y)
'data-p-disabled': isMonthYearDisabled(-1, y)
},
ptm('year', {
context: {
year: y,
yearIndex: i,
selected: isYearSelected(y),
disabled: !isSelectable(0, -1, y)
disabled: isMonthYearDisabled(-1, y)
}
})
);
Expand Down
93 changes: 93 additions & 0 deletions components/lib/calendar/Calendar.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { PrimeReactProvider } from '../api/Api';
import { Calendar } from './Calendar';

describe('Calendar', () => {
function getAllDatesOfYear(year) {
let startDate = new Date(year, 0, 1);
let endDate = new Date(year, 11, 31);

let dates = [];
let currentDate = startDate;

while (currentDate <= endDate) {
dates.push(new Date(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}

return dates;
}

test('When the days of the year are disabled, then the years and month should be disabled', async () => {
const { container } = render(
<PrimeReactProvider>
<Calendar value={new Date(2023, 11, 15)} inline view="year" disabledDates={getAllDatesOfYear(2023)} />
</PrimeReactProvider>
);

const years = container.querySelectorAll('.p-yearpicker-year');

for (const year of years) {
if (year.innerHTML === '2023') {
expect(year).toHaveAttribute('data-p-disabled', 'true');
expect(year).toHaveClass('p-disabled');
} else {
expect(year).toHaveAttribute('data-p-disabled', 'false');
expect(year).not.toHaveClass('p-disabled');
}
}

const { container: monthContainer } = render(
<PrimeReactProvider>
<Calendar value={new Date(2023, 11, 15)} inline view="month" disabledDates={getAllDatesOfYear(2023)} />
</PrimeReactProvider>
);

const months = monthContainer.querySelectorAll('.p-monthpicker-month');

for (const month of months) {
expect(month).toHaveAttribute('data-p-disabled', 'true');
expect(month).toHaveClass('p-disabled');
}
});

test('If any day of the month is not disabled, then both the year and month can be selected', async () => {
const disabledDates = getAllDatesOfYear(2023);

// January and December are not disabled.
disabledDates.shift();
disabledDates.pop();

const { container: yearContainer } = render(
<PrimeReactProvider>
<Calendar value={new Date(2023, 11, 15)} inline view="year" disabledDates={disabledDates} />
</PrimeReactProvider>
);
const years = yearContainer.querySelectorAll('.p-yearpicker-year');

for (const year of years) {
expect(year).toHaveAttribute('data-p-disabled', 'false');
expect(year).not.toHaveClass('p-disabled');
}

// month
const { container: monthContainer } = render(
<PrimeReactProvider>
<Calendar value={new Date(2023, 11, 15)} inline view="month" disabledDates={disabledDates} />
</PrimeReactProvider>
);

const months = monthContainer.querySelectorAll('.p-monthpicker-month');

Array.from(months).forEach((month, index) => {
if (index === 0 || index === 11) {
expect(month).toHaveAttribute('data-p-disabled', 'false');
expect(month).not.toHaveClass('p-disabled');
} else {
expect(month).toHaveAttribute('data-p-disabled', 'true');
expect(month).toHaveClass('p-disabled');
}
});
});
});
4 changes: 2 additions & 2 deletions components/lib/calendar/CalendarBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ const classes = {
clearButton: 'p-button-text',
footer: 'p-datepicker-footer',
yearPicker: 'p-yearpicker',
year: ({ isYearSelected, isSelectable, y }) => classNames('p-yearpicker-year', { 'p-highlight': isYearSelected(y), 'p-disabled': !isSelectable(0, -1, y) }),
year: ({ isYearSelected, y, isMonthYearDisabled }) => classNames('p-yearpicker-year', { 'p-highlight': isYearSelected(y), 'p-disabled': isMonthYearDisabled(-1, y) }),
monthPicker: 'p-monthpicker',
month: ({ isMonthSelected, isSelectable, i, currentYear }) => classNames('p-monthpicker-month', { 'p-highlight': isMonthSelected(i), 'p-disabled': !isSelectable(0, i, currentYear) }),
month: ({ isMonthSelected, isMonthYearDisabled, i, currentYear }) => classNames('p-monthpicker-month', { 'p-highlight': isMonthSelected(i), 'p-disabled': isMonthYearDisabled(i, currentYear) }),
hourPicker: 'p-hour-picker',
secondPicker: 'p-second-picker',
minutePicker: 'p-minute-picker',
Expand Down

0 comments on commit 05a83b4

Please sign in to comment.