@php $badge = $vm['badge']; $cap = $vm['capacity']; $typeKey = $vm['type_key']; $id = $vm['id']; $uid = $typeKey . '-' . $id; $updateUrl = route('agency.operations.update-field', [$typeKey, $id]); $isTerminal = in_array($badge['key'], ['cancelled', 'completed']); $isGuaranteed = in_array($badge['key'], ['auto_guaranteed', 'manual_guaranteed']); $resourceCost = (float) $assignments->sum(fn ($a) => $a->effective_cost); $net = (float) $vm['revenue_won'] - $resourceCost; $roleMeta = [ 'guide' => ['Rehber', 'fa-user-tie', '#3b82f6'], 'vehicle' => ['Araç', 'fa-bus', '#10b981'], 'captain' => ['Kaptan', 'fa-id-card', '#8b5cf6'], ]; $start = $vm['start']; $end = $vm['end']; $dateLabel = $start?->translatedFormat('d F Y') ?? 'Tarih atanmadı'; if ($start && $end && $end->ne($start)) { $dateLabel = $start->isSameMonth($end) ? $start->format('d') . '–' . $end->translatedFormat('d F Y') : $start->translatedFormat('d M') . ' – ' . $end->translatedFormat('d M Y'); } @endphp {{-- slim: müşteri / satış / tedarikçi kartlarıyla aynı kompakt başlık şeridi. Avatar (gün/ay bloğu) slim'de çizilmez — tarih zaten başlığın kendisi. --}} {{ $dateLabel }}@if($vm['start_time']) · {{ $vm['start_time'] }}@endif @if($start){{ $start->translatedFormat('l') }}@endif {{ $vm['tour_name'] }} {{ $vm['type_label'] }} @if($vm['is_private'] ?? false) ÖZEL@endif @if($vm['tour_code']){{ $vm['tour_code'] }}@endif {{ $badge['label'] }}
DOLULUK %{{ $cap['occupancy'] }}
YOLCU {{ $vm['pax'] }}
CİRO {{ number_format($vm['revenue'], 0, ',', '.') }}₺
NET {{ number_format($net, 0, ',', '.') }}₺
{{-- Giderler: tedarikçi + kaynak ödemeleri (planlanan ↔ gerçekleşen) --}} {{-- Sayaç yolcu sayısıdır (rezervasyon değil): tek rezervasyonda 3 yolcu varsa 3 yazar --}} {{-- Odalama yalnızca konaklamalı kalkışlarda (kültür + yurt dışı) anlamlıdır; günübirlik turlarda sekme hiç basılmaz. Özel tur ayrımı etkilemez. --}} @if($isOvernight ?? false) @endif
{{-- ══ OPERASYON ══ --}}
{{-- Kesin kalkış durumu + aksiyonlar (AJAX — drawer içinde kalır). Defter kartına DÖNÜŞTÜRÜLMEDİ bilerek: burası bir alan listesi değil, kalkışın o anki hâli ve alınabilecek kararlar. Kartın tek renkli bloğu bu olsun ki göz önce buraya gitsin. --}}
{{ $badge['label'] }}
@if($op && $op->guaranteed_at)
{{ $op->guaranteed_mode === 'manual' ? 'Manuel olarak' : 'Otomatik (eşik dolunca)' }} kesin kalkışa alındı · {{ $op->guaranteed_at->translatedFormat('d F Y H:i') }} @if($op->guaranteedBy) · {{ $op->guaranteedBy->full_name ?? $op->guaranteedBy->name }}@endif
@elseif($op && $op->departure_status === 'cancelled')
{{ $op->cancellation_reason ?: 'İptal edildi' }}
@else
Rezervasyon toplanıyor, henüz kesin kalkışa geçmedi.
@endif
@if(!$isTerminal)
@if(!$isGuaranteed) @endif @if($isGuaranteed && $op && $op->departure_status !== 'departed') @endif
@endif
{{-- Kalkış künyesi: doluluk, finans ve operasyon notu tek defterde. Önceden altı ayrı kutu karttı; rakamlar alt alta okununca karşılaştırılabiliyor ve kart belirgin biçimde kısalıyor. --}}
@include('agency.operations.partials.qv-summary-ledger')
{{-- Hizmet onayları (yalnızca kültür/yurt dışı) --}} @if($vm['services'])
Hizmet Onayları
@foreach(['accommodation'=>['Konaklama','fa-bed'],'meals'=>['Yemek','fa-utensils'],'transportation'=>['Ulaşım','fa-bus']] as $svc => $info) @php $on = $vm['services'][$svc]; @endphp @endforeach
@endif {{-- İlişkili görevler (görev kartına çapraz link) --}} @if(($relatedTasks ?? collect())->isNotEmpty())
İlişkili Görevler {{ $relatedTasks->count() }} görev
@foreach($relatedTasks as $t) @php $tm = $t->statusMeta(); @endphp
@if($t->is_auto)@endif{{ $t->title }}
{{ $tm['label'] }} @if($t->due_date) · Son tarih: {{ $t->due_date->translatedFormat('d M Y') }}@endif @if($t->assignees->isNotEmpty()) · {{ $t->assignees->map(fn ($u) => $u->full_name)->implode(', ') }}@endif
@endforeach
@endif {{-- ══ ETKİNLİK AKIŞI ══ Operasyon notu tek bir metindir ve "kim, ne zaman" bilgisini taşımaz; kalkışın iletişim geçmişi buraya birikir. Ayrı sekme açılmaz — müşteri ve tedarikçi kartlarındaki gibi genel bakışın içinde durur. Bağlı postalar da bu akışa karışır. --}} @if($activitiesReady ?? false)
@endif
Etkinlik Akışı {{ $activityFeed->count() }} kayıt @if($activityMails->isNotEmpty()) {{ $activityMails->count() }} yazışma @endif
@forelse($activityFeed as $entry) @if($entry['kind'] === 'mail') @include('components.quick-view.mail-flow-row', [ 'mail' => $entry['item'], 'linkId' => $entry['item']->mail_link_id, 'linkAuto' => (bool) $entry['item']->mail_link_auto, 'linkLabel' => $entry['item']->mail_link_auto ? 'Zincirden' : 'İlişkilendirildi', 'detachable' => false, ]) @continue @endif @php $activity = $entry['item']; $type = $activity->activity_type?->value ?? $activity->activity_type; $icon = match($type) { 'call' => 'phone', 'email' => 'envelope', 'meeting' => 'handshake', 'note' => 'sticky-note', 'whatsapp' => 'whatsapp', 'sms' => 'comment-sms', default => 'circle-dot' }; $color = match($type) { 'call' => '#3b82f6', 'email' => '#ec4899', 'meeting' => '#10b981', 'note' => '#f59e0b', 'whatsapp' => '#22c55e', 'sms' => '#8b5cf6', default => '#64748b' }; $isBrandIcon = $type === 'whatsapp'; @endphp
{{ $activity->activity_type_label }} @if($activity->priority === 'urgent') Acil @endif
@if($activity->subject)
{{ $activity->subject }}
@endif @if($activity->description)

{{ $activity->description }}

@endif {{-- Kalkışın o anki durumu: not "rezervasyon toplanırken" mi yoksa kesin kalkıştan sonra mı yazılmış, geriye dönük okunabilsin --}} @if($activity->stage_label)
{{ $activity->stage_label }} @if($activity->duration_minutes) {{ $activity->duration_minutes }} dk @endif
@endif
{{ $activity->performer?->first_name ?: 'Sistem' }}
@empty {{-- Tablo migrate edilmemişse yazma kutusu basılmaz; boş durum da olmayan bir kutuyu işaret etmesin --}} @if($activitiesReady ?? false)Yukarıdaki kutudan not, arama veya görüşme kaydı ekleyin; @endif Mail modülünden bir yazışmayı bu operasyonla ilişkilendirirseniz o da burada görünür. @endforelse
{{-- Ortak katmanlar: pfx satır davranışı ledger-ui'de, yazma kutusu ve akış activity-ui'de, akıştaki posta satırı + okuyucusu mail-*'ta. --}} @include('components.quick-view.ledger-ui') @include('components.quick-view.activity-ui') @include('components.quick-view.mail-ui') @include('components.quick-view.mail-reader')
{{-- ══ KAYNAKLAR ══ --}}
Atanan Kaynaklar ({{ $assignments->count() }})
{{-- Atama paneli (istek üzerine JSON'dan doldurulur) --}}
@foreach($costTitles ?? [] as $t) @endforeach
Kaynaklar yükleniyor…
{{-- Atanmış kaynaklar --}} @forelse($assignments as $a) @php $role = $a->effective_role; $rm = $roleMeta[$role] ?? ['Kaynak', 'fa-cube', '#64748b']; $r = $a->resource; @endphp
@if($r) {{ $r->name }} @else Kaynak @endif {{ $rm[0] }} @if($r?->supplier) {{ $r->supplier->company_name ?: trim(($r->supplier->first_name ?? '') . ' ' . ($r->supplier->last_name ?? '')) }} @endif {{ $a->assignment_status_label }}
@if($role === 'vehicle' && $r?->vehicle_plate){{ $r->vehicle_plate }}@endif @if($r?->phone) @if($role==='vehicle' && $r?->vehicle_plate) · @endif {{ $r->phone }}@endif @if($a->cost_summary) · {{ $a->cost_summary }}@endif
{{ number_format($a->effective_cost, 0, ',', '.') }}₺
@if($a->is_pre_assigned) @else @endif
@empty
Henüz kaynak atanmadı. "Kaynak Ata" ile rehber, araç veya kaptan atayın.
@endforelse {{-- Maliyet özeti — Operasyon sekmesindeki künyeyle aynı defter dili --}} @if($assignments->count()) @php $opsResRo = fn (string $l, $t) => ['label' => $l, 'field' => null, 'type' => 'text', 'value' => (string) $t, 'text' => (string) $t, 'mono' => true]; $opsResMoney = fn ($v) => number_format((float) $v, 0, ',', '.') . '₺'; @endphp
@include('components.quick-view.ledger-card', ['card' => [ 'title' => 'Kaynak Özeti', 'icon' => 'fa-calculator', 'class' => 'pfx-lw', 'sections' => [[ 'title' => 'Maliyet ve Kâr', 'icon' => 'fa-coins', 'rows' => [ $opsResRo('Atanan Kaynak', $assignments->count()), $opsResRo('Toplam Maliyet', $opsResMoney($resourceCost)), $opsResRo('Kesin Ciro', $opsResMoney($vm['revenue_won'])), $opsResRo('Net', $opsResMoney($net)), ], ]], ]])
@endif
{{-- ══ GİDERLER ══ --}}
@include('agency.operations.partials.expense-panel', [ 'uid' => $uid, 'typeKey' => $typeKey, 'id' => $id, 'vm' => $vm, 'rows' => $expenseRows ?? collect(), 'payments' => $expensePayments ?? collect(), 'summary' => $expenseSummary ?? [], 'suppliers' => $expenseSuppliers ?? collect(), 'currencies' => $expenseCurrencies ?? collect(), 'expensesReady' => $expensesReady ?? false, ])
{{-- ══ MANİFESTO ══ --}}
@php $paxTotal = $sales->sum(fn($s) => $s->passengers->count() ?: (int) $s->total_participants); $mfRows = $manifestRows ?? collect(); $mfNamed = $mfRows->where('_named', true); $mfDocumented = $mfRows->filter(fn($r) => !empty($r['_doc_id']))->count(); $mfTicketed = $mfRows->filter(fn($r) => !empty($r['ticket_number']))->count(); @endphp @if($sales->count()) {{-- ═══ MANİFESTO ARAÇ ÇUBUĞU ═══ --}}
{{ $paxTotal }} yolcu {{ $sales->count() }} rezervasyon @if($mfNamed->count() < $paxTotal) {{ $paxTotal - $mfNamed->count() }} isimsiz @endif @if($isFlight ?? false) {{ $mfTicketed }}/{{ $mfNamed->count() }} bilet @endif @if($mfDocumented) {{ $mfDocumented }}/{{ $mfNamed->count() }} belge @endif
{{-- Kişi sayısı dolmamış rezervasyon varsa yeni yolcu girilebilir --}} @if($sales->contains(fn($s) => $s->passengers->count() < max(1, (int) $s->total_participants))) @endif @if(($passengerDocTemplates ?? collect())->count()) @endif
{{-- ═══ TABLO GÖRÜNÜMÜ ═══ --}}
@include('agency.operations.partials.manifest-table', [ 'rows' => $mfRows, 'uid' => $uid, 'typeKey' => $typeKey, 'id' => $id, 'isFlight' => $isFlight ?? false, ])
@endif {{-- ═══ KART GÖRÜNÜMÜ (rezervasyon bazlı — ödeme alma burada) ═══ --}} {{-- /kart görünümü --}} @include('agency.operations.partials.manifest-modals', [ 'uid' => $uid, 'typeKey' => $typeKey, 'id' => $id, 'rows' => $mfRows ?? collect(), 'sales' => $sales, 'groups' => $manifestGroups ?? [], 'groupLabels' => $manifestGroupLabels ?? [], 'presets' => $manifestPresets ?? [], 'defaultColumns' => $manifestDefault ?? [], 'passengerDocTemplates' => $passengerDocTemplates ?? collect(), ])
{{-- ══ ODALAMA ══ (yalnızca konaklamalı kalkışlar) --}} @if($isOvernight ?? false)
@include('agency.operations.partials.rooming-panel', [ 'uid' => $uid, 'typeKey' => $typeKey, 'id' => $id, 'rooming' => $rooming ?? [], 'roomingSummary' => $roomingSummary ?? ['rooms' => 0, 'assigned' => 0, 'unassigned' => 0, 'over' => 0], 'roomTypes' => $roomTypes ?? [], 'roomingReady' => $roomingReady ?? false, ])
@endif {{-- ══ KONTRAT PANELİ (drawer üstü overlay) ══ --}}
{{-- Giderler sekmesinin uçları (kalem ekle/düzenle/sil + hızlı ödeme) --}} @include('agency.operations.partials.expense-panel-scripts', ['uid' => $uid, 'typeKey' => $typeKey, 'id' => $id])