refactor: Split shipping_address into component fields for ShipLogic API
- Create migration to add shipping_street_address, shipping_local_area, shipping_city, shipping_zone, shipping_country, shipping_postcode, shipping_type - Update Order model fillable array with new address component fields - Remove address parsing logic from CourierService - Use individual address fields directly in ShipLogic API payload - Fields match ShipLogic API requirements (street_address, local_area, city, zone, code, country, type) - Note: Custom orders address collection can be implemented later
This commit is contained in:
@@ -0,0 +1,793 @@
|
||||
<?php $__env->startSection('title', 'Request Custom Design - Additional Design'); ?>
|
||||
|
||||
<?php $__env->startSection('styles'); ?>
|
||||
<style>
|
||||
.page-intro {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.page-intro h1 {
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
font-size: 2.5rem;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.page-intro p {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.form-card {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.form-section h2 {
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
font-size: 1.6rem;
|
||||
color: var(--text-primary);
|
||||
/* margin-bottom: var(--spacing-md); */
|
||||
}
|
||||
|
||||
.form-section {
|
||||
/* margin-bottom: var(--spacing-lg); */
|
||||
}
|
||||
|
||||
.form-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-group-hint {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.form-row.full {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group textarea,
|
||||
.form-group select {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
font-family: inherit;
|
||||
background-color: white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
.form-group textarea:focus,
|
||||
.form-group select:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-dark);
|
||||
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.form-group textarea {
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
border: 2px dashed var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: var(--spacing-lg);
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: var(--transition);
|
||||
background-color: var(--bg-primary);
|
||||
}
|
||||
|
||||
.upload-area:hover {
|
||||
border-color: var(--accent-dark);
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.upload-area svg {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
color: var(--text-secondary);
|
||||
margin: 0 auto var(--spacing-sm);
|
||||
}
|
||||
|
||||
.upload-area p {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
.upload-area .hint {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.file-item svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: var(--accent-dark);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
padding: var(--spacing-md);
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 20px;
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.checkbox-option {
|
||||
display: flex;
|
||||
gap: var(--spacing-md);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox-option input[type="checkbox"] {
|
||||
margin-top: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox-content p {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: var(--spacing-md);
|
||||
margin-top: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.button-group .btn {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: var(--bg-secondary) !important;
|
||||
color: var(--text-primary) !important;
|
||||
border: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
background-color: var(--border-color) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #c53030;
|
||||
font-size: 0.9rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.info-box h3 {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: var(--spacing-md);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.info-box ul {
|
||||
list-style-position: inside;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.info-box li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 450px;
|
||||
gap: var(--spacing-lg);
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
.cost-summary {
|
||||
height: fit-content;
|
||||
position: sticky;
|
||||
top: 120px;
|
||||
}
|
||||
.cost-summary-content {
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.cost-summary-content h3 {
|
||||
font-family: 'Abril Fatface', cursive;
|
||||
font-size: 1.3rem;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.cost-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: var(--spacing-sm) 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.cost-item.total {
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
border-top: 2px solid var(--accent-dark);
|
||||
border-bottom: none;
|
||||
margin-top: var(--spacing-md);
|
||||
padding-top: var(--spacing-md);
|
||||
color: var(--accent-dark);
|
||||
}
|
||||
|
||||
.cost-label {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.cost-value {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.cost-item.total .cost-value {
|
||||
color: var(--accent-dark);
|
||||
}
|
||||
|
||||
.design-fee-note {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: var(--spacing-md);
|
||||
padding-top: var(--spacing-md);
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.cost-item.disabled {
|
||||
opacity: 0.5;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.cost-item.discount {
|
||||
color: var(--accent-pink);
|
||||
}
|
||||
|
||||
.cost-item.discount .cost-value {
|
||||
color: var(--accent-pink);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.form-wrapper {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.cost-summary-content {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.form-card {
|
||||
padding: var(--spacing-md);
|
||||
}
|
||||
|
||||
.form-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php $__env->stopSection(); ?>
|
||||
|
||||
<?php $__env->startSection('content'); ?>
|
||||
<div class="container" style="padding:20px;">
|
||||
<div class="page-intro">
|
||||
<h1>Request Custom Design</h1>
|
||||
<p>Create a custom wallpaper, mural, or fabric design tailored to your needs</p>
|
||||
</div>
|
||||
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php if($errors->any()): ?>
|
||||
<div style="background-color: #f8d7da; border: 1px solid var(--border-color); color: var(--text-primary); padding: var(--spacing-md); border-radius: 8px; margin-bottom: var(--spacing-lg);">
|
||||
<h4 style="margin-top: 0;">Please correct the following errors:</h4>
|
||||
<ul>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__currentLoopData = $errors->all(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $error): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||
<li><?php echo e($error); ?></li>
|
||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php if(session('success')): ?>
|
||||
<div style="background-color: var(--accent-light); border: 1px solid var(--border-color); color: var(--text-primary); padding: var(--spacing-md); border-radius: 8px; margin-bottom: var(--spacing-lg);">
|
||||
✓ <?php echo e(session('success')); ?>
|
||||
|
||||
</div>
|
||||
<?php endif; ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
|
||||
<!-- Info Box -->
|
||||
<div class="info-box card--pink">
|
||||
<h2>How It Works</h2>
|
||||
<ul>
|
||||
<li>Submit your custom order with design specifications and reference images</li>
|
||||
<li>Pay a 20% non-refundable deposit to commence design work</li>
|
||||
<li>Our team creates your design and prepares proofs for review</li>
|
||||
<li>Pay the remaining 80% balance to proceed with printing and shipping</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="form-wrapper">
|
||||
<form action="<?php echo e(route('custom-orders.store')); ?>" method="POST" enctype="multipart/form-data" id="custom-order-form" class="form-card card" data-action="<?php echo e(route('custom-orders.store')); ?>">
|
||||
<?php echo csrf_field(); ?>
|
||||
|
||||
<!-- Order Type & Dimensions -->
|
||||
<div class="form-section">
|
||||
<h2>Order Details</h2>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="type">Order Type *</label>
|
||||
<select id="type" name="type" required>
|
||||
<option value="">-- Select a type --</option>
|
||||
<option value="wallpaper" <?php echo e(old('type') == 'wallpaper' ? 'selected' : ''); ?>>Wallpaper (tileable pattern)</option>
|
||||
<option value="mural" <?php echo e(old('type') == 'mural' ? 'selected' : ''); ?>>Mural (large format)</option>
|
||||
<option value="fabric" <?php echo e(old('type') == 'fabric' ? 'selected' : ''); ?>>Fabric (linear meter)</option>
|
||||
</select>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['type'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="width">Width (meters) *</label>
|
||||
<input type="number" id="width" name="width" step="0.01" min="0.1" value="<?php echo e(old('width')); ?>" required>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['width'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="height">Height (meters) *</label>
|
||||
<input type="number" id="height" name="height" step="0.01" min="0.1" value="<?php echo e(old('height')); ?>" required>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['height'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="quantity">Quantity *</label>
|
||||
<input type="number" id="quantity" name="quantity" value="<?php echo e(old('quantity', 1)); ?>" min="1" required>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['quantity'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="print_stock_id">Print Material *</label>
|
||||
<select id="print_stock_id" name="print_stock_id" required>
|
||||
<option value="">-- Select material --</option>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__currentLoopData = $printStocks; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $stock): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||
<option value="<?php echo e($stock->id); ?>" <?php echo e(old('print_stock_id') == $stock->id ? 'selected' : ''); ?>>
|
||||
<?php echo e($stock->name); ?> (<?php echo e($stock->cost_per_meter ? 'R' . number_format($stock->cost_per_meter, 2) . '/m' : 'R' . number_format($stock->cost_per_m2, 2) . '/m²'); ?>)
|
||||
</option>
|
||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</select>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['print_stock_id'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Design Brief -->
|
||||
<div class="form-section">
|
||||
<h2>Design Brief</h2>
|
||||
|
||||
<div class="form-group form-row full">
|
||||
<label for="customer_brief">Design Brief (minimum 50 characters) *</label>
|
||||
<p class="form-group-hint">Tell us about your design concept, colors, style, and any specific requirements</p>
|
||||
<textarea id="customer_brief" name="customer_brief" placeholder="Describe your custom design vision..." minlength="50" required><?php echo e(old('customer_brief')); ?></textarea>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['customer_brief'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-row full">
|
||||
<label for="special_instructions">Special Instructions (optional)</label>
|
||||
<textarea id="special_instructions" name="special_instructions" placeholder="Any additional notes or requirements..."><?php echo e(old('special_instructions')); ?></textarea>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['special_instructions'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reference Images -->
|
||||
<div class="form-section">
|
||||
<h2>Reference Images</h2>
|
||||
|
||||
<div class="form-group form-row full">
|
||||
<label>Upload Reference Images</label>
|
||||
<p class="form-group-hint">Upload inspiration images, mood boards, or reference materials for your design</p>
|
||||
<div class="upload-area" onclick="document.getElementById('reference-images').click()">
|
||||
<input type="file" id="reference-images" name="reference_images[]" multiple accept="image/*" style="display: none;">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 48 48">
|
||||
<path d="M28 8H12a4 4 0 00-4 4v20m32-12v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-12l-3.172-3.172a4 4 0 00-5.656 0L28 12M12 32l3.172-3.172a4 4 0 015.656 0L32 32" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
<p style="margin: 0;">Click to upload or drag and drop</p>
|
||||
<p class="hint">PNG, JPG, GIF, WebP up to 5MB</p>
|
||||
</div>
|
||||
<div id="file-list"></div>
|
||||
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php endif; ?><?php $__errorArgs = ['reference_images.*'];
|
||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||
if ($__bag->has($__errorArgs[0])) :
|
||||
if (isset($message)) { $__messageOriginal = $message; }
|
||||
$message = $__bag->first($__errorArgs[0]); ?>
|
||||
<p class="error-message"><?php echo e($message); ?></p>
|
||||
<?php unset($message);
|
||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||
endif;
|
||||
unset($__errorArgs, $__bag); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Library Agreement -->
|
||||
<div class="form-section">
|
||||
<h2>Design Library</h2>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<label class="checkbox-option">
|
||||
<input type="checkbox" name="library_discount" value="1" <?php echo e(old('library_discount') ? 'checked' : ''); ?>>
|
||||
<div class="checkbox-content">
|
||||
<p style="font-weight: 600; margin-bottom: 0.25rem;">Allow us to use your design in our library</p>
|
||||
<p>If you agree, we'll apply a <strong>20% discount to the design fee</strong>. This means we may offer similar designs to other customers in the future.</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="button-group">
|
||||
<button type="submit" class="btn">Submit Order</button>
|
||||
<a href="<?php echo e(route('my-orders')); ?>" class="btn btn-cancel">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Cost Summary Sidebar -->
|
||||
<div class="cost-summary">
|
||||
<div class="cost-summary-content card">
|
||||
<h3>Cost Summary</h3>
|
||||
|
||||
<div class="cost-item disabled" id="material-cost-item">
|
||||
<span class="cost-label">Material Cost</span>
|
||||
<span class="cost-value">-</span>
|
||||
</div>
|
||||
|
||||
<div class="cost-item disabled" id="design-fee-item">
|
||||
<span class="cost-label">Design Fee</span>
|
||||
<span class="cost-value">-</span>
|
||||
</div>
|
||||
|
||||
<div class="cost-item disabled" id="discount-item" style="display: none;">
|
||||
<span class="cost-label">Library Discount</span>
|
||||
<span class="cost-value">-</span>
|
||||
</div>
|
||||
|
||||
<div class="cost-item total">
|
||||
<span>Deposit Required (20%)</span>
|
||||
<span class="cost-value" id="deposit-amount">R0.00</span>
|
||||
</div>
|
||||
|
||||
<div class="design-fee-note">
|
||||
<strong>Note:</strong> 20% non-refundable deposit covers design work. Pay the remaining 80% after proof approval.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding: 1.5rem; margin-bottom: 1rem; background: var(--accent-light);">
|
||||
<p style="margin: 0 0 0.5rem 0; color: black;">Estimated Total:</p>
|
||||
<div style="font-family: 'Abril Fatface', cursive; font-size: 3rem; font-weight: 400; color: white;">R<span id="total-cost">0.00</span></div>
|
||||
<small style="color: #fff; display: block; margin-top: 0.5rem;">incl. VAT</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Total Cost Display -->
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('=== CUSTOM ORDER FORM DEBUG ===');
|
||||
|
||||
const form = document.getElementById('custom-order-form');
|
||||
console.log('Form element:', form);
|
||||
console.log('Form action:', form.action);
|
||||
console.log('Form method:', form.method);
|
||||
console.log('Form enctype:', form.enctype);
|
||||
console.log('Form ID:', form.id);
|
||||
console.log('Form classes:', form.className);
|
||||
|
||||
if (!form) {
|
||||
console.error('FORM NOT FOUND!');
|
||||
return;
|
||||
}
|
||||
|
||||
// ===== COST CALCULATION =====
|
||||
const DESIGN_FEE = 500; // Base design fee in Rands
|
||||
const DISCOUNT_PERCENTAGE = 0.20; // 20% discount for library usage
|
||||
|
||||
// Get form inputs
|
||||
const typeSelect = document.getElementById('type');
|
||||
const widthInput = document.getElementById('width');
|
||||
const heightInput = document.getElementById('height');
|
||||
const quantityInput = document.getElementById('quantity');
|
||||
const stockSelect = document.getElementById('print_stock_id');
|
||||
const libraryCheckbox = document.querySelector('input[name="library_discount"]');
|
||||
|
||||
// Get summary elements
|
||||
const materialCostItem = document.getElementById('material-cost-item');
|
||||
const designFeeItem = document.getElementById('design-fee-item');
|
||||
const discountItem = document.getElementById('discount-item');
|
||||
const depositAmount = document.getElementById('deposit-amount');
|
||||
|
||||
// Store print stocks data
|
||||
const printStocksData = {};
|
||||
<?php $__currentLoopData = $printStocks; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $stock): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||
printStocksData[<?php echo e($stock->id); ?>] = {
|
||||
name: '<?php echo e($stock->name); ?>',
|
||||
width: <?php echo e($stock->width ?? 0.53); ?>,
|
||||
costPerMeter: <?php echo e($stock->cost_per_meter ?? 0); ?>,
|
||||
costPerM2: <?php echo e($stock->cost_per_m2 ?? 0); ?>
|
||||
|
||||
};
|
||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||
|
||||
function calculateCosts() {
|
||||
const type = typeSelect.value;
|
||||
const width = parseFloat(widthInput.value) || 0;
|
||||
const height = parseFloat(heightInput.value) || 0;
|
||||
const quantity = parseFloat(quantityInput.value) || 1;
|
||||
const stockId = stockSelect.value;
|
||||
const hasLibraryDiscount = libraryCheckbox?.checked || false;
|
||||
|
||||
if (!type || !stockId || width <= 0 || height <= 0) {
|
||||
// Show disabled state
|
||||
materialCostItem.classList.add('disabled');
|
||||
designFeeItem.classList.add('disabled');
|
||||
discountItem.style.display = 'none';
|
||||
depositAmount.textContent = 'R0.00';
|
||||
document.getElementById('total-cost').textContent = '0.00';
|
||||
document.getElementById('cost-breakdown').textContent = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const stock = printStocksData[stockId];
|
||||
if (!stock) return;
|
||||
|
||||
// Calculate material cost based on type
|
||||
let materialCost = 0;
|
||||
let breakdown = '';
|
||||
|
||||
if (type === 'wallpaper') {
|
||||
// Wallpaper: Takes into account stock width
|
||||
// Calculate number of vertical strips needed: ceil(wall_height / stock_width)
|
||||
// Calculate total length: number_of_strips × wall_width
|
||||
// Cost = total_length × cost_per_meter × quantity
|
||||
const stockWidth = stock.width || 0.53; // Default to standard wallpaper width if not specified
|
||||
const stripsNeeded = Math.ceil(height / stockWidth);
|
||||
const totalLength = stripsNeeded * width;
|
||||
materialCost = totalLength * stock.costPerMeter * quantity;
|
||||
breakdown = `Stock: R${stock.costPerMeter.toFixed(2)}/m × ${totalLength.toFixed(2)}m`;
|
||||
} else if (type === 'mural') {
|
||||
// Mural: width × height in m²
|
||||
// Cost = cost_per_m2 × (width × height) × quantity
|
||||
const area = width * height;
|
||||
materialCost = area * stock.costPerM2 * quantity;
|
||||
breakdown = `Stock: R${stock.costPerM2.toFixed(2)}/m² × ${area.toFixed(2)}m²`;
|
||||
} else if (type === 'fabric') {
|
||||
// Fabric: width input = length in linear meters
|
||||
// Cost = cost_per_meter × length × quantity
|
||||
materialCost = width * stock.costPerMeter * quantity;
|
||||
breakdown = `Stock: R${stock.costPerMeter.toFixed(2)}/m × ${width.toFixed(2)}m`;
|
||||
}
|
||||
|
||||
// Calculate design fee
|
||||
let designFee = DESIGN_FEE;
|
||||
let discount = 0;
|
||||
|
||||
if (hasLibraryDiscount) {
|
||||
discount = designFee * DISCOUNT_PERCENTAGE;
|
||||
designFee -= discount;
|
||||
}
|
||||
|
||||
// Total cost
|
||||
const totalCost = materialCost + designFee;
|
||||
const depositRequired = totalCost * 0.20; // 20% deposit
|
||||
const remainingBalance = totalCost * 0.80; // 80% remaining
|
||||
|
||||
// Update UI
|
||||
materialCostItem.classList.remove('disabled');
|
||||
materialCostItem.innerHTML = `<span class="cost-label">Material Cost</span><span class="cost-value">R${materialCost.toFixed(2)}</span>`;
|
||||
|
||||
designFeeItem.classList.remove('disabled');
|
||||
designFeeItem.innerHTML = `<span class="cost-label">Design Fee</span><span class="cost-value">R${designFee.toFixed(2)}</span>`;
|
||||
|
||||
if (hasLibraryDiscount && discount > 0) {
|
||||
discountItem.style.display = 'flex';
|
||||
discountItem.classList.add('discount');
|
||||
discountItem.innerHTML = `<span class="cost-label">Library Discount (20%)</span><span class="cost-value">-R${discount.toFixed(2)}</span>`;
|
||||
} else {
|
||||
discountItem.style.display = 'none';
|
||||
}
|
||||
|
||||
depositAmount.textContent = `R${depositRequired.toFixed(2)}`;
|
||||
document.getElementById('total-cost').textContent = `${totalCost.toFixed(2)}`;
|
||||
document.getElementById('cost-breakdown').textContent = breakdown;
|
||||
}
|
||||
|
||||
// Add event listeners for cost calculation
|
||||
if (typeSelect) typeSelect.addEventListener('change', calculateCosts);
|
||||
if (widthInput) widthInput.addEventListener('input', calculateCosts);
|
||||
if (heightInput) heightInput.addEventListener('input', calculateCosts);
|
||||
if (quantityInput) quantityInput.addEventListener('input', calculateCosts);
|
||||
if (stockSelect) stockSelect.addEventListener('change', calculateCosts);
|
||||
if (libraryCheckbox) libraryCheckbox.addEventListener('change', calculateCosts);
|
||||
|
||||
// Update field labels based on type
|
||||
function updateFieldLabels() {
|
||||
const type = typeSelect.value;
|
||||
const widthLabel = document.querySelector('label[for="width"]');
|
||||
const heightLabel = document.querySelector('label[for="height"]');
|
||||
const heightGroup = heightInput?.parentElement;
|
||||
|
||||
if (type === 'wallpaper') {
|
||||
if (widthLabel) widthLabel.innerHTML = 'Wall Width (meters) *';
|
||||
if (heightLabel) heightLabel.innerHTML = 'Wall Height (meters) *<br><small style="font-weight: normal; color: var(--text-secondary); display: block; margin-top: 0.25rem;">The system will calculate strips needed based on stock width</small>';
|
||||
if (heightGroup) heightGroup.style.display = 'block';
|
||||
} else if (type === 'mural') {
|
||||
if (widthLabel) widthLabel.textContent = 'Width (meters) *';
|
||||
if (heightGroup) heightGroup.style.display = 'block';
|
||||
if (heightLabel) heightLabel.textContent = 'Height (meters) *';
|
||||
} else if (type === 'fabric') {
|
||||
if (widthLabel) widthLabel.textContent = 'Length (meters) *';
|
||||
if (heightGroup) heightGroup.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (typeSelect) {
|
||||
typeSelect.addEventListener('change', updateFieldLabels);
|
||||
}
|
||||
|
||||
// Initial label update
|
||||
updateFieldLabels();
|
||||
|
||||
// Initial calculation
|
||||
calculateCosts();
|
||||
|
||||
// Handle reference image uploads
|
||||
const referenceImagesInput = document.getElementById('reference-images');
|
||||
if (referenceImagesInput) {
|
||||
referenceImagesInput.addEventListener('change', function() {
|
||||
const fileList = document.getElementById('file-list');
|
||||
if (fileList) {
|
||||
fileList.innerHTML = '';
|
||||
|
||||
for (let file of this.files) {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'file-item';
|
||||
item.innerHTML = `<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4z" clip-rule="evenodd"/></svg><span>${file.name}</span>`;
|
||||
fileList.appendChild(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Find the submit button and log when it's clicked
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
if (submitBtn) {
|
||||
console.log('Submit button found:', submitBtn);
|
||||
submitBtn.addEventListener('click', function(e) {
|
||||
console.log('===== SUBMIT BUTTON CLICKED =====');
|
||||
console.log('Event:', e);
|
||||
console.log('Form will submit to:', form.action);
|
||||
});
|
||||
}
|
||||
|
||||
// Handle form submission - FORCE IT TO SUBMIT
|
||||
form.addEventListener('submit', function(e) {
|
||||
console.log('===== FORM SUBMIT EVENT FIRED =====');
|
||||
console.log('Event type:', e.type);
|
||||
console.log('Event defaultPrevented:', e.defaultPrevented);
|
||||
console.log('Action:', form.action);
|
||||
console.log('Method:', form.method);
|
||||
console.log('About to submit to:', form.action);
|
||||
console.log('Checking if global script should skip this form...');
|
||||
console.log('Form action includes /custom-orders:', form.action.includes('/custom-orders'));
|
||||
// Don't prevent - let it submit naturally
|
||||
});
|
||||
|
||||
console.log('Event listeners attached successfully');
|
||||
});
|
||||
</script>
|
||||
<?php $__env->stopSection(); ?>
|
||||
<?php echo $__env->make('layouts.app', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/additional_design/resources/views/custom-orders/create.blade.php ENDPATH**/ ?>
|
||||
Reference in New Issue
Block a user