update shop

timetoconfirm
Raz 8 months ago
parent e9e1f65911
commit b8a708ff44
  1. 46
      shop/static/shop/css/shop.css
  2. 82
      shop/templates/shop/product_item.html
  3. 42
      shop/templatetags/shop_extras.py

@ -12,6 +12,7 @@
object-fit: contain; /* This will maintain the aspect ratio of the image */
background-color: white;
border-radius: 12px;
display: none; /* Hide all images by default */
}
.no-image {
@ -480,3 +481,48 @@ v .cart-table {
position: relative;
overflow: hidden;
}
.slider-container {
position: relative;
width: 100%;
max-height: 240px; /* Match your original height */
}
.slides {
position: relative;
width: 100%;
height: 100%;
}
.product-image.active {
display: block;
}
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
transform: translateY(-50%);
background: none;
color: black;
border: none;
font-size: 24px;
padding: 8px;
opacity: 0.6;
transition: opacity 0.3s;
z-index: 2;
}
.prev {
left: 5px;
}
.next {
right: 5px;
}
.prev:hover,
.next:hover {
opacity: 1;
}

@ -2,10 +2,21 @@
<div class="small-12 medium-6 large-3 my-block">
<div class="bubble">
{% if product.image %}
<img id="product-image-{{ product.id }}"
src="{% color_image_url product.image product.colors.all.0.name product.sku %}"
alt="{{ product.title }}"
class="product-image">
<div class="slider-container" id="slider-{{ product.id }}">
{% color_images_url product.image product.colors.all.0.name product.sku as images %}
<div class="slides">
{% for image_url in images %}
<img src="{{ image_url }}"
alt="{{ product.title }}"
class="product-image {% if forloop.first %}active{% endif %}"
id="product-image-{{ product.id }}-{{ forloop.counter0 }}">
{% endfor %}
</div>
{% if images|length > 1 %}
<button class="prev" onclick="changeSlide({{ product.id }}, -1)"></button>
<button class="next" onclick="changeSlide({{ product.id }}, 1)"></button>
{% endif %}
</div>
{% else %}
<div class="no-image">No Image Available</div>
{% endif %}
@ -28,17 +39,19 @@
<input type="hidden" name="color" id="color-{{ product.id }}" value="{{ product.colors.all.0.id }}" required>
<div class="color-samples">
{% for color in product.colors.all %}
{% color_images_url product.image color.name product.sku as color_images %}
<div class="color-sample {% if forloop.first %}selected{% endif %}"
{% if color.secondary_hex_color %}
style="background-image: linear-gradient(to right, {{ color.colorHex }} 50%, {{ color.secondary_hex_color }} 50%);"
{% else %}
style="background-color: {{ color.colorHex }};"
{% endif %}
{% if color.secondary_hex_color %}
style="background-image: linear-gradient(to right, {{ color.colorHex }} 50%, {{ color.secondary_hex_color }} 50%);"
{% else %}
style="background-color: {{ color.colorHex }};"
{% endif %}
title="{{ color.name }}"
data-color-id="{{ color.id }}"
data-color-name="{{ color.name }}"
data-color-image="{% color_image_url product.image color.name product.sku %}"
onclick="selectColor('{{ product.id }}', '{{ color.id }}', '{{ color.name }}', this)"></div>
data-color-images="{{ color_images|join:',' }}"
onclick="selectColor('{{ product.id }}', '{{ color.id }}', '{{ color.name }}', this)">
</div>
{% endfor %}
</div>
{% endif %}
@ -129,14 +142,30 @@ function selectColor(productId, colorId, colorName, element) {
// Add selected class to clicked color
element.classList.add('selected');
// Update product image based on selected color
const productImage = document.getElementById(`product-image-${productId}`);
// Update product images based on selected color
const slider = document.getElementById(`slider-${productId}`);
if (slider) {
const colorImages = element.getAttribute('data-color-images').split(',');
const slidesContainer = slider.querySelector('.slides');
if (productImage) {
const colorImage = element.getAttribute('data-color-image');
if (colorImage) {
productImage.src = colorImage;
}
// Clear existing slides
slidesContainer.innerHTML = '';
// Add new slides
colorImages.forEach((imageUrl, index) => {
const img = document.createElement('img');
img.src = imageUrl;
img.alt = colorName;
img.className = `product-image ${index === 0 ? 'active' : ''}`;
img.id = `product-image-${productId}-${index}`;
slidesContainer.appendChild(img);
});
// Update navigation buttons visibility
const navButtons = slider.querySelectorAll('.prev, .next');
navButtons.forEach(button => {
button.style.display = colorImages.length > 1 ? 'block' : 'none';
});
}
}
@ -212,4 +241,21 @@ function addToCartAjax(productId) {
}, 3000);
});
}
function changeSlide(productId, direction) {
const slides = document.querySelectorAll(`#slider-${productId} .product-image`);
let activeIndex = Array.from(slides).findIndex(slide => slide.classList.contains('active'));
// Remove active class from current slide
slides[activeIndex].classList.remove('active');
// Calculate new index
activeIndex = activeIndex + direction;
if (activeIndex >= slides.length) activeIndex = 0;
if (activeIndex < 0) activeIndex = slides.length - 1;
// Add active class to new slide
slides[activeIndex].classList.add('active');
}
</script>

@ -5,17 +5,16 @@ register = template.Library()
from django.conf import settings
@register.simple_tag
def color_image_url(default_image, color_name, sku):
def color_images_url(default_image, color_name, sku):
"""
Returns color-specific image URL from the color-specific folder structure.
Returns color-specific image URLs from the color-specific folder structure.
Structure expected:
static/shop/images/products/
{sku}/
default.jpg (or any supported extension)
{color_name}/
image.jpg (or any supported extension)
{sku}/
default.jpg (or any supported extension)
{color_name}/
image.jpg (or any supported extension)
"""
# List of supported image extensions
supported_extensions = ['.png.avif', '.jpg', '.jpeg', '.png', '.gif', '.webp', '.avif']
@ -30,31 +29,34 @@ def color_image_url(default_image, color_name, sku):
# Check color-specific folder
color_path = os.path.join(physical_base_path, color_folder)
if os.path.exists(color_path):
# Get first image from color folder
# Get all images from color folder
files = [f for f in os.listdir(color_path)
if any(f.lower().endswith(ext) for ext in supported_extensions)]
if any(f.lower().endswith(ext) for ext in supported_extensions)]
if files:
# Sort files to ensure consistent selection
# Sort files by specific prefix rules
files.sort(key=lambda x: (
1 if '-B_' in x else
2 if '-S_' in x else
0
))
# Get the first image
first_file = files[0]
return f'{base_path}{color_folder}/{first_file}'
return [f'{base_path}{color_folder}/{file}' for file in files]
# If no color-specific image found, look for default image in product folder
if os.path.exists(physical_base_path):
for file in os.listdir(physical_base_path):
if any(file.lower().endswith(ext) for ext in supported_extensions):
if os.path.isfile(os.path.join(physical_base_path, file)): # Make sure it's a file, not a directory
return f'{base_path}{file}'
files = [f for f in os.listdir(physical_base_path)
if os.path.isfile(os.path.join(physical_base_path, f)) and
any(f.lower().endswith(ext) for ext in supported_extensions)]
if files:
files.sort(key=lambda x: (
1 if '-B_' in x else
2 if '-S_' in x else
0
))
return [f'{base_path}{file}' for file in files]
# If nothing found, return the default image from the database
return default_image
# If nothing found, return list with default image
return [default_image]
def generate_color_folder_name(color_name):
"""

Loading…
Cancel
Save