diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx index e2e8e525..ac36de1f 100644 --- a/src/components/Dashboard.tsx +++ b/src/components/Dashboard.tsx @@ -1,53 +1,22 @@ +import { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useEffect, useState, useCallback } from 'react' -import { useSearchParams, Link, useNavigate } from 'react-router-dom' -import { safeName } from '../lib/name-helper' -import { Budget, BudgetMonth, Translation, UUID } from '../types' -import { CalendarDaysIcon } from '@heroicons/react/24/solid' -import { ChevronRightIcon, ChevronLeftIcon } from '@heroicons/react/20/solid' +import { useSearchParams } from 'react-router-dom' import { get } from '../lib/api/base' +import { monthYearFromDate } from '../lib/dates' import { formatMoney } from '../lib/format' -import isSupported from '../lib/is-supported' -import LoadingSpinner from './LoadingSpinner' -import Error from './Error' -import { - dateFromMonthYear, - monthYearFromDate, - translatedMonthFormat, - shortTranslatedMonthFormat, -} from '../lib/dates' +import { replaceMonthInLinks } from '../lib/month-helper' +import { safeName } from '../lib/name-helper' +import { Budget, BudgetMonth, Translation, UUID } from '../types' import CategoryMonth from './CategoryMonth' -import MonthPicker from './MonthPicker' +import Error from './Error' +import LoadingSpinner from './LoadingSpinner' +import MonthSlider from './MonthSlider' import QuickAllocationForm from './QuickAllocationForm' -import { replaceMonthInLinks } from '../lib/month-helper' type DashboardProps = { budget: Budget } -const previousMonth = (yearMonth: string) => { - const [year, month] = yearMonth.split('-') - - if (month === '01') { - return new Date(parseInt(year) - 1, 11, 15) - } else { - return new Date(parseInt(year), parseInt(month) - 2, 15) - } -} - -const nextMonth = (yearMonth: string) => { - const [year, month] = yearMonth.split('-') - - if (month === '12') { - return new Date(parseInt(year) + 1, 0, 15) - } else { - return new Date(parseInt(year), parseInt(month), 15) - } -} - -const linkToMonth = (month: string) => `/?month=${month}` - const Dashboard = ({ budget }: DashboardProps) => { const { t }: Translation = useTranslation() - const navigate = useNavigate() const [searchParams] = useSearchParams() const activeMonth = @@ -56,11 +25,8 @@ const Dashboard = ({ budget }: DashboardProps) => { const [budgetMonth, setBudgetMonth] = useState() const [error, setError] = useState('') const [isLoading, setIsLoading] = useState(true) - const [showMonthPicker, setShowMonthPicker] = useState(false) const [editingEnvelope, setEditingEnvelope] = useState() - const useNativeMonthPicker = isSupported.inputTypeMonth() - const loadBudgetMonth = useCallback(async () => { return get(replaceMonthInLinks(budget.links.month, activeMonth)) .then(data => { @@ -89,66 +55,11 @@ const Dashboard = ({ budget }: DashboardProps) => {

{safeName(budget, 'budget')}

-
- setIsLoading(true)} - > - - {shortTranslatedMonthFormat.format(previousMonth(activeMonth))} - -
- {useNativeMonthPicker ? ( -
- - { - e.preventDefault() - navigate(linkToMonth(e.target.value)) - }} - /> -
- ) : ( -
- - {translatedMonthFormat.format(dateFromMonthYear(activeMonth))} - - -
- )} -
- setIsLoading(true)} - > - {shortTranslatedMonthFormat.format(nextMonth(activeMonth))} - - -
- - {useNativeMonthPicker ? null : ( - - )} + {isLoading || !budgetMonth ? ( diff --git a/src/components/MonthPicker.tsx b/src/components/MonthPicker.tsx index dac553c1..4451493a 100644 --- a/src/components/MonthPicker.tsx +++ b/src/components/MonthPicker.tsx @@ -1,18 +1,19 @@ -import { Fragment, SetStateAction, Dispatch, useState } from 'react' import { Dialog, Transition } from '@headlessui/react' -import { translatedMonthFormat } from '../lib/dates' import { ArrowLongRightIcon, XMarkIcon } from '@heroicons/react/20/solid' +import { Dispatch, Fragment, SetStateAction, useState } from 'react' +import { useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' +import { translatedMonthFormat } from '../lib/dates' import { Translation } from '../types' -import { useTranslation } from 'react-i18next' type Props = { open: boolean setOpen: Dispatch> activeMonth: string + route?: string } -const MonthPicker = ({ open, setOpen, activeMonth }: Props) => { +const MonthPicker = ({ open, setOpen, activeMonth, route = '' }: Props) => { const { t }: Translation = useTranslation() const [selectedDate, setSelectedDate] = useState(`${activeMonth}-01`) @@ -72,7 +73,7 @@ const MonthPicker = ({ open, setOpen, activeMonth }: Props) => { }} > setOpen(false)} className="pl-2" title={translatedMonthFormat.format( @@ -83,7 +84,7 @@ const MonthPicker = ({ open, setOpen, activeMonth }: Props) => { setOpen(false)} > diff --git a/src/components/MonthSlider.tsx b/src/components/MonthSlider.tsx new file mode 100644 index 00000000..ae7b1d64 --- /dev/null +++ b/src/components/MonthSlider.tsx @@ -0,0 +1,128 @@ +import { + CalendarDaysIcon, + ChevronLeftIcon, + ChevronRightIcon, +} from '@heroicons/react/20/solid' +import { Dispatch, SetStateAction, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Link, useNavigate } from 'react-router-dom' + +import { + dateFromMonthYear, + monthYearFromDate, + shortTranslatedMonthFormat, + translatedMonthFormat, +} from '../lib/dates' +import isSupported from '../lib/is-supported' +import { Budget, Translation } from '../types' +import MonthPicker from './MonthPicker' + +type Props = { + budget: Budget + route?: string + activeMonth: string + setIsLoading: Dispatch> +} + +const previousMonth = (yearMonth: string) => { + const [year, month] = yearMonth.split('-') + + if (month === '01') { + return new Date(parseInt(year) - 1, 11, 15) + } else { + return new Date(parseInt(year), parseInt(month) - 2, 15) + } +} + +const nextMonth = (yearMonth: string) => { + const [year, month] = yearMonth.split('-') + + if (month === '12') { + return new Date(parseInt(year) + 1, 0, 15) + } else { + return new Date(parseInt(year), parseInt(month), 15) + } +} + +const MonthSlider = ({ + budget, + route = '', + activeMonth, + setIsLoading, +}: Props) => { + const { t }: Translation = useTranslation() + const navigate = useNavigate() + + const [showMonthPicker, setShowMonthPicker] = useState(false) + const useNativeMonthPicker = isSupported.inputTypeMonth() + + const linkToMonth = (month: string) => `/${route}?month=${month}` + + return ( +
+
+ setIsLoading(true)} + > + + {shortTranslatedMonthFormat.format(previousMonth(activeMonth))} + +
+ {useNativeMonthPicker ? ( +
+ + { + e.preventDefault() + navigate(linkToMonth(e.target.value)) + }} + /> +
+ ) : ( +
+ + {translatedMonthFormat.format(dateFromMonthYear(activeMonth))} + + +
+ )} +
+ setIsLoading(true)} + > + {shortTranslatedMonthFormat.format(nextMonth(activeMonth))} + + +
+ + {useNativeMonthPicker ? null : ( + + )} +
+ ) +} + +export default MonthSlider