{{-- MÜŞTERİ KÜNYESİ — "Özet" ve "Profil Bilgileri" sekmelerinin birleşimi. Tasarım fikri: kart içinde kart yığmak yerine defter (ledger) satırı. Her alan tek satır: solda küçük etiket, sağda değer, en sağda hover'da beliren kopyala/düzenle. Düzenleme yerinde açılır ve satır yüksekliği değişmez — bu yüzden liste "zıplamaz" ve çok alan az yer kaplar. Kaydırmayı azaltan iki karar: 1) Etiket + değer aynı satırda; bölüm başlıkları ince ve yapışkan. 2) Boş alanlar VARSAYILAN OLARAK GÖRÜNÜR (soluk italik placeholder ile) — böylece hangi bilgilerin eksik olduğu ilk bakışta anlaşılır ve tıklanıp hemen doldurulabilir. Başlıktaki "boş alan" düğmesi onları GİZLER. Beklenen: $customer, $definitions, $agents, $linkedCompanies Kaydetme: PATCH agency.customers.update-field {field, value} --}} @php $isCorp = $customer->customer_type === 'corporate'; $genderOpts = [['value' => '', 'label' => '—'], ['value' => 'male', 'label' => 'Erkek'], ['value' => 'female', 'label' => 'Kadın'], ['value' => 'other', 'label' => 'Diğer']]; $contactOpts = [['value' => '', 'label' => '—'], ['value' => 'email', 'label' => 'E-posta'], ['value' => 'phone', 'label' => 'Telefon'], ['value' => 'sms', 'label' => 'SMS']]; $typeOpts = [['value' => 'individual', 'label' => 'Kişi'], ['value' => 'corporate', 'label' => 'Şirket']]; $prioOpts = [['value' => '1', 'label' => 'Öncelikli'], ['value' => '0', 'label' => 'Normal']]; $companyTypeOpts = collect(\App\Models\Customer\Customer::companyTypes()) ->map(fn ($l, $v) => ['value' => (string) $v, 'label' => $l])->values()->all(); /** Seçim listesinde değerin etiketini bulur. */ $optLabel = function (array $opts, $value) { foreach ($opts as $o) { if ((string) $o['value'] === (string) $value) return $o['label'] === '—' ? '' : $o['label']; } return (string) ($value ?? ''); }; /** * Tek satır tanımı. * $field null ise satır salt okunur (yalnızca kopyalanır). * $value düzenlemede kullanılan ham değer, $text ekranda görünen metin. */ $row = function (string $label, ?string $field, $value, ?string $text = null, array $o = []) { return [ 'label' => $label, 'field' => $field, 'type' => $o['type'] ?? 'text', 'value' => $value === null ? '' : (string) $value, 'text' => $text === null ? ($value === null ? '' : (string) $value) : $text, 'options' => $o['options'] ?? null, // lookup satırlarında seçenekler gömülmez, liste anahtarı taşınır 'lookup' => $o['lookup'] ?? null, 'mono' => $o['mono'] ?? false, 'ctype' => $o['ctype'] ?? null, 'ph' => $o['ph'] ?? null, // Sayı satırlarında ekran metnine eklenen birim (₺, gün) ve basamak 'suffix' => $o['suffix'] ?? null, 'dec' => $o['dec'] ?? null, ]; }; $emails = is_array($customer->emails) ? ($customer->emails[0] ?? '') : (string) ($customer->emails ?? ''); $tags = is_array($customer->tags) ? implode(', ', $customer->tags) : (string) ($customer->tags ?? ''); $interests = is_array($customer->interests) ? implode(', ', $customer->interests) : (string) ($customer->interests ?? ''); $dmy = fn ($d) => $d ? \Carbon\Carbon::parse($d)->format('d.m.Y') : ''; $iso = fn ($d) => $d ? \Carbon\Carbon::parse($d)->format('Y-m-d') : ''; $sections = []; // ── Kimlik (kişi) ── $sections[] = [ 'title' => 'Kimlik', 'icon' => 'fa-id-badge', 'ctype' => 'individual', 'rows' => [ $row('Ad', 'first_name', $customer->first_name), $row('İkinci Ad', 'middle_name', $customer->middle_name, null, ['ph' => 'Varsa ikinci ad']), $row('Soyad', 'last_name', $customer->last_name), $row('Ad Soyad', null, $customer->full_name), $row('T.C. Kimlik No', 'national_id', $customer->national_id, null, ['mono' => true, 'ph' => '11 hane']), $row('Cinsiyet', 'gender', $customer->gender, $optLabel($genderOpts, $customer->gender), ['type' => 'select', 'options' => $genderOpts]), $row('Doğum Tarihi', 'birth_date', $iso($customer->birth_date), $dmy($customer->birth_date), ['type' => 'date', 'mono' => true]), $row('Doğum Yeri', 'birth_place', $customer->birth_place, null, ['ph' => 'Şehir / ilçe']), $row('Uyruk', 'nationality', $customer->nationality, \App\Models\Definition\Country::nameByCode($customer->nationality), ['type' => 'lookup', 'lookup' => 'countries', 'ph' => 'Ülke arayın']), $row('Pasaport No', 'passport_number', $customer->passport_number, null, ['mono' => true]), $row('Pasaport Geçerlilik', 'passport_expiry', $iso($customer->passport_expiry), $dmy($customer->passport_expiry), ['type' => 'date', 'mono' => true]), ], ]; // ── Şirket (kurumsal) ── $sections[] = [ 'title' => 'Şirket', 'icon' => 'fa-building', 'ctype' => 'corporate', 'rows' => [ $row('Unvan', 'company_name', $customer->company_name, null, ['ph' => 'Şirket unvanı']), $row('Şirket Türü', 'company_type', $customer->company_type, $optLabel($companyTypeOpts, $customer->company_type), ['type' => 'select', 'options' => $companyTypeOpts]), $row('Vergi Dairesi', 'company_tax_office', $customer->company_tax_office), $row('Vergi No', 'company_tax_number', $customer->company_tax_number, null, ['mono' => true, 'ph' => '10 hane']), $row('Yetkili Pozisyonu', 'company_position', $customer->company_position, null, ['ph' => 'Ör. Genel Müdür']), ], ]; // ── İletişim ── $sections[] = [ 'title' => 'İletişim', 'icon' => 'fa-address-book', 'rows' => [ $row('Telefon', 'phone', $customer->phone, null, ['mono' => true]), $row('İkinci Telefon', 'phone_alt', $customer->phone_alt, null, ['mono' => true]), $row('E-posta', 'emails', $emails, $emails, ['type' => 'email']), $row('İkinci E-posta', 'email_alt', $customer->email_alt, null, ['type' => 'email']), $row('Tercih', 'preferred_contact_method', $customer->preferred_contact_method, $optLabel($contactOpts, $customer->preferred_contact_method), ['type' => 'select', 'options' => $contactOpts]), ], ]; // ── Adres ── $sections[] = [ 'title' => 'Adres', 'icon' => 'fa-location-dot', 'rows' => [ $row('Açık Adres', 'address', $customer->address, null, ['type' => 'textarea']), $row('İl', 'city', $customer->city), $row('İlçe', 'district', $customer->district), $row('Posta Kodu', 'postal_code', $customer->postal_code, null, ['mono' => true]), ], ]; // ── Fatura ── $billingSvc = app(\App\Services\Customer\CustomerBillingService::class); $billingProfiles = $billingSvc->profiles($customer); // ── Sınıflandırma ── $sections[] = [ 'title' => 'Sınıflandırma', 'icon' => 'fa-tags', 'rows' => [ $row('Kart Tipi', 'customer_type', $customer->customer_type, $isCorp ? 'Şirket' : 'Kişi', ['type' => 'select', 'options' => $typeOpts]), $row('Öncelik', 'priority', $customer->priority ? '1' : '0', $customer->priority_label, ['type' => 'select', 'options' => $prioOpts]), $row('Referans Kaynağı', 'referral_source', $customer->referral_source, null, ['ph' => 'Ör. Google, tavsiye']), $row('Etiketler', 'tags', $tags, $tags, ['ph' => 'vip, balayı']), $row('İlgi Alanları', 'interests', $interests, $interests, ['ph' => 'kültür, doğa']), ], ]; // ── Cari / Borçlandırma ── // Ödeme alınmadan satış yapılabilmesinin kuralları burada tutulur; satış // kartı aynı değerleri okuyup limiti aşan satışı engeller. Kullanılan / // kullanılabilir limit salt okunurdur — hesap CustomerCreditService'te. $cr = $credit ?? $customer->creditSummary(); $crMoney = fn ($v) => $cr['symbol'] . number_format((float) $v, 2, ',', '.'); $creditOpts = [['value' => '1', 'label' => 'Açık — ödeme alınmadan satış yapılabilir'], ['value' => '0', 'label' => 'Kapalı']]; $currencyOpts = auth()->user()->agency?->getActiveCurrencies() ->map(fn ($c) => ['value' => $c->code, 'label' => $c->code . ' (' . $c->symbol . ')'])->values()->all() ?: [['value' => 'TRY', 'label' => 'TRY (₺)']]; $sections[] = [ 'title' => 'Cari / Borçlandırma', 'icon' => 'fa-hand-holding-dollar', 'rows' => [ $row('Borçlandırma', 'credit_allowed', $customer->credit_allowed ? '1' : '0', $customer->credit_allowed_label, ['type' => 'select', 'options' => $creditOpts]), $row('Kredi Limiti', 'credit_limit', number_format((float) $customer->credit_limit, 2, '.', ''), $crMoney($cr['limit']), ['type' => 'number', 'mono' => true, 'suffix' => $cr['symbol'], 'dec' => 2, 'ph' => 'Ör. 50.000']), $row('Limit Para Birimi', 'credit_limit_currency', $cr['currency'], $cr['currency'], ['type' => 'select', 'options' => $currencyOpts]), $row('Vade (gün)', 'payment_term_days', (string) $cr['term_days'], $cr['term_days'] > 0 ? $cr['term_days'] . ' gün' : '', ['type' => 'number', 'mono' => true, 'suffix' => 'gün', 'dec' => 0, 'ph' => 'Ör. 30']), $row('Kullanılan Limit', null, $cr['used'], $crMoney($cr['used']), ['mono' => true]), $row('Kullanılabilir Limit', null, $cr['available'], $cr['allowed'] ? $crMoney($cr['available']) : 'Borçlandırma kapalı', ['mono' => true]), $row('Limit Notu', 'credit_note', $customer->credit_note, null, ['type' => 'textarea', 'ph' => 'Ör. vade sonu çek ile kapanır']), ], ]; // ── Özel alanlar ── if (isset($definitions) && $definitions->isNotEmpty()) { $customRows = []; foreach ($definitions as $def) { $raw = $customer->getCustomFieldValue($def->field_key); $opts = collect($def->options ?? []) ->map(fn ($o) => is_array($o) ? ['value' => (string) ($o['value'] ?? $o['label'] ?? ''), 'label' => (string) ($o['label'] ?? $o['value'] ?? '')] : ['value' => (string) $o, 'label' => (string) $o]) ->values()->all(); if ($opts) { array_unshift($opts, ['value' => '', 'label' => '—']); $customRows[] = $row($def->label, 'custom_field_' . $def->id, $raw, $optLabel($opts, $raw), ['type' => 'select', 'options' => $opts]); continue; } $inputType = in_array($def->input_type, ['date', 'textarea', 'email'], true) ? $def->input_type : 'text'; $customRows[] = $row( $def->label, 'custom_field_' . $def->id, $inputType === 'date' ? $iso($raw) : $raw, $inputType === 'date' ? $dmy($raw) : (string) ($raw ?? ''), ['type' => $inputType] ); } $sections[] = ['title' => 'Özel Alanlar', 'icon' => 'fa-sliders', 'rows' => $customRows]; } // ── Sistem (salt okunur) ── $sections[] = [ 'title' => 'Sistem', 'icon' => 'fa-clock-rotate-left', 'muted' => true, 'rows' => [ $row('Kayıt No', null, '#' . $customer->id, '#' . $customer->id, ['mono' => true]), $row('Temsilci', null, $customer->assignedAgent?->full_name), $row('Oluşturulma', null, $customer->created_at?->format('d.m.Y H:i')), $row('Son Güncelleme', null, $customer->updated_at?->format('d.m.Y H:i')), ], ]; // Kart tanımı: markup ledger-card'da, boş alan sayacı da orada (kart tipine // uymayan satırlar sayılmaz — 'ctype' bunun için verilir). $qvCard = [ 'title' => 'Künye', 'icon' => 'fa-address-card', 'url' => route('agency.customers.update-field', $customer), 'ctype' => $customer->customer_type, 'foldable' => true, 'sections' => $sections, 'append' => count($billingProfiles) ? 'agency.customers.partials.qv-billing' : null, ]; @endphp {{-- Markup ledger-card'da: kart yalnızca yukarıdaki dizi tanımını verir. Fatura muhatabı bölümü karta 'append' ile takılır. --}} @include('components.quick-view.ledger-card', ['card' => $qvCard]) {{-- Ortak katmanlar: pfx satır davranışı ledger-ui'de, etkinlik yazma alanı ve akış activity-ui'de. Burada yalnızca müşteri kartına özgü stil kalır. --}} @include('components.quick-view.ledger-ui') @include('components.quick-view.activity-ui') @once @endonce