23-01-2026

This commit is contained in:
Kevin Adametz 2026-01-23 17:35:23 +01:00
parent a939cd51ef
commit a8b395e20d
248 changed files with 29342 additions and 4805 deletions

View file

@ -205,6 +205,16 @@
@endsection
@section('scripts')
<style>
/* Highlight return shipments */
#dhl-shipments-table tbody tr.return-shipment {
background-color: rgba(255, 193, 7, 0.08) !important;
border-left: 3px solid #ffc107;
}
#dhl-shipments-table tbody tr.return-shipment:hover {
background-color: rgba(255, 193, 7, 0.15) !important;
}
</style>
<script>
$(document).ready(function() {
// DataTable initialization
@ -245,6 +255,7 @@ $(document).ready(function() {
// Re-initialize tooltips on each table draw
drawCallback: function () {
$('[data-toggle="tooltip"]').tooltip();
// Row classes are now added automatically by DataTables via DT_RowClass
}
});
@ -414,11 +425,15 @@ $(document).ready(function() {
$('#dhl-shipments-table').on('click', '.create-return-btn', function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Möchten Sie ein Retourenlabel für diese Sendung erstellen?')) {
return;
}
// Disable button to prevent double-click
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/return-label`,
method: 'POST',
@ -428,20 +443,25 @@ $(document).ready(function() {
success: function(response) {
if (response.success) {
showAlert('success', response.message);
location.reload();
setTimeout(function() {
location.reload();
}, 1500);
} else {
showAlert('error', response.message);
btn.prop('disabled', false).html('<i class="fas fa-undo"></i>');
}
},
error: function(xhr) {
showAlert('error', 'Fehler beim Erstellen des Retourenlabels.');
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Erstellen des Retourenlabels.';
showAlert('error', errorMsg);
btn.prop('disabled', false).html('<i class="fas fa-undo"></i>');
}
});
});
$('#dhl-shipments-table').on('click', '.update-tracking-btn', function() {
var shipmentId = $(this).data('shipment-id');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/update-tracking`,
method: 'POST',
@ -463,6 +483,114 @@ $(document).ready(function() {
}
});
});
// Send tracking email button
$('#dhl-shipments-table').on('click', '.send-tracking-email-btn', function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Möchten Sie die Tracking-E-Mail an den Kunden senden?')) {
return;
}
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/send-tracking-email`,
method: 'POST',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
showAlert('success', response.message);
btn.removeClass('btn-outline-info').addClass('btn-success');
btn.html('<i class="fas fa-envelope"></i>');
btn.attr('title', 'E-Mail gesendet: ' + response.sent_at);
} else {
showAlert('error', response.message);
btn.prop('disabled', false).html('<i class="fas fa-envelope"></i>');
}
},
error: function(xhr) {
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Senden der E-Mail.';
showAlert('error', errorMsg);
btn.prop('disabled', false).html('<i class="fas fa-envelope"></i>');
}
});
});
// Cancel shipment button
$('#dhl-shipments-table').on('click', '.cancel-shipment-btn', function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Möchten Sie diese Sendung wirklich stornieren?\n\nDas Label wird bei DHL ungültig und kann nicht mehr verwendet werden.')) {
return;
}
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/cancel`,
method: 'DELETE',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
showAlert('success', response.message || 'Sendung wird storniert...');
setTimeout(function() {
table.ajax.reload();
}, 2000);
} else {
showAlert('error', response.message);
btn.prop('disabled', false).html('<i class="fas fa-ban"></i>');
}
},
error: function(xhr) {
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Stornieren der Sendung.';
showAlert('error', errorMsg);
btn.prop('disabled', false).html('<i class="fas fa-ban"></i>');
}
});
});
// Create return label button
$('#dhl-shipments-table').on('click', '.create-return-btn', function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Möchten Sie ein Retourenlabel für diese Sendung erstellen?')) {
return;
}
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/return-label`,
method: 'POST',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
showAlert('success', response.message || 'Retourenlabel wird erstellt...');
setTimeout(function() {
table.ajax.reload();
}, 2000);
} else {
showAlert('error', response.message);
btn.prop('disabled', false).html('<i class="fas fa-undo"></i>');
}
},
error: function(xhr) {
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Erstellen des Retourenlabels.';
showAlert('error', errorMsg);
btn.prop('disabled', false).html('<i class="fas fa-undo"></i>');
}
});
});
// Remove old auto-submit logic
/*
@ -474,6 +602,9 @@ $(document).ready(function() {
// Alert helper function
function showAlert(type, message) {
// Remove any existing alerts first to prevent duplicates
$('.alert.alert-dismissible').remove();
var alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
var alertHtml = `
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">

