Skip to main content

Template View Dosyaları Referansı

Bu dokümantasyon, public/templates/basic/views/ dizinindeki tüm template dosyalarının detaylı analizini içerir. Her dosyanın ne işe yaradığı, özel özellikleri ve kullanım örnekleri ile birlikte açıklanmıştır.

Ana Layout ve Temel Templateler

layouts/theme.twig.php

Ana Layout Template'i - Tüm sayfa içeriklerini saran master template

Özellikler:

  • HTML5 doküment yapısı ve responsive meta etiketler
  • SEO optimizasyonu ve Open Graph entegrasyonu
  • Webpack bundle entegrasyonu
  • JavaScript konfigürasyon enjeksiyonu
  • CSS özel özellikler için tema desteği
  • Sidebar sepet offcanvas entegrasyonu
<main>
{{ render_header() }}
{{ content_for_layout | raw }} {# ÖNEMLİ: Backend'den gelen sayfa içeriği buraya yerleşir #}
{% set footer_url = theme_config('footer_url') %}
{% if footer_url %}
{{ render_page(footer_url) }}
{% endif %}
</main>

content_for_layout Özel Açıklama:

{{ content_for_layout | raw }} değişkeni, template sisteminin en kritik parçalarından biridir. Bu değişken:

  • Backend'den gelen dinamik içeriği layout template'ine yerleştirir
  • Her sayfa (index.twig.php, product.twig.php, login.twig.php vb.) kendi içeriğini üretir ve bu içerik content_for_layout değişkenine atanır.
  • raw filtresi HTML içeriğin escape edilmeden, olduğu gibi render edilmesini sağlar.
  • Layout template'i (theme.twig.php) bir çerçeve görevi görür, asıl içerik bu placeholder'a yerleştirilir.
  • Örneğin: /product/123 URL'si çağrıldığında, backend product.twig.php template'ini işler ve sonucu content_for_layout olarak layout'a gönderir.

Çalışma Akışı:

  1. Backend controller bir sayfa template'ini render eder (örn: product.twig.php)
  2. Render edilen içerik content_for_layout değişkenine atanır.
  3. Layout template'i (theme.twig.php) yüklenir.
  4. {{ content_for_layout | raw }} yerinde sayfa içeriği görüntülenir.
  5. Böylece her sayfa aynı header, footer ve genel yapıyı kullanır.

open_graph.twig.php

Sosyal Medya Meta Etiketleri - Dinamik Open Graph etiketleri

Özellikler:

  • Ürün spesifik Open Graph etiketleri
  • Stok durumu entegrasyonu
  • Marka ve kategori metadata'sı
  • Genel website metadata'sına fallback
{% if request.page_type == 'product' and product is defined %}
<meta property="og:type" content="product">
<meta property="product:availability" content="{{ stock_status }}">
<meta property="product:brand" content="{{ product.brand }}">
{% endif %}

index.twig.php

Ana Sayfa Template'i - Modüler widget sistemi ile homepage

Özellikler:

  • Webpack bundle yükleme
  • Özel widget placeholder'ları
  • Modüler widget include'ları (slider'lar, kategoriler, ürünler)
{{ webpack_bundle('index') }}
{{ ___('page__signin_box') }}

{% include 'widgets/brands_slider.twig.php' %}
{% include 'widgets/manset_slider.twig.php' %}
{% include 'widgets/category_grid.twig.php' %}
{% include 'widgets/last_products.twig.php' %}

ÖNEMLİ NOT - CMS Önceliği:

Eğer CMS'de "index" adında bir sayfa oluşturulmuşsa:

  • CMS'deki "index" sayfası içeriği önceliklidir.
  • index.twig.php template'i devre dışı kalır.
  • CMS içeriği doğrudan content_for_layout değişkeni aracılığıyla theme.twig.php layout'una yerleştirilir
  • Widget'lar ve özel içerikler CMS editöründen yönetilir.
  • Bu sayede kod değişikliği yapmadan ana sayfa içeriği güncellenebilir.

Template Öncelik Sırası:

  1. CMS'de tanımlı "index" sayfası varsa → CMS içeriği kullanılır.
  2. CMS'de "index" sayfası yoksa → index.twig.php template'i kullanılır.

Header Varyantları

header.twig.php

Standart Header - İki bölümlü layout ile temel header

Özellikler:

  • Çok dil desteği ve bayrak gösterimi
  • Kullanıcı kimlik doğrulama durumları (giriş yapmış/yapmamış)
  • Dropdown menüler ile kategori navigasyonu
  • Arama işlevselliği
  • Alışveriş sepeti entegrasyonu
  • Sticky header seçeneği
<div class="header-sec-one">
<!-- Logo, dil seçimi, kullanıcı işlemleri -->
<div class="language">
{% for locale_data in get_locales() %}
<a href="{{ locale_data.url }}">
<img src="{{ ('flags/' ~ locale_data.code ~ '.png') | image }}">
</a>
{% endfor %}
</div>
</div>
<div class="header-sec-two">
<!-- Navigasyon ve arama -->
<nav class="navbar">
{% for category in categories %}
<a href="{{ category.url }}">{{ category.name }}</a>
{% endfor %}
</nav>
</div>

header_ella.twig.php

Alternatif Header - Tam genişlik navigasyon ile

Özellikler:

  • Dil seçim dropdown'u
  • Yatay kategori navigasyonu
  • Kullanıcı hesap dropdown'u
  • Typewriter efekti ile arama
<div class="language">
<div class="dropdown">
<button class="dropdown-toggle">
<img src="{{ ('flags/' ~ locale ~ '.png') | image }}">
</button>
</div>
</div>
<nav class="row">
<!-- Logo, navigasyon, kullanıcı butonları -->
</nav>

header_fox.twig.php

Gelişmiş Header - Mega menü ve promosyon banner'ı ile

Özellikler:

  • Üst promosyon carousel'ı
  • Resim desteği ile mega menü
  • Katlanabilir arama işlevselliği
  • Hesap sidebar'ı
