@extends('layouts.app', ['title' => 'Angebot ' . $offer->offer_nr]) @section('content')
{{-- Header --}}
{{-- Breadcrumb-Zeile --}}
Zurück @if($offer->category) | {{ $offer->category->nr_prefix }} · {{ $offer->category->name }} @endif {{ $offer->offer_nr }}
{{-- Titel + Actions --}}

{{ $offer->title }}

{{-- Aktionen: alle in einer Zeile, visuell gruppiert --}}
{{-- Sekundär: Kopieren --}} {{-- Trennlinie --}} | {{-- PDF-Gruppe --}} @if(!$offer->order) @endif @if($dmsFile) Angebot PDF v{{ $dmsFile->version }} @else Angebot PDF @endif {{-- Trennlinie --}} | {{-- Haupt-CTA: Beauftragen / Zum Auftrag --}} @if($offer->order) Zum Auftrag @if($abFile) AB @endif @elseif($dmsFile) @else Erst PDF erstellen @endif
@if(session('success'))
{{ session('success') }}
@endif {{-- Workflow-Banner (nur wenn Workflow zugewiesen) --}} @if($offer->fk_workflow_id && $wfCurrentStation)
{{-- Zeile 1: Zurück · Phase/Abteilung · Weiter --}}
{{-- Zurück --}}
@if($wfPrevStation && !$offer->order)
@csrf
@endif
{{-- Phase / Abteilung (Mitte) --}}
Phase {{ $offer->current_phase }}: {{ $wfCurrentStation->department->name ?? '—' }}
{{-- Weiter --}}
@if(!$offer->order) @if($wfNextStation)
@csrf
@else Workflow abgeschlossen @endif @endif
{{-- Zeile 2: Aufgabe --}} @if($wfCurrentStation->aufgabe)
{{ $wfCurrentStation->aufgabe }}
@endif
@endif {{-- Status-Leiste --}} @php $allOfferStatuses = \App\Models\PmsStatus::offer()->where('is_deleted',0)->orderBy('sort')->get(); $allDeptStatuses = \App\Models\PmsStatus::dept()->where('is_deleted',0)->orderBy('sort')->get(); @endphp
HAUPTSTATUS @foreach($allOfferStatuses as $s)
@csrf
@endforeach
ABTEILUNG @foreach($allDeptStatuses as $s)
@csrf
@endforeach
{{-- Linke Spalte --}}
{{-- Stammdaten --}}
Stammdaten Bearbeiten
{{-- Gruppe 1: Auftraggeber --}}
KUNDE
{{ $offer->customer?->name ?? '—' }}
ANSPRECHPARTNER
{{ $offer->customer_contact ? $offer->customer_contact->first_name . ' ' . $offer->customer_contact->last_name : '—' }}

{{-- Gruppe 2: Bauvorhaben --}}
BAUVORHABEN
@if($offer->project_location) {{ $offer->project_location->name }} @if($offer->project_location->address) — {{ $offer->project_location->address }} @endif @else @endif

{{-- Gruppe 3: Konditionen --}}
ANGEBOTSDATUM
{{ $offer->offer_date ? \Carbon\Carbon::parse($offer->offer_date)->format('d.m.Y') : '—' }}
GÜLTIG BIS
@php $validUntil = $offer->valid_until ? \Carbon\Carbon::parse($offer->valid_until) : null; @endphp @if($validUntil) {{ $validUntil->format('d.m.Y') }} @else — @endif
PROJEKTART
{{ $offer->type?->name ?? '—' }}

