Add German comma decimal input for currency/decimal fields
- New utility module `germanDecimal.js` with parseGermanDecimal(), sanitizeDecimalInput(), and formatGermanDecimal() - New DecimalInput component replacing type="number" inputs - Enables users to enter comma as decimal separator (12,50) - Applied to: hourlyWage, weeklyHours (ContractForm) and billingRate, travelCostRate, travelCostPerKm, mealAllowanceRate, minimumHours, and percent surcharges (FacilityForm) - Display formatting updated in FacilityDetailPanel to show comma decimals Both comma and dot are accepted as decimal separators. Backend decimal types remain unchanged (already decimal?). Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
fd20b07e83
commit
52fbec3214
@@ -1,7 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import OmsorgButton from "../../components/ui/OmsorgButton";
|
||||
import DecimalInput from "../../components/ui/DecimalInput";
|
||||
import { useValueListItems } from "../../app/useValueListItems";
|
||||
import { parseGermanDecimal } from "../../utils/germanDecimal";
|
||||
|
||||
export const emptyFacilityForm = {
|
||||
name: "",
|
||||
@@ -79,16 +81,16 @@ export function facilityFormToPayload(form, { includeCrmStatus = false, followUp
|
||||
if (includeCrmStatus) {
|
||||
payload.crmStatus = form.crmStatus;
|
||||
payload.followUpDays = followUpDays;
|
||||
payload.billingRate = form.billingRate === "" ? null : Number(form.billingRate);
|
||||
payload.nightSurchargePercent = form.nightSurchargePercent === "" ? null : Number(form.nightSurchargePercent);
|
||||
payload.saturdaySurchargePercent = form.saturdaySurchargePercent === "" ? null : Number(form.saturdaySurchargePercent);
|
||||
payload.sundaySurchargePercent = form.sundaySurchargePercent === "" ? null : Number(form.sundaySurchargePercent);
|
||||
payload.holidaySurchargePercent = form.holidaySurchargePercent === "" ? null : Number(form.holidaySurchargePercent);
|
||||
payload.billingRate = parseGermanDecimal(form.billingRate);
|
||||
payload.nightSurchargePercent = parseGermanDecimal(form.nightSurchargePercent);
|
||||
payload.saturdaySurchargePercent = parseGermanDecimal(form.saturdaySurchargePercent);
|
||||
payload.sundaySurchargePercent = parseGermanDecimal(form.sundaySurchargePercent);
|
||||
payload.holidaySurchargePercent = parseGermanDecimal(form.holidaySurchargePercent);
|
||||
payload.travelCostMode = form.travelCostMode || "Pauschale";
|
||||
payload.travelCostRate = form.travelCostRate === "" ? null : Number(form.travelCostRate);
|
||||
payload.travelCostPerKm = form.travelCostPerKm === "" ? null : Number(form.travelCostPerKm);
|
||||
payload.mealAllowanceRate = form.mealAllowanceRate === "" ? null : Number(form.mealAllowanceRate);
|
||||
payload.minimumHours = form.minimumHours === "" ? null : Number(form.minimumHours);
|
||||
payload.travelCostRate = parseGermanDecimal(form.travelCostRate);
|
||||
payload.travelCostPerKm = parseGermanDecimal(form.travelCostPerKm);
|
||||
payload.mealAllowanceRate = parseGermanDecimal(form.mealAllowanceRate);
|
||||
payload.minimumHours = parseGermanDecimal(form.minimumHours);
|
||||
payload.billingInterval = form.billingInterval || null;
|
||||
payload.paymentTermDays = form.paymentTermDays === "" ? null : Number(form.paymentTermDays);
|
||||
payload.individualAgreements = form.individualAgreements.trim() || null;
|
||||
@@ -131,6 +133,10 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
|
||||
return (event) => onChange({ ...form, [field]: event.target.value });
|
||||
}
|
||||
|
||||
function updateDecimalField(field) {
|
||||
return (rawValue) => onChange({ ...form, [field]: rawValue });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="form-grid">
|
||||
<label className="form-field">
|
||||
@@ -226,30 +232,30 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
|
||||
|
||||
<label className="form-field">
|
||||
<span>Verrechnungssatz (EUR/Std.)</span>
|
||||
<input type="number" min="0" step="0.01" value={form.billingRate} onChange={updateField("billingRate")} />
|
||||
<DecimalInput value={form.billingRate} onChange={updateDecimalField("billingRate")} />
|
||||
</label>
|
||||
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Nachtzuschlag (%)</span>
|
||||
<input type="number" min="0" step="0.1" value={form.nightSurchargePercent} onChange={updateField("nightSurchargePercent")} />
|
||||
<DecimalInput value={form.nightSurchargePercent} onChange={updateDecimalField("nightSurchargePercent")} />
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Samstagszuschlag (%)</span>
|
||||
<input type="number" min="0" step="0.1" value={form.saturdaySurchargePercent} onChange={updateField("saturdaySurchargePercent")} />
|
||||
<DecimalInput value={form.saturdaySurchargePercent} onChange={updateDecimalField("saturdaySurchargePercent")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Sonntagszuschlag (%)</span>
|
||||
<input type="number" min="0" step="0.1" value={form.sundaySurchargePercent} onChange={updateField("sundaySurchargePercent")} />
|
||||
<DecimalInput value={form.sundaySurchargePercent} onChange={updateDecimalField("sundaySurchargePercent")} />
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Feiertagszuschlag (%)</span>
|
||||
<input type="number" min="0" step="0.1" value={form.holidaySurchargePercent} onChange={updateField("holidaySurchargePercent")} />
|
||||
<DecimalInput value={form.holidaySurchargePercent} onChange={updateDecimalField("holidaySurchargePercent")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -264,7 +270,7 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
|
||||
|
||||
<label className="form-field">
|
||||
<span>Mindeststunden je Einsatz</span>
|
||||
<input type="number" min="0" step="0.5" value={form.minimumHours} onChange={updateField("minimumHours")} />
|
||||
<DecimalInput value={form.minimumHours} onChange={updateDecimalField("minimumHours")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -272,12 +278,12 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
|
||||
{form.travelCostMode === "ProKilometer" ? (
|
||||
<label className="form-field">
|
||||
<span>Fahrtkosten (EUR/km)</span>
|
||||
<input type="number" min="0" step="0.01" value={form.travelCostPerKm} onChange={updateField("travelCostPerKm")} />
|
||||
<DecimalInput value={form.travelCostPerKm} onChange={updateDecimalField("travelCostPerKm")} />
|
||||
</label>
|
||||
) : (
|
||||
<label className="form-field">
|
||||
<span>Fahrtkosten (EUR, Pauschale je Einsatz)</span>
|
||||
<input type="number" min="0" step="0.01" value={form.travelCostRate} onChange={updateField("travelCostRate")} />
|
||||
<DecimalInput value={form.travelCostRate} onChange={updateDecimalField("travelCostRate")} />
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
@@ -285,7 +291,7 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Verpflegungsmehraufwand (EUR, Pauschale je Einsatz)</span>
|
||||
<input type="number" min="0" step="0.01" value={form.mealAllowanceRate} onChange={updateField("mealAllowanceRate")} />
|
||||
<DecimalInput value={form.mealAllowanceRate} onChange={updateDecimalField("mealAllowanceRate")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user