@php $statusLabel = $tour->is_draft ? 'Taslak' : ($tour->is_active ? ($tour->is_public ? 'Yayında' : 'Gizli') : 'Pasif'); $statusClass = $tour->is_draft ? 'pqv-b-amber' : ($tour->is_active ? ($tour->is_public ? 'pqv-b-green' : 'pqv-b-slate') : 'pqv-b-red'); $marketplaces = $tour->product?->marketplaces ?? collect(); $editBase = 'agency.products.gunubirlik-turlar'; $uf = route("$editBase.update-field", $tour); $cityOptions = collect($cities)->map(fn($c) => ['value' => (string) $c->id, 'label' => $c->city ?? $c->name])->values(); $boolOptions = [['value' => '1', 'label' => 'Evet'], ['value' => '0', 'label' => 'Hayır']]; $tourTypeOptions = [['value' => 'domestic', 'label' => 'Yurt İçi'], ['value' => 'international', 'label' => 'Yurt Dışı']]; $difficultyOptions = [['value' => 'easy', 'label' => 'Kolay'], ['value' => 'moderate', 'label' => 'Orta'], ['value' => 'challenging', 'label' => 'Zor'], ['value' => 'extreme', 'label' => 'Çok Zor']]; // Para birimleri: statik pricing.blade gibi ajansın aktif para birimlerinden; yoksa güvenli varsayılan liste. $currencyOptions = collect($activeCurrencies ?? []) ->map(fn($c) => ['value' => $c->code, 'label' => $c->code])->values()->all(); if (empty($currencyOptions)) { $currencyOptions = [['value' => 'TRY', 'label' => 'TRY'], ['value' => 'USD', 'label' => 'USD'], ['value' => 'EUR', 'label' => 'EUR'], ['value' => 'GBP', 'label' => 'GBP']]; } @endphp {{-- slim: minimal header — avatar yok, başlık + rozetler tek şeritte (hedef sabit tasarım) --}} {{-- Header'da avatar yok (slim); yığın tutamağı ikonu buradan okur --}} {{ $statusLabel }} {{ $tour->code ?? '—' }} {{ $tour->tour_type_display_name ?? '' }} {{-- Güzergâh: kalkış – varış (yalnız biri doluysa o gösterilir) --}} @php $depCity = $tour->departureCity?->city ?? $tour->departureCity?->name; $arrCity = $tour->arrivalCity?->city ?? $tour->arrivalCity?->name; $route = implode(' - ', array_filter([$depCity, $arrCity])); @endphp @if($route) {{ $route }} @endif
SAAT {{ substr($tour->start_time ?? '', 0, 5) ?: '—' }}@if($tour->end_time)–{{ substr($tour->end_time, 0, 5) }}@endif
FİYAT {{ $tour->adult_price ? number_format($tour->adult_price, 0, ',', '.') . ' ' . $tour->currency : '—' }}
KAPASİTE {{ $tour->min_participants ?? '—' }}–{{ $tour->max_participants ?? '—' }}
TARİH {{ $tour->upcomingDates->count() }}
PAZARYERİ {{ $marketplaces->count() }}
@if($tour->is_draft) @endif
{{-- ── GENEL ── --}}
{{-- Müşteri kartındaki Künye ile aynı ledger tasarımı (sabit QV tasarımı) --}} @include('agency.products._qv-general-ledger', [ 'tour' => $tour, 'editBase' => $editBase, 'cities' => $cities, 'categories' => $categories, 'uf' => $uf, 'productType' => 'day', ])
{{-- ── PROGRAM ── --}}
{{-- Tablo + defter (ledger) tasarımı — sabit QV alan tasarımı --}} @include('agency.products._qv-itinerary', [ 'tour' => $tour, 'editBase' => $editBase, 'itMode' => 'day', 'items' => $tour->activeItineraries, ])
{{-- ── FİYATLANDIRMA — ledger (sabit QV tasarımı) ── --}}
@php // Para gösterimi: sunucunun update-field display_value formatıyla birebir $qpMoney = fn ($v) => $v !== null ? number_format($v, 2, ',', '.') . ' ' . $tour->currency : ''; // Pazaryeri input placeholder'ı: varsayılan fiyatı soluk göster (",00" sadeleşir) $qpPh = function ($v) { if ($v === null) return '—'; $s = number_format($v, 2, ',', '.'); return str_ends_with($s, ',00') ? substr($s, 0, -3) : $s; }; $qpPriceRows = [ ['label' => 'Yetişkin Fiyatı', 'field' => 'adult_price', 'type' => 'number', 'mono' => true, 'value' => $tour->adult_price, 'text' => $qpMoney($tour->adult_price)], ['label' => 'Çocuk Fiyatı', 'field' => 'child_price', 'type' => 'number', 'mono' => true, 'value' => $tour->child_price, 'text' => $qpMoney($tour->child_price)], ]; if ($tour->infant_allowed) { $qpPriceRows[] = ['label' => 'Bebek Fiyatı', 'field' => 'infant_price', 'type' => 'number', 'mono' => true, 'value' => $tour->infant_price, 'text' => $qpMoney($tour->infant_price)]; } $qpPriceRows[] = ['label' => 'Para Birimi', 'field' => 'currency', 'type' => 'select', 'options' => $currencyOptions, 'value' => $tour->currency, 'text' => $tour->currency]; $qpAgeRows = [ ['label' => 'Çocuk Min. Yaş', 'field' => 'child_min_age', 'type' => 'number', 'mono' => true, 'value' => $tour->child_min_age, 'text' => $tour->child_min_age], ['label' => 'Çocuk Maks. Yaş', 'field' => 'child_max_age', 'type' => 'number', 'mono' => true, 'value' => $tour->child_max_age, 'text' => $tour->child_max_age], ]; if ($tour->infant_allowed) { $qpAgeRows[] = ['label' => 'Bebek Maks. Yaş', 'field' => 'infant_max_age', 'type' => 'number', 'mono' => true, 'value' => $tour->infant_max_age, 'text' => $tour->infant_max_age]; } @endphp
@include('components.quick-view.ledger-card', ['card' => [ 'title' => 'Fiyatlandırma', 'icon' => 'fa-dollar-sign', 'url' => $uf, 'note' => 'Yaş aralıkları rezervasyonda yolcu tipini belirler.' . ($tour->infant_allowed ? '' : ' Bu tur bebek kabul etmiyor; bebek alanları gizlendi (Ayarlar → Bebek Kabul).'), 'sections' => [ ['title' => 'Varsayılan Fiyatlar', 'icon' => 'fa-dollar-sign', 'rows' => $qpPriceRows], ['title' => 'Yaş Aralıkları', 'icon' => 'fa-child', 'rows' => $qpAgeRows], ], ]]) {{-- ── Pazaryeri bazlı fiyatlar: satış kanalı kartları, otomatik kayıt ── Kayıt sözleşmesi DEĞİŞMEDİ: [data-qv-mpprices-save] > .qmp-row[data-mp-id] > [data-mp="…"] (_qv-inline-blocks change olayında bloğu toplayıp POST eder). --}}
Pazaryeri Bazlı Fiyatlar @if($marketplaces->count()) Otomatik kayıt @endif
@if($marketplaces->count())
@foreach($marketplaces as $mp) @php $mpp = $marketplacePrices[$mp->id] ?? null; $mpCur = $mp->defaultCurrency?->code ?? $tour->currency; @endphp
{{ mb_substr(trim($mp->name), 0, 1) !== '' ? mb_strtoupper(mb_substr(trim($mp->name), 0, 1), 'UTF-8') : '?' }} {{ $mp->name }} {{ $mpCur }}
@if($tour->infant_allowed) @endif
@endforeach
Boş bırakılan alanda soluk görünen varsayılan fiyat geçerlidir — değişiklikler alandan çıkınca otomatik kaydedilir.
@else
Bu tura bağlı pazaryeri yok Ayarlar sekmesinden pazaryeri seçtiğinizde kanala özel fiyat girebilirsiniz.
@endif
{{-- Kademeli (sınıf) fiyatlandırma — kendi bileşeni, davranışı değişmedi --}}
@include('agency.products._qv-pricing-classes', ['pricingClasses' => $pricingClasses, 'saveUrl' => route("$editBase.pricing-classes", $tour)])
{{-- ── TARİHLER — ledger kart dili (sabit QV tasarımı) ── --}}
{{-- Açılır-kapanır: tarih yoksa açık başlar, varsa kapalı (liste öne çıksın). summary aynı zamanda kartın pfx-top başlığıdır. --}}
upcomingDates->count()) open @endif> Sezon & Tarih Oluşturucu Tarih eklemek için tıklayınGizle
@php $qvDayNames = ['monday' => 'Pazartesi', 'tuesday' => 'Salı', 'wednesday' => 'Çarşamba', 'thursday' => 'Perşembe', 'friday' => 'Cuma', 'saturday' => 'Cumartesi', 'sunday' => 'Pazar']; $qvDayShort = ['monday' => 'Pzt', 'tuesday' => 'Sal', 'wednesday' => 'Çar', 'thursday' => 'Per', 'friday' => 'Cum', 'saturday' => 'Cmt', 'sunday' => 'Paz']; @endphp
1
Sezona bir isim verin (opsiyonel)
Oluşturulan tüm tarihler bu isimle etiketlenir, listede birlikte görünür.
2
Tarih aralığını seçin
3
Tur hangi günler yapılacak?
Ayarlar sekmesindeki "Tur Günleri" otomatik seçili gelir; buradan değiştirebilirsiniz.
@foreach($qvDayNames as $key => $name) @endforeach
{{-- Çakışma seçenekleri: çoğu zaman gerekmez, katlanır bölümde --}}
Çakışma seçenekleri — varsayılan: sorulur
Gün ve tarih aralığı seçin
@php $gbMpFields = [ ['key' => 'adult_price', 'label' => 'Yetişkin'], ['key' => 'child_price', 'label' => 'Çocuk'], ]; // Bebek kabul edilmiyorsa bebek fiyatı sorulmaz if ($tour->infant_allowed) { $gbMpFields[] = ['key' => 'infant_price', 'label' => 'Bebek']; } $gbMpList = $tour->product?->marketplaces ?? collect(); // Sınıf kapasitesi eksikse: kalan kontenjan en yüksek sınıftan fiyatlanır (tarih notu) $gbCapSum = collect(is_array($tour->class_capacities ?? null) ? $tour->class_capacities : []) ->only($pricingClasses->pluck('id')->all())->sum(fn ($v) => (int) $v); $gbHighest = ($tour->use_pricing_classes && $gbCapSum > 0) ? \App\Models\Agency\TourClass::highestOf($pricingClasses) : null; @endphp {{-- Yaklaşan tarihler: müşteri kartındaki gibi minimal satır listesi. Satır: takvim yaprağı + tarih/rozetler; eylemler hover'da belirir (pfx dili). --}}
Yaklaşan Tarihler {{ $tour->upcomingDates->count() }}
{{-- Sezon filtresi: sezon adı girilmiş tarih varsa çip şeridi çıkar --}} @php $gbSeasons = $tour->upcomingDates->pluck('season_name')->filter()->countBy(); $gbNoSeason = $tour->upcomingDates->filter(fn ($d) => blank($d->season_name))->count(); @endphp @if($gbSeasons->isNotEmpty())
@foreach($gbSeasons as $gbSeason => $gbCnt) @endforeach @if($gbNoSeason > 0) @endif
@endif @forelse($tour->upcomingDates as $date) @php $gbD = \Carbon\Carbon::parse($date->tour_date); $gbTime = substr($date->start_time ?? $tour->start_time ?? '', 0, 5); $gbLeft = is_null($date->available_seats) ? null : (int) $date->available_seats; $gbNew = $date->created_at && $date->created_at->gt(now()->subDays(7)); $gbMax = (int) ($date->max_participants ?? $tour->max_participants ?? 0); $gbShort = ($gbHighest && $gbMax > $gbCapSum) ? $gbMax - $gbCapSum : 0; @endphp
{{-- Satırın kendisi fiyat panelini açar/kapatır (butonlar hariç — aşağıdaki script) --}}
{{ $gbD->format('d') }}{{ $gbD->translatedFormat('M') }}
{{ $gbD->translatedFormat('d F Y') }} {{ $gbD->translatedFormat('l') }} @if($gbTime){{ $gbTime }}@endif {{ $date->available_seats ?? '—' }}/{{ $gbMax ?: '—' }}
@if(!$date->is_active)Pasif@endif @if($date->is_guaranteed) Kesin Kalkış @else Opsiyonlu @endif @if(!is_null($gbLeft) && $gbLeft <= 0) Dolu @elseif(!is_null($gbLeft) && $gbLeft <= 5) Son {{ $gbLeft }} @endif @if($gbNew)Yeni@endif @if($date->season_name) {{ $date->season_name }} @endif @if($gbShort > 0) +{{ $gbShort }} → {{ $gbHighest->code ?: $gbHighest->name }} @endif
{{-- Çapraz link: bu tarihin operasyon (kalkış) kartı --}}
id]) }}"> @php $gbEx = []; foreach ($date->marketplacePrices as $mpp) { $gbEx[$mpp->marketplace_id][$mpp->tour_class_id ?? 'none'] = $mpp; } @endphp {{-- Minimal fiyat tablosu: satır = pazaryeri (+sınıf), sütun = fiyat tipi. Motor aynı (_qv-marketplace-prices-ui) — yalnızca görünüm sadeleşti. --}} @include('agency.products._qv-date-prices-mini', [ 'marketplaces' => $gbMpList, 'existing' => $gbEx, 'fields' => $gbMpFields, 'classes' => $pricingClasses, 'useClasses' => (bool) $tour->use_pricing_classes, ])
@empty
Yaklaşan tarih bulunmuyor Yukarıdaki Sezon & Tarih Oluşturucu ile toplu tarih üretebilirsiniz.
@endforelse
{{-- /qv-left-stack --}} {{-- Tarih satırı (qvd) + açılır kart kabuğu (qvsg) ortak stil/davranışı --}} @include('agency.products._qv-dates-list-ui')
{{-- ── GÖRSELLER ── --}}
@include('agency.products._qv-media', [ 'tour' => $tour, 'images' => $tour->activeImages, 'uploadUrl' => route("$editBase.media.upload-images", $tour), 'deleteRoute' => "$editBase.media.delete-image", 'coverRoute' => "$editBase.media.set-cover", 'featuredRoute' => "$editBase.media.toggle-featured", ])
{{-- ── SEO — ledger (sabit QV tasarımı) ── --}}
@include('agency.products._qv-seo-ledger', ['tour' => $tour, 'editBase' => $editBase, 'uf' => $uf])
{{-- ── AYARLAR — ledger (sabit QV tasarımı) ── --}}
{{-- "Ayarları düzenle" linki kaldırıldı: statik ayarlar sayfası artık kullanılmıyor, tüm ayarlar bu sekmeden yönetiliyor. --}} @php // Evet/Hayır satırı üretici (bool alanlar hiç "boş" olmaz) $qsBool = fn (string $label, string $field, $v) => [ 'label' => $label, 'field' => $field, 'type' => 'select', 'options' => $boolOptions, 'value' => $v ? '1' : '0', 'text' => $v ? 'Evet' : 'Hayır', ]; $qsDT = fn ($v) => $v ? \Carbon\Carbon::parse($v) : null; $qsPub = $qsDT($tour->published_at); $qsExp = $qsDT($tour->expires_at); @endphp
{{-- Pazaryerleri en üstte: en sık kullanılan ayar --}} @include('agency.products._qv-marketplaces-ledger', ['allMarketplaces' => $allMarketplaces, 'selectedIds' => $marketplaces->pluck('id'), 'syncUrl' => route("$editBase.sync-marketplaces", $tour)]) {{-- Durum, rezervasyon ve sayısal ayarlar: ledger kartı --}} @include('components.quick-view.ledger-card', ['card' => [ 'title' => 'Ayarlar', 'icon' => 'fa-cog', 'url' => $uf, 'class' => 'pfx-lw', 'note' => 'Son Rezervasyon: kalkıştan kaç saat önce rezervasyonun kapanacağı. Otomatik Kesin Kalkış: minimum katılımcı sayısına ulaşınca kalkış kendiliğinden kesinleşir.', 'sections' => [ ['title' => 'Durum & Görünürlük', 'icon' => 'fa-toggle-on', 'rows' => [ $qsBool('Aktif', 'is_active', $tour->is_active), $qsBool('Yayında', 'is_public', $tour->is_public), $qsBool('Rezervasyona Açık', 'is_bookable', $tour->is_bookable), $qsBool('Öne Çıkan', 'is_featured', $tour->is_featured), $qsBool('Çok Satan', 'is_bestseller', $tour->is_bestseller), $qsBool('Yeni', 'is_new', $tour->is_new), $qsBool('Anında Rezervasyon', 'instant_booking', $tour->instant_booking), $qsBool('İade Edilebilir', 'refundable', $tour->refundable), $qsBool('Çocuk Dostu', 'child_friendly', $tour->child_friendly), $qsBool('Bebek Kabul', 'infant_allowed', $tour->infant_allowed), ]], ['title' => 'Rezervasyon & Kesin Kalkış', 'icon' => 'fa-shield-alt', 'rows' => [ $qsBool('Otomatik Kesin Kalkış', 'auto_guarantee_on_min', $tour->auto_guarantee_on_min), ]], ['title' => 'Sayısal Ayarlar', 'icon' => 'fa-sliders', 'rows' => [ ['label' => 'Öncelik', 'field' => 'priority', 'type' => 'number', 'mono' => true, 'value' => $tour->priority ?? 0, 'text' => $tour->priority ?? 0], ['label' => 'Son Rezervasyon (saat)', 'field' => 'booking_deadline_hours', 'type' => 'number', 'mono' => true, 'value' => $tour->booking_deadline_hours, 'text' => $tour->booking_deadline_hours], ['label' => 'Yayın Tarihi', 'field' => 'published_at', 'type' => 'datetime-local', 'mono' => true, 'value' => $qsPub?->format('Y-m-d\TH:i'), 'text' => $qsPub?->format('d.m.Y H:i')], ['label' => 'Son Geçerlilik', 'field' => 'expires_at', 'type' => 'datetime-local', 'mono' => true, 'value' => $qsExp?->format('Y-m-d\TH:i'), 'text' => $qsExp?->format('d.m.Y H:i')], ]], ], ]]) {{-- İptal son süresi: saat/gün birimli özel alan (değer daima saat kaydedilir) --}}
İptal Son Süresi
@include('agency.products._qv-hours-unit-field', ['field' => 'cancellation_deadline_hours', 'label' => 'Ücretsiz İptal (kalkıştan önce)', 'hours' => $tour->cancellation_deadline_hours, 'uf' => $uf])
Rezervasyonun ücretsiz iptal edilebileceği son süre; birim gün seçilse de saat olarak kaydedilir.
{{-- Tur Günleri: turun genel olarak gerçekleştiği günler (tarih oluşturucuda ön-seçili gelir) --}}
Tur Günleri Otomatik kayıt
@php $stDayNames = ['monday' => 'Pazartesi', 'tuesday' => 'Salı', 'wednesday' => 'Çarşamba', 'thursday' => 'Perşembe', 'friday' => 'Cuma', 'saturday' => 'Cumartesi', 'sunday' => 'Pazar']; $stDayShort = ['monday' => 'Pzt', 'tuesday' => 'Sal', 'wednesday' => 'Çar', 'thursday' => 'Per', 'friday' => 'Cum', 'saturday' => 'Cmt', 'sunday' => 'Paz']; @endphp @foreach($stDayNames as $key => $name) @endforeach
Turun genel olarak yapıldığı günler; Tarihler sekmesindeki Sezon & Tarih Oluşturucu'da otomatik seçili gelir.
{{-- Kademeli Ödeme: ledger satırları + aşama repeater'ı aynı kartta --}}
Kademeli Ödeme Planı
@foreach([ $qsBool('Kademeli Ödeme Aktif', 'payment_plan_enabled', $tour->payment_plan_enabled), $qsBool('Web Satışında Kullan', 'online_payment_enabled', $tour->online_payment_enabled), ['label' => "Web'de İlk Alınacak (%)", 'field' => 'online_deposit_percent', 'type' => 'number', 'mono' => true, 'value' => $tour->online_deposit_percent, 'text' => $tour->online_deposit_percent], ] as $r) @php $shown = trim((string) ($r['text'] ?? '')); @endphp
{{ $r['label'] }} {{ $shown }}
@endforeach
Ödemeler, aşamaları eklediğiniz sıraya göre (1, 2, 3…) tahsil edilir. Numaralar ödeme sırasını gösterir.
@foreach(($tour->payment_plan ?? []) as $st)
@endforeach
{{-- ── ÇEVİRİLER — ledger (sabit QV tasarımı) ── --}}
@include('agency.products._qv-translations-ledger', ['tour' => $tour, 'marketplaces' => $marketplaces, 'fetchUrl' => route("$editBase.translations.fetch", $tour), 'saveUrl' => route("$editBase.translations.save", $tour)])
@include('agency.products._quick-view-styles') @include('agency.products._qv-general-ui') @include('agency.products._qv-marketplace-prices-ui') @include('agency.products._qv-pricing-classes-ui') @include('agency.products._qv-richtext') @include('agency.products._qv-inline-blocks') @include('agency.products._qv-seo-ui') @include('agency.products._quick-view-crud-script')