{{-- Gruppe 4: Workflow & AGB --}}
WORKFLOW
@if($offer->workflow) {{ $offer->workflow->name }} @else @endif
AGB / ZAHLUNGSBEDINGUNGEN
@if($offer->terms) {{ $offer->terms->title }} @else Standard AGB @endif
@if($offer->description)
BESCHREIBUNG
{{ $offer->description }}
@endif
{{-- Positionen --}}
{{-- Aktions-Buttons --}}
Noch keine Positionen angelegt.
@foreach($offer->positions as $i => $pos) @include('pms.offers._position_row', ['pos' => $pos, 'depth' => 0, 'nr' => ($i+1)]) @endforeach {{-- Inline-Eingabezeile --}}
@if($offer->positions->count()) @php $netto = $offer->positions->where('is_optional', 0)->sum('calculated_total'); $vatFactor = (float)($offer->vat_rate ?? 19) / 100; $mwst = $netto * $vatFactor; $brutto = $netto + $mwst; @endphp @php $totalRowStyle = 'd-flex align-items-center gap-2 px-3'; @endphp
{{-- Nettosumme --}}
NETTOSUMME {{ number_format($netto, 2, ',', '.') }} €
{{-- MwSt --}}
@if($offer->vat_hinweis){{ $offer->vat_hinweis }} · @endif UMSATZSTEUER {{ number_format($offer->vat_rate ?? 19, 0) }} % {{ number_format($mwst, 2, ',', '.') }} €
{{-- Gesamtsumme --}}
GESAMTSUMME {{ number_format($brutto, 2, ',', '.') }} €
@endif
{{-- end tab-pane positionen --}} {{-- Tab: Dateien / Anhänge --}}
{{-- Header --}}
{{ $attachments->count() }} Datei(en) angehängt
{{-- Datei-Liste --}} @if($attachments->isEmpty())
Noch keine Dateien angehängt.
@else @foreach($attachments as $att) @php $ext = strtolower(pathinfo($att->filename, PATHINFO_EXTENSION)); $icon = match(true) { in_array($ext, ['pdf']) => ['bi-file-earmark-pdf', 'text-danger'], in_array($ext, ['jpg','jpeg','png','gif','webp','svg']) => ['bi-file-earmark-image', 'text-success'], in_array($ext, ['doc','docx']) => ['bi-file-earmark-word', 'text-primary'], in_array($ext, ['xls','xlsx','csv']) => ['bi-file-earmark-excel', 'text-success'], in_array($ext, ['zip','rar','7z']) => ['bi-file-earmark-zip', 'text-warning'], default => ['bi-file-earmark', 'text-muted'], }; @endphp @endforeach
Dateiname Größe Hochgeladen Aktionen
{{ $att->original_name ?? $att->filename }}
@if($att->original_name && $att->original_name !== $att->filename)
{{ $att->filename }}
@endif
@if($att->filesize) {{ $att->filesize >= 1048576 ? number_format($att->filesize / 1048576, 1) . ' MB' : number_format($att->filesize / 1024, 0) . ' KB' }} @else — @endif {{ $att->created_at ? \Carbon\Carbon::parse($att->created_at)->format('d.m.Y H:i') : '—' }} Download @if(Auth::user()->get_employee->is_dms || Auth::user()->get_employee->is_mgt)
@csrf
@endif
@endif
{{-- end tab-pane attachments --}} {{-- Tab: PDF Versionen --}}
@if($pdfHistory->isEmpty())
Noch kein PDF erstellt.
@else @foreach($pdfHistory as $pdf) @endforeach
Version Dateiname Erstellt am Status Aktionen
v{{ $pdf->version }} {{ $pdf->filename }} {{ $pdf->created_at ? \Carbon\Carbon::parse($pdf->created_at)->format('d.m.Y H:i') : '—' }} @if($pdf->is_deleted) Archiviert @else Aktuell @endif
@endif
{{-- end tab-pane pdf-history --}}
{{--
PDF noch nicht erstellt — oben auf PDF erstellen klicken.
--}}
{{-- end tab-pane pdf --}}
{{-- end tab-content --}}
{{-- Rechte Spalte: Termine + Timeline --}}
{{-- Termine --}}
Termine @php $now = now(); $upcoming = $appointments->where('is_done', 0)->filter(fn($a) => $a->starts_at->gte($now))->sortBy('starts_at'); $missed = $appointments->where('is_done', 0)->filter(fn($a) => $a->starts_at->lt($now))->sortByDesc('starts_at'); $done = $appointments->where('is_done', 1)->sortByDesc('starts_at'); @endphp @if($upcoming->count()) {{ $upcoming->count() }} @endif @if($missed->count()) {{ $missed->count() }} verpasst @endif
@if($appointments->isEmpty())
Noch keine Termine vereinbart.
@else {{-- Bevorstehende --}} @foreach($upcoming as $apt)
{{ $apt->type_label }}
{{ $apt->title }}
{{ $apt->starts_at->format('d.m.Y H:i') }} @if($apt->ends_at) – {{ $apt->ends_at->format('H:i') }} @endif
@if($apt->notes)
{{ $apt->notes }}
@endif
@csrf
@csrf
@endforeach {{-- Verpasst --}} @if($missed->count())
VERPASST
@foreach($missed as $apt)
{{ $apt->type_label }}
{{ $apt->title }}
{{ $apt->starts_at->format('d.m.Y H:i') }} @if($apt->ends_at) – {{ $apt->ends_at->format('H:i') }} @endif
@if($apt->notes)
{{ $apt->notes }}
@endif
@csrf
@csrf
@endforeach
@endif {{-- Erledigte (eingeklappt) --}} @if($done->count())
@foreach($done as $apt)
{{ $apt->title }}
{{ $apt->starts_at->format('d.m.Y H:i') }}
@csrf
@csrf
@endforeach
@endif @endif
{{-- Timeline --}}
Verlauf / Hinweise
{{-- Neuer Eintrag --}}
@csrf {{-- Typ-Auswahl --}}
@foreach([ ['4','notes','bi-info-square-fill','Info','text-info'], ['0','call','bi-telephone-fill','Anruf','text-success'], ['1','mail','bi-envelope-fill','E-Mail','text-primary'], ['2','poste','bi-mailbox2','Post','text-secondary'], ['3','personally','bi-people-fill','Persönlich','text-warning'], ] as [$val,$rid,$ico,$lbl,$col]) @endforeach
{{-- Kontakt mit --}}

