Files
evidencija-rezija/app/ui/HomePage.tsx

121 lines
3.2 KiB
TypeScript

"use client";
import { BillingLocation, YearMonth } from '@/app/lib/db-types';
import { FC, useEffect, useState } from 'react';
import { MonthLocationList } from '@/app/ui/MonthLocationList';
import { WithId } from 'mongodb';
import { MonthCardSkeleton } from './MonthCardSkeleton';
export interface HomePageProps {
}
const fetchAllLocations = async (year: number) => {
const response = await fetch(`/api/all-locations/?year=${year}`);
const { locations } : { locations: WithId<BillingLocation>[] } = await response.json();
return locations;
}
const fetchAvailableYears = async () => {
const response = await fetch(`/api/available-years/`);
const { availableYears }: { availableYears: number[]} = await response.json();
return availableYears;
}
export const HomePage:FC<HomePageProps> = () => {
const [ homePageStatus, setHomePageStatus ] = useState<{
status: "loading" | "loaded" | "error",
availableYears: number[],
locations: WithId<BillingLocation>[],
error?: string
}>({
status: "loading",
availableYears: [],
locations: []
});
const {availableYears, locations, status, error} = homePageStatus;
const year = new URLSearchParams(window.location.search).get('year');
const currentYear = year ? parseInt(year, 10) : new Date().getFullYear();
useEffect(() => {
const fetchData = async () => {
try {
setHomePageStatus({
availableYears: await fetchAvailableYears(),
locations: await fetchAllLocations(currentYear),
status: "loaded",
});
} catch (error: any) {
setHomePageStatus({
status: "error",
availableYears: [],
locations: [],
error: error.message
});
}
}
fetchData();
}, [currentYear]);
if(status === "loading") {
return (
<>
<MonthCardSkeleton checked={true} />
<MonthCardSkeleton />
<MonthCardSkeleton />
</>
);
}
if(status === "error") {
return(<p className="text-center text-2xl text-red-500">{error}</p>);
}
// if the database is in it's initial state, show the add location button for the current month
if(availableYears.length === 0) {
return (<MonthLocationList />);
}
// 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 (
<MonthLocationList availableYears={availableYears} months={months} />
);
}
export default HomePage;