locations grouped by month before rendering

This commit is contained in:
2024-02-01 14:02:36 +01:00
parent 2728b5c302
commit 2366ed16cc

View File

@@ -6,7 +6,7 @@ import { PageFooter } from './ui/PageFooter';
import { fetchAllLocations } from './lib/actions/locationActions'; import { fetchAllLocations } from './lib/actions/locationActions';
import { formatCurrency } from './lib/formatStrings'; import { formatCurrency } from './lib/formatStrings';
import { fetchAvailableYears } from './lib/actions/monthActions'; import { fetchAvailableYears } from './lib/actions/monthActions';
import { YearMonth } from './lib/db-types'; import { BillingLocation, YearMonth } from './lib/db-types';
import { formatYearMonth } from './lib/format'; import { formatYearMonth } from './lib/format';
import { FC, Fragment } from 'react'; import { FC, Fragment } from 'react';
import Pagination from './ui/Pagination'; import Pagination from './ui/Pagination';
@@ -62,53 +62,55 @@ const Page:FC<PageProps> = async ({ searchParams }) => {
const currentYear = Number(searchParams?.year) || availableYears[0]; const currentYear = Number(searchParams?.year) || availableYears[0];
const locations = await fetchAllLocations(currentYear); const locations = await fetchAllLocations(currentYear);
let monthlyExpense = 0; // group locations by month
const months = locations.reduce((acc, location) => {
const {year, month} = location.yearMonth;
const key = `${year}-${month}`;
const locationsInMonth = acc[key];
if(locationsInMonth) {
return({
...acc,
[key]: {
yearMonth: location.yearMonth,
locations: [...locationsInMonth.locations, location],
monthlyExpense: locationsInMonth.monthlyExpense + location.bills.reduce((acc, bill) => bill.paid ? acc + (bill.payedAmount ?? 0) : acc, 0)
}
})
}
return({
...acc,
[key]: {
yearMonth: location.yearMonth,
locations: [location],
monthlyExpense: location.bills.reduce((acc, bill) => bill.paid ? acc + (bill.payedAmount ?? 0) : acc, 0)
}
});
}, {} as {[key:string]:{
yearMonth: YearMonth,
locations: BillingLocation[],
monthlyExpense: number
} });
return ( return (
<Main> <Main>
<AddMonthButton yearMonth={getNextYearMonth(locations[0].yearMonth)} />
{ {
// if this is the latest year, show the add month button Object.entries(months).map(([monthKey, { yearMonth, locations, monthlyExpense }], monthIx) =>
currentYear === latestYear && <Fragment key={`month-${monthKey}`}>
<AddMonthButton yearMonth={getNextYearMonth(locations[0].yearMonth)} /> <MonthTitle yearMonth={yearMonth} />
} {
{ locations.map((location, ix) => <LocationCard key={`location-${location._id}`} location={location} />)
locations.map((location, ix, array) => { }
{
const { year, month } = location.yearMonth // show AddLocationButton as a last item in the first month
const { year: prevYear, month: prevMonth } = array[ix-1]?.yearMonth ?? { year: undefined, month: undefined }; monthIx === 0 ? <AddLocationButton yearMonth={yearMonth} /> : null
const { year: nextYear, month: nextMonth } = array[ix+1]?.yearMonth ?? { year: undefined, month: undefined }; }
<MontlyExpensesCard monthlyExpense={monthlyExpense} />
const isLatestYear = year === latestYear; </Fragment>
const isFirstLocationInMonth = ix === 0 || year !== prevYear || month !== prevMonth; )
const isLastLocationInMonth = year !== nextYear || month !== nextMonth;
const isLastLocationOfLatestMonth = isLastLocationInMonth && year === array[0].yearMonth.year && month === array[0].yearMonth.month
if(isFirstLocationInMonth) {
monthlyExpense = 0;
}
monthlyExpense += location.bills.reduce((acc, bill) => bill.paid ? acc + (bill.payedAmount ?? 0) : acc, 0);
return (
<Fragment key={`location-${location._id}`}>
{
// show month title above the first LocationCard in the month
isFirstLocationInMonth ?
<MonthTitle yearMonth={location.yearMonth} /> : null
}
<LocationCard location={location} />
{
// show AddLocationButton as a last item in the first month
isLastLocationOfLatestMonth && isLatestYear ?
<AddLocationButton yearMonth={location.yearMonth} /> : null
}
{
isLastLocationInMonth ?
<MontlyExpensesCard monthlyExpense={monthlyExpense} /> : null
}
</Fragment>
)
})
} }
<div className="mt-5 flex w-full justify-center"> <div className="mt-5 flex w-full justify-center">
<Pagination availableYears={availableYears} /> <Pagination availableYears={availableYears} />