<div class="mega">
<div class="listBox">
<!-- Kategori listeleri -->
{% for category in categories %}
<div class="category-group">
<h5>{{ category.name }}</h5>
{% for subcategory in category.subcategories %}
<a href="{{ subcategory.url }}">{{ subcategory.name }}</a>
{% endfor %}
</div>
{% endfor %}
</div>
<div class="visualBox">
<!-- Kategori resimleri -->
<img src="{{ category.featured_image }}" alt="{{ category.name }}">
</div>
</div>

header_helen.twig.php

Üç Katmanlı Header - Dikey hiyerarşi ile

Özellikler:

  • Üst promosyon banner'ı
  • Orta bölümde logo ve arama
  • Alt navigasyon çubuğu
<div class="top">
<!-- Promosyon carousel'ı -->
</div>
<div class="medium">
<!-- Logo ve arama -->
</div>
<div class="bottom">
<!-- Navigasyon -->
</div>

header_mobile.twig.php

Mobil Header - Offcanvas navigasyon ile optimize edilmiş

Özellikler:

  • Offcanvas ile hamburger menü
  • Katlanabilir arama
  • Mobil dostu layout
  • Akordeon kategori menüsü
<div class="offcanvas offcanvas-start" id="staticBackdrop">
<div class="accordion accordion-flush">
{% for category in categories %}
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" data-bs-target="#flush-collapse{{ loop.index }}">
{{ category.name }}
</button>
</h2>
<div id="flush-collapse{{ loop.index }}" class="accordion-collapse collapse">
{% for subcategory in category.subcategories %}
<a href="{{ subcategory.url }}">{{ subcategory.name }}</a>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>

Ürün Templateleri

📚 İlgili Dokümantasyon: Ürün objesinde kullanılabilir tüm alanlar ve özellikler için Ürün Data Alanları dokümantasyonuna bakınız.

_product_card.twig.php

Ürün Kartı Bileşeni - Listelerde kullanılan yeniden kullanılabilir ürün kartı

Özellikler:

  • Lazy loading resimler
  • Favori işlevselliği
  • Thumbnaillar ile varyant seçimi
  • Sepete ekleme formu
  • Ölçü seçimi (paketleme birimleri)
  • İndirim desteği ile fiyat gösterimi
