Skip to content
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

Фикс кликов в слайдере #71

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 36 additions & 48 deletions src/components/SliderCalendar/SliderCalendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
startOfMonth,
lastDayOfMonth,
setMonth,
parseISO,
isSameDay,
differenceInCalendarDays,
getMonth,
getUnixTime,
fromUnixTime,
isWeekend,
differenceInCalendarDays,
} from 'date-fns'
import PropTypes from 'prop-types'
import Carousel, { slidesToShowPlugin, arrowsPlugin } from '@brainhubeu/react-carousel'
Expand All @@ -18,50 +18,22 @@ import { toDatetime } from '@/utils/dateLib'

import './Slider.scss'

// собирает все дни текущего месяца в массив с датами
function generateMonthDates(month) {
const dates = eachDayOfInterval({
start: startOfMonth(setMonth(new Date(), month)),
end: lastDayOfMonth(setMonth(new Date(), month)),
})

return dates
}

// преобразоввывает массив с днями в финальный массив вида [[Date, 'disabled'], [Date, '']],
// отключает прошлые дни и дни из disabledDates
function sortDates(dates, disabledDates) {
dates.forEach((date, index) => {
dates[index] = [date, '']

const diffInDays = differenceInCalendarDays(new Date(), date)
if (diffInDays > 0) {
dates[index][1] = 'disabled'
}
if (disabledDates.some((dDate) => isSameDay(parseISO(dDate), date))) {
dates[index][1] = 'disabled'
}
})

return dates
}

// генерируется разметка всех дней месяца, для активных дней устанавливаются нужные классы,
// для выключенных тоже
function generateDays(dates, dailyClasses) {
const days = dates.map((dateArr) => {
const date = dateArr[0]
const isDisabled = dateArr[1]
function generateDays(dates, dailyClasses, disabledDates, clickHandler) {
const days = dates.map((date) => {
const dateUnix = getUnixTime(date)
const disabled = disabledDates.includes(toDatetime(date)) ? 'disabled' : ''
const weekend = isWeekend(date) ? 'weekend' : ''
const daily = dailyClasses[toDatetime(date)] || ''

return (
<button
id={dateUnix}
key={dateUnix}
className={`text-white rounded ${isDisabled} ${isWeekend(date) ? 'weekend' : ''} ${
dailyClasses[toDatetime(date)] || ''
} `}
className={`text-white rounded ${disabled} ${weekend} ${daily}`}
style={{ width: '90%', height: '4rem', border: '0' }}
onClick={(e) => clickHandler(fromUnixTime(e.currentTarget.id))}
>
<div className="d-flex flex-column justify-content-center align-items-center">
<p className="mb-2">{date.toLocaleDateString('ru-RU', { weekday: 'short' })}</p>
Expand All @@ -76,6 +48,14 @@ function generateDays(dates, dailyClasses) {
return days
}

// собирает все дни текущего месяца в массив с датами
function generateMonthDates(month) {
return eachDayOfInterval({
start: startOfMonth(setMonth(new Date(), month)),
end: lastDayOfMonth(setMonth(new Date(), month)),
})
}

export default function SliderCalendar({
onChange = () => {},
value,
Expand All @@ -84,24 +64,32 @@ export default function SliderCalendar({
disabledDates = [],
show = true,
}) {
const today = new Date()
const month = value.getMonth()

const [dates, setDates] = useState(sortDates(generateMonthDates(month), disabledDates))
const [monthDates, setMonthDates] = useState(generateMonthDates(getMonth(today)))

useEffect(() => {
setDates(sortDates(generateMonthDates(month), disabledDates))
}, [month, disabledDates])
// Добавляем в 'выключенные' все прошедшие дни
const disabledDates2 = [...disabledDates] // копируем пропс, ибо они рид-онли
monthDates.forEach((date) => {
if (differenceInCalendarDays(today, date) > 0) {
disabledDates2.push(toDatetime(date))
}
})

const days = generateDays(dates, dailyClasses, onChange)
useEffect(() => {
setMonthDates(generateMonthDates(month))
}, [month])

// вызывает коллбек с новым date, если день не отключен
function onDateChange(index) {
// проверка из-за неправильного поведения слайдера, при клике на любой слайд он выбрасывает NaN
if (!Number.isNaN(index)) {
if (!dates[index].includes('disabled')) onChange(dates[index][0])
function onDateChange(newDate) {
if (typeof newDate !== 'undefined') {
if (!disabledDates2.includes(toDatetime(newDate))) onChange(newDate)
}
}

const days = generateDays(monthDates, dailyClasses, disabledDates2, onDateChange)

if (show) {
return (
<Carousel
Expand All @@ -127,7 +115,7 @@ export default function SliderCalendar({
]}
clickToChange
value={getDate(value) - 1}
onChange={onDateChange}
onChange={(index) => onDateChange(monthDates[index])}
animationSpeed={150}
>
{days}
Expand Down