{{-- Filter --}}
Filter: @foreach([ ['0','all','bi-list-ul','Alle'], ['1','fnotes','bi-info-square-fill','Info'], ['2','fcall','bi-telephone-fill','Anruf'], ['3','fmail','bi-envelope-fill','E-Mail'], ['4','fposte','bi-mailbox2','Post'], ['5','fpersonally','bi-people-fill','Person'], ] as [$val,$fid,$ico,$lbl]) @endforeach
{{-- Einträge --}} @forelse($offer->timeline as $entry) @php $isNote = $entry->contact_type == 4; $isCall = $entry->contact_type == 0; $isEmail = $entry->contact_type == 1; $isPost = $entry->contact_type == 2; $isPersonally = $entry->contact_type == 3; $tlIcon = $isNote ? 'bi-info-square-fill' : ($isCall ? 'bi-telephone-fill' : ($isEmail ? 'bi-envelope-fill' : ($isPost ? 'bi-mailbox2' : 'bi-people-fill'))); $tlColor = $isNote ? '#0dcaf0' : ($isCall ? '#198754' : ($isEmail ? '#0d6efd' : ($isPost ? '#6c757d' : '#ffc107'))); @endphp
@if(!$isNote && $entry->contact_dst) {{ $entry->contact_dst }} @endif {{ $entry->created_at ? \Carbon\Carbon::parse($entry->created_at)->format('d.m.Y - H:i') : '—' }}
{!! $entry->message !!}
{{ $entry->employee?->first_name }} {{ $entry->employee?->last_name }}
@empty
Noch keine Einträge.
@endforelse
{{-- Formular für Inline-Position (außerhalb Tabelle, via form="inline-pos-form") --}}
@csrf
{{-- Modal: Angebot kopieren --}} {{-- Modal: Beauftragt / Auftragsbestätigung hochladen --}} {{-- Modal: PDF Vollbild-Ansicht --}} {{-- Modal: Leistungsbibliothek (Angebot) --}} {{-- Modal: Materialkatalog --}} {{-- Flatpickr --}} {{-- Modal: Dateien hochladen --}} {{-- Modal: Neuer Termin --}} {{-- Modal: AGB Vorschau --}} @if($offer->terms) @endif @endsection