date-fns#isSameMonth TypeScript Examples

The following examples show how to use date-fns#isSameMonth. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: GraphUtils.ts    From cashcash-desktop with MIT License 6 votes vote down vote up
static reduceByMonth(
        splitList: GraphSplit[],
        useOriginalCurrency: boolean = false,
    ): GraphSplit[] {
        const amountField = useOriginalCurrency ? 'originalAmount' : 'amount';
        return splitList.reduce((list: GraphSplit[], s: GraphSplit) => {
            s.transactionDate = startOfMonth(s.transactionDate);
            if (
                list.length === 0 ||
                !isSameMonth(list[list.length - 1].transactionDate, s.transactionDate)
            ) {
                list.push(s);
            } else {
                list[list.length - 1][amountField] += s[amountField];
            }
            return list;
        }, []);
    }
Example #2
Source File: GraphUtils.ts    From cashcash-desktop with MIT License 6 votes vote down vote up
static reduceByAddingEmptyMonth(
        splitList: GraphSplit[],
        fromDate: Date,
        toDate: Date,
        key: string,
    ): GraphSplit[] {
        const result: GraphSplit[] = [];
        const startOfMonthFromDate = startOfMonth(fromDate);
        const toDateStartOfMonth = startOfMonth(toDate);
        let currentDate = toDateStartOfMonth;
        let index = 0;
        const ids = CashAccountUtils.extractKey(key);
        while (currentDate >= startOfMonthFromDate) {
            const currentSplit = splitList[index];
            if (currentSplit && isSameMonth(currentSplit.transactionDate, currentDate)) {
                result.push(currentSplit);
                index++;
            } else {
                result.push({
                    accountId: ids.accountId,
                    currencyId: ids.currencyId,
                    amount: 0,
                    transactionDate: currentDate,
                    originalCurrencyId: ids.currencyId,
                    originalAmount: 0,
                });
            }
            currentDate = subMonths(currentDate, 1);
        }
        return result;
    }
