diff --git a/app/lib/actions/billActions.ts b/app/lib/actions/billActions.ts index 48155fc..98ae03b 100644 --- a/app/lib/actions/billActions.ts +++ b/app/lib/actions/billActions.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { getDbClient } from '../dbClient'; -import { Bill, BillAttachment, BillingLocation, YearMonth } from '../db-types'; +import { Bill, BilledTo, BillAttachment, BillingLocation, YearMonth } from '../db-types'; import { ObjectId } from 'mongodb'; import { withUser } from '@/app/lib/auth'; import { AuthenticatedUser } from '../types/next-auth'; @@ -145,7 +145,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI } = validatedFields.data; const billPaid = formData.get('billPaid') === 'on'; - const billedToTenant = formData.get('billedToTenant') === 'on'; + const billedTo = (formData.get('billedTo') as BilledTo) ?? BilledTo.Tenant; const barcodeImage = formData.get('barcodeImage')?.valueOf() as string; // update the bill in the mongodb @@ -160,7 +160,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI const mongoDbSet = billAttachment ? { "bills.$[elem].name": billName, "bills.$[elem].paid": billPaid, - "bills.$[elem].billedToTenant": billedToTenant, + "bills.$[elem].billedTo": billedTo, "bills.$[elem].attachment": billAttachment, "bills.$[elem].notes": billNotes, "bills.$[elem].payedAmount": payedAmount, @@ -169,7 +169,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI }: { "bills.$[elem].name": billName, "bills.$[elem].paid": billPaid, - "bills.$[elem].billedToTenant": billedToTenant, + "bills.$[elem].billedTo": billedTo, "bills.$[elem].notes": billNotes, "bills.$[elem].payedAmount": payedAmount, "bills.$[elem].barcodeImage": barcodeImage, @@ -194,7 +194,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI _id: (new ObjectId()).toHexString(), name: billName, paid: billPaid, - billedToTenant: billedToTenant, + billedTo: billedTo, attachment: billAttachment, notes: billNotes, payedAmount, @@ -258,7 +258,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI _id: (new ObjectId()).toHexString(), name: billName, paid: false, // New bills in subsequent months are unpaid - billedToTenant: true, // Default to true for subsequent months + billedTo: BilledTo.Tenant, // Default to tenant for subsequent months attachment: null, // No attachment for subsequent months notes: billNotes, payedAmount: null, diff --git a/app/lib/actions/printActions.ts b/app/lib/actions/printActions.ts index 2f23ecc..6a3756f 100644 --- a/app/lib/actions/printActions.ts +++ b/app/lib/actions/printActions.ts @@ -1,7 +1,7 @@ 'use server'; import { getDbClient } from '../dbClient'; -import { BillingLocation, Bill } from '../db-types'; +import { BilledTo, BillingLocation, Bill } from '../db-types'; import { AuthenticatedUser } from '../types/next-auth'; import { withUser } from '../auth'; import { unstable_noStore as noStore } from 'next/cache'; @@ -42,7 +42,7 @@ export const fetchBarcodeDataForPrint = withUser(async (user: AuthenticatedUser, for (const location of locations) { for (const bill of location.bills) { // Only include bills that are billed to tenant and have barcode images - if (bill.barcodeImage && bill.barcodeImage.trim() !== "" && (bill.billedToTenant ?? true)) { + if (bill.barcodeImage && bill.barcodeImage.trim() !== "" && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) { printData.push({ locationName: location.name, billName: bill.name, diff --git a/app/lib/db-types.ts b/app/lib/db-types.ts index bf2caef..dc63601 100644 --- a/app/lib/db-types.ts +++ b/app/lib/db-types.ts @@ -31,6 +31,11 @@ export interface BillingLocation { notes: string|null; }; +export enum BilledTo { + Tenant = "tenant", + Landlord = "landlord" +} + /** Bill basic data */ export interface Bill { _id: string; @@ -38,8 +43,8 @@ export interface Bill { name: string; /** is the bill paid */ paid: boolean; - /** true if tenant to cover the bill */ - billedToTenant: boolean; + /** who is billed for the bill */ + billedTo?: BilledTo; /** payed amount amount in cents */ payedAmount?: number | null; /** attached document (optional) */ diff --git a/app/ui/BillEditForm.tsx b/app/ui/BillEditForm.tsx index 7586b66..6c6d8a4 100644 --- a/app/ui/BillEditForm.tsx +++ b/app/ui/BillEditForm.tsx @@ -1,7 +1,7 @@ "use client"; import { DocumentIcon, TrashIcon } from "@heroicons/react/24/outline"; -import { Bill, BillingLocation } from "../lib/db-types"; +import { Bill, BilledTo, BillingLocation } from "../lib/db-types"; import React, { FC } from "react"; import { useFormState } from "react-dom"; import { updateOrAddBill } from "../lib/actions/billActions"; @@ -29,7 +29,7 @@ export const BillEditForm:FC = ({ location, bill }) => { const t = useTranslations("bill-edit-form"); const locale = useLocale(); - const { _id: billID, name, paid, billedToTenant = true, attachment, notes, payedAmount: initialPayedAmount, barcodeImage: initialBarcodeImage } = bill ?? { _id:undefined, name:"", paid:false, notes:"" }; + const { _id: billID, name, paid, billedTo = BilledTo.Tenant, attachment, notes, payedAmount: initialPayedAmount, barcodeImage: initialBarcodeImage } = bill ?? { _id:undefined, name:"", paid:false, notes:"" }; const { yearMonth:{year: billYear, month: billMonth}, _id: locationID } = location; @@ -40,14 +40,14 @@ export const BillEditForm:FC = ({ location, bill }) => { const [ isScanningPDF, setIsScanningPDF ] = React.useState(false); const [ state, dispatch ] = useFormState(handleAction, initialState); const [ isPaid, setIsPaid ] = React.useState(paid); - const [ isBilledToTenant, setIsBilledToTenant ] = React.useState(billedToTenant); + const [ billedToValue, setBilledToValue ] = React.useState(billedTo); const [ payedAmount, setPayedAmount ] = React.useState(initialPayedAmount ? `${initialPayedAmount/100}` : "" ); const [ barcodeImage, setBarcodeImage ] = React.useState(initialBarcodeImage); const [ barcodeResults, setBarcodeResults ] = React.useState | null>(null); - const billedToTenant_handleChange = (event: React.ChangeEvent) => { - setIsBilledToTenant(event.target.checked); + const billedTo_handleChange = (event: React.ChangeEvent) => { + setBilledToValue(event.target.value as BilledTo); } const billPaid_handleChange = (event: React.ChangeEvent) => { @@ -209,10 +209,33 @@ export const BillEditForm:FC = ({ location, bill }) => {
-
{/* Show toggle only when adding a new bill (not editing) */} diff --git a/app/ui/HomePage.tsx b/app/ui/HomePage.tsx index 5b0cb3a..51584c3 100644 --- a/app/ui/HomePage.tsx +++ b/app/ui/HomePage.tsx @@ -1,6 +1,6 @@ import { fetchAllLocations } from '@/app/lib/actions/locationActions'; import { fetchAvailableYears } from '@/app/lib/actions/monthActions'; -import { BillingLocation, YearMonth } from '@/app/lib/db-types'; +import { BilledTo, BillingLocation, YearMonth } from '@/app/lib/db-types'; import { FC } from 'react'; import { MonthLocationList } from '@/app/ui/MonthLocationList'; @@ -49,7 +49,7 @@ export const HomePage:FC = async ({ searchParams }) => { [key]: { yearMonth: location.yearMonth, locations: [...locationsInMonth.locations, location], - monthlyExpense: locationsInMonth.monthlyExpense + location.bills.reduce((acc, bill) => (bill.paid && (bill.billedToTenant ?? true)) ? acc + (bill.payedAmount ?? 0) : acc, 0) + monthlyExpense: locationsInMonth.monthlyExpense + location.bills.reduce((acc, bill) => (bill.paid && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) ? acc + (bill.payedAmount ?? 0) : acc, 0) } }) } @@ -59,7 +59,7 @@ export const HomePage:FC = async ({ searchParams }) => { [key]: { yearMonth: location.yearMonth, locations: [location], - monthlyExpense: location.bills.reduce((acc, bill) => (bill.paid && (bill.billedToTenant ?? true)) ? acc + (bill.payedAmount ?? 0) : acc, 0) + monthlyExpense: location.bills.reduce((acc, bill) => (bill.paid && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) ? acc + (bill.payedAmount ?? 0) : acc, 0) } }); }, {} as {[key:string]:{ diff --git a/app/ui/LocationCard.tsx b/app/ui/LocationCard.tsx index 76c1785..bb40638 100644 --- a/app/ui/LocationCard.tsx +++ b/app/ui/LocationCard.tsx @@ -3,7 +3,7 @@ import { Cog8ToothIcon, PlusCircleIcon, ShareIcon } from "@heroicons/react/24/outline"; import { FC } from "react"; import { BillBadge } from "./BillBadge"; -import { BillingLocation } from "../lib/db-types"; +import { BilledTo, BillingLocation } from "../lib/db-types"; import { formatYearMonth } from "../lib/format"; import { formatCurrency } from "../lib/formatStrings"; import Link from "next/link"; @@ -20,7 +20,7 @@ export const LocationCard:FC = ({location: { _id, name, yearM const currentLocale = useLocale(); // sum all the billAmounts (only for bills billed to tenant) - const monthlyExpense = bills.reduce((acc, bill) => (bill.paid && (bill.billedToTenant ?? true)) ? acc + (bill.payedAmount ?? 0) : acc, 0); + const monthlyExpense = bills.reduce((acc, bill) => (bill.paid && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) ? acc + (bill.payedAmount ?? 0) : acc, 0); const handleCopyLinkClick = () => { // copy URL to clipboard @@ -40,7 +40,7 @@ export const LocationCard:FC = ({location: { _id, name, yearM

{formatYearMonth(yearMonth)} {name}

{ - bills.filter(bill => bill.billedToTenant ?? true).map(bill => ) + bills.filter(bill => (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant).map(bill => ) } {t("add-bill-button-tooltip")} diff --git a/app/ui/ViewLocationCard.tsx b/app/ui/ViewLocationCard.tsx index 0aeb661..021db63 100644 --- a/app/ui/ViewLocationCard.tsx +++ b/app/ui/ViewLocationCard.tsx @@ -1,7 +1,7 @@ 'use client'; import { FC } from "react"; -import { BillingLocation } from "../lib/db-types"; +import { BilledTo, BillingLocation } from "../lib/db-types"; import { formatYearMonth } from "../lib/format"; import { formatCurrency } from "../lib/formatStrings"; import { useTranslations } from "next-intl"; @@ -16,7 +16,7 @@ export const ViewLocationCard:FC = ({location: { _id, nam const t = useTranslations("home-page.location-card"); // sum all the billAmounts (only for bills billed to tenant) - const monthlyExpense = bills.reduce((acc, bill) => (bill.paid && (bill.billedToTenant ?? true)) ? acc + (bill.payedAmount ?? 0) : acc, 0); + const monthlyExpense = bills.reduce((acc, bill) => (bill.paid && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) ? acc + (bill.payedAmount ?? 0) : acc, 0); return(
@@ -24,7 +24,7 @@ export const ViewLocationCard:FC = ({location: { _id, nam

{formatYearMonth(yearMonth)} {name}

{ - bills.filter(bill => bill.billedToTenant ?? true).map(bill => ) + bills.filter(bill => (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant).map(bill => ) }
{ diff --git a/messages/en.json b/messages/en.json index cbe7c4b..8852bf1 100644 --- a/messages/en.json +++ b/messages/en.json @@ -104,7 +104,9 @@ }, "attachment": "Attachment", "back-button": "Back", - "billed-to-tenant": "Billed to tenant" + "billed-to-label": "Billed to", + "billed-to-tenant-option": "Tenant", + "billed-to-landlord-option": "Landlord" }, "location-delete-form": { "text": "Please confirm deletion of realestate \"{name}\".", diff --git a/messages/hr.json b/messages/hr.json index 17364e6..730a1c2 100644 --- a/messages/hr.json +++ b/messages/hr.json @@ -103,7 +103,9 @@ }, "attachment": "Privitak", "back-button": "Nazad", - "billed-to-tenant": "Plaća podstanar" + "billed-to-label": "Račun plaća", + "billed-to-tenant-option": "Podstanar", + "billed-to-landlord-option": "Vlasnik" }, "location-delete-form": { "text": "Molim potvrdi brisanje nekretnine \"{name}\".",