Quelltext des aktuellen Standes
<?php
$this->layout('layouts/main', [
'page_title' => 'Neuer Vertrag',
'current_route' => 'contracts',
'full_width' => true,
'breadcrumbs' => [],
'extra_css' => ['/assets/css/company-search.css'],
'extra_js' => ['/assets/js/company-search.js'],
]);
// Der Vorschlag, eine unbekannte Firma anzulegen, setzt das Adressbuch und
// das Recht voraus, es zu pflegen.
$kannFirmaAnlegen = ($modules['contacts'] ?? false) && $this->hasCapability('manage_contacts');
?>
<div class="cf-wrap">
<!-- Content Header -->
<div class="content-header">
<div>
<h1><?= $this->te('Neuer Vertrag') ?></h1>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
<li class="breadcrumb-item"><a href="/contracts"><?= $this->te('Verträge') ?></a></li>
<li class="breadcrumb-item active"><?= $this->te('Neuer Vertrag') ?></li>
</ol>
</div>
</div>
<!-- FORM: zwei Spalten -->
<form action="/contracts" method="POST" class="cf-layout" id="contractForm">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<!-- ─── LINKE SPALTE ──────────────────────────────────── -->
<div class="cf-main">
<section class="cf-card">
<h2 class="cf-section-head">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
<?= $this->te('Stammdaten') ?>
</h2>
<div class="cf-card-body">
<div class="cf-row-2">
<div class="cf-field">
<label for="company_id"><?= $this->te('Firma') ?> <span class="cf-req">*</span></label>
<select id="company_id" name="company_id" required <?= $kannFirmaAnlegen ? 'data-create-company' : '' ?>>
<option value=""><?= $this->te('Firma auswählen…') ?></option>
<?php foreach ($companies as $c): ?>
<option value="<?= $c['id'] ?>" <?= ($preselected_company ?? 0) == $c['id'] ? 'selected' : '' ?>>
<?= $this->e($c['name']) ?><?php if (!empty($c['customer_number'])): ?> · <?= $this->e($c['customer_number']) ?><?php endif; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="cf-field">
<label for="contract_number"><?= $this->te('Vertragsnummer') ?></label>
<input type="text" id="contract_number" name="contract_number" maxlength="100" placeholder="z.B. V-2026-001">
</div>
</div>
<div class="cf-row-2">
<div class="cf-field">
<label for="category_id"><?= $this->te('Kategorie') ?></label>
<select id="category_id" name="category_id">
<option value=""><?= $this->te('Keine Kategorie') ?></option>
<?php foreach ($categories ?? [] as $cat): ?>
<option value="<?= $cat['id'] ?>">
<?= $this->e($cat['name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="cf-field"> </div>
</div>
<div class="cf-field">
<label for="title"><?= $this->te('Bezeichnung') ?> <span class="cf-req">*</span></label>
<input type="text" id="title" name="title" required maxlength="255" placeholder="<?= $this->te('z.B. Wartungsvertrag Server') ?>">
</div>
<div class="cf-field">
<label for="description"><?= $this->te('Beschreibung / Leistungsumfang') ?></label>
<textarea id="description" name="description" rows="4" placeholder="<?= $this->te('Leistungsbeschreibung, was ist im Vertrag enthalten…') ?>"></textarea>
</div>
</div>
</section>
<section class="cf-card">
<h2 class="cf-section-head">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
<?= $this->te('Laufzeit & Kündigung') ?>
</h2>
<div class="cf-card-body">
<div class="cf-row-2">
<div class="cf-field">
<label for="start_date"><?= $this->te('Vertragsbeginn') ?></label>
<input type="date" id="start_date" name="start_date">
</div>
<div class="cf-field">
<label for="end_date"><?= $this->te('Vertragsende') ?></label>
<input type="date" id="end_date" name="end_date">
</div>
</div>
<div class="cf-row-2">
<div class="cf-field">
<label for="cancellation_period_months"><?= $this->te('Kündigungsfrist (Monate)') ?></label>
<input type="number" id="cancellation_period_months" name="cancellation_period_months" min="0" max="60" placeholder="z.B. 3">
<span class="cf-hint"><?= $this->te('Erinnerung 1 Monat vor Fristbeginn') ?></span>
</div>
<div class="cf-field">
<label> </label>
<label class="cf-toggle">
<input type="checkbox" name="auto_renew" value="1">
<span class="cf-toggle-track"></span>
<span class="cf-toggle-label">
<strong><?= $this->te('Automatische Verlängerung') ?></strong>
<small><?= $this->te('Vertrag verlängert sich automatisch') ?></small>
</span>
</label>
</div>
</div>
<div class="cf-row-2">
<div class="cf-field">
<label for="renewal_period_months"><?= $this->te('Verlängerung um (Monate)') ?></label>
<input type="number" id="renewal_period_months" name="renewal_period_months" min="1" max="120" placeholder="<?= $this->te('Standard: 12') ?>">
<span class="cf-hint"><?= $this->te('Nur bei automatischer Verlängerung – um wie viel sich das Enddatum verschiebt, wenn nicht gekündigt wird.') ?></span>
</div>
<div class="cf-field"><label> </label></div>
</div>
</div>
</section>
<section class="cf-card">
<h2 class="cf-section-head">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
<?= $this->te('Verantwortung & Notizen') ?>
</h2>
<div class="cf-card-body">
<div class="cf-row-2">
<div class="cf-field">
<label for="status"><?= $this->te('Status') ?></label>
<select id="status" name="status" onchange="cfToggleCancellationDate(this.value)">
<option value="active"><?= $this->te('Aktiv') ?></option>
<option value="future"><?= $this->te('Zukünftig') ?></option>
<option value="cancelled"><?= $this->te('Gekündigt') ?></option>
</select>
<small style="color:var(--gray-500);"><?= $this->te('Bei Startdatum in der Zukunft wird "Aktiv" automatisch auf "Zukünftig" gesetzt.') ?></small>
</div>
<div class="cf-field">
<label for="responsible_user_id"><?= $this->te('Verantwortlich') ?></label>
<select id="responsible_user_id" name="responsible_user_id">
<option value=""><?= $this->te('Nicht zugewiesen') ?></option>
<?php foreach ($users as $u): ?>
<option value="<?= $u['id'] ?>"><?= $this->e($u['display_name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="cf-field" id="cancellation-date-field" style="display:none;">
<label for="cancellation_date"><?= $this->te('Kündigungsdatum') ?> <span style="color:var(--red-600);">*</span></label>
<input type="date" id="cancellation_date" name="cancellation_date">
<span class="cf-hint"><?= $this->te('Datum ab dem der Vertrag offiziell endet (leer = heute)') ?></span>
</div>
<div class="cf-field">
<label for="notify_scope"><?= $this->te('Fristerinnerung senden an') ?></label>
<select id="notify_scope" name="notify_scope">
<option value="all"><?= $this->te('Alle mit Vertragszugriff') ?></option>
<option value="responsible"><?= $this->te('Nur Verantwortliche/r') ?></option>
</select>
<span class="cf-hint"><?= $this->te('Wer wird bei Kündigungsfrist/Vertragsende benachrichtigt? „Nur Verantwortliche/r" fällt auf „alle" zurück, wenn niemand zugewiesen ist.') ?></span>
</div>
<div class="cf-field">
<label for="notes"><?= $this->te('Interne Notizen') ?></label>
<textarea id="notes" name="notes" rows="3" placeholder="<?= $this->te('Ansprechpartner beim Anbieter, besondere Konditionen…') ?>"></textarea>
</div>
</div>
</section>
</div><!-- /cf-main -->
<!-- ─── RECHTE SPALTE (Sidebar) ───────────────────────── -->
<aside class="cf-sidebar">
<section class="cf-card">
<h2 class="cf-section-head">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
<?= $this->te('Kosten') ?>
</h2>
<div class="cf-card-body">
<div class="cf-row-2">
<div class="cf-field">
<label for="cost_amount"><?= $this->te('Betrag Brutto ({cur})', ['cur' => $this->currency()]) ?></label>
<input type="number" id="cost_amount" name="cost_amount" step="0.01" min="0" placeholder="0,00">
</div>
<div class="cf-field">
<label for="cost_amount_net"><?= $this->te('Betrag Netto ({cur})', ['cur' => $this->currency()]) ?></label>
<input type="number" id="cost_amount_net" step="0.01" min="0" placeholder="0,00">
<span class="cf-hint"><?= $this->te('Rechnet Brutto über den MwSt-Satz hoch') ?></span>
</div>
</div>
<div class="cf-row-2">
<div class="cf-field">
<label for="tax_rate"><?= $this->te('MwSt-Satz (%)') ?></label>
<input type="number" id="tax_rate" name="tax_rate" step="0.01" min="0" max="100" placeholder="z.B. 19">
<span class="cf-hint"><?= $this->te('Leer lassen = keine MwSt') ?></span>
</div>
<div class="cf-field">
<label for="cost_interval"><?= $this->te('Intervall') ?></label>
<select id="cost_interval" name="cost_interval">
<option value="monthly"><?= $this->te('Monatlich') ?></option>
<option value="quarterly"><?= $this->te('Quartalsweise') ?></option>
<option value="yearly"><?= $this->te('Jährlich') ?></option>
<option value="one_time"><?= $this->te('Einmalig') ?></option>
</select>
</div>
</div>
<div class="cf-field">
<label for="first_payment_date"><?= $this->te('Erste Zahlung') ?></label>
<input type="date" id="first_payment_date" name="first_payment_date">
<span class="cf-hint"><?= $this->te('Für Fälligkeitsberechnung') ?></span>
</div>
</div>
</section>
<!-- Live-Vorschau (erscheint wenn Betrag eingegeben) -->
<section class="cf-card cf-preview-card" id="costPreviewCard" style="display:none;">
<h2 class="cf-section-head cf-head-accent">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<?= $this->te('Kostenvorschau') ?>
</h2>
<div class="cf-card-body">
<div class="cf-preview-grid">
<div class="cf-tile cf-tile-blue">
<span><?= $this->te('Monatl. Brutto') ?></span>
<strong id="prev-monthly-gross">–</strong>
</div>
<div class="cf-tile cf-tile-green">
<span><?= $this->te('Monatl. Netto') ?></span>
<strong id="prev-monthly-net">–</strong>
</div>
<div class="cf-tile cf-tile-indigo">
<span><?= $this->te('Jährl. Brutto') ?></span>
<strong id="prev-yearly-gross">–</strong>
</div>
<div class="cf-tile cf-tile-teal">
<span><?= $this->te('Jährl. Netto') ?></span>
<strong id="prev-yearly-net">–</strong>
</div>
</div>
<div id="prev-next-payment" class="cf-due" style="display:none;">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
<?= $this->te('Nächste Fälligkeit:') ?> <strong id="prev-next-payment-text"></strong>
</div>
</div>
</section>
<div class="cf-actions">
<button type="submit" class="cf-btn cf-btn-primary">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="20 6 9 17 4 12"/></svg>
<?= $this->te('Vertrag erstellen') ?>
</button>
<a href="/contracts" class="cf-btn cf-btn-cancel"><?= $this->te('Abbrechen') ?></a>
</div>
</aside>
</form>
</div>
<style>
<?php include __DIR__ . '/_contract_form.css.php'; ?>
</style>
<script>
<?php include __DIR__ . '/_contract_form.js.php'; ?>
function cfToggleCancellationDate(status) {
var field = document.getElementById('cancellation-date-field');
var input = document.getElementById('cancellation_date');
if (!field) return;
if (status === 'cancelled') {
field.style.display = '';
if (input) input.required = true;
} else {
field.style.display = 'none';
if (input) { input.required = false; input.value = ''; }
}
}
</script>
<?php if ($kannFirmaAnlegen): ?>
<?= $this->render('partials/_company_quick_create') ?>
<?php endif; ?>