UNPKG

@chayns-components/date

Version:

A set of beautiful React components for developing your own applications with chayns.

230 lines • 8.33 kB
import { Checkbox, Popup, useElementSize } from '@chayns-components/core'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { HintTextPosition } from '../../types/openingTimes'; import HintText from './hint-text/HintText'; import OpeningInputs from './opening-inputs/OpeningInputs'; import { StyledOpeningTimes, StyledOpeningTimesTooltipContent, StyledOpeningTimesWeekDay, StyledOpeningTimesWrapper } from './OpeningTimes.styles'; const OpeningTimes = ({ closedText = 'closed', currentDayId, editMode = false, hintText, hintTextPosition = HintTextPosition.Bottom, openingTimes, weekdays, onChange, onTimeAdd, onTimeRemove }) => { const [newOpeningTimes, setNewOpeningTimes] = useState(); const [invalidOpeningTimes, setInvalidOpeningTimes] = useState([]); const [isPopupOpen, setIsPopupOpen] = useState(false); const ref = useRef(null); const popupRef = useRef(null); useEffect(() => { setNewOpeningTimes(openingTimes); }, [openingTimes]); const validateTime = useCallback((newTime, dayId) => { if (newTime.start === newTime.end || newTime.start >= newTime.end) { return false; } const dayTimes = newOpeningTimes?.find(day => day.id === dayId)?.times || []; return dayTimes.every(time => time.id === newTime.id || newTime.end <= time.start || newTime.start >= time.end); }, [newOpeningTimes]); const handleCheckBoxChange = useCallback(id => { setNewOpeningTimes(prevOpeningTimes => { const updatedOpeningTimes = (prevOpeningTimes ?? []).map(openingTime => { if (openingTime.id === id) { return { ...openingTime, isDisabled: !openingTime.isDisabled }; } return openingTime; }); if (typeof onChange === 'function') { onChange({ enabledDays: updatedOpeningTimes.filter(item => !item.isDisabled).map(item => item.id) }); } return updatedOpeningTimes; }); }, [onChange]); const handleChange = useCallback((newTime, id) => { const isValid = validateTime(newTime, id); setNewOpeningTimes(prevOpeningTimes => { const updatedOpeningTimes = (prevOpeningTimes ?? []).map(openingTime => { if (openingTime.id === id) { const newTimes = openingTime.times.map(time => { if (time.id === newTime.id) { return newTime; } return time; }); return { ...openingTime, times: newTimes }; } return openingTime; }); const changedOpeningTime = updatedOpeningTimes.find(updatedOpeningTime => updatedOpeningTime.id === id); if (typeof onChange === 'function') { onChange({ isValid, dayId: changedOpeningTime?.id, time: newTime }); } return updatedOpeningTimes; }); }, [onChange, validateTime]); const handleAdd = useCallback((time, id) => { const isValid = validateTime(time, id); if (typeof onTimeAdd === 'function') { onTimeAdd({ time, dayId: id, isValid }); } setNewOpeningTimes(prevOpeningTimes => (prevOpeningTimes ?? []).map(openingTime => { if (openingTime.id === id) { return { ...openingTime, times: [...openingTime.times, time] }; } return openingTime; })); }, [onTimeAdd, validateTime]); const handleUpdateInvalidIds = useCallback((openingTimeId, invalidTimeIds) => { setInvalidOpeningTimes(prevState => { const updatedInvalidOpeningTimes = prevState.map(invalidOpeningTime => { if (invalidOpeningTime.openingTimeId === openingTimeId) { return { openingTimeId, invalidTimeIds }; } return invalidOpeningTime; }); if (!updatedInvalidOpeningTimes.some(({ openingTimeId: updatedInvalidOpeningId }) => updatedInvalidOpeningId === openingTimeId) && invalidTimeIds.length > 0) { updatedInvalidOpeningTimes.push({ openingTimeId, invalidTimeIds }); } return updatedInvalidOpeningTimes.filter(updatedInvalidOpeningTime => updatedInvalidOpeningTime.invalidTimeIds.length !== 0); }); }, []); const handleRemove = useCallback(id => { setNewOpeningTimes(prevOpeningTimes => (prevOpeningTimes ?? []).map(openingTime => { const newTimes = openingTime.times.filter(time => time.id !== id); return { ...openingTime, times: newTimes }; })); if (typeof onTimeRemove === 'function') { onTimeRemove(id); } }, [onTimeRemove]); const content = useMemo(() => { const items = []; if (!newOpeningTimes) { return items; } newOpeningTimes.forEach(({ times, id, weekdayId, isDisabled }) => { const weekday = weekdays.find(weekDay => weekDay.id === weekdayId)?.name; if (!weekday) { return; } items.push(/*#__PURE__*/React.createElement(StyledOpeningTimesWrapper, { key: `openingTimes__${id}` }, editMode ? /*#__PURE__*/React.createElement(Checkbox, { isChecked: !isDisabled, onChange: () => handleCheckBoxChange(id) }, weekday) : /*#__PURE__*/React.createElement(StyledOpeningTimesWeekDay, null, weekday), /*#__PURE__*/React.createElement(OpeningInputs, { closedText: closedText, currentDayId: currentDayId, id: id, times: times, isDisabled: isDisabled, onInvalid: handleUpdateInvalidIds, onChange: newTime => handleChange(newTime, id), onRemove: handleRemove, onAdd: handleAdd, editMode: editMode }))); }); return items; }, [closedText, currentDayId, editMode, handleAdd, handleChange, handleCheckBoxChange, handleRemove, handleUpdateInvalidIds, newOpeningTimes, weekdays]); const size = useElementSize(ref); const hidePopup = useCallback(() => { setIsPopupOpen(false); popupRef.current?.hide(); }, []); const showPopup = useCallback(() => { setIsPopupOpen(true); popupRef.current?.show(); }, []); const displayedContent = useMemo(() => { if (!currentDayId || editMode) { return content; } const singleDay = newOpeningTimes?.find(({ id }) => id === currentDayId); if (!singleDay) { return content; } const { id, times, weekdayId } = singleDay; const weekday = weekdays.find(weekDay => weekDay.id === weekdayId)?.name; return /*#__PURE__*/React.createElement(StyledOpeningTimesWrapper, { key: `currentDay__${currentDayId}`, style: size && { width: size.width }, onMouseEnter: showPopup, onMouseLeave: hidePopup, onClick: () => isPopupOpen ? hidePopup() : showPopup() }, /*#__PURE__*/React.createElement(Popup, { onShow: () => setIsPopupOpen(true), onHide: () => setIsPopupOpen(false), ref: popupRef, content: /*#__PURE__*/React.createElement(StyledOpeningTimesTooltipContent, { key: "opening-time-tooltip" }, content) }, /*#__PURE__*/React.createElement(StyledOpeningTimesWeekDay, null, weekday)), /*#__PURE__*/React.createElement(OpeningInputs, { closedText: closedText, currentDayId: currentDayId, onInvalid: handleUpdateInvalidIds, id: id, times: times, editMode: editMode })); }, [currentDayId, editMode, newOpeningTimes, weekdays, size, showPopup, hidePopup, content, closedText, handleUpdateInvalidIds, isPopupOpen]); const shouldShowHint = useMemo(() => invalidOpeningTimes.length > 0, [invalidOpeningTimes.length]); return useMemo(() => /*#__PURE__*/React.createElement(StyledOpeningTimes, { ref: ref }, shouldShowHint && hintText && hintTextPosition === HintTextPosition.Top && /*#__PURE__*/React.createElement(HintText, { text: hintText }), displayedContent, shouldShowHint && hintText && hintTextPosition === HintTextPosition.Bottom && /*#__PURE__*/React.createElement(HintText, { text: hintText })), [displayedContent, hintText, hintTextPosition, shouldShowHint]); }; OpeningTimes.displayName = 'OpeningTimes'; export default OpeningTimes; //# sourceMappingURL=OpeningTimes.js.map