UNPKG

@parkassist/pa-ui-library

Version:
370 lines (369 loc) 12.7 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import React, { useEffect, useState } from "react"; import DayRangePicker from "./DateRangeCalendar2"; import { Column, Row } from "../Layout/Flex"; import Modal from "../Modal"; import styled from "styled-components"; import "react-day-picker/lib/style.css"; import { Separator } from "../../index"; import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import { ExpandMore } from "@mui/icons-material"; import Typography from "@mui/material/Typography"; import FontStyles from "../../constants/FontStyles"; import { ClockSquareIcon } from "../Icons"; import AccordionDetails from "@mui/material/AccordionDetails"; import FormControl from "@mui/material/FormControl"; import RadioGroup from "@mui/material/RadioGroup"; import FormControlLabel from "@mui/material/FormControlLabel"; import Radio from "@mui/material/Radio"; import DaysPicker from "./DaysPicker"; import TimeRangePicker from "./TimeRangePicker"; import dayjs from "dayjs"; import Helmet from "react-helmet"; import Palette from "../../constants/Palette"; import { StyledEngineProvider } from "@mui/material/styles"; import * as Icons from "../Icons"; import { formatToDesiredTimezone, formatToLocalTimezone } from '../DateRangePicker'; import MaterialInput from '../MaterialInput'; const SelectorWrapper = styled.div(() => ({ marginTop: 0 })); const LabelWrapper = styled(Row)(() => ({ marginBottom: 1, font: FontStyles.LABEL_FONT })); const FakeSelector = styled.div(({ width, backgroundColor, borderColor }) => ({ width, minWidth: 180, display: "flex", paddingLeft: 8, alignItems: "center", backgroundColor, border: `1px solid ${borderColor}`, borderRadius: 3, color: Palette.BLACK, height: 32 })); const timeTabs = (selectDayOfTheWeekText, selectTimePeriodText, selectTimeScheduleText) => [{ name: "DAY_OF_WEEK", value: "0", label: selectDayOfTheWeekText || "Select Day of the Week" }, { name: "TIME_PERIOD", value: "1", label: selectTimePeriodText || "Select Time Period" }, { name: "TIME_SCHEDULE", value: "2", label: selectTimeScheduleText || "Select Time Schedule" }]; const NewDateRangePickerComponent = ({ from, to, hourFrom = "00:00:00", hourTo = "23:59:59", onUpdate = () => null, width, label = null, backgroundColor = Palette.WHITE, borderColor = Palette.DIM_GREY, hideHourFilter = false, allowedTabs = ["DAY_OF_WEEK", "TIME_PERIOD", "TIME_SCHEDULE"], timezoneId, rangeLimit, minDate, maxDate, isAmPm = true, minimalDateFormat = "M/DD", compactDateFormat = "YYYY-MM-DD hh:mm a", weekStartsOn = 0, useMaterialInput = true, showSelectedDays = false, title = "Date and time range", saveText = "Save", locale, selectDayOfTheWeekText = "Select Day of the Week", selectTimePeriodText = "Select Time Period", selectTimeScheduleText = "Select Time Schedule", startText = "Start", endText = "End", detailedRangeText = "Detailed range", everydayFromText = "Everyday From", everydayToText = "Everyday To", days = null, timeStaticRanges = {} }) => { var _a; const tabs = timeTabs(selectDayOfTheWeekText, selectTimePeriodText, selectTimeScheduleText).filter(tab => allowedTabs.includes(tab.name)); const [open, setOpen] = useState(false); const [hourRange, setHourRange] = useState([hourFrom, hourTo, isAmPm]); const [partialDate, setPartialDate] = useState(JSON.parse(JSON.stringify({ from, to }))); const compactTimeFormat = hourRange[2] ? "hh:mm a" : "HH:mm"; const [timeRange, setTimeRange] = useState({ hourFrom: dayjs(hourFrom, 'HH:mm:ss'), hourTo: dayjs(hourTo, 'HH:mm:ss') }); const [radioValue, setRadioValue] = React.useState(((_a = tabs[0]) === null || _a === void 0 ? void 0 : _a.value) || "0"); const [daysOfWeek, setDaysOfWeek] = React.useState({ monday: true, tuesday: true, wednesday: true, thursday: true, friday: true, saturday: true, sunday: true }); const [selectedDays, setSelectedDays] = React.useState(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]); useEffect(() => { let isMounted = true; if (isMounted) { setPartialDate(JSON.parse(JSON.stringify({ from, to }))); setHourRange([dayjs(hourFrom, 'HH:mm:ss').format(compactTimeFormat), dayjs(hourTo, 'HH:mm:ss').format(compactTimeFormat), isAmPm]); } return () => { isMounted = false; }; }, [to, from, hourFrom, hourTo]); const selectorWidth = width || (hideHourFilter ? 120 : "auto"); const rangeToZeroHour = range => { const fromResult = dayjs(partialDate.from).tz(timezoneId).startOf("day"); const toResult = dayjs(partialDate.to).tz(timezoneId).endOf("day"); const hourFrom = range.hourFrom.date(fromResult.date()).month(fromResult.month()).year(fromResult.year()).format(); const hourTo = range.hourTo.date(toResult.date()).month(toResult.month()).year(toResult.year()).format(); setHourRange([dayjs(hourFrom).format(compactTimeFormat), dayjs(hourTo).format(compactTimeFormat), isAmPm]); return { from: fromResult.format(), to: toResult.format(), hourFrom, hourTo }; }; const togglePopover = () => setOpen(!open); const forceClosePopover = () => setOpen(false); const toToShow = formatToLocalTimezone(partialDate.to); const fromToShow = formatToLocalTimezone(partialDate.from); const format = date => dayjs(date).format(minimalDateFormat); let textToShow = `${format(fromToShow)} - ${format(toToShow)}`; if (!hideHourFilter) textToShow += ` — ${hourRange[0]} - ${hourRange[1]}`; const mobile = window.innerWidth < 900; const confirmChanges = () => { const range = timeRange; let dayNames = []; Object.entries(daysOfWeek).map(([key, value]) => { if (value) { dayNames.push(key); } return dayNames; }); setSelectedDays(dayNames); onUpdate(rangeToZeroHour(range)); forceClosePopover(); }; const handleChange = e => { setRadioValue(e.target.value); }; const handleSelectedDays = days => { setDaysOfWeek(days); }; const handleSelectedHours = hours => { setTimeRange(Object.assign(Object.assign({}, timeRange), { hourFrom: hours.hourFrom, hourTo: hours.hourTo })); }; const btnDisabled = () => { const from = dayjs(timeRange.hourFrom, 'HH:mm:ss'); const to = dayjs(timeRange.hourTo, 'HH:mm:ss'); return from.isAfter(to); }; return _jsxs(StyledEngineProvider, { injectFirst: true, children: [_jsx(Modal, { hideButtons: false, visible: open, modalTitle: title, onClose: () => { setPartialDate(JSON.parse(JSON.stringify({ from, to }))); forceClosePopover(); }, onConfirm: () => { confirmChanges(); }, okDisabled: btnDisabled(), width: mobile ? 350 : 920, height: 900, okButton: saveText, padding: "24px", children: _jsxs(Column, { style: { width: "100%", height: "100%", font: FontStyles.BODY2_FONT }, children: [_jsx(DayRangePicker, { weekStartsOn: weekStartsOn, rangeLimit: rangeLimit, minDate: minDate, maxDate: maxDate, locale: locale, timeStaticRanges: timeStaticRanges, update: range => { const preferedZoneStr = timezoneId; if (!range.selection.startDate || !range.selection.endDate) { return; } const from = formatToDesiredTimezone(range.selection.startDate, preferedZoneStr).startOf("day"); const to = formatToDesiredTimezone(range.selection.endDate, preferedZoneStr).endOf("day"); setPartialDate({ from, to }); }, to: toToShow, from: fromToShow, timezoneId: timezoneId }), !hideHourFilter && _jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(Row, { style: { width: "auto" }, children: _jsxs(Accordion, { children: [_jsx(AccordionSummary, { expandIcon: _jsx(ExpandMore, {}), "aria-controls": "panel1a-content", id: "panel1a-header", children: _jsxs(Typography, { style: { display: "flex", flexDirection: "row" }, children: [_jsx(ClockSquareIcon, { style: { marginRight: 16 } }), " ", detailedRangeText] }) }), _jsxs(AccordionDetails, { children: [_jsx(FormControl, { children: _jsx(RadioGroup, { row: true, name: "row-radio-buttons-group", value: radioValue, onChange: handleChange, children: tabs.map(tab => _jsx(FormControlLabel, { value: tab.value, control: _jsx(Radio, {}), label: tab.label })) }) }), radioValue === "0" && _jsx(DaysPicker, { days: days, selectedWeekDays: handleSelectedDays }), radioValue === "1" && _jsx(TimeRangePicker, { timeRange: timeRange, labelFrom: startText, labelTo: endText, selectedHours: hour => handleSelectedHours(hour), periodRange: true }), radioValue === "2" && _jsx(TimeRangePicker, { timeRange: timeRange, labelFrom: everydayFromText, labelTo: everydayToText, selectedHours: hour => handleSelectedHours(hour), scheduleRange: true })] })] }) })] })] }) }), useMaterialInput ? _jsx(SelectorWrapper, { style: { width: selectorWidth }, children: _jsx(MaterialInput, { label: label, iconEnd: _jsx(Icons.CalendarIcon, { onClick: () => togglePopover() }), fullWidth: true, onFocus: () => togglePopover(), value: textToShow, readOnly: true }) }) : _jsxs(SelectorWrapper, { children: [label && _jsx(LabelWrapper, { children: label }), _jsx(FakeSelector, { width: selectorWidth, backgroundColor: backgroundColor, borderColor: borderColor, onClick: () => togglePopover(), children: _jsxs(Row, { style: { font: FontStyles.BODY1_FONT }, children: [_jsx(Column, { style: { marginRight: 8, marginTop: 1 }, children: _jsx(Icons.CalendarIcon, { size: 15 }) }), _jsx(Column, { children: textToShow })] }) })] }), showSelectedDays && _jsx(Row, { children: _jsxs(Column, { children: [_jsx(LabelWrapper, { children: "Selected days of week:" }), selectedDays.map((day, i) => _jsx("div", { children: day }, i))] }) }), _jsx(Helmet, { children: _jsx("style", { children: ` .MuiAccordionDetails-root .MuiFormControl-root, .MuiAccordion-root.MuiPaper-root { width: 100%; margin-bottom: 24px; } .Mui-checked.MuiRadio-root.MuiRadio-colorPrimary { color: ${Palette.BLACK}; } .MuiPickersClock-pin, .MuiPickersClockPointer-pointer, .MuiPickersClockPointer-noPoint, .MuiPickersToolbar-toolbar { background-color: ${Palette.BLACK}; } .MuiPickersClockPointer-thumb { border-color: ${Palette.BLACK}; } .MuiButton-textPrimary { color: ${Palette.BLACK}; } ` }) })] }); }; export default NewDateRangePickerComponent;