View file

@ -190,6 +190,41 @@
value="{{ $shippingAddress['phone'] ?? '' }}">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="shipping_email">E-Mail <span class="text-danger">*</span></label>
<input type="email"
class="form-control {{ empty($shippingAddress['email']) ? 'border-warning' : '' }}"
name="shipping_email"
id="shipping_email"
value="{{ $shippingAddress['email'] ?? $order->shopping_user->email ?? '' }}"
required>
<small class="form-text text-muted">
Wird für DHL Benachrichtigungen und Tracking-E-Mails verwendet.
</small>
</div>
</div>
{{-- DHL Packstation/Paketbox --}}
<div class="col-md-12 mt-2">
<hr>
<h6 class="text-muted mb-2">
<i class="fas fa-cube"></i>
Packstation / Paketbox
<small class="text-muted">(nur wenn zutreffend)</small>
</h6>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="shipping_postnumber">DHL Postnummer <small class="text-muted">(optional)</small></label>
<input type="text" class="form-control" name="shipping_postnumber" id="shipping_postnumber"
value="{{ $shippingAddress['postnumber'] ?? '' }}" maxlength="20"
placeholder="z.B. 12345678">
<small class="form-text text-muted">
Nur bei Lieferung an Packstation/Paketbox. Im Feld "Straße" dann "Packstation XXX" eintragen.
</small>
</div>
</div>
</div>
</div>
</div>

View file

@ -147,6 +147,14 @@
</a>
@endif
@if($shipment['can_send_email'] ?? false)
<button type="button"
class="btn btn-info btn-sm mb-2 send-tracking-email-modal-btn"
data-shipment-id="{{ $shipment['id'] }}">
<i class="fas fa-envelope"></i> Tracking-E-Mail senden
</button>
@endif
<a href="{{ route('admin.dhl.show', $shipment['id']) }}"
class="btn btn-outline-primary btn-sm mb-2" target="_blank">
<i class="fas fa-eye"></i> Details anzeigen
@ -302,5 +310,42 @@ window.showAlert = function(type, message) {
// Initialize modal
$(document).ready(function() {
// Modal is ready for interaction
// Tracking E-Mail senden Button
$(document).on('click', '.send-tracking-email-modal-btn', function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Tracking-E-Mail an den Kunden senden?')) {
return;
}
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird gesendet...');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/send-tracking-email`,
method: 'POST',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
showAlert('success', response.message);
btn.removeClass('btn-info').addClass('btn-success')
.html('<i class="fas fa-check"></i> E-Mail gesendet');
} else {
showAlert('error', response.message);
btn.prop('disabled', false).html('<i class="fas fa-envelope"></i> Tracking-E-Mail senden');
}
},
error: function(xhr) {
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Senden der E-Mail.';
showAlert('error', errorMsg);
btn.prop('disabled', false).html('<i class="fas fa-envelope"></i> Tracking-E-Mail senden');
}
});
});
});
</script>

View file

