Opencart 3.0.4.0 Versiyonları için Daha modern Kategoride(List/Grid) Göürünümü
İlerleyen zaman zarfında list görünümünü yenilemeyi planlıyorum.
Bu modifikasyon kapsamında, "default" temanın kategori bölümüne daha modern bir görünüm kazandırmayı hedefliyoruz. Bu doğrultuda, listeleme ve gridleme butonlarına tıklandığında kategori görünümünün değişmesini sağlayacağız. Bu işlemi gerçekleştirmek için aşağıdaki adımları takip edeceğiz:
Controller Dosyası Düzenlemesi: Görünüm değişikliğinin temel işleyişini kontrol eden kodlar üzerinde gerekli değişiklikleri yapacağız. Bu, kategori görünümünü etkileyen temel yapı taşlarını içerir.
Template Dosyası Güncellemeleri: Görsel düzenlemeleri yaparak, liste ve grid görünümlerinin daha modern ve estetik bir yapıya kavuşmasını sağlayacağız.
common.js'deki list/grid Fonksiyonları: Butonların görünüm değiştirme işlevlerini kontrol eden JavaScript kodlarını düzenleyeceğiz. Bu sayede, kullanıcı butonlara tıkladığında anında tepki veren dinamik bir yapı oluşturacağız.
Önemli Not: Belirtilen dosyalarda düzenlemelere başlamadan önce mevcut dosyaların yedeklerini almanız önemle tavsiye edilir. Böylece, herhangi bir sorunla karşılaşmanız durumunda dosyalarınızı kolayca geri yükleyebilirsiniz.
Daha modern bir kategori deneyimi sunmak için bu düzenlemeler önemli bir adım olacaktır.
Şimdi Düzenlememize başlayalım.
1-) Template klasöründe ki düzenlemeler: İlk önce "catalog\view\theme\default\template\product" dizininde yer alan "category.twig" dosyasını açalım.
Bulalım :
<div class="row"> {% for product in products %}
<div class="product-layout product-list col-xs-12">
<div class="product-thumb">
<div class="image"><a href="{{ product.href }}"><img src="{{ product.thumb }}" alt="{{ product.name }}" title="{{ product.name }}" class="img-responsive" /></a></div>
<div>
<div class="caption">
<h4><a href="{{ product.href }}">{{ product.name }}</a></h4>
<p>{{ product.description }}</p>
{% if product.price %}
<p class="price"> {% if not product.special %}
{{ product.price }}
{% else %} <span class="price-new">{{ product.special }}</span> <span class="price-old">{{ product.price }}</span> {% endif %}
{% if product.tax %} <span class="price-tax">{{ text_tax }} {{ product.tax }}</span> {% endif %} </p>
{% endif %}
{% if product.rating %}
<div class="rating"> {% for i in 1..5 %}
{% if product.rating < i %} <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-2x"></i></span> {% else %} <span class="fa fa-stack"><i class="fa fa-star fa-stack-2x"></i><i class="fa fa-star-o fa-stack-2x"></i></span>{% endif %}
{% endfor %} </div>
{% endif %} </div>
<div class="button-group">
<button type="button" onclick="cart.add('{{ product.product_id }}', '{{ product.minimum }}');"><i class="fa fa-shopping-cart"></i> <span class="hidden-xs hidden-sm hidden-md">{{ button_cart }}</span></button>
<button type="button" data-toggle="tooltip" title="{{ button_wishlist }}" onclick="wishlist.add('{{ product.product_id }}');"><i class="fa fa-heart"></i></button>
<button type="button" data-toggle="tooltip" title="{{ button_compare }}" onclick="compare.add('{{ product.product_id }}');"><i class="fa fa-exchange"></i></button>
</div>
</div>
</div>
</div>
{% endfor %} </div>
Değiştirelim:
<div id="product-view">
{% for product in products %}
<!-- List Görünümü -->
<div class="product-layout product-list" style="display: none;">
<div class="card card-body mt-3">
<div class="media align-items-center align-items-lg-start text-center text-lg-left flex-column flex-lg-row">
<div class="mr-2 mb-3 mb-lg-0">
<a href="{{ product.href }}">
<img src="{{ product.thumb }}" width="150" height="150" alt="{{ product.name }}">
</a>
</div>
<div class="media-body">
<h6 class="media-title font-weight-semibold">
<a href="{{ product.href }}">{{ product.name }}</a>
</h6>
<p class="mb-3">{{ product.description }}</p>
</div>
<div class="mt-3 mt-lg-0 ml-lg-3 text-center">
<h3 class="mb-0 font-weight-semibold">{{ product.price }}</h3>
<button type="button" class="btn btn-warning mt-4 text-white" onclick="cart.add('{{ product.product_id }}', '{{ product.minimum }}');">Add to cart</button>
</div>
</div>
</div>
</div>
<!-- Grid (Featured) Görünümü -->
<div class="product-layout product-grid featured-container" style="display: none;">
<div class="featured-card">
<div class="featured-top">
<img src="{{ product.brand_image }}" alt="{{ product.manufacturer }}" class="featured-brand-img">
<h6 class="featured-brand-name">
<a href="{{ product.manufacturer_url }}">{{ product.manufacturer }}</a>
</h6>
</div>
<div class="featured-middle">
<a href="{{ product.href }}">
<img src="{{ product.thumb }}" alt="{{ product.name }}" class="featured-product-img">
</a>
<h5 class="featured-product-name">{{ product.name }}</h5>
</div>
<div class="featured-bottom">
<div class="quantity-wrapper">
<button class="quantity-btn" onclick="decreaseQuantity('{{ product.product_id }}')">-</button>
<input type="text" class="quantity-input" value="1" id="quantity_{{ product.product_id }}">
<button class="quantity-btn" onclick="increaseQuantity('{{ product.product_id }}')">+</button>
</div>
<button class="featured-add-btn" onclick="cart.add('{{ product.product_id }}', document.getElementById('quantity_{{ product.product_id }}').value)">
<b>{{ product.price }}</b>
</button>
</div>
</div>
</div>
{% endfor %}
</div>
Bulalım:
{{ footer }}
Üst Satıra Ekleyelim:
<style>
/* Modern Grid Görünümü */
.card {
position: relative;
display: flex;
flex-direction: column;
background-color: #fff;
border: 1px solid #e7e7e7;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 15px;
}
.card-body {
flex: 1 1 auto;
padding: 15px;
}
.media {
display: flex;
align-items: flex-start;
}
.media-body {
flex: 1;
}
.text-center {
text-align: center !important;
}
.text-lg-left {
text-align: left !important;
}
.mt-3 {
margin-top: 1rem !important;
}
.mb-3 {
margin-bottom: 1rem !important;
}
.mr-2 {
margin-right: 0.5rem !important;
}
.ml-lg-3 {
margin-left: 1rem !important;
}
.align-items-center {
align-items: center !important;
}
.align-items-lg-start {
align-items: flex-start !important;
}
.font-weight-semibold {
font-weight: 600;
}
.btn-warning {
color: #fff;
background-color: #f0ad4e;
border-color: #eea236;
text-transform: uppercase;
}
.btn-warning:hover {
color: #fff;
background-color: #ec971f;
border-color: #d58512;
}
.text-muted {
color: #636c72 !important;
}
.list-inline {
padding-left: 0;
list-style: none;
margin: 0;
}
.list-inline-item {
display: inline-block;
margin-right: 0.5rem;
}
/* Grid Konteyner /
/ Genel Grid Görünümü /
#product-view {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); / Dinamik sütun yapısı /
gap: 20px; / Ürünler arasındaki boşluk */
margin-top: 20px;
}
/* List Görünümü /
.product-layout.product-list {
display: none; / Varsayılan olarak gizli /
grid-column: 1 / -1; / Tüm satırı kaplar /
}
/ Genel Stil */
.featured-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* Dinamik sütun düzeni /
gap: 20px; / Ürünler arasındaki boşluk /
padding: 20px; / İçerik etrafındaki boşluk */
}
/* Ürün Kartı /
.featured-card {
background: #fff; / Beyaz arka plan /
border-radius: 5px; / Köşeleri yuvarla /
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); / Hafif gölge efekti /
overflow: hidden; / Taşmaları gizle /
display: flex;
flex-direction: column; / Dikey içerik düzeni /
justify-content: space-between; / Alan dağılımı /
height: 100%; / Yükseklik sorunu çözümü */
}
/* Üst Alan /
.featured-top {
display: flex; / Yan yana içerik /
align-items: center; / Dikey hizalama /
justify-content: space-between; / Alan dağılımı /
background-color: #ff8900; / Turuncu arka plan /
padding: 10px; / İç boşluk /
color: white; / Beyaz yazı rengi */
}
/* Ürün Markası /
.featured-brand-img {
border-radius: 50%; / Yuvarlak görsel /
margin-right: 10px; / Sağ boşluk */
}
.featured-brand-name {
font-size: 16px; /* Yazı boyutu /
font-weight: bold; / Kalın yazı /
margin: 0; / Dış boşluk kaldır */
}
.featured-brand-name a {
color: white; /* Beyaz yazı rengi /
text-decoration: none; / Alt çizgi kaldır */
}
/* Orta Alan /
.featured-middle {
padding: 20px; / İç boşluk /
text-align: center; / Ortalanmış içerik */
}
.featured-product-img {
max-width: 100%; /* Görsel genişliği sınırlaması /
height: auto; / Orantılı yükseklik /
margin-bottom: 10px; / Görsel alt boşluk */
}
.featured-product-name {
font-size: 18px; /* Yazı boyutu /
font-weight: bold; / Kalın yazı /
margin: 10px 0; / Alt ve üst boşluk /
color: #333; / Yazı rengi */
}
/* Alt Alan /
.featured-bottom {
padding: 15px; / İç boşluk /
background: #f9f9f9; / Açık gri arka plan /
text-align: center; / Ortalanmış içerik */
}
.featured-add-btn {
background: #28a745; /* Yeşil arka plan /
color: white; / Beyaz yazı /
border: none; / Çerçevesiz /
padding: 10px 15px; / İç boşluk /
font-size: 14px; / Yazı boyutu /
border-radius: 5px; / Köşeleri yuvarla /
cursor: pointer; / Tıklanabilir imleç /
transition: background 0.3s ease; / Hover geçiş efekti */
}
.featured-add-btn:hover {
background: #218838; /* Daha koyu yeşil */
}
.quantity-wrapper {
display: flex;
align-items: center;
justify-content: center;
gap: 5px; /* Butonlar ve input arasındaki mesafe /
margin-top: 10px; / Üstten biraz boşluk */
}
.quantity-btn {
background: #f0f0f0;
border: 1px solid #ddd;
padding: 5px 10px; /* Daha küçük padding */
cursor: pointer;
font-size: 14px;
font-weight: bold;
border-radius: 3px;
transition: background 0.3s ease;
}
.quantity-btn:hover {
background: #e0e0e0;
}
.quantity-input {
width: 50px;
text-align: center;
border: 1px solid #ddd;
font-size: 14px;
font-weight: bold;
height: 35px; /* Sabit bir yükseklik */
border-radius: 3px;
outline: none;
padding: 0;
}
.featured-add-btn {
background: #28a745;
color: white;
border: none;
padding: 10px 20px;
font-size: 14px;
border-radius: 3px;
cursor: pointer;
transition: background 0.3s ease;
margin-top: 10px; /* Üst boşluk */
}
.featured-add-btn:hover {
background: #218838;
}
.featured-bottom {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10px;
}
/* Responsive Ayarlar /
@media (max-width: 1200px) {
.featured-container {
grid-template-columns: repeat(3, 1fr); / 3 sütun */
}
}
@media (max-width: 992px) {
.featured-container {
grid-template-columns: repeat(2, 1fr); /* 2 sütun */
}
}
@media (max-width: 768px) {
.featured-container {
grid-template-columns: 1fr; /* Tek sütun */
}
}
</style>
<script>
function increaseQuantity(productId) {
const input = document.getElementById(quantity_${productId}
);
input.value = parseInt(input.value) + 1;
}
function decreaseQuantity(productId) {
const input = document.getElementById(quantity_${productId}
);
if (parseInt(input.value) > 1) {
input.value = parseInt(input.value) - 1;
}
}
</script>
2-) Controller klasöründe ki düzenlemeler: İlk önce "catalog\controller\product" dizininde yer alan "category.php" dosyasını açalım.
Bulalım:
$this->load->model('catalog/product');
Alt Satıra Ekleyelim:
$this->load->model('catalog/manufacturer');
Bulalım:
$data['products'][] = array(
Üst Satıra Ekleyelim:
// Üretici bilgileri ve marka resmi
$manufacturer_info = $this->model_catalog_manufacturer->getManufacturer($result['manufacturer_id']);
$manufacturer_name = $manufacturer_info ? $manufacturer_info['name'] : '';
$manufacturer_url = $manufacturer_info ? $this->url->link('product/manufacturer/info', 'manufacturer_id=' . $result['manufacturer_id']) : '';
$brand_image = $manufacturer_info && $manufacturer_info['image'] ? $this->model_tool_image->resize($manufacturer_info['image'], 50, 50) : '';
Bulalım :
'rating' => $result['rating'],
Alt Satıra yada Üst Satıra Farketmez Aşağıdaki Kodu Ekleyiniz:
'manufacturer' => $manufacturer_name,
'manufacturer_url' => $manufacturer_url,
'brand_image' => $brand_image,
3-) JavaScript klasöründe ki düzenlemeler: İlk önce "catalog\view\javascript"
Bulalım:
// Product List
$('#list-view').click(function() {
$('#content .product-grid > .clearfix').remove();
$('#content .row > .product-grid').attr('class', 'product-layout product-list col-xs-12');
$('#grid-view').removeClass('active');
$('#list-view').addClass('active');
localStorage.setItem('display', 'list');
});
// Product Grid
$('#grid-view').click(function() {
// What a shame bootstrap does not take into account dynamically loaded columns
var cols = $('#column-right, #column-left').length;
if (cols == 2) {
$('#content .product-list').attr('class', 'product-layout product-grid col-lg-6 col-md-6 col-sm-12 col-xs-12');
} else if (cols == 1) {
$('#content .product-list').attr('class', 'product-layout product-grid col-lg-4 col-md-4 col-sm-6 col-xs-12');
} else {
$('#content .product-list').attr('class', 'product-layout product-grid col-lg-3 col-md-3 col-sm-6 col-xs-12');
}
$('#list-view').removeClass('active');
$('#grid-view').addClass('active');
localStorage.setItem('display', 'grid');
});
if (localStorage.getItem('display') == 'list') {
$('#list-view').trigger('click');
$('#list-view').addClass('active');
} else {
$('#grid-view').trigger('click');
$('#grid-view').addClass('active');
}
Değiştirelim:
// Product List
$('#list-view').click(function () {
$('.product-grid').hide(); // Grid görünümünü gizle
$('.product-list').show(); // List görünümünü göster
$('#grid-view').removeClass('active');
$('#list-view').addClass('active');
localStorage.setItem('display', 'list'); // Görünüm tercihine göre kaydet
});
$('#grid-view').click(function () {
$('.product-list').hide(); // List görünümünü gizle
$('.product-grid').show(); // Grid görünümünü göster
$('#list-view').removeClass('active');
$('#grid-view').addClass('active');
localStorage.setItem('display', 'grid'); // Görünüm tercihine göre kaydet
});
// Varsayılan Görünüm
if (localStorage.getItem('display') == 'list') {
$('#list-view').trigger('click'); // List görünümü tetiklenir
} else {
$('#grid-view').trigger('click'); // Grid görünümü tetiklenir
}
Ekran Görüntüleri:
Grid Eski Görünüm :

List Eski Görünüm :

Yeni Grid Görünümü :

Yeni List Görünümü :
