DHL Modul v0.5 Shipping Label ok
This commit is contained in:
parent
480fdc65ed
commit
8fdaa0ba1d
122 changed files with 17938 additions and 2239 deletions
498
resources/views/admin/dhl/modal_create_shipment.blade.php
Normal file
498
resources/views/admin/dhl/modal_create_shipment.blade.php
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
{{--
|
||||
DHL Shipment Creation Modal
|
||||
|
||||
This view is optimized to work with data prepared by DhlModalService.
|
||||
The service handles address parsing, validation, and data preparation.
|
||||
--}}
|
||||
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-shipping-fast text-primary"></i>
|
||||
DHL Sendung erstellen
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- Display any errors at the top --}}
|
||||
@if(!empty($errors))
|
||||
<div class="alert alert-danger mx-3 mt-3">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<strong>Fehler:</strong>
|
||||
<ul class="mb-0 mt-1">
|
||||
@foreach($errors as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Display warnings --}}
|
||||
@if(!empty($warnings))
|
||||
<div class="alert alert-warning mx-3 mt-3">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<strong>Achtung:</strong>
|
||||
<ul class="mb-0 mt-1">
|
||||
@foreach($warnings as $warning)
|
||||
<li>{{ $warning }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($order)
|
||||
<form id="modal-create-shipment-form" method="POST" action="{{ route('admin.dhl.store') }}">
|
||||
@csrf
|
||||
<input type="hidden" name="order_id" value="{{ $order->id }}">
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
{{-- Left Column: Order Info --}}
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-primary mb-3">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Bestellinformationen
|
||||
</h6>
|
||||
|
||||
<div class="card bg-light">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Bestellung #{{ $order->id }}</h6>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<small class="text-muted d-block">Kunde:</small>
|
||||
<strong>{{ $order->shopping_user->billing_firstname ?? '' }} {{ $order->shopping_user->billing_lastname ?? '' }}</strong>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<small class="text-muted d-block">Datum:</small>
|
||||
<strong>{{ $order->created_at->format('d.m.Y') }}</strong>
|
||||
</div>
|
||||
<div class="col-6 mt-2">
|
||||
<small class="text-muted d-block">Wert:</small>
|
||||
<strong>{{ number_format($order->total, 2) }} €</strong>
|
||||
</div>
|
||||
<div class="col-6 mt-2">
|
||||
<small class="text-muted d-block">Artikel:</small>
|
||||
<strong>{{ $order->shopping_order_items->count() }} Stück</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Right Column: Shipment Config --}}
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-primary mb-3">
|
||||
<i class="fas fa-cog"></i>
|
||||
Sendungskonfiguration
|
||||
</h6>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="modal-weight" class="font-weight-semibold">
|
||||
<i class="fas fa-weight"></i>
|
||||
Gewicht (kg) <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
id="modal-weight"
|
||||
name="weight"
|
||||
min="0.1"
|
||||
max="31.5"
|
||||
step="0.1"
|
||||
value="{{ number_format($orderWeight, 1) }}"
|
||||
required>
|
||||
<small class="form-text text-muted">
|
||||
Berechnet: {{ number_format($orderWeight, 1) }} kg
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="modal-product-code" class="font-weight-semibold">
|
||||
<i class="fas fa-cube"></i>
|
||||
Produktcode
|
||||
</label>
|
||||
<select class="form-control custom-select" id="modal-product-code" name="product_code">
|
||||
@foreach($productCodes as $code => $name)
|
||||
<option value="{{ $code }}">{{ $code }} - {{ $name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="modal-priority" class="font-weight-semibold">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Priorität
|
||||
</label>
|
||||
<select class="form-control custom-select" id="modal-priority" name="priority">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="high">Hoch</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox"
|
||||
class="custom-control-input"
|
||||
id="modal-auto-track"
|
||||
name="auto_track"
|
||||
value="1"
|
||||
checked>
|
||||
<label class="custom-control-label" for="modal-auto-track">
|
||||
Automatisches Tracking
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{{-- Shipping Address Section --}}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h6 class="text-primary mb-3">
|
||||
<i class="fas fa-map-marker-alt"></i>
|
||||
Lieferadresse
|
||||
@if(!empty($warnings))
|
||||
<small class="text-warning">(Bitte Adresse prüfen)</small>
|
||||
@else
|
||||
<small class="text-muted">(zur Not anpassbar)</small>
|
||||
@endif
|
||||
</h6>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="shipping_firstname">Vorname <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['firstname']) ? 'is-invalid' : '' }}"
|
||||
name="shipping_firstname"
|
||||
id="shipping_firstname"
|
||||
value="{{ $shippingAddress['firstname'] ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="shipping_lastname">Nachname <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['lastname']) ? 'is-invalid' : '' }}"
|
||||
name="shipping_lastname"
|
||||
id="shipping_lastname"
|
||||
value="{{ $shippingAddress['lastname'] ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="shipping_company">Firma <small class="text-muted">(optional)</small></label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="shipping_company"
|
||||
id="shipping_company"
|
||||
value="{{ $shippingAddress['company'] ?? '' }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<label for="shipping_address">Straße <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['address']) ? 'is-invalid' : '' }}"
|
||||
name="shipping_address"
|
||||
id="shipping_address"
|
||||
value="{{ $shippingAddress['address'] ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="shipping_houseNumber">Nr./Zusatz <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['houseNumber']) ? 'border-warning' : '' }}"
|
||||
name="shipping_houseNumber"
|
||||
id="shipping_houseNumber"
|
||||
value="{{ $shippingAddress['houseNumber'] ?? '' }}"
|
||||
required>
|
||||
@if(empty($shippingAddress['houseNumber']))
|
||||
<small class="text-warning">Hausnummer benötigt</small>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="shipping_zipcode">PLZ <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['zipcode']) ? 'is-invalid' : '' }}"
|
||||
name="shipping_zipcode"
|
||||
id="shipping_zipcode"
|
||||
value="{{ $shippingAddress['zipcode'] ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<label for="shipping_city">Ort <span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control {{ empty($shippingAddress['city']) ? 'is-invalid' : '' }}"
|
||||
name="shipping_city"
|
||||
id="shipping_city"
|
||||
value="{{ $shippingAddress['city'] ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="shipping_country">Land <span class="text-danger">*</span></label>
|
||||
<select class="form-control custom-select" name="shipping_country_id" id="shipping_country" required>
|
||||
@foreach($availableCountries as $countryOption)
|
||||
<option value="{{ $countryOption->id }}"
|
||||
{{ $shippingAddress['country'] && $shippingAddress['country']->id == $countryOption->id ? 'selected' : '' }}>
|
||||
{{ $countryOption->getLocated() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="shipping_phone">Telefon <small class="text-muted">(empfohlen)</small></label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="shipping_phone"
|
||||
id="shipping_phone"
|
||||
value="{{ $shippingAddress['phone'] ?? '' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fas fa-times"></i> Abbrechen
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" id="create-shipment-btn" {{ !empty($errors) ? 'disabled' : '' }}>
|
||||
<i class="fas fa-shipping-fast"></i> Sendung erstellen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@else
|
||||
{{-- Order Selection when no order ID provided --}}
|
||||
<div class="modal-body">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-search fa-3x text-primary mb-4"></i>
|
||||
<h4>Bestellung auswählen</h4>
|
||||
<p class="text-muted mb-4">Geben Sie eine Bestellungs-ID ein, um eine DHL-Sendung zu erstellen.</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 mx-auto">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">#</span>
|
||||
</div>
|
||||
<input type="number"
|
||||
class="form-control form-control-lg"
|
||||
id="order-id-input"
|
||||
placeholder="z.B. 12345"
|
||||
min="1">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="button" id="load-order-btn">
|
||||
<i class="fas fa-search"></i> Laden
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<div class="mb-3">oder</div>
|
||||
<a href="{{ route('admin_sales_customers') }}"
|
||||
target="_blank"
|
||||
class="btn btn-outline-secondary">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
In Bestellverwaltung suchen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fas fa-times"></i> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
@if(!$order)
|
||||
// Load order functionality
|
||||
$('#load-order-btn').click(function() {
|
||||
var orderId = $('#order-id-input').val();
|
||||
|
||||
if (!orderId || orderId < 1) {
|
||||
alert('Bitte geben Sie eine gültige Bestellungs-ID ein.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Reload modal with order ID
|
||||
var btn = $(this);
|
||||
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Laden...');
|
||||
|
||||
$.post('{{ route('modal_load') }}', {
|
||||
action: 'create-dhl-shipment',
|
||||
id: orderId,
|
||||
_token: '{{ csrf_token() }}'
|
||||
}).done(function(response) {
|
||||
console.log(response);
|
||||
$('#modals-load-content .modal-dialog').html(response.html);
|
||||
}).fail(function() {
|
||||
alert('Bestellung konnte nicht geladen werden.');
|
||||
btn.prop('disabled', false).html('<i class="fas fa-search"></i> Laden');
|
||||
});
|
||||
});
|
||||
|
||||
// Enter key handling
|
||||
$('#order-id-input').keypress(function(e) {
|
||||
if (e.which === 13) {
|
||||
$('#load-order-btn').click();
|
||||
}
|
||||
});
|
||||
@endif
|
||||
|
||||
@if($order)
|
||||
// Form submission with improved validation
|
||||
$('#modal-create-shipment-form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var form = $(this);
|
||||
var formData = form.serialize();
|
||||
var submitBtn = $('#create-shipment-btn');
|
||||
|
||||
// Client-side validation
|
||||
var isValid = validateForm();
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable submit button
|
||||
submitBtn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird erstellt...');
|
||||
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Close modal
|
||||
$('#modals-load-content').modal('hide');
|
||||
|
||||
// Show success message and reload
|
||||
if (typeof showAlert === 'function') {
|
||||
showAlert('success', response.message);
|
||||
} else {
|
||||
alert(response.message);
|
||||
}
|
||||
|
||||
// Reload page after 2 seconds
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 2000);
|
||||
} else {
|
||||
alert(response.message || 'Fehler beim Erstellen der Sendung.');
|
||||
submitBtn.prop('disabled', false).html('<i class="fas fa-shipping-fast"></i> Sendung erstellen');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
var errorMessage = 'Fehler beim Erstellen der Sendung.';
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
errorMessage = xhr.responseJSON.message;
|
||||
} else if (xhr.responseText) {
|
||||
try {
|
||||
var errorData = JSON.parse(xhr.responseText);
|
||||
if (errorData.errors) {
|
||||
errorMessage = Object.values(errorData.errors).flat().join(', ');
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore JSON parse errors
|
||||
}
|
||||
}
|
||||
|
||||
alert(errorMessage);
|
||||
submitBtn.prop('disabled', false).html('<i class="fas fa-shipping-fast"></i> Sendung erstellen');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Enhanced form validation
|
||||
function validateForm() {
|
||||
var isValid = true;
|
||||
|
||||
// Clear previous validation states
|
||||
$('.form-control').removeClass('is-invalid');
|
||||
$('.invalid-feedback').remove();
|
||||
|
||||
// Weight validation
|
||||
var weight = parseFloat($('#modal-weight').val());
|
||||
if (!weight || weight < 0.1 || weight > 31.5) {
|
||||
$('#modal-weight').addClass('is-invalid').after('<div class="invalid-feedback">Gewicht muss zwischen 0.1 und 31.5 kg liegen.</div>');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// Required fields validation
|
||||
var requiredFields = [
|
||||
'#shipping_firstname',
|
||||
'#shipping_lastname',
|
||||
'#shipping_address',
|
||||
'#shipping_zipcode',
|
||||
'#shipping_city'
|
||||
];
|
||||
|
||||
requiredFields.forEach(function(fieldId) {
|
||||
var field = $(fieldId);
|
||||
if (!field.val().trim()) {
|
||||
field.addClass('is-invalid').after('<div class="invalid-feedback">Dieses Feld ist erforderlich.</div>');
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// Real-time weight validation
|
||||
$('#modal-weight').on('input', function() {
|
||||
var weight = parseFloat($(this).val());
|
||||
var input = $(this);
|
||||
|
||||
input.removeClass('is-invalid');
|
||||
input.siblings('.invalid-feedback').remove();
|
||||
|
||||
if (weight && (weight < 0.1 || weight > 31.5)) {
|
||||
input.addClass('is-invalid');
|
||||
if (weight < 0.1) {
|
||||
input.after('<div class="invalid-feedback">Mindestgewicht: 0.1 kg</div>');
|
||||
} else {
|
||||
input.after('<div class="invalid-feedback">Maximalgewicht: 31.5 kg</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time required field validation
|
||||
$('input[required], select[required]').on('blur', function() {
|
||||
var field = $(this);
|
||||
if (!field.val().trim()) {
|
||||
field.addClass('is-invalid');
|
||||
if (!field.siblings('.invalid-feedback').length) {
|
||||
field.after('<div class="invalid-feedback">Dieses Feld ist erforderlich.</div>');
|
||||
}
|
||||
} else {
|
||||
field.removeClass('is-invalid');
|
||||
field.siblings('.invalid-feedback').remove();
|
||||
}
|
||||
});
|
||||
@endif
|
||||
});
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue