feat: add multi-bill-edit page for batch bill status updates

- Add getLocationsByMonth server action with aggregation pipeline to calculate hasAttachment
- Add updateMonth server action for bulk bill status updates with path revalidation
- Create multi-bill-edit page at /home/multi-bill-edit/[year]/[month]
- Implement MultiBillEdit component with toggle functionality for all bills
- Add BillToggleBadge component integration for consistent bill display
- Add "set all as paid/unpaid" toggle button for batch operations
- Implement server-side redirect with success message after save
- Add Suspense boundary with loading skeleton
- Update translations for multi-bill-edit feature (Croatian and English)
- Ensure data freshness with unstable_noStore and revalidatePath

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-18 17:45:27 +01:00
parent e9ade045d8
commit 0145a2030d
10 changed files with 442 additions and 25 deletions

View File

@@ -58,6 +58,9 @@
"add-month-button": {
"tooltip": "Add next mont"
},
"multi-bill-edit-button": {
"tooltip": "Multi Bills Edit"
},
"location-card": {
"edit-card-tooltip": "Edit realestate",
"add-bill-button-tooltip": "Add a new bill",
@@ -103,7 +106,8 @@
"bill-saved-message": "Bill saved successfully",
"bill-deleted-message": "Bill deleted successfully",
"location-saved-message": "Location saved successfully",
"location-deleted-message": "Location deleted successfully"
"location-deleted-message": "Location deleted successfully",
"bill-multi-edit-save-success-message": "Changes saved successfully"
},
"bill-delete-form": {
"text": "Please confirm deletion of bill \"<strong>{bill_name}</strong>\" at \"<strong>{location_name}</strong>\".",
@@ -153,7 +157,6 @@
"location-name-legend": "Realestate name",
"location-name-placeholder": "enter realestate name",
"notes-placeholder": "notes",
"proof-of-payment-attachment-type--legend": "Proof of Payment",
"proof-of-payment-attachment-type--info": "Here you can choose how the tenant can provide proof of payment for utilities. Select the option that best matches the payment arrangement you have agreed upon.",
"proof-of-payment-attachment-type--option--label": "Tenant provides ...",
@@ -164,24 +167,20 @@
"proof-of-payment-attachment-type--option--combined--hint": "💡 with the selected option you might also want to activate <strong>payment instructions</strong> - see above",
"proof-of-payment-attachment-type--option--per-bill": "✂️ separate proof of payment for each bill",
"proof-of-payment-attachment-type--option--per-bill--tooltip": "The selected option is useful if the tenant pays utilities directly to individual service providers",
"tenant-payment-instructions-legend": "PAYMENT INSTRUCTIONS",
"tenant-payment-instructions-code-info": "When the tenant opens the link to the statement for the given month, the application can show payment instructions for utility costs to your IBAN, as well as a 2D code they can scan.",
"tenant-payment-instructions-method--legend": "Show payment instructions to tenant:",
"tenant-payment-instructions-method--none": "⛔ do not show payment instructions",
"tenant-payment-instructions-method--iban": "🏛️ payment via IBAN",
"tenant-payment-instructions-method--iban-disabled": "payment via IBAN - disabled in app settings",
"tenant-payment-instructions-method--revolut": "🅡 payment via Revolut",
"tenant-payment-instructions-method--revolut-disabled": "payment via Revolut - disabled in app settings",
"iban-payment--tenant-name-label": "Tenant First and Last Name",
"iban-payment--tenant-name-placeholder": "enter tenant's first and last name",
"iban-payment--tenant-street-label": "Tenant Street and House Number",
"iban-payment--tenant-street-placeholder": "enter tenant's street",
"iban-payment--tenant-town-label": "Tenant Postal Code and Town",
"iban-payment--tenant-town-placeholder": "enter tenant's town",
"auto-utility-bill-forwarding-legend": "Automatic utility bill forwarding",
"auto-utility-bill-forwarding-info": "This option enables automatic forwarding of utility bills to the tenant via email according to the selected forwarding strategy.",
"auto-utility-bill-forwarding-toggle-label": "forward utility bills",
@@ -222,12 +221,10 @@
},
"user-settings-form": {
"title": "User settings",
"iban-payment-instructions--legend": "Payment to Your IBAN",
"iban-payment-instructions--intro-title": "What does this option do?",
"iban-payment-instructions--intro-message": "By activating this option, the monthly statement sent to the tenant will contain payment details and a 2D barcode allowing a direct payment to your bank account.",
"iban-payment-instructions--toggle-label": "enable IBAN payment instructions",
"iban-form-title": "Payment Information for IBAN",
"iban-owner-name-label": "Your First and Last Name",
"iban-owner-name-placeholder": "enter your first and last name",
@@ -237,22 +234,17 @@
"iban-owner-town-placeholder": "enter your postal code and town",
"iban-owner-iban-label": "IBAN",
"iban-owner-iban-placeholder": "enter your IBAN for receiving payments",
"revolut-form-title": "Payment Information for Revolut",
"revolut-payment-instructions--legend": "Payment to Your Revolut Profile",
"revolut-payment-instructions--intro-title": "What does this option do?",
"revolut-payment-instructions--intro-message": "By activating this option, the monthly statement sent to the tenant will contain a link allowing a direct payment to your Revolut account.",
"revolut-payment-instructions--toggle-label": "enable Revolut payment instructions",
"revolut-profile-label": "Revolut profile name",
"revolut-profile-placeholder": "enter your Revolut profile name for receiving payments",
"revolut-profile-tooltip": "You can find your Revolut profile name in the Revolut app under your user profile. It is displayed below your name and starts with the '@' symbol (e.g., '@john123').",
"revolut-profile--test-link-label": "Test your Revolut link:",
"revolut-profile--test-link-text": "Pay with Revolut",
"payment-additional-notes": "IMPORTANT: For the payment instructions to be displayed to the tenant, you must also enable this option in the property's settings.",
"general-settings-legend": "General Settings",
"currency-label": "Currency",
"save-button": "Save",
@@ -271,5 +263,20 @@
},
"info-box": {
"default-title": "What is this option for?"
},
"multi-bill-edit": {
"title": "Multi Bill Edit",
"loading-message": "Loading...",
"error-title": "Error",
"no-locations-title": "No Locations",
"no-locations-message": "No locations found for the selected month",
"no-bills-message": "No bills",
"set-all-as-paid-button": "Mark all as paid",
"set-all-as-unpaid-button": "Mark all as unpaid",
"save-button": "Save",
"saving-button": "Saving...",
"cancel-button": "Cancel",
"back-to-home-button": "Back to Home",
"save-error-message": "Error saving changes"
}
}

