Vertragsansicht: Kunden-Schnellansicht-Modal + Cent/Euro-Input

Feature 1 – Kunden-Schnellansicht:
Info-Icon neben dem Kundenlink im Vertragsdetail oeffnet ein Modal
mit den wichtigsten Kundendaten (Firma, Name, Geburtsdatum/-ort,
Gruendungsdatum, Adresse, Telefon, Mobil, E-Mail, Portal-E-Mail,
Steuer-/Handelsregisternr). Jedes Feld hat einen Copy-Button.
Lazy-Fetch via customerApi.getById, staleTime 30s.

Feature 2 – Cent/Euro-Doppel-Input:
Neben dem €/kWh-Arbeitspreis-Feld jetzt ein zweites ct/kWh-Feld.
Bidirektional gekoppelt – Tippen in € aktualisiert ct (×100),
Tippen in ct aktualisiert € (÷100). Backend speichert weiterhin
nur den Euro-Wert; Cent ist reine UI-Hilfe. Float-Rausch-Schutz
verhindert "0.25 → 25.0000000000004". Greift fuer unitPrice und
unitPriceNt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 14:41:37 +02:00
co-authored by Claude Opus 4.7
parent 20d42c5270
commit 771f46d2ac
4 changed files with 245 additions and 9 deletions
@@ -6,6 +6,7 @@ import { contractApi, uploadApi, meterApi, contractTaskApi, appSettingsApi, gdpr
import { ContractEmailsSection } from '../../components/email';
import { ContractDetailModal, ContractHistorySection } from '../../components/contracts';
import InvoicesSection from '../../components/contracts/InvoicesSection';
import CustomerInfoModal from '../../components/contracts/CustomerInfoModal';
import { useAuth } from '../../context/AuthContext';
import Card from '../../components/ui/Card';
import Button from '../../components/ui/Button';
@@ -1492,6 +1493,9 @@ export default function ContractDetail() {
() => new Date().toISOString().split('T')[0]
);
// Kunden-Schnellansicht-Modal
const [showCustomerInfo, setShowCustomerInfo] = useState(false);
const { data, isLoading } = useQuery({
queryKey: ['contract', id],
queryFn: () => contractApi.getById(contractId),
@@ -1771,11 +1775,20 @@ export default function ContractDetail() {
)}
</div>
{c.customer && (
<p className="text-gray-500 ml-10">
<p className="text-gray-500 ml-10 flex items-center gap-1">
Kunde:{' '}
<Link to={`/customers/${c.customer.id}`} state={pushHistory(currentPath, location.state)} className="text-blue-600 hover:underline">
{c.customer.companyName || `${c.customer.firstName} ${c.customer.lastName}`}
</Link>
<button
type="button"
onClick={() => setShowCustomerInfo(true)}
title="Wichtige Kundendaten anzeigen (Schnellansicht mit Copy-Buttons)"
className="text-gray-400 hover:text-blue-600 p-1 rounded"
aria-label="Kundendaten anzeigen"
>
<Info className="w-4 h-4" />
</button>
</p>
)}
</div>
@@ -3130,6 +3143,15 @@ export default function ContractDetail() {
/>
)}
{/* Kunden-Schnellansicht */}
{c.customer && (
<CustomerInfoModal
customerId={c.customer.id}
open={showCustomerInfo}
onClose={() => setShowCustomerInfo(false)}
/>
)}
{/* Folgevertrag Bestätigung */}
<Modal
isOpen={showFollowUpConfirm}