578 lines
No EOL
23 KiB
PHP
578 lines
No EOL
23 KiB
PHP
@extends('layouts.layout-2')
|
|
|
|
@section('content')
|
|
|
|
<h4 class="font-weight-bold py-2 mb-2">
|
|
<i class="fas fa-shipping-fast text-primary"></i>
|
|
DHL Cockpit
|
|
</h4>
|
|
|
|
<!-- Statistics Cards -->
|
|
<div class="row mb-4">
|
|
<div class="col-xl-3 col-md-6 mb-3">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body">
|
|
<div class="media align-items-center">
|
|
<div class="media-body">
|
|
<h5 class="mt-0 mb-1">{{ number_format($stats['total_shipments']) }}</h5>
|
|
<small class="mb-0">Sendungen gesamt</small>
|
|
</div>
|
|
<div class="ml-3">
|
|
<i class="fas fa-boxes fa-2x opacity-75"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-3">
|
|
<div class="card bg-warning text-white">
|
|
<div class="card-body">
|
|
<div class="media align-items-center">
|
|
<div class="media-body">
|
|
<h5 class="mt-0 mb-1">{{ number_format($stats['pending_shipments']) }}</h5>
|
|
<small class="mb-0">In Bearbeitung</small>
|
|
</div>
|
|
<div class="ml-3">
|
|
<i class="fas fa-clock fa-2x opacity-75"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-3">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body">
|
|
<div class="media align-items-center">
|
|
<div class="media-body">
|
|
<h5 class="mt-0 mb-1">{{ number_format($stats['shipped_today']) }}</h5>
|
|
<small class="mb-0">Heute versandt</small>
|
|
</div>
|
|
<div class="ml-3">
|
|
<i class="fas fa-truck fa-2x opacity-75"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-3">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body">
|
|
<div class="media align-items-center">
|
|
<div class="media-body">
|
|
<h5 class="mt-0 mb-1">{{ number_format($stats['returns_count']) }}</h5>
|
|
<small class="mb-0">Retouren</small>
|
|
</div>
|
|
<div class="ml-3">
|
|
<i class="fas fa-undo fa-2x opacity-75"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters Card -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-filter text-primary"></i>
|
|
Filter & Suche
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="GET" action="{{ route('admin.dhl.cockpit') }}" id="dhl-filter-form">
|
|
<div class="form-row">
|
|
<div class="col-md-3 mb-3">
|
|
<label for="type">Sendungstyp</label>
|
|
<select class="form-control custom-select" name="type" id="type">
|
|
<option value="">Alle Typen</option>
|
|
<option value="outbound" {{ request('type') == 'outbound' ? 'selected' : '' }}>Ausgehend</option>
|
|
<option value="return" {{ request('type') == 'return' ? 'selected' : '' }}>Retoure</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-3 mb-3">
|
|
<label for="status">Status</label>
|
|
<select class="form-control custom-select" name="status" id="status">
|
|
<option value="">Alle Status</option>
|
|
<option value="pending" {{ request('status') == 'pending' ? 'selected' : '' }}>Wartend</option>
|
|
<option value="created" {{ request('status') == 'created' ? 'selected' : '' }}>Erstellt</option>
|
|
<option value="shipped" {{ request('status') == 'shipped' ? 'selected' : '' }}>Versendet</option>
|
|
<option value="delivered" {{ request('status') == 'delivered' ? 'selected' : '' }}>Zugestellt</option>
|
|
<option value="cancelled" {{ request('status') == 'cancelled' ? 'selected' : '' }}>Storniert</option>
|
|
<option value="failed" {{ request('status') == 'failed' ? 'selected' : '' }}>Fehler</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-3 mb-3">
|
|
<label for="date_from">Von Datum</label>
|
|
<input type="date" class="form-control" name="date_from" id="date_from" value="{{ request('date_from') }}">
|
|
</div>
|
|
|
|
<div class="col-md-3 mb-3">
|
|
<label for="date_to">Bis Datum</label>
|
|
<input type="date" class="form-control" name="date_to" id="date_to" value="{{ request('date_to') }}">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="col-md-8 mb-3">
|
|
<label for="search">Suche (Sendungsnummer, Tracking-Nummer, Bestellungs-ID)</label>
|
|
<input type="text" class="form-control" name="search" id="search" value="{{ request('search') }}" placeholder="Suchen...">
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary mr-2">
|
|
<i class="fas fa-search"></i> Filtern
|
|
</button>
|
|
<a href="{{ route('admin.dhl.cockpit') }}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-sync"></i> Zurücksetzen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-bolt text-warning"></i>
|
|
Schnellaktionen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="card bg-light border-primary h-100">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-plus-circle fa-3x text-primary mb-3"></i>
|
|
<h5 class="card-title">Neue Sendung erstellen</h5>
|
|
<p class="card-text text-muted">
|
|
Erstellen Sie eine neue DHL-Sendung basierend auf einer bestehenden Bestellung.
|
|
</p>
|
|
<button type="button" class="btn btn-primary"
|
|
data-toggle="modal"
|
|
data-id="new"
|
|
data-target="#modals-load-content"
|
|
data-action="create-dhl-shipment"
|
|
data-route="{{ route('modal_load') }}">
|
|
<i class="fas fa-shipping-fast"></i> Sendung erstellen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card bg-light border-info h-100">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-search fa-3x text-info mb-3"></i>
|
|
<h5 class="card-title">Sendung anzeigen</h5>
|
|
<p class="card-text text-muted">
|
|
Suchen und anzeigen einer bestimmten Sendung nach ID oder Tracking-Nummer.
|
|
</p>
|
|
<div class="dropdown">
|
|
<button class="btn btn-info dropdown-toggle" type="button" id="showDropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
<i class="fas fa-eye"></i> Sendung anzeigen
|
|
</button>
|
|
<div class="dropdown-menu" aria-labelledby="showDropdown">
|
|
<h6 class="dropdown-header">Sendung finden:</h6>
|
|
<a class="dropdown-item" href="#" onclick="promptShipmentId()">
|
|
<i class="fas fa-hashtag"></i> Sendungs-ID eingeben
|
|
</a>
|
|
<a class="dropdown-item" href="#" onclick="promptTrackingNumber()">
|
|
<i class="fas fa-barcode"></i> Tracking-Nummer eingeben
|
|
</a>
|
|
<div class="dropdown-divider"></div>
|
|
<a class="dropdown-item" href="#" onclick="$('#search').focus();">
|
|
<i class="fas fa-filter"></i> Filter verwenden
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card bg-light border-secondary h-100">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-plug fa-3x text-secondary mb-3"></i>
|
|
<h5 class="card-title">API Login Test</h5>
|
|
<p class="card-text text-muted">
|
|
Überprüfen Sie, ob die in der <code>.env</code>-Datei hinterlegten DHL-Zugangsdaten korrekt sind.
|
|
</p>
|
|
<button type="button" class="btn btn-secondary" id="test-dhl-login-btn">
|
|
<span class="spinner-border spinner-border-sm" role="status" style="display: none;"></span>
|
|
<i class="fas fa-key"></i> Login testen
|
|
</button>
|
|
<div id="dhl-test-result" class="mt-3 text-left"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Batch Actions -->
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-list text-primary"></i>
|
|
Sendungsübersicht
|
|
</h5>
|
|
|
|
<div class="batch-actions" style="display: none;">
|
|
<button type="button" class="btn btn-sm btn-warning batch-action-btn" data-action="cancel">
|
|
<i class="fas fa-ban"></i> Ausgewählte stornieren
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-info batch-action-btn" data-action="update_tracking">
|
|
<i class="fas fa-sync"></i> Tracking aktualisieren
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-secondary batch-action-btn" data-action="download_labels">
|
|
<i class="fas fa-download"></i> Labels herunterladen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-datatable table-responsive">
|
|
<table class="table table-striped table-bordered" id="dhl-shipments-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 40px;">
|
|
<label class="custom-control custom-checkbox mb-0">
|
|
<input type="checkbox" class="custom-control-input" id="select-all">
|
|
<span class="custom-control-label"></span>
|
|
</label>
|
|
</th>
|
|
<th>#</th>
|
|
<th>Typ</th>
|
|
<th>Bestellung</th>
|
|
<th>Kunde</th>
|
|
<th>Sendungsnummer</th>
|
|
<th>Status</th>
|
|
<th>Tracking-Status</th>
|
|
<th>Gewicht</th>
|
|
<th>Erstellt</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{-- Data will be loaded by DataTables --}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{{-- Pagination will be handled by DataTables --}}
|
|
</div>
|
|
|
|
|
|
@endsection
|
|
|
|
@section('scripts')
|
|
<script>
|
|
$(document).ready(function() {
|
|
// DataTable initialization
|
|
var dhlTable = $('#dhl-shipments-table').DataTable({
|
|
processing: true,
|
|
serverSide: true,
|
|
ajax: {
|
|
url: "{{ route('admin.dhl.datatable') }}",
|
|
type: "POST",
|
|
data: function (d) {
|
|
d._token = '{{ csrf_token() }}';
|
|
d.type = $('#type').val();
|
|
d.status = $('#status').val();
|
|
d.date_from = $('#date_from').val();
|
|
d.date_to = $('#date_to').val();
|
|
d.search = $('#search').val();
|
|
}
|
|
},
|
|
columns: [
|
|
{ data: 'checkbox', name: 'checkbox', orderable: false, searchable: false },
|
|
{ data: 'id', name: 'id' },
|
|
{ data: 'type', name: 'type' },
|
|
{ data: 'order', name: 'order_id' },
|
|
{ data: 'customer', name: 'shoppingOrder.shopping_user.billing_firstname' },
|
|
{ data: 'dhl_shipment_no', name: 'dhl_shipment_no' },
|
|
{ data: 'status', name: 'status' },
|
|
{ data: 'tracking_status', name: 'tracking_status', orderable: false, searchable: false },
|
|
{ data: 'weight_kg', name: 'weight_kg' },
|
|
{ data: 'created_at', name: 'created_at' },
|
|
{ data: 'actions', name: 'actions', orderable: false, searchable: false }
|
|
],
|
|
order: [[1, 'desc']],
|
|
language: {
|
|
url: "//cdn.datatables.net/plug-ins/1.10.25/i18n/German.json"
|
|
},
|
|
// Re-initialize tooltips on each table draw
|
|
drawCallback: function () {
|
|
$('[data-toggle="tooltip"]').tooltip();
|
|
}
|
|
});
|
|
|
|
// Handle filter form submission
|
|
$('#dhl-filter-form').on('submit', function(e) {
|
|
e.preventDefault();
|
|
dhlTable.draw();
|
|
});
|
|
|
|
// Auto-reload on specific filter changes
|
|
$('#type, #status').change(function() {
|
|
dhlTable.draw();
|
|
});
|
|
|
|
// Tooltip initialization for static elements
|
|
$('[data-toggle="tooltip"]').tooltip();
|
|
|
|
// --- DHL LOGIN TEST ---
|
|
$('#test-dhl-login-btn').click(function() {
|
|
var btn = $(this);
|
|
var spinner = btn.find('.spinner-border');
|
|
var resultContainer = $('#dhl-test-result');
|
|
|
|
btn.prop('disabled', true);
|
|
spinner.show();
|
|
resultContainer.html('');
|
|
|
|
$.ajax({
|
|
url: '{{ route("admin.dhl.test_login") }}',
|
|
method: 'POST',
|
|
data: {
|
|
_token: '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
var alertClass = response.success ? 'alert-success' : 'alert-danger';
|
|
var icon = response.success ? 'fas fa-check-circle' : 'fas fa-times-circle';
|
|
var resultHtml = `
|
|
<div class="alert ${alertClass} d-flex align-items-center" role="alert">
|
|
<i class="${icon} mr-2"></i>
|
|
<div>
|
|
${response.message}
|
|
</div>
|
|
</div>
|
|
`;
|
|
resultContainer.html(resultHtml);
|
|
},
|
|
error: function(xhr) {
|
|
var errorHtml = `
|
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
|
<i class="fas fa-server mr-2"></i>
|
|
<div>
|
|
Ein Serverfehler ist aufgetreten. Prüfen Sie die Browser-Konsole und die Laravel-Logs.
|
|
</div>
|
|
</div>
|
|
`;
|
|
resultContainer.html(errorHtml);
|
|
},
|
|
complete: function() {
|
|
btn.prop('disabled', false);
|
|
spinner.hide();
|
|
}
|
|
});
|
|
});
|
|
|
|
// --- BATCH & ROW ACTIONS ---
|
|
|
|
// Select All functionality
|
|
$('#dhl-shipments-table').on('change', '#select-all', function() {
|
|
var checked = $(this).is(':checked');
|
|
$('.shipment-checkbox').prop('checked', checked);
|
|
toggleBatchActions();
|
|
});
|
|
|
|
// Individual checkbox change
|
|
$('#dhl-shipments-table').on('change', '.shipment-checkbox', function() {
|
|
var totalCheckboxes = $('.shipment-checkbox').length;
|
|
var checkedCheckboxes = $('.shipment-checkbox:checked').length;
|
|
|
|
$('#select-all').prop('checked', totalCheckboxes > 0 && totalCheckboxes === checkedCheckboxes);
|
|
toggleBatchActions();
|
|
});
|
|
|
|
// Toggle batch actions visibility
|
|
function toggleBatchActions() {
|
|
var checkedCount = $('.shipment-checkbox:checked').length;
|
|
if (checkedCount > 0) {
|
|
$('.batch-actions').show();
|
|
} else {
|
|
$('.batch-actions').hide();
|
|
}
|
|
}
|
|
|
|
// Batch actions
|
|
$('.batch-action-btn').click(function() {
|
|
var action = $(this).data('action');
|
|
var selectedIds = $('.shipment-checkbox:checked').map(function() {
|
|
return $(this).val();
|
|
}).get();
|
|
|
|
if (selectedIds.length === 0) {
|
|
alert('Bitte wählen Sie mindestens eine Sendung aus.');
|
|
return;
|
|
}
|
|
|
|
if (!confirm('Möchten Sie diese Aktion für ' + selectedIds.length + ' Sendung(en) ausführen?')) {
|
|
return;
|
|
}
|
|
|
|
// Perform batch action
|
|
$.ajax({
|
|
url: '{{ route("admin.dhl.batch-action") }}',
|
|
method: 'POST',
|
|
data: {
|
|
action: action,
|
|
shipment_ids: selectedIds,
|
|
_token: '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
showAlert('success', response.message);
|
|
location.reload();
|
|
} else {
|
|
showAlert('error', response.message);
|
|
}
|
|
},
|
|
error: function(xhr) {
|
|
showAlert('error', 'Fehler bei der Stapelverarbeitung.');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Individual action buttons (delegated events)
|
|
$('#dhl-shipments-table').on('click', '.cancel-shipment-btn', function() {
|
|
var shipmentId = $(this).data('shipment-id');
|
|
|
|
if (!confirm('Möchten Sie diese Sendung wirklich stornieren?')) {
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: `/admin/dhl/shipment/${shipmentId}/cancel`,
|
|
method: 'DELETE',
|
|
data: {
|
|
_token: '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
showAlert('success', response.message);
|
|
location.reload();
|
|
} else {
|
|
showAlert('error', response.message);
|
|
}
|
|
},
|
|
error: function(xhr) {
|
|
showAlert('error', 'Fehler beim Stornieren der Sendung.');
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#dhl-shipments-table').on('click', '.create-return-btn', function() {
|
|
var shipmentId = $(this).data('shipment-id');
|
|
|
|
if (!confirm('Möchten Sie ein Retourenlabel für diese Sendung erstellen?')) {
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: `/admin/dhl/shipment/${shipmentId}/return-label`,
|
|
method: 'POST',
|
|
data: {
|
|
_token: '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
showAlert('success', response.message);
|
|
location.reload();
|
|
} else {
|
|
showAlert('error', response.message);
|
|
}
|
|
},
|
|
error: function(xhr) {
|
|
showAlert('error', 'Fehler beim Erstellen des Retourenlabels.');
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#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',
|
|
data: {
|
|
_token: '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
showAlert('success', response.message);
|
|
setTimeout(function() {
|
|
location.reload();
|
|
}, 2000);
|
|
} else {
|
|
showAlert('error', response.message);
|
|
}
|
|
},
|
|
error: function(xhr) {
|
|
showAlert('error', 'Fehler beim Aktualisieren der Tracking-Informationen.');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Remove old auto-submit logic
|
|
/*
|
|
$('#type, #status').change(function() {
|
|
$('#dhl-filter-form').submit();
|
|
});
|
|
*/
|
|
|
|
function promptShipmentId() {
|
|
var shipmentId = prompt('Bitte geben Sie die Sendungs-ID ein:');
|
|
if (shipmentId && shipmentId.trim()) {
|
|
shipmentId = shipmentId.trim();
|
|
if (!isNaN(shipmentId) && shipmentId > 0) {
|
|
window.location.href = '{{ route("admin.dhl.show", ":shipmentId") }}'.replace(':shipmentId', shipmentId);
|
|
} else {
|
|
alert('Bitte geben Sie eine gültige Sendungs-ID (Zahl) ein.');
|
|
}
|
|
}
|
|
}
|
|
|
|
function promptTrackingNumber() {
|
|
var trackingNumber = prompt('Bitte geben Sie die Tracking-Nummer ein:');
|
|
if (trackingNumber && trackingNumber.trim()) {
|
|
trackingNumber = trackingNumber.trim();
|
|
if (trackingNumber.length >= 10) {
|
|
// Use search functionality to find by tracking number
|
|
$('#search').val(trackingNumber);
|
|
$('#dhl-filter-form').submit();
|
|
} else {
|
|
alert('Bitte geben Sie eine gültige Tracking-Nummer ein (mindestens 10 Zeichen).');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Alert helper function
|
|
function showAlert(type, message) {
|
|
var alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
|
|
var alertHtml = `
|
|
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">
|
|
${message}
|
|
<button type="button" class="close" data-dismiss="alert">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
`;
|
|
|
|
$('h4.font-weight-bold').after(alertHtml);
|
|
|
|
// Auto-hide after 5 seconds
|
|
setTimeout(function() {
|
|
$('.alert').alert('close');
|
|
}, 5000);
|
|
}
|
|
});
|
|
</script>
|
|
@endsection |