Example #3
Source File: DateRangePicker.tsx    From UUI with MIT License 4 votes vote down vote up
DateRangePicker = UUIFunctionComponent({
  name: 'DateRangePicker',
  nodes: {
    Root: 'div',
    ConnectIcon: Icons.ArrowRight,
    CalendarIcon: Icons.Calendar,
    Popover: UUIPopover,
    TextField: UUITextField,
    Activator: 'div',
    Container: 'div',
    Toolbar: 'div',
    Main: 'div',
    StartSection: 'div',
    EndSection: 'div',
    YearMonthSelect: UUIYearMonthSelect,
    DateSelect: UUIDateSelect,
    DateTimeShortcut: UUIDateTimeShortcut,
  },
  propTypes: DateRangePickerPropTypes,
}, (props: DateRangePickerFeatureProps, { nodes }) => {
  const {
    Root, ConnectIcon, CalendarIcon, Popover, TextField,
    Activator, Container, Toolbar, Main, StartSection, EndSection,
    YearMonthSelect, DateSelect, DateTimeShortcut,
  } = nodes

  const startInputRef = useRef<HTMLInputElement | null>(null)
  const endInputRef = useRef<HTMLInputElement | null>(null)
  const [whichFocusing, setWhichFocusing] = useState<'start' | 'end'>()
  const [active, setActive] = useState(false)

  const [hoverDate, setHoverDate] = useState<Date>()

  const initialInnerValue = useMemo<DateRangePickerInnerValue>(() => {
    if (props.value === null) {
      return {
        startDate: null,
        endDate: null,
        startInput: '',
        endInput: '',
        startYearMonth: startOfMonth(new Date),
        endYearMonth: add(startOfMonth(new Date), { months: 1 }),
      }
    }
    return {
      startDate: props.value[0],
      endDate: props.value[1],
      startInput: formatDate(props.value[0]),
      endInput: formatDate(props.value[1]),
      startYearMonth: startOfMonth(props.value[0]),
      endYearMonth: isSameMonth(props.value[0], props.value[1]) ? add(startOfMonth(props.value[1]), { months: 1 }) : props.value[1],
    }
  }, [props.value])
  const [innerValue, setInnerValue, resetInnerValue] = usePendingValue<DateRangePickerInnerValue>(initialInnerValue, (value) => {
    if (value.startDate && value.endDate) {
      handleValueOnChange([value.startDate, value.endDate])
      setActive(false)
    }
  }, { resetWhenInitialValueChanged: true })

  const selectedDates = useMemo(() => {
    return compact([innerValue.startDate, innerValue.endDate])
  }, [innerValue.endDate, innerValue.startDate])

  const handleValueOnChange = useCallback((value: [Date, Date] | null) => {
    const sortedValue = value?.sort((i, j) => Number(i) - Number(j)) || null
    props.onChange(sortedValue)
  }, [props])
  /**
   *
   */
  const handleInputOnSubmit = useCallback((type: 'start' | 'end') => {
    if (innerValue.startDate && innerValue.endDate) {
      const originalInput = formatDate(props.value && (type === 'start' ? props.value[0] : props.value[1]))
      const input = type === 'start' ? innerValue.startInput : innerValue.endInput
      if (originalInput === input) return;
      try {
        if (input === '') {
          handleValueOnChange(null)
        } else {
          const result = tryParseDateFromString(input)
          handleValueOnChange(type === 'start' ? [result, innerValue.endDate] : [innerValue.startDate, result])
        }
      } catch {
        resetInnerValue()
      }
    }
  }, [handleValueOnChange, innerValue.endInput, innerValue.endDate, innerValue.startInput, innerValue.startDate, props.value, resetInnerValue])
  /**
   * handle user change year or month in YearMonthSelect.
   */
  const handleStartYearMonthSelect = useCallback((value: Date) => {
    setInnerValue((oldValue) => {
      const startYearMonthDate = value
      let endYearMonthDate = oldValue.endYearMonth
      if (!isBefore(startYearMonthDate, endYearMonthDate)) {
        endYearMonthDate = add(startYearMonthDate, { months: 1 })
      }
      return {
        ...oldValue,
        startYearMonth: startYearMonthDate,
        endYearMonth: endYearMonthDate,
      }
    })
  }, [setInnerValue])
  const handleEndYearMonthSelect = useCallback((value: Date) => {
    setInnerValue((oldValue) => {
      const endYearMonthDate = value
      let startYearMonthDate = oldValue.startYearMonth
      if (!isAfter(endYearMonthDate, startYearMonthDate)) {
        startYearMonthDate = add(endYearMonthDate, { months: -1 })
      }
      return {
        ...oldValue,
        startYearMonth: startYearMonthDate,
        endYearMonth: endYearMonthDate,
      }
    })
  }, [setInnerValue])
  /**
   * handle user select date in DateSelect.
   */
  const handleDateSelect = useCallback((value: Date) => {
    let shouldSubmit = false
    let newStartValue = innerValue.startDate
    let newEndValue = innerValue.endDate
    if (
      (newStartValue !== null && newEndValue !== null) ||
      (newStartValue === null && newEndValue === null)
    ) {
      if (whichFocusing === 'end') {
        newStartValue = null
        newEndValue = value
      } else {
        newStartValue = value
        newEndValue = null
      }
    } else {
      if (newStartValue === null) newStartValue = value
      if (newEndValue === null) newEndValue = value
      if (isAfter(newStartValue, newEndValue)) {
        const tmp = new Date(newStartValue)
        newStartValue = new Date(newEndValue)
        newEndValue = tmp
      }
      shouldSubmit = true
    }
    setInnerValue((oldValue) => {
      return {
        ...oldValue,
        startDate: newStartValue,
        startInput: formatDate(newStartValue),
        endDate: newEndValue,
        endInput: formatDate(newEndValue),
      }
    }, shouldSubmit)
  }, [innerValue.endDate, innerValue.startDate, setInnerValue, whichFocusing])

  return (
    <Root>
      <Popover
        placement={'bottom-start'}
        active={active}
        onClickAway={() => { setActive(false); resetInnerValue(); }}
        activator={
          <Activator
            onClick={() => {
              setActive(true)
              setTimeout(() => {
                if (whichFocusing === undefined && startInputRef.current) {
                  startInputRef.current.focus()
                }
              }, 0)
            }}
          >
            <TextField
              placeholder={props.startPlaceholder}
              value={innerValue.startInput}
              onChange={(value) => { setInnerValue((oldValue) => ({ ...oldValue, startInput: value })) }}
              customize={{
                Input: {
                  ref: startInputRef,
                  onFocus: () => {
                    setWhichFocusing('start')
                  },
                  onBlur: () => {
                    setWhichFocusing(undefined)
                    handleInputOnSubmit('start')
                  },
                  onKeyDown: (event) => {
                    if (event.key === 'Enter') {
                      handleInputOnSubmit('start')
                    }
                  }
                }
              }}
            />
            <ConnectIcon />
            <TextField
              placeholder={props.endPlaceholder}
              value={innerValue.endInput}
              onChange={(value) => { setInnerValue((oldValue) => ({ ...oldValue, endInput: value })) }}
              customize={{
                Input: {
                  ref: endInputRef,
                  onFocus: () => {
                    setWhichFocusing('end')
                  },
                  onBlur: () => {
                    setWhichFocusing(undefined)
                    handleInputOnSubmit('end')
                  },
                  onKeyDown: (event) => {
                    if (event.key === 'Enter') {
                      handleInputOnSubmit('end')
                    }
                  }
                }
              }}
            />
            <CalendarIcon />
          </Activator>
        }
      >
        <Container>
          <Toolbar>
            {props.shortcuts && (
              <DateTimeShortcut
                options={props.shortcuts}
                onSelect={(value) => {
                  handleValueOnChange(value)
                  setActive(false)
                }}
              />
            )}
          </Toolbar>
          <Main tabIndex={-1}>
            <StartSection>
              <YearMonthSelect
                value={innerValue.startYearMonth}
                onChange={handleStartYearMonthSelect}
              />
              <DateSelect
                yearMonth={innerValue.startYearMonth}
                selectedDates={selectedDates}
                onSelect={handleDateSelect}
                hoverDate={hoverDate}
                onHoverDateChange={(date) => { setHoverDate(date) }}
              />
            </StartSection>
            <EndSection>
              <YearMonthSelect
                value={innerValue.endYearMonth}
                onChange={handleEndYearMonthSelect}
              />
              <DateSelect
                yearMonth={innerValue.endYearMonth}
                selectedDates={selectedDates}
                onSelect={handleDateSelect}
                hoverDate={hoverDate}
                onHoverDateChange={(date) => { setHoverDate(date) }}
              />
            </EndSection>
          </Main>
        </Container>
      </Popover>
    </Root>
  )
})
Example #4
Source File: DateSelect.tsx    From UUI with MIT License 4 votes vote down vote up
DateSelect = UUIFunctionComponent({
  name: 'DateSelect',
  nodes: {
    Root: 'div',
    Calendar: 'div',
    WeekGrid: 'div',
    WeekItem: 'div',
    DayGrid: 'div',
    DayItem: 'div',
  },
  propTypes: DateSelectPropTypes,
}, (props: DateSelectFeatureProps, { nodes, NodeDataProps }) => {
  const {
    Root, Calendar,
    WeekGrid, WeekItem,
    DayGrid, DayItem,
  } = nodes

  const betweenIncludeDates = useCallback((date: Date, range: [Date, Date] | Date[]) => {
    return !isBefore(date, range[0]) && !isAfter(date, range[1])
  }, [])

  const dateInfo = useMemo(() => {
    const firstDayInMonth = startOfMonth(props.yearMonth)
    const weekdayOfFirstDayInMonth = getDay(firstDayInMonth)

    const weekdays = range(0, 7).map((i) => {
      let date = new Date(props.yearMonth)
      date = startOfWeek(date)
      date = add(date, { days: i })
      return {
        key: format(date, 'yyyy-MM-dd'),
        date: date,
        label: format(date, 'EEEEEE', { locale: zhCN }),
      };
    });

    const days = range(
      1 - weekdayOfFirstDayInMonth,
      1 - weekdayOfFirstDayInMonth + 6*7,
    ).map((i) => {
      const date = add(firstDayInMonth, { days: i - 1 })
      const selected = props.selectedDates.findIndex((i) => isSameDay(date, i)) !== -1
      const inSelectedRange = (() => {
        if (props.selectedDates.length >= 2) {
          return betweenIncludeDates(date, props.selectedDates)
        }
        return false;
      })()
      return {
        key: format(date, 'yyyy-MM-dd'),
        date: date,
        label: getDate(date),
        active: isSameMonth(props.yearMonth, date),
        selected: selected,
        inSelectedRange: inSelectedRange,
      }
    })

    return {
      weekdays,
      days
    }
  }, [props.yearMonth, props.selectedDates, betweenIncludeDates])

  return (
    <Root>
      <Calendar>
        <WeekGrid>
          {dateInfo.weekdays.map((weekday) => {
            return (
              <WeekItem key={weekday.key}>
                {weekday.label}
              </WeekItem>
            );
          })}
        </WeekGrid>
        <DayGrid
          onMouseLeave={() => {
            props.onHoverDateChange && props.onHoverDateChange(undefined)
          }}
        >
          {dateInfo.days.map((day) => {
            const hovering = props.hoverDate ? isSameDay(day.date, props.hoverDate) : false
            const inHoverRange = (() => {
              if (props.selectedDates.length === 1 && props.hoverDate) {
                return betweenIncludeDates(day.date, [props.selectedDates[0], props.hoverDate].sort((i, j) => Number(i) - Number(j)))
              }
              return false
            })()
            return (
              <DayItem
                {...NodeDataProps({
                  'active': day.active,
                  'selected': day.selected,
                  'in-selected-range': day.inSelectedRange,
                  'in-hover-range': inHoverRange,
                  'hovering': hovering,
                })}
                key={day.key}
                onClick={() => {
                  props.onSelect(day.date)
                }}
                onMouseEnter={() => {
                  props.onHoverDateChange && props.onHoverDateChange(day.date)
                }}
                onMouseLeave={() => {
                  props.onHoverDateChange && props.onHoverDateChange(undefined)
                }}
              >
                {day.label}
              </DayItem>
            )
          })}
        </DayGrid>
      </Calendar>
    </Root>
  )
})
Example #5
Source File: DateTimeRangePicker.tsx    From UUI with MIT License 4 votes vote down vote up
DateTimeRangePicker = UUIFunctionComponent({
  name: 'DateTimeRangePicker',
  nodes: {
    Root: 'div',
    ConnectIcon: Icons.ArrowRight,
    CalendarIcon: Icons.Calendar,
    Popover: UUIPopover,
    TextField: UUITextField,
    Activator: 'div',
    Container: 'div',
    Toolbar: 'div',
    Main: 'div',
    StartSection: 'div',
    EndSection: 'div',
    Section: 'div',
    PickerButtons: UUIPickerButtons,
    YearMonthSelect: UUIYearMonthSelect,
    DateSelect: UUIDateSelect,
    TimeSelect: UUITimeSelect,
    DateTimeShortcut: UUIDateTimeShortcut,
  },
  propTypes: DateTimeRangePickerPropTypes,
}, (props: DateTimeRangePickerFeatureProps, { nodes }) => {
  const {
    Root, ConnectIcon, CalendarIcon, Popover, TextField,
    Activator, Container, Main, StartSection, EndSection, Section,
    YearMonthSelect, DateSelect, TimeSelect, DateTimeShortcut, PickerButtons,
  } = nodes

  const startTimeSelectRef = useRef<any | null>(null)
  const endTimeSelectRef = useRef<any | null>(null)
  const startInputRef = useRef<HTMLInputElement | null>(null)
  const endInputRef = useRef<HTMLInputElement | null>(null)
  const [active, setActive] = useState(false)
  const [whichFocusing, setWhichFocusing] = useState<'start' | 'end'>()
  const [hoverDate, setHoverDate] = useState<Date>()

  const initialInnerValue = useMemo(() => {
    if (props.value === null) {
      return {
        startDate: null,
        endDate: null,
        startInput: '',
        endInput: '',
        startYearMonth: startOfMonth(new Date),
        endYearMonth: add(startOfMonth(new Date), { months: 1 }),
      }
    }
    return {
      startDate: props.value[0],
      endDate: props.value[1],
      startInput: formatDateTime(props.value[0]),
      endInput: formatDateTime(props.value[1]),
      startYearMonth: startOfMonth(props.value[0]),
      endYearMonth: isSameMonth(props.value[0], props.value[1]) ? add(startOfMonth(props.value[1]), { months: 1 }) : props.value[1],
    }
  }, [props.value])
  const [innerValue, setInnerValue, resetInnerValue] = usePendingValue<DateTimeRangePickerInnerValue>(initialInnerValue, (value) => {
    if (value.startDate && value.endDate) {
      handleValueOnChange([value.startDate, value.endDate])
      closePopover()
    }
  }, { resetWhenInitialValueChanged: true })

  const selectedDates = useMemo(() => {
    return compact([innerValue.startDate, innerValue.endDate])
  }, [innerValue.endDate, innerValue.startDate])

  const timeSelectScrollToValue = useCallback((type: 'start' | 'end', value: Date, animate?: boolean) => {
    if (type === 'start' && startTimeSelectRef.current) {
      startTimeSelectRef.current.scrollToValue(value, animate)
    }
    if (type === 'end' && endTimeSelectRef.current) {
      endTimeSelectRef.current.scrollToValue(value, animate)
    }
  }, [])
  const openPopover = useCallback(() => { setActive(true) }, [])
  const closePopover = useCallback(() => { setActive(false) }, [])
  const handleValueOnChange = useCallback((value: DateTimeRangePickerValue | null) => {
    const sortedValue = value?.sort((i, j) => Number(i) - Number(j)) || null
    props.onChange(sortedValue)
  }, [props])

  /**
   *
   */
  const handleInputOnSubmit = useCallback((type: 'start' | 'end') => {
    if (innerValue.startDate && innerValue.endDate) {
      const originalInput = formatDateTime(type === 'start' ? innerValue.startDate : innerValue.endDate)
      const input = type === 'start' ? innerValue.startInput : innerValue.endInput
      if (originalInput === input) return;
      try {
        if (input === '') {
          handleValueOnChange(null)
        } else {
          const result = tryParseDateTimeFromString(input)
          handleValueOnChange(type === 'start' ? [result, innerValue.endDate] : [innerValue.startDate, result])
        }
      } catch {
        resetInnerValue()
      }
    }
  }, [handleValueOnChange, innerValue.endInput, innerValue.endDate, innerValue.startInput, innerValue.startDate, resetInnerValue])
    /**
   * handle user change year or month in YearMonthSelect.
   */
  const handleStartYearMonthSelect = useCallback((value: Date) => {
    setInnerValue((oldValue) => {
      const startYearMonthDate = value
      let endYearMonthDate = oldValue.endYearMonth
      if (!isBefore(startYearMonthDate, endYearMonthDate)) {
        endYearMonthDate = add(startYearMonthDate, { months: 1 })
      }
      return {
        ...oldValue,
        startYearMonth: startYearMonthDate,
        endYearMonth: endYearMonthDate,
      }
    })
  }, [setInnerValue])
  const handleEndYearMonthSelect = useCallback((value: Date) => {
    setInnerValue((oldValue) => {
      const endYearMonthDate = value
      let startYearMonthDate = oldValue.startYearMonth
      if (!isAfter(endYearMonthDate, startYearMonthDate)) {
        startYearMonthDate = add(endYearMonthDate, { months: -1 })
      }
      return {
        ...oldValue,
        startYearMonth: startYearMonthDate,
        endYearMonth: endYearMonthDate,
      }
    })
  }, [setInnerValue])
  /**
   * handle user select date in DateSelect.
   */
  const handleDateSelect = useCallback((value: Date) => {
    let newStartValue = innerValue.startDate
    let newEndValue = innerValue.endDate
    if (
      (newStartValue !== null && newEndValue !== null) ||
      (newStartValue === null && newEndValue === null)
    ) {
      if (whichFocusing === 'end') {
        newStartValue = null
        newEndValue = value
      } else {
        newStartValue = value
        newEndValue = null
      }
    } else {
      if (newStartValue === null) newStartValue = value
      if (newEndValue === null) newEndValue = value
      if (isAfter(newStartValue, newEndValue)) {
        const tmp = new Date(newStartValue)
        newStartValue = new Date(newEndValue)
        newEndValue = tmp
      }
    }
    setInnerValue((oldValue) => {
      return {
        ...oldValue,
        startDate: newStartValue,
        startInput: formatDateTime(newStartValue),
        endDate: newEndValue,
        endInput: formatDateTime(newEndValue),
      }
    })
  }, [innerValue.endDate, innerValue.startDate, setInnerValue, whichFocusing])
  /**
   * handle user select date in TimeSelect.
   */
  const handleTimeSelect = useCallback((type: 'start' | 'end') => {
    return (value: Date) => {
      setInnerValue((oldValue) => {
        const oldDate = type === 'start' ? oldValue.startDate : oldValue.endDate
        const newDate = set(oldDate || getZeroDate(), {
          hours: value.getHours(),
          minutes: value.getMinutes(),
          seconds: value.getSeconds(),
        })
        const newInput = formatDateTime(newDate)
        return {
          ...oldValue,
          ...(type === 'start' ? {
            startDate: newDate,
            startInput: newInput,
          } : {}),
          ...(type === 'end' ? {
            endDate: newDate,
            endInput: newInput,
          } : {}),
        }
      })
    }
  }, [setInnerValue])

  return (
    <Root>
      <Popover
        placement={'bottom-start'}
        active={active}
        onClickAway={() => {
          resetInnerValue();
          timeSelectScrollToValue('start', props.value ? props.value[0] : getZeroDate(), false)
          timeSelectScrollToValue('end', props.value ? props.value[1] : getZeroDate(), false)
          setTimeout(() => { closePopover() }, 10)
        }}
        activator={
          <Activator
            onClick={() => {
              openPopover()
              setTimeout(() => {
                const focusedElement = ReactHelper.document?.activeElement
                if (startInputRef.current === focusedElement || endInputRef.current === focusedElement) return;
                if (startInputRef.current) {
                  startInputRef.current.focus()
                }
              }, 0)
            }}
          >
            <TextField
              placeholder={props.startPlaceholder}
              value={innerValue.startInput}
              onChange={(value) => { setInnerValue((oldValue) => ({ ...oldValue, startInput: value })) }}
              customize={{
                Input: {
                  ref: startInputRef,
                  onFocus: () => {
                    setWhichFocusing('start')
                  },
                  onBlur: () => {
                    setWhichFocusing(undefined)
                    handleInputOnSubmit('start')
                  },
                  onKeyDown: (event) => {
                    if (event.key === 'Enter') {
                      handleInputOnSubmit('start')
                    }
                  }
                }
              }}
            />
            <ConnectIcon />
            <TextField
              placeholder={props.endPlaceholder}
              value={innerValue.endInput}
              onChange={(value) => { setInnerValue((oldValue) => ({ ...oldValue, endInput: value })) }}
              customize={{
                Input: {
                  ref: endInputRef,
                  onFocus: () => {
                    setWhichFocusing('end')
                  },
                  onBlur: () => {
                    setWhichFocusing(undefined)
                    handleInputOnSubmit('end')
                  },
                  onKeyDown: (event) => {
                    if (event.key === 'Enter') {
                      handleInputOnSubmit('end')
                    }
                  }
                }
              }}
            />
            <CalendarIcon />
          </Activator>
        }
      >
        <Container>
          <Main tabIndex={-1}>
            {props.shortcuts && (
              <DateTimeShortcut
                options={props.shortcuts}
                onSelect={(value) => {
                  handleValueOnChange(value)
                  timeSelectScrollToValue('start', value ? value[0] : getZeroDate(), false)
                  timeSelectScrollToValue('end', value ? value[1] : getZeroDate(), false)
                  closePopover()
                }}
              />
            )}
            <StartSection>
              <YearMonthSelect
                value={innerValue.startYearMonth}
                onChange={handleStartYearMonthSelect}
              />
              <Section>
                <DateSelect
                  yearMonth={innerValue.startYearMonth}
                  selectedDates={selectedDates}
                  onSelect={handleDateSelect}
                  hoverDate={hoverDate}
                  onHoverDateChange={(date) => { setHoverDate(date) }}
                />
                <TimeSelect
                  ref={startTimeSelectRef}
                  value={innerValue.startDate || getZeroDate()}
                  onChange={handleTimeSelect('start')}
                />
              </Section>
            </StartSection>
            <EndSection>
              <YearMonthSelect
                value={innerValue.endYearMonth}
                onChange={handleEndYearMonthSelect}
              />
              <Section>
                <DateSelect
                  yearMonth={innerValue.endYearMonth}
                  selectedDates={selectedDates}
                  onSelect={handleDateSelect}
                  hoverDate={hoverDate}
                  onHoverDateChange={(date) => { setHoverDate(date) }}
                />
                <TimeSelect
                  ref={endTimeSelectRef}
                  value={innerValue.endDate || getZeroDate()}
                  onChange={handleTimeSelect('end')}
                />
              </Section>
            </EndSection>
          </Main>
          <PickerButtons
            confirmLabel={props.confirmLabel}
            cancelLabel={props.cancelLabel}
            onCancel={() => {
              resetInnerValue()
              timeSelectScrollToValue('start', props.value ? props.value[0] : getZeroDate(), false)
              timeSelectScrollToValue('end', props.value ? props.value[1] : getZeroDate(), false)
              setTimeout(() => { closePopover() }, 10)
            }}
            onConfirm={() => {
              setInnerValue((value) => value, true)
              if (innerValue.startDate && innerValue.endDate) {
                let data = [innerValue.startDate, innerValue.endDate]
                if (isAfter(innerValue.startDate, innerValue.endDate)) {
                  data = data.reverse()
                }
                timeSelectScrollToValue('start', data[0], false)
                timeSelectScrollToValue('end', data[1], false)
              } else {
                timeSelectScrollToValue('start', getZeroDate(), false)
                timeSelectScrollToValue('end', getZeroDate(), false)
              }
              setTimeout(() => { closePopover() }, 10)
            }}
          />
        </Container>
      </Popover>
    </Root>
  )
})
Example #6
Source File: BudgetTransaction.ts    From cashcash-desktop with MIT License 4 votes vote down vote up
getters = {
    getField,
    inOutBudgetSplitObject(
        state: IBudgetTransactionState,
        getters,
        rootState,
    ): InOutBudgetSplitObject {
        const result: InOutBudgetSplitObject = {
            outBudgetSplitMap: new Map(),
            inBudgetSplitMap: new Map(),
            outBudgetSplitSum: 0,
            inBudgetSplitSum: 0,
        };
        const contextAccount = state.contextAccount;
        const budgetSplitList: GraphSplitExtended[] = rootState.PermanentData.budgetSplitList;
        const accountDescendantMap: Map<number, number[]> =
            rootState.PermanentData.accountDescendantMap;
        if (!state.isPageOpen || !contextAccount || budgetSplitList.length === 0) {
            return result;
        }
        const accountDescendantList = [
            ...(accountDescendantMap.get(contextAccount.id) || []),
            contextAccount.id,
        ];
        for (const budgetSplit of budgetSplitList) {
            if (
                accountDescendantList.includes(budgetSplit.accountId) &&
                !accountDescendantList.includes(budgetSplit.otherSplitAccountId)
            ) {
                const key = CashBudgetUtils.generateKey(budgetSplit);
                if (budgetSplit.isToSplit) {
                    // It's a in split
                    result.inBudgetSplitMap.set(key, budgetSplit);
                    result.inBudgetSplitSum += +budgetSplit.amount;
                } else {
                    // It's a out split
                    result.outBudgetSplitMap.set(key, budgetSplit);
                    result.outBudgetSplitSum += +budgetSplit.amount;
                }
            }
        }

        return result;
    },
    deltaBudgetObject(state: IBudgetTransactionState, getters): DeltaBudgetObject {
        const result: DeltaBudgetObject = {
            deltaPerMonth: 0,
            deltaPerWeek: 0,
            deltaPerDay: 0,
        };
        const budgetDate = state.budgetDate;
        const inOutBudgetSplitObject: InOutBudgetSplitObject = getters.inOutBudgetSplitObject;
        if (!state.isPageOpen || !budgetDate || !inOutBudgetSplitObject) {
            return result;
        }
        const delta =
            inOutBudgetSplitObject.inBudgetSplitSum - inOutBudgetSplitObject.outBudgetSplitSum;
        const numberOfDays = getDaysInMonth(budgetDate);
        const deltaPerDay = delta / numberOfDays;
        return {
            deltaPerMonth: delta,
            deltaPerWeek: deltaPerDay * 7,
            deltaPerDay,
        };
    },
    inOutCurrentSplitObject(
        state: IBudgetTransactionState,
        getters,
        rootState,
    ): InOutCurrentSplitObject {
        const result: InOutCurrentSplitObject = {
            outCurrentSplitList: [],
            inCurrentSplitList: [],
            outCurrentSplitSum: 0,
            inCurrentSplitSum: 0,
            outBudgetedCurrentSumMap: new Map(),
            inBudgetedCurrentSumMap: new Map(),
            currentSumMap: new Map(),
            outBudgetedCurrentSplitSum: 0,
            inBudgetedCurrentSplitSum: 0,
            outNoneBudgetedCurrentSplitList: [],
            inNoneBudgetedCurrentSplitList: [],
            outNoneBudgetedCurrentSplitSum: 0,
            inNoneBudgetedCurrentSplitSum: 0,
        };
        const inOutBudgetSplitObject: InOutBudgetSplitObject = getters.inOutBudgetSplitObject;
        const contextAccount = state.contextAccount;
        const splitList: GraphSplitExtended[] = rootState.TimeFrameData.splitList;
        const budgetDate = state.budgetDate;
        const accountDescendantMap: Map<number, number[]> =
            rootState.PermanentData.accountDescendantMap;
        if (
            !state.isPageOpen ||
            !inOutBudgetSplitObject ||
            !contextAccount ||
            splitList.length === 0 ||
            !budgetDate
        ) {
            return result;
        }
        const accountDescendantList = [
            ...(accountDescendantMap.get(contextAccount.id) || []),
            contextAccount.id,
        ];
        for (const split of splitList) {
            if (
                isSameMonth(split.transactionDate, budgetDate) &&
                accountDescendantList.includes(split.accountId) &&
                !accountDescendantList.includes(split.otherSplitAccountId)
            ) {
                const key = CashBudgetUtils.generateKey(split);
                if (split.isToSplit) {
                    // It's a in split
                    if (inOutBudgetSplitObject.inBudgetSplitMap.get(key)) {
                        // It's part of a budgeted account
                        let oneSum = result.inBudgetedCurrentSumMap.get(key) || 0;
                        oneSum += split.amount;
                        result.inBudgetedCurrentSumMap.set(key, oneSum);
                        result.currentSumMap.set(key, oneSum);
                        result.inBudgetedCurrentSplitSum += split.amount;
                    } else {
                        result.inNoneBudgetedCurrentSplitList.push(split);
                        result.inNoneBudgetedCurrentSplitSum += split.amount;
                    }
                    result.inCurrentSplitList.push(split);
                    result.inCurrentSplitSum += split.amount;
                } else {
                    // It's a out split
                    if (inOutBudgetSplitObject.outBudgetSplitMap.get(key)) {
                        // It's part of a budgeted account
                        let oneSum = result.outBudgetedCurrentSumMap.get(key) || 0;
                        oneSum += split.amount;
                        result.outBudgetedCurrentSumMap.set(key, oneSum);
                        result.currentSumMap.set(key, oneSum);
                        result.outBudgetedCurrentSplitSum += split.amount;
                    } else {
                        result.outNoneBudgetedCurrentSplitList.push(split);
                        result.outNoneBudgetedCurrentSplitSum += split.amount;
                    }
                    result.outCurrentSplitList.push(split);
                    result.outCurrentSplitSum += split.amount;
                }
            }
        }
        return result;
    },
    deltaCurrentObject(state: IBudgetTransactionState, getters): DeltaCurrentObject {
        const result: DeltaCurrentObject = {
            deltaPerMonth: 0,
            deltaPerWeek: 0,
            deltaPerDay: 0,
        };
        const budgetDate = state.budgetDate;
        const inOutCurrentSplitObject: InOutCurrentSplitObject = getters.inOutCurrentSplitObject;
        if (!state.isPageOpen || !budgetDate || !inOutCurrentSplitObject) {
            return result;
        }
        const delta = inOutCurrentSplitObject.outNoneBudgetedCurrentSplitSum;
        const numberOfDays = getDaysInMonth(budgetDate);
        const deltaPerDay = delta / numberOfDays;
        return {
            deltaPerMonth: delta,
            deltaPerWeek: deltaPerDay * 7,
            deltaPerDay,
        };
    },
    optionChart(state: IBudgetTransactionState, getters, rootState, rootGetters) {
        const inOutCurrentSplitObject: InOutCurrentSplitObject = getters.inOutCurrentSplitObject;
        const inOutBudgetSplitObject: InOutBudgetSplitObject = getters.inOutBudgetSplitObject;
        const preferedCurrency = rootState.App.preferences
            ? rootState.App.preferences.preferedCurrency
            : null;
        const accountMap = rootState.PermanentData.accountMap;
        const currencyMap = rootGetters['PermanentData/currencyMap'];
        const service = Container.get(CashGraphService);
        if (
            !state.isPageOpen ||
            !inOutBudgetSplitObject ||
            !inOutBudgetSplitObject ||
            !preferedCurrency ||
            !accountMap ||
            !currencyMap
        ) {
            return {};
        }
        return service.generateBudgetGraph(
            inOutBudgetSplitObject.inBudgetSplitSum,
            -inOutBudgetSplitObject.outBudgetSplitSum,
            inOutCurrentSplitObject.inBudgetedCurrentSplitSum,
            -inOutCurrentSplitObject.outBudgetedCurrentSplitSum,
            inOutCurrentSplitObject.inNoneBudgetedCurrentSplitSum,
            -inOutCurrentSplitObject.outNoneBudgetedCurrentSplitSum,
            state.budgetDate,
            preferedCurrency,
            accountMap,
            currencyMap,
        );
    },
}