New Initial Commit
This commit is contained in:
@@ -0,0 +1,733 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', $product->name . ' - Premium Custom Designs')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
.breadcrumb {
|
||||
margin-bottom: 2rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: var(--accent-primary);
|
||||
text-decoration: none;
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
.product-section {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 3rem;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
.lightbox.active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lightbox-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.lightbox-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 85vh;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.lightbox-close {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 35px;
|
||||
color: white;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.lightbox-close:hover {
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
.lightbox-nav {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: white;
|
||||
font-size: 36px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 10px 15px;
|
||||
transition: color 0.2s;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.lightbox-nav:hover {
|
||||
color: var(--accent-primary);
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.lightbox-prev {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.lightbox-next {
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.lightbox-counter {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.product-info h1 {
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
font-size: 2.5rem;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.category-tag {
|
||||
display: inline-block;
|
||||
background-color: var(--accent-pink);
|
||||
color: white;
|
||||
padding: 0.4rem 1rem;
|
||||
border-radius: 20px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 900;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 2rem;
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.stock-status {
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.stock-status.in-stock {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.stock-status.low-stock {
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
.stock-status.out-of-stock {
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
.description {
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
margin-bottom: 2rem;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.quantity-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.quantity-selector label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.quantity-selector input {
|
||||
width: 80px;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.related-products {
|
||||
margin-top: 4rem;
|
||||
padding-top: 3rem;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.related-products h2 {
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
font-size: 2rem;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background-color: #d4e8d4;
|
||||
color: var(--primary-color);
|
||||
border: 1px solid #a8d4a8;
|
||||
}
|
||||
|
||||
.calculator-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 2000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.calculator-modal.active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.calculator-content {
|
||||
background: white;
|
||||
padding: 2rem;
|
||||
border-radius: 12px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.calculator-close {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.calculator-close:hover {
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
.wall-schematic {
|
||||
background: var(--section-light-bg);
|
||||
padding: 2rem;
|
||||
border-radius: 8px;
|
||||
margin: 1.5rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wall-diagram {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
height: 150px;
|
||||
border: 3px solid var(--primary-color);
|
||||
position: relative;
|
||||
margin: 1rem auto;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.wall-label {
|
||||
position: absolute;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.wall-label.width {
|
||||
bottom: -25px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.wall-label.height {
|
||||
right: -60px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.calc-input-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.calc-input-group label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.calc-input-group input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.calc-result {
|
||||
background: var(--accent-light);
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
margin-top: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.calc-result h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: white;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.calc-result .result-value {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
}
|
||||
|
||||
.calc-result small {
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.product-section {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.product-info h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.calculator-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<main class="container" style="padding-top: 20px;">
|
||||
<!-- Breadcrumb -->
|
||||
<!-- <div class="breadcrumb">
|
||||
<a href="{{ route('home') }}">Home</a> /
|
||||
<a href="{{ route('wallpapers') }}">Products</a> /
|
||||
<span>{{ $product->name }}</span>
|
||||
</div> -->
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Product Section -->
|
||||
<section class="product-section">
|
||||
<div>
|
||||
@if($product->images->count() > 0)
|
||||
<img id="mainImage" src="{{ asset('storage/' . $product->images->first()->image_path) }}" alt="{{ $product->name }}" class="product-image">
|
||||
|
||||
@if($product->images->count() > 1)
|
||||
<div style="display: flex; gap: 0.5rem; margin-top: 1rem; overflow-x: auto;">
|
||||
@foreach($product->images as $image)
|
||||
<img
|
||||
src="{{ asset('storage/' . $image->image_path) }}"
|
||||
alt="{{ $product->name }}"
|
||||
class="product-thumbnail"
|
||||
onclick="document.getElementById('mainImage').src = '{{ asset('storage/' . $image->image_path) }}'"
|
||||
style="width: 80px; height: 80px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 2px solid transparent; transition: border-color 0.2s; flex-shrink: 0;"
|
||||
onmouseover="this.style.borderColor = 'var(--accent-primary)'"
|
||||
onmouseout="this.style.borderColor = 'transparent'"
|
||||
>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<img id="mainImage" src="{{ $product->image }}" alt="{{ $product->name }}" class="product-image">
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="product-info">
|
||||
<h1>{{ $product->name }}</h1>
|
||||
<span class="category-tag">{{ $product->category->name }}</span>
|
||||
<!-- <div class="stock-status @if($product->stock > 10) in-stock @elseif($product->stock > 0) low-stock @else out-of-stock @endif">
|
||||
@if($product->stock > 0)
|
||||
<strong>{{ $product->stock }} in stock</strong>
|
||||
@else
|
||||
<strong>Out of stock</strong>
|
||||
@endif
|
||||
</div> -->
|
||||
|
||||
<p class="description">{{ $product->description }}</p>
|
||||
|
||||
@if($product->type === 'wallpaper')
|
||||
<div style="background: var(--section-light-bg); padding: 1rem; border-radius: 4px; margin-bottom: 1.5rem; font-size: 0.9rem;">
|
||||
<p><strong>Wallpaper Info:</strong> Sold per meter (10m rolls). Pattern is 1m wide x 2.7m high. For a wall height of 2.7m, you need 3m of wallpaper.</p>
|
||||
</div>
|
||||
@elseif($product->type === 'mural')
|
||||
<div style="background: var(--section-light-bg); padding: 1rem; border-radius: 4px; margin-bottom: 1.5rem; font-size: 0.9rem;">
|
||||
<p><strong>Mural Info:</strong> Sold per m² (square meter). Single image, non-repeating pattern. Perfect for accent walls.</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($product->stock > 0)
|
||||
<form action="{{ route('cart-add', $product) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<!-- Print Stock Selection -->
|
||||
<div class="quantity-selector" style="flex-direction: column; align-items: flex-start; gap: 0.5rem; margin-bottom: 2rem;">
|
||||
<label for="print_stock_id" style="font-weight: 600;">Select Print Stock:</label>
|
||||
<select id="print_stock_id" name="print_stock_id" required style="width: 100%; padding: 0.75rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem;">
|
||||
@foreach($product->printStocks as $stock)
|
||||
<option value="{{ $stock->id }}"
|
||||
data-cost="{{ $product->type === 'wallpaper' ? $stock->cost_per_meter : $stock->cost_per_m2 }}"
|
||||
data-width="{{ $stock->width ?? 1 }}">
|
||||
{{ $stock->name }} ({{ $stock->width ?? 1 }}m wide) - R{{ $product->type === 'wallpaper' ? number_format($stock->cost_per_meter, 2) : number_format($stock->cost_per_m2, 2) }}/{{ $product->type === 'wallpaper' ? 'm' : 'm²' }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<small style="color: #666;">Base cost per {{ $product->type === 'wallpaper' ? 'meter' : 'm²' }} of print stock</small>
|
||||
</div>
|
||||
|
||||
@if($product->type === 'wallpaper')
|
||||
<!-- Calculator Button -->
|
||||
<div style="margin-bottom: 1.5rem;">
|
||||
<button type="button" class="btn btn--secondary" onclick="openCalculator()" style="width: 100%;">
|
||||
📐 Calculate Required Length
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="quantity-selector" style="flex-direction: column; align-items: flex-start; gap: 0.5rem;">
|
||||
<label for="length">Length Required (meters):</label>
|
||||
<input type="number" id="length" name="length" min="1" step="0.5" value="3" required style="width: 150px;">
|
||||
<small style="color: #666;">Recommended: Add 0.5m for pattern matching and trimming</small>
|
||||
</div>
|
||||
@elseif($product->type === 'mural')
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 2rem;">
|
||||
<div>
|
||||
<label for="width" style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Width (meters):</label>
|
||||
<input type="number" id="width" name="width" min="0.5" step="0.1" value="2" required style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
|
||||
</div>
|
||||
<div>
|
||||
<label for="height" style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Height (meters):</label>
|
||||
<input type="number" id="height" name="height" min="0.5" step="0.1" value="2.7" required style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Total Price Display -->
|
||||
<div style="background: var(--accent-light); padding: 1.5rem; border-radius: 20px; margin-bottom: 2rem;">
|
||||
<p style="margin: 0 0 0.5rem 0; color: black;">Estimated Total:</p>
|
||||
<div style="font-family: Abril fatface;font-size: 3rem; font-weight: 400; color: white;">R<span id="totalPrice">{{ number_format($product->price, 2) }}</span></div>
|
||||
<small style="color: #fff; display: block; margin-top: 0.5rem;" id="priceBreakdown"></small>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" style="gap: 1rem;">
|
||||
<button type="submit" class="btn" style="flex: 1;">Add to Cart</button>
|
||||
<a href="{{ route('cart') }}" class="btn btn--secondary" style="flex: 1; text-align: center;">View Cart</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const productType = 'wallpaper' === 'wallpaper' ? 'wallpaper' : 'mural';
|
||||
const basePrice = {{ $product->price }};
|
||||
const isWallpaper = {{ $product->type === 'wallpaper' ? 'true' : 'false' }};
|
||||
|
||||
function updatePrice() {
|
||||
const stockSelect = document.getElementById('print_stock_id');
|
||||
const selectedOption = stockSelect.options[stockSelect.selectedIndex];
|
||||
const stockCost = parseFloat(selectedOption.dataset.cost) || 0;
|
||||
|
||||
let totalCost = stockCost;
|
||||
let breakdown = '';
|
||||
|
||||
if (isWallpaper) {
|
||||
const length = parseFloat(document.getElementById('length').value) || 0;
|
||||
totalCost = stockCost * length;
|
||||
breakdown = `Stock: R${stockCost.toFixed(2)}/m × ${length}m`;
|
||||
} else {
|
||||
const width = parseFloat(document.getElementById('width').value) || 0;
|
||||
const height = parseFloat(document.getElementById('height').value) || 0;
|
||||
const m2 = width * height;
|
||||
totalCost = stockCost * m2;
|
||||
breakdown = `Stock: R${stockCost.toFixed(2)}/m² × ${m2.toFixed(2)}m²`;
|
||||
}
|
||||
|
||||
document.getElementById('totalPrice').textContent = totalCost.toFixed(2);
|
||||
document.getElementById('priceBreakdown').textContent = breakdown;
|
||||
}
|
||||
|
||||
document.getElementById('print_stock_id').addEventListener('change', updatePrice);
|
||||
if (isWallpaper) {
|
||||
document.getElementById('length').addEventListener('input', updatePrice);
|
||||
} else {
|
||||
document.getElementById('width').addEventListener('input', updatePrice);
|
||||
document.getElementById('height').addEventListener('input', updatePrice);
|
||||
}
|
||||
|
||||
updatePrice();
|
||||
</script>
|
||||
@else
|
||||
<button class="btn" disabled style="background-color: #ccc; cursor: not-allowed;">Out of Stock</button>
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator Modal -->
|
||||
<div id="calculatorModal" class="calculator-modal">
|
||||
<div class="calculator-content">
|
||||
<span class="calculator-close" onclick="closeCalculator()">×</span>
|
||||
<h2 style="color: var(--primary-color); margin-bottom: 1rem; font-family: 'Abril Fatface', cursive;">Wallpaper Calculator</h2>
|
||||
|
||||
<div class="wall-schematic">
|
||||
<p style="margin-bottom: 1rem; font-size: 0.9rem; color: #666;">Enter your wall dimensions:</p>
|
||||
<div class="wall-diagram">
|
||||
<span class="wall-label width">Width</span>
|
||||
<span class="wall-label height">Height</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="calc-input-group">
|
||||
<label for="calc-wall-width">Wall Width (meters):</label>
|
||||
<input type="number" id="calc-wall-width" min="0.1" step="0.1" value="4" oninput="calculateWallpaper()">
|
||||
</div>
|
||||
|
||||
<div class="calc-input-group">
|
||||
<label for="calc-wall-height">Wall Height (meters):</label>
|
||||
<input type="number" id="calc-wall-height" min="0.1" step="0.1" value="2.7" oninput="calculateWallpaper()">
|
||||
</div>
|
||||
|
||||
<div class="calc-input-group">
|
||||
<label for="calc-wallpaper-width">Wallpaper Width (meters):</label>
|
||||
<div style="padding: 0.75rem; background: var(--section-light-bg); border-radius: 6px; font-size: 1rem; font-weight: 600; color: var(--primary-color);">
|
||||
<span id="calc-wallpaper-width">1</span>m
|
||||
</div>
|
||||
<small style="color: #666; display: block; margin-top: 0.25rem;">Width from selected print stock</small>
|
||||
</div>
|
||||
|
||||
<div class="calc-result" id="calcResult" style="display: none;">
|
||||
<h3>Required Length:</h3>
|
||||
<div class="result-value"><span id="calcResultValue">0</span>m</div>
|
||||
<small id="calcBreakdown"></small>
|
||||
</div>
|
||||
|
||||
<button class="btn" onclick="useCalculatedLength()" style="width: 100%; margin-top: 1rem;">
|
||||
Use This Length
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lightbox Modal -->
|
||||
<div id="lightbox" class="lightbox">
|
||||
<div class="lightbox-content">
|
||||
<span class="lightbox-close" onclick="closeLightbox()">×</span>
|
||||
<span class="lightbox-nav lightbox-prev" onclick="prevImage()">‹</span>
|
||||
<img id="lightboxImage" class="lightbox-image" style="border-radius: 20px;" src="" alt="">
|
||||
<span class="lightbox-nav lightbox-next" onclick="nextImage()">›</span>
|
||||
<div class="lightbox-counter">
|
||||
<span id="imageCounter">1</span> / <span id="totalImages">1</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentImageIndex = 0;
|
||||
let allImages = [];
|
||||
|
||||
function initLightboxImages() {
|
||||
@if($product->images->count() > 0)
|
||||
allImages = [
|
||||
@foreach($product->images as $image)
|
||||
'{{ asset('storage/' . $image->image_path) }}',
|
||||
@endforeach
|
||||
];
|
||||
@else
|
||||
allImages = ['{{ $product->image }}'];
|
||||
@endif
|
||||
|
||||
document.getElementById('totalImages').textContent = allImages.length;
|
||||
}
|
||||
|
||||
function openLightbox(imageSrc) {
|
||||
currentImageIndex = allImages.indexOf(imageSrc);
|
||||
if (currentImageIndex === -1) {
|
||||
currentImageIndex = 0;
|
||||
}
|
||||
updateLightboxImage();
|
||||
document.getElementById('lightbox').classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
document.getElementById('lightbox').classList.remove('active');
|
||||
document.body.style.overflow = 'auto';
|
||||
}
|
||||
|
||||
function nextImage() {
|
||||
currentImageIndex = (currentImageIndex + 1) % allImages.length;
|
||||
updateLightboxImage();
|
||||
}
|
||||
|
||||
function prevImage() {
|
||||
currentImageIndex = (currentImageIndex - 1 + allImages.length) % allImages.length;
|
||||
updateLightboxImage();
|
||||
}
|
||||
|
||||
function updateLightboxImage() {
|
||||
document.getElementById('lightboxImage').src = allImages[currentImageIndex];
|
||||
document.getElementById('imageCounter').textContent = currentImageIndex + 1;
|
||||
}
|
||||
|
||||
// Close lightbox when clicking outside the image
|
||||
document.getElementById('lightbox').addEventListener('click', function(event) {
|
||||
if (event.target === this) {
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
|
||||
// Close lightbox with Escape key
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Escape') {
|
||||
closeLightbox();
|
||||
}
|
||||
// Navigate with arrow keys
|
||||
if (document.getElementById('lightbox').classList.contains('active')) {
|
||||
if (event.key === 'ArrowRight') {
|
||||
nextImage();
|
||||
}
|
||||
if (event.key === 'ArrowLeft') {
|
||||
prevImage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add click handler to main image
|
||||
document.getElementById('mainImage').addEventListener('click', function() {
|
||||
openLightbox(this.src);
|
||||
});
|
||||
|
||||
// Initialize lightbox images on page load
|
||||
initLightboxImages();
|
||||
|
||||
// Calculator functions
|
||||
function openCalculator() {
|
||||
// Update calculator width from selected print stock
|
||||
const stockSelect = document.getElementById('print_stock_id');
|
||||
const selectedOption = stockSelect.options[stockSelect.selectedIndex];
|
||||
const stockWidth = parseFloat(selectedOption.dataset.width) || 1;
|
||||
document.getElementById('calc-wallpaper-width').textContent = stockWidth;
|
||||
|
||||
document.getElementById('calculatorModal').classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
calculateWallpaper();
|
||||
}
|
||||
|
||||
function closeCalculator() {
|
||||
document.getElementById('calculatorModal').classList.remove('active');
|
||||
document.body.style.overflow = 'auto';
|
||||
}
|
||||
|
||||
function calculateWallpaper() {
|
||||
const wallWidth = parseFloat(document.getElementById('calc-wall-width').value) || 0;
|
||||
const wallHeight = parseFloat(document.getElementById('calc-wall-height').value) || 0;
|
||||
const wallpaperWidth = parseFloat(document.getElementById('calc-wallpaper-width').textContent) || 1;
|
||||
|
||||
if (wallWidth > 0 && wallHeight > 0 && wallpaperWidth > 0) {
|
||||
// Calculate number of strips needed
|
||||
const stripsNeeded = Math.ceil(wallWidth / wallpaperWidth);
|
||||
|
||||
// Calculate total length needed (strips × wall height)
|
||||
const totalLength = stripsNeeded * wallHeight;
|
||||
|
||||
// Add 10% for pattern matching and waste
|
||||
const withWaste = totalLength * 1.1;
|
||||
const finalLength = Math.ceil(withWaste * 2) / 2; // Round up to nearest 0.5m
|
||||
|
||||
// Display results
|
||||
document.getElementById('calcResultValue').textContent = finalLength.toFixed(1);
|
||||
document.getElementById('calcBreakdown').innerHTML =
|
||||
`${stripsNeeded} strips × ${wallHeight}m height = ${totalLength.toFixed(1)}m<br>` +
|
||||
`+ 10% waste allowance = ${finalLength.toFixed(1)}m total`;
|
||||
document.getElementById('calcResult').style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function useCalculatedLength() {
|
||||
const calculatedLength = parseFloat(document.getElementById('calcResultValue').textContent);
|
||||
document.getElementById('length').value = calculatedLength;
|
||||
closeCalculator();
|
||||
updatePrice();
|
||||
}
|
||||
|
||||
// Close calculator when clicking outside
|
||||
document.getElementById('calculatorModal').addEventListener('click', function(event) {
|
||||
if (event.target === this) {
|
||||
closeCalculator();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Related Products -->
|
||||
@if($product->category->products->count() > 1)
|
||||
<section class="related-products" style="margin-bottom: 20px;">
|
||||
<h2>More from {{ $product->category->name }}</h2>
|
||||
<div class="grid grid--3">
|
||||
@foreach($product->category->products->where('id', '!=', $product->id)->take(3) as $relatedProduct)
|
||||
@include('components.product-card', ['product' => $relatedProduct])
|
||||
@endforeach
|
||||
</div>
|
||||
</section>
|
||||
@endif
|
||||
</main>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user