Files
ProxLedger/src/components/kunden/KundeFormular.tsx
T
florian.wildeandClaude Opus 5 840e902b26 feat(kunden): Eigenbedarf fuer eigene Hosts (#044)
Eigene Hosts brauchen einen Kunden - sonst stehen sie unter "Nicht
zugeordnet" und fehlen in jeder Auswertung. Als gewoehnlicher Kunde erzeugen
sie aber Aufgaben, die es nicht gibt: Kundenrechnung erstellen, Kundenrechnung
unbezahlt, dazu eine negative Marge in jeder Summe.

Das Kennzeichen Eigenbedarf am Kunden nimmt die Verkaufsseite heraus: kein
Formular fuer die Kundenrechnung, keine Warnungen darueber, keine Aufgabe,
keine Marge - und in den Summen zaehlt der Einkauf mit, Verkauf und Marge
nicht.

Die Einkaufsseite bleibt vollstaendig: Eigene Hosts kosten echtes Geld, und
die Rechnung von Proxmox will bezahlt werden.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-04 06:54:43 +02:00

147 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import { useActionState } from "react";
import { kundeSpeichern, type AktionsErgebnis } from "@/server/actions/kunden";
export interface KundeFormularWerte {
id?: string;
name: string;
kundennummer: string;
ansprechpartner: string | null;
email: string | null;
telefon: string | null;
eigenbedarf: boolean;
notizen: string | null;
}
const LEER: AktionsErgebnis = {};
export function KundeFormular({ werte }: { werte?: KundeFormularWerte }) {
const [ergebnis, aktion, laeuft] = useActionState(kundeSpeichern, LEER);
function feldKlasse(feld: string) {
return `form-control ${ergebnis.felder?.[feld] ? "is-invalid" : ""}`;
}
return (
<form action={aktion}>
{werte?.id ? <input type="hidden" name="id" value={werte.id} /> : null}
{ergebnis.fehler ? (
<div className="alert alert-danger" role="alert">
{ergebnis.fehler}
</div>
) : null}
<div className="row g-3">
<div className="col-md-6">
<label className="form-label" htmlFor="name">
Name *
</label>
<input
id="name"
name="name"
className={feldKlasse("name")}
defaultValue={werte?.name ?? ""}
required
/>
{ergebnis.felder?.name ? <div className="invalid-feedback">{ergebnis.felder.name}</div> : null}
</div>
<div className="col-md-6">
<label className="form-label" htmlFor="kundennummer">
Kundennummer *
</label>
<input
id="kundennummer"
name="kundennummer"
className={`${feldKlasse("kundennummer")} pl-mono`}
defaultValue={werte?.kundennummer ?? ""}
placeholder="K-1001"
required
/>
{ergebnis.felder?.kundennummer ? (
<div className="invalid-feedback">{ergebnis.felder.kundennummer}</div>
) : null}
</div>
<div className="col-md-6">
<label className="form-label" htmlFor="ansprechpartner">
Ansprechpartner
</label>
<input
id="ansprechpartner"
name="ansprechpartner"
className="form-control"
defaultValue={werte?.ansprechpartner ?? ""}
/>
</div>
<div className="col-md-6">
<label className="form-label" htmlFor="email">
E-Mail
</label>
<input
id="email"
name="email"
type="email"
className={feldKlasse("email")}
defaultValue={werte?.email ?? ""}
/>
{ergebnis.felder?.email ? <div className="invalid-feedback">{ergebnis.felder.email}</div> : null}
</div>
<div className="col-md-6">
<label className="form-label" htmlFor="telefon">
Telefon
</label>
<input id="telefon" name="telefon" className="form-control" defaultValue={werte?.telefon ?? ""} />
</div>
<div className="col-12">
<div className="form-check">
<input
className="form-check-input pl-touch-target"
type="checkbox"
id="eigenbedarf"
name="eigenbedarf"
value="an"
defaultChecked={werte?.eigenbedarf ?? false}
/>
<label className="form-check-label" htmlFor="eigenbedarf">
Eigenbedarf – diese Hosts werden nicht weiterberechnet
</label>
<div className="form-text">
Für solche Kunden entfällt die Kundenrechnung: keine Warnungen darüber, keine Marge. Die
Einkaufsrechnung von Proxmox wird weiterhin geführt.
</div>
</div>
</div>
<div className="col-12">
<label className="form-label" htmlFor="notizen">
Notizen
</label>
<textarea
id="notizen"
name="notizen"
rows={3}
className="form-control"
defaultValue={werte?.notizen ?? ""}
/>
</div>
</div>
<div className="d-flex gap-2 mt-4">
<button type="submit" className="btn btn-primary pl-touch-target" disabled={laeuft}>
{laeuft ? "Speichert …" : "Speichern"}
</button>
<Link href={werte?.id ? `/kunden/${werte.id}` : "/kunden"} className="btn btn-outline-secondary">
Abbrechen
</Link>
</div>
</form>
);
}