add option to delete location in all subsequent months

- Added toggle in LocationDeleteForm for deleting locations from future months (disabled by default)
- Modified deleteLocationById action to support batch deletion across subsequent months
- When enabled, deletes all locations with same name in current and future months/years
- Only deletes user's own locations with proper data isolation
- Added translations for toggle text in Croatian and English
- Removed unused imports and variables to fix TypeScript warnings
- Uses efficient MongoDB deleteMany operation for bulk deletions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-11 11:01:16 +02:00
parent 2cf338c50a
commit 1eac116a55
4 changed files with 45 additions and 15 deletions

View File

@@ -302,7 +302,7 @@ export const fetchLocationById = async (locationID:string) => {
return(billLocation); return(billLocation);
}; };
export const deleteLocationById = withUser(async (user:AuthenticatedUser, locationID:string, yearMonth:YearMonth) => { export const deleteLocationById = withUser(async (user:AuthenticatedUser, locationID:string, yearMonth:YearMonth, _prevState:any, formData: FormData) => {
noStore(); noStore();
@@ -310,8 +310,35 @@ export const deleteLocationById = withUser(async (user:AuthenticatedUser, locati
const { id: userId } = user; const { id: userId } = user;
// find a location with the given locationID const deleteInSubsequentMonths = formData.get('deleteInSubsequentMonths') === 'on';
await dbClient.collection<BillingLocation>("lokacije").deleteOne({ _id: locationID, userId });
await gotoHome(yearMonth) if (deleteInSubsequentMonths) {
// Get the location name first to find all locations with the same name
const location = await dbClient.collection<BillingLocation>("lokacije")
.findOne({ _id: locationID, userId });
if (location) {
// Delete all locations with the same name in current and subsequent months
await dbClient.collection<BillingLocation>("lokacije").deleteMany({
userId,
name: location.name,
$or: [
{ "yearMonth.year": { $gt: yearMonth.year } },
{
"yearMonth.year": yearMonth.year,
"yearMonth.month": { $gte: yearMonth.month }
}
]
});
}
} else {
// Delete only the specific location (current behavior)
await dbClient.collection<BillingLocation>("lokacije").deleteOne({ _id: locationID, userId });
}
await gotoHome(yearMonth);
return {
message: null
};
}) })

View File

@@ -4,7 +4,6 @@ import { FC, ReactNode } from "react";
import { BillingLocation } from "../lib/db-types"; import { BillingLocation } from "../lib/db-types";
import { deleteLocationById } from "../lib/actions/locationActions"; import { deleteLocationById } from "../lib/actions/locationActions";
import { useFormState } from "react-dom"; import { useFormState } from "react-dom";
import { gotoUrl } from "../lib/actions/navigationActions";
import Link from "next/link"; import Link from "next/link";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@@ -16,14 +15,9 @@ export interface LocationDeleteFormProps {
export const LocationDeleteForm:FC<LocationDeleteFormProps> = ({ location }) => export const LocationDeleteForm:FC<LocationDeleteFormProps> = ({ location }) =>
{ {
const handleAction = deleteLocationById.bind(null, location._id, location.yearMonth); const handleAction = deleteLocationById.bind(null, location._id, location.yearMonth);
const [ state, dispatch ] = useFormState(handleAction, null); const [ , dispatch ] = useFormState(handleAction, null);
const t = useTranslations("location-delete-form"); const t = useTranslations("location-delete-form");
const handleCancel = () => {
gotoUrl(`/location/${location._id}/edit/`);
};
return( return(
<div className="card card-compact card-bordered min-w-[20em] max-w-[90em] bg-base-100 shadow-s my-1"> <div className="card card-compact card-bordered min-w-[20em] max-w-[90em] bg-base-100 shadow-s my-1">
<div className="card-body"> <div className="card-body">
@@ -36,6 +30,13 @@ export const LocationDeleteForm:FC<LocationDeleteFormProps> = ({ location }) =>
}) })
} }
</p> </p>
<div className="form-control">
<label className="label cursor-pointer">
<span className="label-text">{t("delete-in-subsequent-months")}</span>
<input type="checkbox" name="deleteInSubsequentMonths" className="toggle toggle-error" />
</label>
</div>
<div className="pt-4 text-center"> <div className="pt-4 text-center">
<button className="btn btn-primary w-[5.5em]">{t("confirm-button")}</button> <button className="btn btn-primary w-[5.5em]">{t("confirm-button")}</button>
<Link className="btn btn-neutral w-[5.5em] ml-3" href={`/location/${location._id}/edit/`}>{t("cancel-button")}</Link> <Link className="btn btn-neutral w-[5.5em] ml-3" href={`/location/${location._id}/edit/`}>{t("cancel-button")}</Link>

View File

@@ -88,9 +88,10 @@
"back-button": "Back" "back-button": "Back"
}, },
"location-delete-form": { "location-delete-form": {
"text": "Please confirm deletion of realestate “<strong>{name}</strong>””.", "text": "Please confirm deletion of realestate “<strong>{name}</strong>.",
"cancel-button": "Cancel", "cancel-button": "Cancel",
"confirm-button": "Confirm" "confirm-button": "Confirm",
"delete-in-subsequent-months": "Delete in all subsequent months"
}, },
"location-edit-form": { "location-edit-form": {
"location-name-placeholder": "Realestate name", "location-name-placeholder": "Realestate name",

View File

@@ -87,9 +87,10 @@
"back-button": "Nazad" "back-button": "Nazad"
}, },
"location-delete-form": { "location-delete-form": {
"text": "Molim potvrdi brisanje nekretnine “<strong>{name}</strong>””.", "text": "Molim potvrdi brisanje nekretnine “<strong>{name}</strong>.",
"cancel-button": "Odustani", "cancel-button": "Odustani",
"confirm-button": "Potvrdi" "confirm-button": "Potvrdi",
"delete-in-subsequent-months": "Obriši u svim mjesecima koji slijede"
}, },
"location-edit-form": { "location-edit-form": {
"location-name-placeholder": "Ime nekretnine", "location-name-placeholder": "Ime nekretnine",