@ -4,11 +4,11 @@
<div class="d-flex justify-content-between align-items-center py-2 mb-4">
<h4 class="font-weight-bold mb-0">
<i class="fas fa-box text-primary"></i>
<i class="fas fa-box {{ $shipment->type == 'return' ? 'text-warning' : 'text-primary' }}"></i>
DHL Sendung #{{ $shipment->id }}
@if($shipment->type == 'return')
<span class="badge badge-info ml-2">
<i class="fas fa-undo"></i> Retoure
<span class="badge badge-warning ml-2" style="font-size: 1rem; font-weight: 700; padding: 0.5rem 1rem;">
<i class="fas fa-undo"></i> RETOURE
</span>
@endif
</h4>
@ -157,17 +157,8 @@
<i class="fas fa-download"></i> Label herunterladen
</a>
@endif
{{-- Todo: Add tracking button
@if($shipment->canCancel())
<button type="button"
class="btn btn-warning mr-2"
id="cancel-shipment-btn"
data-shipment-id="{{ $shipment->id }}">
<i class="fas fa-ban"></i> Sendung stornieren
</button>
@endif
@if($shipment->type == 'outbound' && !$shipment->relatedShipment)
@if($shipment->type == 'outbound' && !$shipment->returns->count())
<button type="button"
class="btn btn-info mr-2"
id="create-return-btn"
@ -175,14 +166,23 @@
<i class="fas fa-undo"></i> Retourenlabel erstellen
</button>
@endif
--}}
@if($shipment->dhl_shipment_no)
<button type="button"
class="btn btn-secondary mr-2"
<button type="button"
class="btn btn-secondary mr-2"
id="update-tracking-btn"
data-shipment-id="{{ $shipment->id }}">
<i class="fas fa-sync"></i> Tracking aktualisieren
</button>
@if($shipment->canSendTrackingEmail())
<button type="button"
class="btn {{ $shipment->wasTrackingEmailSent() ? 'btn-success' : 'btn-info' }} mr-2"
id="send-tracking-email-btn"
data-shipment-id="{{ $shipment->id }}">
<i class="fas fa-envelope"></i>
{{ $shipment->wasTrackingEmailSent() ? 'Tracking-E-Mail erneut senden' : 'Tracking-E-Mail senden' }}
</button>
@endif
@endif
</div>
</div>
@ -345,6 +345,14 @@
</td>
</tr>
@endif
@if($shipment->recipient && isset($shipment->recipient['street']))
<tr>
<td class="font-weight-semibold">Straße:</td>
<td>
{{ $shipment->recipient['street'] }}
</td>
</tr>
@endif
<tr>
<td class="font-weight-semibold">Straße:</td>
<td>
@ -492,6 +500,42 @@
<div class="col-lg-4">
<!-- Email Status -->
@if($shipment->dhl_shipment_no)
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-envelope text-{{ $shipment->wasTrackingEmailSent() ? 'success' : 'secondary' }}"></i>
Tracking-E-Mail Status
</h5>
</div>
<div class="card-body">
@if($shipment->wasTrackingEmailSent())
<div class="alert alert-success mb-0">
<i class="fas fa-check-circle"></i>
<strong>E-Mail gesendet</strong><br>
<small>
Am {{ $shipment->tracking_email_sent_at->format('d.m.Y \u\m H:i') }} Uhr
({{ $shipment->tracking_email_type === 'auto' ? 'automatisch' : 'manuell' }})
</small>
</div>
@else
<div class="alert alert-secondary mb-0">
<i class="fas fa-clock"></i>
<strong>Noch nicht gesendet</strong><br>
<small>
@if($shipment->canSendTrackingEmail())
Klicken Sie auf "Tracking-E-Mail senden" um den Kunden zu benachrichtigen.
@else
E-Mail kann nicht gesendet werden (keine Empfänger-E-Mail verfügbar).
@endif
</small>
</div>
@endif
</div>
</div>
@endif
<!-- Tracking Information -->
@if($shipment->tracking_status || $shipment->dhl_shipment_no)
<div class="card mb-4">
@ -709,6 +753,42 @@ $(document).ready(function() {
});
});
// Send tracking email
$('#send-tracking-email-btn').click(function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
if (!confirm('Tracking-E-Mail an den Kunden senden?')) {
return;
}
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird gesendet...');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/send-tracking-email`,
method: 'POST',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
showAlert('success', response.message);
setTimeout(function() {
location.reload();
}, 2000);
} else {
showAlert('error', response.message);
resetButton(btn, '<i class="fas fa-envelope"></i> Tracking-E-Mail senden');
}
},
error: function(xhr) {
var errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Fehler beim Senden der Tracking-E-Mail.';
showAlert('error', errorMsg);
resetButton(btn, '<i class="fas fa-envelope"></i> Tracking-E-Mail senden');
}
});
});
// Helper functions
function resetButton(btn, originalText) {
btn.prop('disabled', false).html(originalText);