<div class="product pnlurun-item product-card-body" id="divUrunKutu_{{ product.id }}">
<div class="pro card">
{# Giriş yapmış kullanıcılar için favori butonu #}
{% if config('ADD_TO_FAVORITE') and is_logged %}
<button class="fav-icon btn-add-to-favorites" data-urunid="{{ product.id }}">
<i class="bi {% if product.is_favorited %} bi-heart-fill text-danger {% else %} bi-heart {% endif %}"></i>
</button>
{% endif %}

{# Ürün resmi ve linki #}
<a href="{{ product.url }}" title="{{ product.title }}">
<img data-src="{{ product.med_image }}" class="mainImg lazyload"
src="{{ product.min_image }}" alt="{{ product.title }}" />
</a>

{# Varyantlar #}
<div class="product-variant-img-cont">
{% for variant in product.variants %}
<div {{ variant['html-data'] | html_data_attributes }}
class="variant-container {{ loop.first ? 'selectedThumb' : '' }}">
<img data-src="{{ variant['image'] }}" src="{{ variant['image_min'] }}"
class="product-color-img lazyload" alt="{{ variant['name'] }}">
<p class="product-color">{{ variant['name'] ?: '&nbsp;' }}</p>
</div>
{% endfor %}
</div>

{# Sepete ekleme formu #}
{% if is_logged and not product.sale_disabled %}
<form action="{{ 'ADD_TO_CART' | route }}" method="post" class="frm-add-to-cart">
<input type="hidden" name="urun_id" value="{{ product.id }}"/>
<input type="hidden" name="renk" class="drUrunRenk{{ product.id }}"
value="{{ product.default_variant_id }}"/>

<div class="d-flex align-items-center justify-content-between">
<div class="count-btns d-flex">
<span class="decrease-btn btn-qty-decrease">
<i class="bi bi-dash"></i>
</span>
<input class="count" type="text" name="adet" value="{{ product.package_qty ?: 1 }}">
<span class="increase-btn btn-qty-increase">
<i class="bi bi-plus"></i>
</span>
</div>
<button type="submit" class="cart basket-btn addtocartbtn">
<i class="bi bi-cart-plus"></i>
</button>
</div>
</form>
{% endif %}
</div>
</div>

product.twig.php

Ürün Detay Sayfası - Kapsamlı ürün görüntüleme template'i

Özellikler:

  • Zoom işlevselliği ile ürün galerisi
  • Resim değiştirme ile varyant seçimi
  • Modal ile video desteği
  • Miktar kontrolleri ile sepete ekleme formu
  • Ürün özellikleri gösterimi
  • Benzer ürünler bölümü
  • Tam ekran görüntüleme için resim modal'ı
<div class="renkkategori d-flex gap-2">
{% for variant in product.variants_with_gallery %}
<div class="productVariantSelect" data-galeri_index="{{ iiVariant }}">
<img src="{{ variant.image_thumb }}" />
<p>{{ variant.name }}</p>
</div>
{% endfor %}
</div>

{# Ürün galerisi #}
<div class="product-gallery">
<div class="main-image">
<img id="mainProductImage" src="{{ product.main_image }}" data-zoom="{{ product.large_image }}">
</div>
<div class="thumbnail-gallery">
{% for image in product.gallery %}
<img src="{{ image.thumb }}" data-main="{{ image.large }}" class="gallery-thumb">
{% endfor %}
</div>
</div>

{# Video desteği #}
{% if product.video_url %}
<div class="product-video">
<button type="button" data-bs-toggle="modal" data-bs-target="#videoModal">
<i class="bi bi-play-circle"></i> {{ 'video_izle' | t }}
</button>
</div>
{% endif %}

product_list.twig.php

Kategori/Arama Sonuç Listesi - Filtrelenebilir ürün listesi

Özellikler:

  • Responsive filtre paneli (masaüstü/mobil)
  • Sıralama seçenekleri dropdown'u
  • Infinite scroll sayfalama
  • Ürün kartları ile grid layout
  • Mobil offcanvas filtreler
{# Filtreler ve sıralama #}
<div class="row">
<div class="col-md-3">
{% include 'filters.twig.php' %}
</div>
<div class="col-md-9">
<div class="sorting-options">
<select id="sort-products">
<option value="name">{{ 'isme_gore_sirala' | t }}</option>
<option value="price_asc">{{ 'fiyat_artan' | t }}</option>
<option value="price_desc">{{ 'fiyat_azalan' | t }}</option>
</select>
</div>

{# Ürün listesi #}
<div class="row row-cols-2 row-cols-md-4 urunlistesi">
{% for product in products.getData %}
{% include '_product_card.twig.php' with {'product': product} %}
{% endfor %}
</div>

{# Infinite scroll için loading #}
<div id="loading" class="text-center" style="display: none;">
<div class="spinner-border"></div>
</div>
</div>
</div>

Müşteri Yönetimi Templateleri

customers/login.twig.php

Kullanıcı Giriş Formu - Kimlik doğrulama template'i

Özellikler:

  • Email/müşteri kodu ile giriş desteği
  • Otomatik tamamlama ile şifre alanı
  • Responsive form layout'u
  • Kayıt olma ve şifre kurtarma linkleri
<form id="frmLogin" action="{{ 'LOGIN' | route }}" method="post">
<div class="form-group">
<label for="email">{{ 'email_veya_musteri_kodu' | t }}</label>
<input type="email" name="email" id="email" autocomplete="username" required
placeholder="{{ 'email_giriniz' | t }}">
</div>

<div class="form-group">
<label for="password">{{ 'sifre' | t }}</label>
<input type="password" name="sifre" id="password" autocomplete="current-password" required
placeholder="{{ 'sifre_giriniz' | t }}">
</div>

<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ 'giris_yap' | t }}</button>
<a href="{{ 'register' | url }}">{{ 'kayit_ol' | t }}</a>
<a href="{{ 'forgot_password' | url }}">{{ 'sifremi_unuttum' | t }}</a>
</div>
</form>

customers/register.twig.php

Kullanıcı Kayıt Formu - Kapsamlı kayıt template'i

Özellikler:

  • Firma/kişisel bilgi formu
  • AJAX ile ülke/şehir seçimi
  • Konfigürasyona dayalı koşullu alanlar
  • Özel alan entegrasyonu
  • reCAPTCHA desteği
  • Şartlar ve koşullar onay kutusu
<form id="frmRegister" action="{{ 'REGISTER' | route }}" method="post">
<div class="row">
<div class="col-md-6">
<label for="firma">{{ 'firma_adi' | t }}</label>
<input type="text" name="firma" id="firma" required>
</div>
<div class="col-md-6">
<label for="mail">{{ 'email' | t }}</label>
<input type="email" name="mail" id="mail" required>
</div>
</div>

<div class="row">
<div class="col-md-6">
<label for="ulke">{{ 'ulke' | t }}</label>
<select name="ulke" id="ulke" class="ulkeSecim" required>
<option value="">{{ 'ulke_seciniz' | t }}</option>
{% for ulke in ulkeler %}
<option value="{{ ulke.Id }}">{{ ulke.UlkeAdi }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label for="sehir">{{ 'sehir' | t }}</label>
<select name="sehir" id="sehir" class="sehirSecim" required>
<option value="">{{ 'once_ulke_seciniz' | t }}</option>
</select>
</div>
</div>

{# Özel alanlar #}
{% include 'customers/register_customs.twig.php' %}

{# reCAPTCHA #}
{% if config('RECAPTCHA_SITE_KEY') %}
<div class="g-recaptcha" data-sitekey="{{ config('RECAPTCHA_SITE_KEY') }}"></div>
{% endif %}

<div class="form-check">
<input type="checkbox" name="terms" id="terms" required>
<label for="terms">{{ 'sartlari_kabul_ediyorum' | t }}</label>
</div>

<button type="submit" class="btn btn-primary">{{ 'kayit_ol' | t }}</button>
</form>

customers/register_customs.twig.php

Dinamik Özel Alanlar - Kayıt formu için özelleştirilebilir alanlar

Özellikler:

  • Çoklu alan tipleri (input, textarea, select, checkbox, file, datepicker)
  • Konfigürasyondan dinamik alan üretimi
  • Koşullu zorunlu alanlar
{% for key_name, field_data in custom_fields %}
<div class="form-group">
<label for="custom_field_{{ key_name }}">{{ field_data.label }}</label>

{% if field_data.type == 'input' %}
<input type="text" name="custom_field_{{ key_name }}" id="custom_field_{{ key_name }}"
{{ field_data.required ? 'required' : '' }}
placeholder="{{ field_data.placeholder }}">

{% elseif field_data.type == 'textarea' %}
<textarea name="custom_field_{{ key_name }}" id="custom_field_{{ key_name }}"
{{ field_data.required ? 'required' : '' }}
placeholder="{{ field_data.placeholder }}"></textarea>

{% elseif field_data.type == 'select' %}
<select name="custom_field_{{ key_name }}" id="custom_field_{{ key_name }}"
{{ field_data.required ? 'required' : '' }}>
<option value="">{{ 'seciniz' | t }}</option>
{% for option in field_data.options %}
<option value="{{ option }}">{{ option }}</option>
{% endfor %}
</select>

{% elseif field_data.type == 'checkbox' %}
<div class="form-check">
<input type="checkbox" name="custom_field_{{ key_name }}" value="1"
id="custom_field_{{ key_name }}" {{ field_data.required ? 'required' : '' }}>
<label for="custom_field_{{ key_name }}">{{ field_data.label }}</label>
</div>

{% elseif field_data.type == 'file' %}
<input type="file" name="custom_field_{{ key_name }}" id="custom_field_{{ key_name }}"
{{ field_data.required ? 'required' : '' }}
accept="{{ field_data.accept }}">

{% elseif field_data.type == 'datepicker' %}
<input type="date" name="custom_field_{{ key_name }}" id="custom_field_{{ key_name }}"
{{ field_data.required ? 'required' : '' }}>
{% endif %}
</div>
{% endfor %}

Sipariş Yönetimi Templateleri

orders/index.twig.php

Sipariş Geçmişi - Kullanıcının sipariş listesi

Özellikler:

  • Tablo formatında sipariş gösterimi
  • Sipariş durumu ve tutarlar
  • Kargo bilgileri
  • Sayfalama desteği
  • Sipariş detaylarına linkler
<div class="orders-table-container">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>{{ 'tarih' | t }}</th>
<th>{{ 'siparis_no' | t }}</th>
<th>{{ 'tutar' | t }}</th>
<th>{{ 'durum' | t }}</th>
<th>{{ 'kargo' | t }}</th>
<th>{{ 'islemler' | t }}</th>
</tr>
</thead>
<tbody>
{% for order in orders.data %}
<tr>
<td>{{ order.short_date }}</td>
<td>{{ order.order_number }}</td>
<td>{{ order.amount_text }}</td>
<td>
<span class="badge badge-{{ order.status_class }}">
{{ order.status_text }}
</span>
</td>
<td>{{ order.shipping_info }}</td>
<td>
<a href="{{ order.detail_url }}" class="btn btn-sm btn-outline-primary">
{{ 'detay' | t }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>

{# Sayfalama #}
{% if orders.pagination %}
{{ orders.pagination | raw }}
{% endif %}
</div>

orders/detail.twig.php

Sipariş Detayı - Bireysel sipariş görüntüleme

Özellikler:

  • Sipariş bilgi tablosu
  • Excel export işlevselliği
  • Fotoğraf export özelliği
  • Tekrar sipariş işlevselliği
  • Sipariş HTML içerik gösterimi
<div class="order-detail-header">
<h2>{{ 'siparis_detayi' | t }} - {{ order.order_number }}</h2>

<div class="order-actions">
<a href="{{ order.excel_export_url }}" class="btn btn-success">
<i class="bi bi-file-excel"></i> {{ 'excel_indir' | t }}
</a>

<button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#photoExportModal">
<i class="bi bi-download"></i> {{ 'urun_fotograflarini_indir' | t }}
</button>

<button type="button" class="btn btn-primary" onclick="reorderProducts({{ order.id }})">
<i class="bi bi-arrow-repeat"></i> {{ 'tekrar_siparis_ver' | t }}
</button>
</div>
</div>

<div class="order-info-table">
<table class="table">
<tr>
<td>{{ 'siparis_tarihi' | t }}</td>
<td>{{ order.created_date }}</td>
</tr>
<tr>
<td>{{ 'durum' | t }}</td>
<td>{{ order.status_text }}</td>
</tr>
<tr>
<td>{{ 'toplam_tutar' | t }}</td>
<td>{{ order.total_amount_text }}</td>
</tr>
</table>
</div>

<div class="pnl-order-detail">
{{ order.order_html | raw }}
</div>

{# Fotoğraf export modal'ı #}
{% include 'orders/_photo_export_modal.twig.php' %}

Widget Templateleri

widgets/brands_slider.twig.php

Marka Carousel'ı - Ana sayfada marka gösterimi

Özellikler:

  • Swiffy slider entegrasyonu
  • Konfigüre edilebilir görüntüleme ayarları
  • Navigasyon ve göstergeler
  • Responsive tasarım
{% set brands_banner = get_banner('brands_slider') %}
{% if brands_banner and theme_config('brands_slider_active') %}
<div class="container mt-5" data-widget="brands-slider">
<h3 class="text-center">{{ 'markalar' | t }}</h3>

<div class="swiffy-slider {{ theme_config('brands_slider_settings') }}">
<ul class="slider-container">
{% for slide in brands_banner.slide_items %}
<li class="brand-container">
{% if slide.link %}
<a href="{{ slide.link }}" target="_blank">
{% endif %}

<img src="{{ slide.image }}" alt="{{ slide.title }}" class="brand-logo">

{% if slide.link %}
</a>
{% endif %}
</li>
{% endfor %}
</ul>

<button type="button" class="slider-nav" aria-label="Go left">
<i class="bi bi-chevron-left"></i>
</button>
<button type="button" class="slider-nav slider-nav-next" aria-label="Go right">
<i class="bi bi-chevron-right"></i>
</button>

<div class="slider-indicators">
{% for slide in brands_banner.slide_items %}
<button class="{{ loop.first ? 'active' : '' }}" aria-label="Go to slide {{ loop.index }}"></button>
{% endfor %}
</div>
</div>
</div>
{% endif %}

widgets/category_grid.twig.php

Kategori Grid'i - Ana sayfada kategori vitrine edimi

Özellikler:

  • 4'e kadar konfigüre edilebilir kategori grid'i
  • Renk özelleştirmesi
  • Alt kategoriler ile öne çıkan kategori
{% for ii in 1..4 %}
{% if theme_config('category_grid_slider_' ~ ii ~ '_active') %}
{% set grid_category = theme_config('category_grid_slider_' ~ ii ~ '_category') %}
{% set grid_color = theme_config('category_grid_slider_' ~ ii ~ '_color') %}

<div class="category-grid-{{ ii }}" style="background-color: {{ grid_color }};">
<div class="container">
<div class="row">
<div class="col-md-8">
<h3>{{ grid_category.name }}</h3>
<div class="subcategories">
{% for subcategory in grid_category.subcategories %}
<a href="{{ subcategory.url }}" class="subcategory-link">
{{ subcategory.name }}
</a>
{% endfor %}
</div>
</div>
<div class="col-md-4">
<img src="{{ grid_category.featured_image }}" alt="{{ grid_category.name }}" class="category-featured-image">
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}

widgets/last_products.twig.php

Son Ürünler - Ana sayfada son eklenen ürünler

Özellikler:

  • Ürün kartı template'ini yeniden kullanma
  • Responsive grid layout
{% set last_products = get_last_products() %}
{% if last_products %}
<div class="container mt-5" data-widget="last-products">
<h3 class="text-center">{{ 'son_eklenenler' | t }}</h3>
<div class="row row-cols-md-4 row-cols-2 g-1">
{% for product in last_products %}
{{ include('_product_card.twig.php', {'product': product}) }}
{% endfor %}
</div>
</div>
{% endif %}

widgets/instagram.twig.php

Instagram Feed - Sosyal medya entegrasyonu

Özellikler:

  • Instagram API entegrasyonu
  • Takip butonu
  • Responsive fotoğraf grid'i
{% if theme_config('module_instagram') and theme_config('module_instagram_token') %}
<div class="container mt-5" data-widget="instagram">
<h3 class="text-center">{{ 'instagram' | t }}</h3>

<div id="instagram-feed1" class="instagram_feed"
data-token="{{ theme_config('module_instagram_token') }}"
data-count="{{ theme_config('module_instagram_count') ?: 6 }}">
</div>

<div class="text-center mt-3">
<a href="{{ config('SITE_INSTAGRAM_LINK') }}" target="_blank" class="btn btn-primary">
<i class="bi bi-instagram"></i> {{ 'takip_et' | t }}
</a>
</div>
</div>
{% endif %}

Yardımcı Templateler

filters.twig.php

Ürün Filtreleme Arayüzü - Kategori sayfalarında filtreleme

Özellikler:

  • Akordeon stil filtre grupları
  • Filtre içinde arama
  • Checkbox stil seçim
  • URL tabanlı filtreleme
<div class="accordion accordion-filter" id="accordionFilter">
{% for group in filters %}
<div class="accordion-item">
<h2 class="accordion-header" id="heading{{ loop.index }}">
<button class="accordion-button {{ loop.first ? '' : 'collapsed' }}"
data-bs-toggle="collapse" data-bs-target="#collapse{{ loop.index }}">
{{ group.name }}
</button>
</h2>

<div id="collapse{{ loop.index }}"
class="accordion-collapse collapse {{ loop.first ? 'show' : '' }}">
<div class="accordion-body">
{% if group.filters|length > 5 %}
<input type="text" class="filter-search form-control mb-2"
placeholder="{{ 'filtrele' | t }}" />
{% endif %}

<div class="filter-options">
{% for filter in group.filters %}
<div class="filter-option">
<a href="{{ filter.url }}" class="filter-link {{ filter.selected ? 'active' : '' }}">
<span class="filter-checkbox">
{% if filter.selected %}
<i class="bi bi-check-square"></i>
{% else %}
<i class="bi bi-square"></i>
{% endif %}
</span>
{{ filter.label }}
<small class="text-muted">({{ filter.count }})</small>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>

no_records.twig.php

Boş Durum Template'i - Sonuç bulunamadığında

Özellikler:

  • Şirket logosu gösterimi
  • "Ürün yok" mesajı
  • Ana sayfaya dönüş butonu
<div class="no-records-container text-center py-5">
<div class="mb-4">
<img src="{{ config('LOGO_URL') }}" alt="{{ config('FIRMA_ISIM') }}" class="company-logo">
</div>

<h4 class="mb-3">{{ 'kategori_urun_yok' | t }}</h4>
<p class="text-muted mb-4">{{ 'aradiginiz_kriterlere_uygun_urun_bulunamadi' | t }}</p>

<a href="{{ base_url }}" class="btn btn-primary">
<i class="bi bi-house"></i> {{ 'ana_sayfaya_don' | t }}
</a>
</div>

Kısmi Templateler (Partial)

partial/product/add_to_cart.twig.php

Sepete Ekleme Formu - Yeniden kullanılabilir sepet formu

Özellikler:

  • Miktar kontrolleri
  • Ölçü/paketleme seçimi
  • Favori butonu entegrasyonu
  • Satış devre dışı durumu
  • Giriş yapmamış kullanıcılar için gereklilik
{% if is_logged and not product.sale_disabled %}
<form action="{{ 'ADD_TO_CART' | route }}" method="post" class="add-to-cart-form">
<input type="hidden" name="urun_id" value="{{ product.id }}">
<input type="hidden" name="renk" value="{{ product.default_variant_id }}">

{# Ölçü seçimi #}
{% if product.measures %}
<div class="measure-selection mb-3">
<label>{{ 'olcu' | t }}</label>
<select name="olcu" class="form-control">
{% for measure in product.measures %}
<option value="{{ measure.id }}">{{ measure.name }}</option>
{% endfor %}
</select>
</div>
{% endif %}

<div class="quantity-controls d-flex align-items-center mb-3">
<div class="count-btns d-flex">
<span class="decrease-btn btn-qty-decrease" data-package-qty="{{ product.package_qty }}">
<i class="bi bi-dash"></i>
</span>
<input class="count form-control" type="number" name="adet"
value="{{ product.package_qty ?: 1 }}" min="1" step="{{ product.package_qty ?: 1 }}">
<span class="increase-btn btn-qty-increase" data-package-qty="{{ product.package_qty }}">
<i class="bi bi-plus"></i>
</span>
</div>
</div>

<div class="cart-actions">
<button type="submit" class="btn btn-primary add-to-cart-btn">
<i class="bi bi-cart-plus"></i> {{ 'sepete_ekle' | t }}
</button>

{% if config('ADD_TO_FAVORITE') %}
<button type="button" class="btn btn-outline-secondary btn-add-to-favorites" data-urunid="{{ product.id }}">
<i class="bi {% if product.is_favorited %} bi-heart-fill {% else %} bi-heart {% endif %}"></i>
</button>
{% endif %}
</div>
</form>
{% else %}
{% if not is_logged %}
<div class="login-required text-center p-3">
<p>{{ 'siparis_vermek_icin_giris_yapin' | t }}</p>
<a href="{{ 'login' | url }}" class="btn btn-primary">{{ 'giris_yap' | t }}</a>
</div>
{% else %}
<div class="sale-disabled text-center p-3">
<p>{{ 'bu_urun_satis_disi' | t }}</p>
</div>
{% endif %}
{% endif %}

Temel Teknik Özellikler

Çok Dil Desteği

Tüm templateler {{ 'girisyap' | t }} filtresi ile çeviri desteği sağlar:

{{ 'merhaba_dunya' | t }}
{{ 'hosgeldin_mesaji' | translate }}

Responsive Tasarım

Bootstrap 5 sınıfları ile responsive yapı:

<div class="row row-cols-2 row-cols-md-4 g-2">
<div class="col">
<!-- İçerik -->
</div>
</div>

Lazy Loading

Performans optimizasyonu için resim lazy loading:

<img data-src="{{ product.med_image }}" 
src="{{ product.min_image }}"
class="lazyload"
alt="{{ product.title }}">

Webpack Entegrasyonu

Varlık yönetimi için webpack bundle sistemi:

{{ webpack_bundle('layout') }}
{{ webpack_bundle('product') }}
{{ webpack_bundle_header() }}

Tema Konfigürasyonu

Dinamik tema ayarları:

{% if theme_config('header_style') == 'modern' %}
{% include 'header_modern.twig.php' %}
{% endif %}

Kullanıcı Durumu Yönetimi

Koşullu rendering:

{% if is_logged %}
{{ 'hosgeldin' | t }} {{ user.name }}!
{% else %}
<a href="{{ 'login' | url }}">{{ 'giris_yap' | t }}</a>
{% endif %}

Bu kapsamlı referans, frontend geliştiricilerin template sistemiyle etkili şekilde çalışabilmesi için her dosyanın amacını, özelliklerini ve kullanım şeklini detaylı olarak açıklamaktadır.

JavaScript Etkileşimli CSS Classları

Bu bölüm, sadece JavaScript tarafından kullanılan CSS classlarını içerir. Bu classlar event listenerlar, DOM manipülasyonu veya kütüphane entegrasyonları için kullanılır. Sadece stil amaçlı classlar bu listeye dahil edilmemiştir.

Varyant Seçimi & Görsel Yönetimi

productThumbSelector

JavaScript İşlevi: Varyant seçimi için click event handler. Varyant seçildiğinde selectedThumb class'ını toggle eder, ürün görselini ve fiyatını günceller.

Dosyalar: product.js, product_detail.js

<div class="variant-container position-relative productThumbSelector {{ loop.first ? 'selectedThumb' : '' }}"
data-urunid="{{ product.id }}"
data-min-src="{{ variant.image_min }}"
data-med-src="{{ variant.image_thumb }}">
<img class="product-color-img card-img-top lazyload" data-src="{{ variant.image_min }}">
</div>
// product.js
on(document, "click", ".productThumbSelector", function (e) {
el.classList.toggle("selectedThumb");
renkInput.value = el.dataset.renk;
price.innerHTML = selector.dataset.price;
});

selectedThumb

JavaScript İşlevi: Seçili varyantı işaretlemek için JavaScript tarafından eklenir/kaldırılır.

Dosyalar: product.js, product_detail.js

// product.js
selected.classList.remove("selectedThumb"); // Öncekinden kaldır
el.classList.add("selectedThumb"); // Yeniye ekle

productVariantSelect

JavaScript İşlevi: Ürün detay sayfasında varyant seçimi için click handler. Galeri görsellerini değiştirir.

Dosyalar: product_detail.js

<div class="renk-img-container productVariantSelect flex-shrink-0"
data-urunid="{{ product.id }}"
data-varyantid="{{ variant.id }}"
data-galeri_index="{{ iiVariant }}">
<img class="lazyload" data-src="{{ variant.image_min }}">
</div>
// product_detail.js
on(document, "click", ".productVariantSelect", function (e) {
this.classList.toggle("selectedThumb");
getGallery(this.dataset.galeri_index, photo);
});

mainImg

JavaScript İşlevi: Ana ürün görseli - src attribute'ü güncellenir, fade animasyon class'ı eklenir/kaldırılır.

Dosyalar: product.js, product_detail.js

<img class="mainImg lazyload"
data-src="{{ product.med_image }}"
src="{{ product.min_image }}">
// product.js
pnlMainImg.classList.add('fade-transition');
pnlMainImg.src = medPhoto;
setTimeout(() => pnlMainImg.classList.remove('fade-transition'), 50);

product-card-body

JavaScript İşlevi: Mouseenter event ile varyant görsellerini preload eder.

Dosyalar: product.js

<div class="product pnlurun-item product-card-body" id="divUrunKutu_{{ product.id }}">
<!-- Ürün kartı içeriği -->
</div>
// product.js
on(document, "mouseenter", ".product-card-body", function (e) {
const variantImages = this.querySelectorAll('.productThumbSelector img');
// Varyant görsellerini preload et
});

urungorselleri

JavaScript İşlevi: Galeri thumbnail'ına tıklandığında ana görseli değiştirir.

Dosyalar: product_detail.js

<div class="urungorselleri d-flex gap-2">
{% for image in product.gallery %}
<div class="imgs-container">
<img class="gallery-item" src="{{ image.thumb }}">
</div>
{% endfor %}
</div>
// product_detail.js
on(document, "click", ".urungorselleri", function (e) {
changeImages(this); // Ana görseli değiştir
});

JavaScript İşlevi: JavaScript tarafından dinamik olarak oluşturulan galeri görselleri.

Dosyalar: product_detail.js

// product_detail.js
img.classList.add("w-100", "h-100", "object-fit-cover", "gallery-item");

JavaScript İşlevi: Ana galeri görseli - varyant değiştiğinde src güncellenir.

Dosyalar: product_detail.js

// product_detail.js
galleryMainItem.src = mainImg;
galleryMainItem.dataset.medSrc = mainImg;

pnl_urun_galeri

JavaScript İşlevi: Galeri container'ı varyant değiştiğinde içeriği temizlenip yeniden doldurulur.

Dosyalar: product_detail.js

// product_detail.js
var gallery = document.querySelector(".pnl_urun_galeri");
gallery.innerHTML = ""; // Temizle
gallery.appendChild(galleryContainer); // Yeni içerik ekle

zoom

JavaScript İşlevi: jQuery zoom plugin'i ile görsel yakınlaştırma. Görsel değiştiğinde yeniden initialize edilir.

Dosyalar: product_detail.js

<figure class="zoom" style="background-image: url('{{ product.large_image }}')">
<img src="{{ product.image }}">
</figure>
// product_detail.js
$('.zoom').trigger('zoom.destroy').zoom({
url: photo, // Yeni görsel ile zoom'u yeniden başlat
});

product-image-clickable

JavaScript İşlevi: Tıklandığında ürün görselini modal'da büyük boyutta gösterir.

Dosyalar: product_detail.js

<img class="mainImg product-image-clickable" data-src="{{ product.image }}">
// product_detail.js
on(document, "click", ".product-image-clickable", function (e) {
let fullImageUrl = this.dataset.src || this.src;
modalImage.src = fullImageUrl;
modal.show();
});

product-modal-image

JavaScript İşlevi: Modal içindeki görsel, src JavaScript ile güncellenir.

Dosyalar: product_detail.js

// product_detail.js
modalImage.src = fullImageUrl;

product-video-btn

JavaScript İşlevi: Video modal'ını açar, video URL'ini yükler.

Dosyalar: product.js, index.js

<button class="product-video-btn" data-video-url="{{ product.video }}">
<i class="bi bi-play-circle"></i>
</button>
// product.js
on(document, "click", ".product-video-btn", function (e) {
const videoUrl = this.getAttribute('data-video-url');
videoSource.src = videoUrl;
bsModal.show();
});

videoSelector

JavaScript İşlevi: Video thumbnail'ı hover ile video gösterir, click ile seçer.

Dosyalar: product.js

// product.js
$(".videoSelector").hover(function () {
mainVid.show(); // Hover'da videoyu göster
}).click(function () {
selector.toggleClass("selectedThumb");
});

Sepet & Miktar Kontrolleri

frm-add-to-cart

JavaScript İşlevi: Form submit event handler, ürünü sepete ekler veya günceller.

Dosyalar: product.js, product_shared.js

<form class="frm-add-to-cart" method="post" action="{{ 'ADD_TO_CART' | route }}">
<input type="hidden" name="urun_id" value="{{ product.id }}">
<input type="hidden" name="renk" value="{{ product.default_variant_id }}">
<button type="submit" class="addtocartbtn">Sepete Ekle</button>
</form>
// product.js
on(document, "submit", ".frm-add-to-cart", function (e) {
addToCart(this, afterAddToCart);
});

btn-qty-increase

JavaScript İşlevi: Miktar artırma butonu, click ile ürün miktarını artırır.

Dosyalar: product_shared.js

<span class="increase-btn btn-qty-increase">
<i data-lucide="plus"></i>
</span>
// product_shared.js
on(document, "click", ".btn-qty-increase", function (e) {
updateCount(this, false); // Miktarı artır
});

btn-qty-decrease

JavaScript İşlevi: Miktar azaltma butonu, click ile ürün miktarını azaltır.

Dosyalar: product_shared.js

<span class="decrease-btn btn-qty-decrease">
<i data-lucide="minus"></i>
</span>
// product_shared.js
on(document, "click", ".btn-qty-decrease", function (e) {
updateCount(this, true); // Miktarı azalt
});

Ölçü/Paket Seçimi

pc-measure-box

JavaScript İşlevi: Ürün kartında ölçü seçimi, click ile radio button'ı seçer, miktar input'unu günceller.

Dosyalar: product.js

<div class="pc-measure-box mb-1 me-1">
<p class="pc-measure-title">{{ measure.name }}</p>
<button class="pc-select-btn">{{ 'sec' | t }}</button>
</div>
// product.js
selectButton.addEventListener("click", function (e) {
radioButton.checked = true;
box.classList.add("pc-active");
updatePackageQty(radioButton);
});

pc-active

JavaScript İşlevi: Aktif ölçü kutusunu işaretlemek için JavaScript tarafından eklenir/kaldırılır.

Dosyalar: product.js

// product.js
subMeasureBoxes.forEach(function (subBox) {
subBox.classList.remove("pc-active");
});
box.classList.add("pc-active");

measure-box

JavaScript İşlevi: Detay sayfasında ölçü seçimi, click ile aktif hale gelir.

Dosyalar: product_detail.js

<div class="measure-box" data-measure-id="{{ measure.id }}">
<p class="measure-title">{{ measure.name }}</p>
<button class="measure-select-btn">{{ 'sec' | t }}</button>
</div>
// product_detail.js
box.addEventListener("click", function (e) {
radioButton.checked = true;
measureBoxes.forEach(box => box.classList.remove("active"));
box.classList.add("active");
});

select-btn

JavaScript İşlevi: Ölçü seçim butonu click event triggerlar.

Dosyalar: product.js, product_detail.js

// product.js
const selectButton = box.querySelector(".select-btn");
selectButton.addEventListener("click", function (e) {
radioButton.checked = true;
});

Favoriler

btn-add-to-favorites

JavaScript İşlevi: Ürünü favorilere ekler/çıkarır.

Dosyalar: product.js

<button class="btn-add-to-favorites border-0 bg-transparent"
data-urunid="{{ product.id }}">
<i data-lucide="heart" class="icon-favorite"></i>
</button>
// product.js
on(document, "click", ".btn-add-to-favorites", function (e) {
addToFavorite(this); // Favorilere ekle
});

pnlSidebarCart

JavaScript İşlevi: Bootstrap offcanvas show event'inde sepet içeriğini render eder.

Dosyalar: layout.js

// layout.js
pnlSidebarCart.addEventListener("show.bs.offcanvas", function () {
renderSidebarCart(); // Sepet içeriğini yükle
});

Filtreleme & Liste

urunlistesi

JavaScript İşlevi: Infinite scroll kütüphanesi için container, yeni ürünler buraya eklenir.

Dosyalar: list.js

<div class="row row-cols-2 row-cols-md-3 urunlistesi">
{% for product in products %}
{% include '_product_card.twig.php' %}
{% endfor %}
</div>
// list.js
var elem = document.querySelector(".urunlistesi");
let infScroll = new InfiniteScroll(elem, {
append: ".pnlurun-item"
});

pnlurun-item

JavaScript İşlevi: Infinite scroll tarafından append edilen ürün kartı.

Dosyalar: list.js

<div class="pnlurun-item">
{% include '_product_card.twig.php' %}
</div>
// list.js
let infScroll = new InfiniteScroll(elem, {
append: ".pnlurun-item" // Yeni ürünler buraya eklenir
});

JavaScript İşlevi: Filtre içinde arama için keyup event handler.

Dosyalar: list.js

<input class="filter-input filter-search form-control"
placeholder="{{ 'ara' | t }}">
// list.js
filter_inputs.forEach((input) => {
input.addEventListener("keyup", filterList);
});

filters

JavaScript İşlevi: Filtre item'ı arama sonucuna göre gösterilir/gizlenir.

Dosyalar: list.js

<a class="filters text-decoration-none"
href="{{ filter.url }}"
data-search="{{ filter.label }}">
{{ filter.label }}
</a>
// list.js
function filterList() {
list.forEach((item) => {
if (text.includes(filter)) {
item.style.display = ''; // Göster
} else {
item.style.display = 'none'; // Gizle
}
});
}

Fiyat Gösterimi

price

JavaScript İşlevi: Fiyat gösterim elemanı innerHTML varyant değiştiğinde güncellenir.

Dosyalar: product.js, product_detail.js

<h4 class="price">{{ product.first_variant_price_text }}</h4>
// product.js
var price = document.querySelector(".product-card-body .price");
price.innerHTML = selector.dataset.price;

alternate-price

JavaScript İşlevi: Alternatif para birimi fiyatı varyant değiştiğinde güncellenir.

Dosyalar: product.js, product_detail.js

// product.js
alternate_price.innerHTML = selector.dataset.alternatePrice;

Lazy Loading

lazyload

JavaScript İşlevi: LazySizes kütüphanesi tarafından kullanılır ve viewport'a girdiğinde görselleri yükler.

Dosyalar: Tüm template dosyaları

<img class="lazyload"
data-src="{{ product.med_image }}"
src="{{ product.min_image }}"
alt="{{ product.title }}">

Özel Container Seçicileri

pro / card

JavaScript İşlevi: Ürün container'ı bulmak için closest() ile kullanılır.

Dosyalar: product.js

// product.js
var pnlContainer = selector.closest(".pro") || selector.closest(".card");

Önemli Data Attribute'leri

JavaScript işlevselliği için kritik data attribute'leri:

{# Ürün Data Attributes #}
<div class="product-card-body"
data-product-id="{{ product.id }}"
data-urunid="{{ product.id }}">
</div>

{# Varyant Data Attributes #}
<div class="productThumbSelector"
data-renk="{{ variant.id }}"
data-min-src="{{ variant.image_min }}"
data-med-src="{{ variant.image_thumb }}"
data-price="{{ variant.price | price_with_currency }}"
data-alternate-price="{{ variant.alternate_price }}">
</div>

{# Miktar Data Attributes #}
<input class="count"
data-min-qty="{{ product.minimum_buy_qty }}"
data-max-qty="{{ product.maximum_buy_qty }}"
data-package-qty="{{ product.package_qty }}">

{# Lazy Load Data Attributes #}
<img class="lazyload"
data-src="{{ product.med_image }}"
data-min-src="{{ product.min_image }}"
data-med-src="{{ product.med_image }}">

{# Galeri Data Attributes #}
<div class="productVariantSelect"
data-galeri_index="{{ iiVariant }}"
data-varyantid="{{ variant.id }}">
</div>

{# Filtre Data Attributes #}
<a class="filters" data-search="{{ filter.label }}">
{{ filter.label }}
</a>

JavaScript İşlev Özeti

Class AdıJavaScript İşleviEvent TipiDosya
productThumbSelectorVaryant seçimi, görsel/fiyat güncellemeclickproduct.js
selectedThumbSeçili durum işaretlemeclassListproduct.js
productVariantSelectDetay sayfası varyant seçimiclickproduct_detail.js
mainImgAna görsel güncellemesrc, classListproduct.js
product-card-bodyVaryant görselleri preloadmouseenterproduct.js
urungorselleriGaleri thumbnail seçimiclickproduct_detail.js
product-image-clickableGörsel modal açmaclickproduct_detail.js
product-video-btnVideo modal açmaclickproduct.js
frm-add-to-cartSepete eklemesubmitproduct.js
btn-qty-increaseMiktar artırmaclickproduct_shared.js
btn-qty-decreaseMiktar azaltmaclickproduct_shared.js
pc-measure-boxÖlçü seçimiclickproduct.js
pc-activeAktif ölçü işaretlemeclassListproduct.js
measure-boxDetay ölçü seçimiclickproduct_detail.js
btn-add-to-favoritesFavorilere ekleme/çıkarmaclickproduct.js
pnlSidebarCartSepet offcanvas renderbootstrap eventlayout.js
urunlistesiInfinite scroll containerplugin initlist.js
pnlurun-itemInfinite scroll appendplugin appendlist.js
filter-searchFiltre aramakeyuplist.js
filtersFiltre göster/gizleclassList togglelist.js
zoomGörsel zoomplugin initproduct_detail.js
priceFiyat güncellemeinnerHTMLproduct.js
alternate-priceAlternatif fiyat güncellemeinnerHTMLproduct.js
lazyloadLazy loadinglibraryLazySizes
pro / cardContainer seçiciclosest()product.js

Bu classlar SerB2B sistemindeki tüm JavaScript etkileşimleri için kullanılır. Yeni özellik eklerken bu classları kullanın veya benzer naming convention ile yeni classlar oluşturun.