View File

@@ -58,6 +58,9 @@
"add-month-button": {
"tooltip": "Dodaj idući mjesec"
},
"multi-bill-edit-button": {
"tooltip": "Izmjena više računa"
},
"location-card": {
"edit-card-tooltip": "Izmjeni nekretninu",
"add-bill-button-tooltip": "Dodaj novi račun",
@@ -103,7 +106,10 @@
"bill-saved-message": "Račun uspješno spremljen",
"bill-deleted-message": "Račun uspješno obrisan",
"location-saved-message": "Nekretnina uspješno spremljena",
"location-deleted-message": "Nekretnina uspješno obrisana"
"location-deleted-message": "Nekretnina uspješno obrisana",
"bill-multi-edit-save-success-message": "Promjene uspješno spremljene",
"bill-multi-edit-save-error-message": "Greška pri spremanju promjena",
"bill-multi-edit-load-error-message": "Greška pri učitavanju podataka"
},
"bill-delete-form": {
"text": "Molim potvrdi brisanje računa \"<strong>{bill_name}</strong>\" koji pripada nekretnini \"<strong>{location_name}</strong>\".",
@@ -152,7 +158,6 @@
"location-name-legend": "Realestate name",
"location-name-placeholder": "unesite naziv nekretnine",
"notes-placeholder": "bilješke",
"proof-of-payment-attachment-type--legend": "Potvrda o uplati",
"proof-of-payment-attachment-type--info": "Ovdje možete odabrati na koji način na koji podstanar može priložiti potvrdu o uplati režija. Izaberite način koji najbolje odgovara načinu na koji ste dogovorili plaćanje režija.",
"proof-of-payment-attachment-type--option--label": "Podstanar prilaže ...",
@@ -163,10 +168,8 @@
"proof-of-payment-attachment-type--option--combined--hint": "💡 za odabranu opciju dobro je uključiti i <strong>prikaz uputa za uplatu</strong> - vidi gore",
"proof-of-payment-attachment-type--option--per-bill": "✂️ zasebna potvrda za svaki račun",
"proof-of-payment-attachment-type--option--per-bill--tooltip": "Odabrana opcija je korisna ako podstanar plaća režije izravno pojedinačnim davateljima usluga",
"tenant-payment-instructions-legend": "Upute za uplatu",
"tenant-payment-instructions-code-info": "Kada podstanar otvori poveznicu na obračun za zadani mjesec aplikacija mu može prikazati upute za uplatu troškova režija na vaš IBAN ili Revolut.",
"tenant-payment-instructions-method--legend": "Podstanaru prikaži upute za uplatu:",
"tenant-payment-instructions-method--none": "⛔ ne prikazuj upute za uplatu",
"tenant-payment-instructions-method--iban": "🏛️ uplata na IBAN",
@@ -174,7 +177,6 @@
"tenant-payment-instructions-method--revolut": "🅡 uplata na Revolut",
"tenant-payment-instructions-method--revolut-disabled": "uplata na Revolut - onemogućeno u app postavkama",
"tenant-payment-instructions-method--disabled-message": "Ova opcija je nedostupna zato što nije omogućena u postavkama aplikacije.",
"iban-payment--form-title": "Informacije za uplatu na IBAN",
"iban-payment--tenant-name-label": "Ime i prezime podstanara",
"iban-payment--tenant-name-placeholder": "unesite ime i prezime podstanara",
@@ -182,7 +184,6 @@
"iban-payment--tenant-street-placeholder": "unesite ulicu podstanara",
"iban-payment--tenant-town-label": "Poštanski broj i Grad podstanara",
"iban-payment--tenant-town-placeholder": "unesite poštanski broj i grad podstanara",
"auto-utility-bill-forwarding-legend": "AUTOMATSKO PROSLJEĐIVANJE REŽIJA",
"auto-utility-bill-forwarding-info": "Ova opcija omogućuje automatsko prosljeđivanje režija podstanaru putem emaila u skladu s odabranom strategijom.",
"auto-utility-bill-forwarding-toggle-label": "proslijedi režije automatski",
@@ -223,11 +224,9 @@
},
"user-settings-form": {
"title": "Korisničke postavke",
"iban-payment-instructions--legend": "Uplata na vaš IBAN",
"iban-payment-instructions--intro-message": "Aktiviranjem ove opcije, mjesečni obračun poslan podstanaru sadržavati će podatke za uplatu i 2D barkod putem kojeg će podstanar moći izvršiti izravnu uplatu sredstava na bankovni račun.",
"iban-payment-instructions--toggle-label": "omogući IBAN uplatu",
"iban-form-title": "Informacije za uplatu na IBAN",
"iban-owner-name-label": "Vaše ime i prezime",
"iban-owner-name-placeholder": "unesite svoje ime i prezime",
@@ -237,18 +236,15 @@
"iban-owner-town-placeholder": "unesite poštanski broj i grad",
"iban-owner-iban-label": "IBAN",
"iban-owner-iban-placeholder": "IBAN putem kojeg ćete primate uplate",
"revolut-payment-instructions--legend": "Uplata na vaš Revolut profil",
"revolut-payment-instructions--intro-message": "Aktiviranjem ove opcije, mjesečni obračun poslan podstanaru sadržavati će link putem kojeg će podstanar moći izvršiti izravnu uplatu sredstava na vaš Revolut račun.",
"revolut-payment-instructions--toggle-label": "omogući Revolut uplatu",
"revolut-form-title": "Info za uplatu na Revolut",
"revolut-profile-label": "Naziv vašeg Revolut profila",
"revolut-profile-placeholder": "profil putem kojeg ćete primati uplate",
"revolut-profile-tooltip": "Naziv vašeg Revolut profila možete pronaći u aplikaciji Revolut u korisničkom profilu. Prikazan je ispod vašeg imena i prezimena - počinje sa znakom '@' (npr: '@ivan123').",
"revolut-profile--test-link-label": "Testiraj svoju Revolut poveznicu:",
"revolut-profile--test-link-text": "Plati pomoću Revoluta",
"general-settings-legend": "Opće postavke",
"currency-label": "Valuta",
"save-button": "Spremi",
@@ -268,5 +264,20 @@
},
"info-box": {
"default-title": "Čemu služi ova opcija?"
},
"multi-bill-edit": {
"title": "Masovna izmjena računa",
"loading-message": "Učitavanje...",
"error-title": "Greška",
"no-locations-title": "Nema lokacija",
"no-locations-message": "Nisu pronađene lokacije za odabrani mjesec",
"no-bills-message": "Nema računa",
"set-all-as-paid-button": "Označi sve kao plaćeno",
"set-all-as-unpaid-button": "Označi sve kao neplaćeno",
"save-button": "Spremi",
"saving-button": "Spremanje...",
"cancel-button": "Odustani",
"back-to-home-button": "Povratak na početnu",
"save-error-message": "Greška pri spremanju promjena"
}
}