import { useState } from "react"; import { useTranslation } from "react-i18next"; import Icon from "./Icon"; import { formatMonthLabel } from "../format"; /** Auf welchen Tag der Monat gekappt fällt – einen 31. Februar gibt es nicht. * Dieselbe Kappung wie `_clamp_day` im Server, sonst fiele der 28. Februar bei * Starttag 31 in einen Monat, der ihn gar nicht enthält. */ function gekappt(jahr, monat, tag) { return Math.min(tag, new Date(jahr, monat, 0).getDate()); } /** Der Budget-Monat, in den ein Datum von selbst fällt – die Entsprechung zu * `budget.period_of` im Server. Hier gerechnet und nicht erfragt, damit die * Anzeige mitläuft, während man im Formular noch am Datum dreht. */ export function budgetMonat(iso, startTag) { const [j, m, d] = String(iso).split("-").map(Number); if (!j || !m) return ""; const zwei = (n) => String(n).padStart(2, "0"); if (startTag <= 1 || d < gekappt(j, m, startTag)) return `${j}-${zwei(m)}`; return m === 12 ? `${j + 1}-01` : `${j}-${zwei(m + 1)}`; } export function verschoben(label, monate) { const [j, m] = label.split("-").map(Number); const d = new Date(j, m - 1 + monate, 1); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; } // Drei Monate in jede Richtung – so weit wie der Server es annimmt, und weit // genug für den echten Fall (eine Zahlung kurz vor dem Stichtag, eine // verspätet beglichene Rechnung). const REICHWEITE = 3; /** * Zu welchem Budget-Monat eine Buchung zählt. * * Normalerweise entscheidet das Datum, und dann ist hier nichts zu tun – das * Feld sagt nur, was gilt. Das Ändern liegt bewusst hinter einem Klick und * hinter Pfeilen statt hinter einer Auswahlliste: Es ist der Ausnahmefall, * nicht der Normalfall, und soll sich auch so anfühlen. */ export default function BudgetZeitraum({ wert, datum, startTag, onChange }) { const { t, i18n } = useTranslation(); const [offen, setOffen] = useState(false); const eigen = budgetMonat(datum, startTag); if (!eigen) return null; const gilt = wert || eigen; const abstand = Math.round( (Number(gilt.split("-")[0]) - Number(eigen.split("-")[0])) * 12 + Number(gilt.split("-")[1]) - Number(eigen.split("-")[1])); function setze(schritt) { const neu = verschoben(gilt, schritt); onChange(neu === eigen ? null : neu); } return (
{t("transactions.budgetPeriodHint")}