DHL Modul v0.5 Shipping Label ok

This commit is contained in:
Kevin Adametz 2025-08-22 18:18:26 +02:00
parent 480fdc65ed
commit 8fdaa0ba1d
122 changed files with 17938 additions and 2239 deletions

View file

@ -68,4 +68,6 @@ return array (
'shop' => 'Shop',
'to_shop' => 'Zum Shop',
'marketingplan' => 'Marketingplan',
'dhl_cockpit' => 'DHL Cockpit',
'revenue' => 'Umsatz',
);

View file

@ -8,6 +8,7 @@ return array (
'Your Shop' => 'Dein Shop',
'Your Shop Name' => 'Gib deinem Shop einen Namen',
'accept_and_next' => 'akzeptieren und weiter',
'accept_and_change' => 'akzeptieren und ändern',
'active_since' => 'Aktiv seit',
'available' => 'erreichbar',
'check' => 'prüfen',
@ -16,11 +17,12 @@ return array (
'name' => 'Name',
'not_available' => 'nicht erreichbar',
'not_available_copy' => 'Bei neu angelegten Shops dauert es einige Minuten, bis die Domain zu erreichen ist. Bitte schaue in einigen Minuten noch einmal nach.',
'open_copy_1' => 'Wähle das Präfix Deines Shopnamens - z. B. vorname(.mivita.care) - Du musst nicht "mivita.care" eingeben. Wähle einen kurzen und prägnanten Namen, damit Du diese URL auch auf kleinen Werbemitteln unterbringen kannst. Achte auch darauf, dass Du keine Markenrechte Dritter verletzt. Dafür kann MIVITA keine Haftung übernehmen. Daher versucht Phantasiebegriffe zu vermeiden, es sei denn Du hast sie als Marke angemeldet.',
'open_copy_2' => 'Deine Internetadresse kann später mit „www.“ und ohne aufgerufen werden.',
'open_note_1' => 'Aus Deinem Shop-Namen wird die Internet-Adresse (Domain) erstellt, mit der Dein Shop aufgerufen werden kann. Wähle Deinen Shop-Namen sorgfältig aus. Dieser ist nur durch die IT änderbar und wir müssten eine Aufwandsentschädigung von 59,50 € erheben.',
'open_copy_1' => 'Wähle das Präfix Deines Shopnamens - z. B. vorname(.mivita.care).<br>Du musst nicht "mivita.care" eingeben.<br><br>Achte darauf, einen kurzen und prägnanten Namen zu wählen, damit Deine Internetadresse auch auf kleinen Werbemitteln gut Platz findet. Stelle außerdem sicher, dass Du keine Markenrechte Dritter verletzt dafür kann MIVITA keine Haftung übernehmen. Vermeide daher möglichst Fantasiebegriffe, es sei denn, Du hast diese bereits als Marke angemeldet.',
'open_copy_2' => 'Deine Internetadresse wird ohne „www.“ aufgerufen: https://deinshopname.mivita.care',
'open_note_1' => 'Du kannst den Namen Deines Shops jederzeit ändern. Der alte Shopname verfällt jedoch sofort und unwiderruflich. Wenn Du die alte Adresse bereits verteilt hast (z. B. auf Flyern, Visitenkarten oder in sozialen Medien), ist diese danach nicht mehr erreichbar.',
'open_note_hl' => 'WICHTIGER HINWEIS:',
'open_your_shop' => 'Eröffne Deinen eigenen mivita-Shop.',
'open_your_shop' => 'Eröffne jetzt Deinen eigenen mivita-Shop!',
'edit_your_shop' => 'Dein Shop-Name anpassen',
'order_customer' => 'Bestellung Kunde',
'orders_customers' => 'Bestellungen Kunden',
'preview_shop_internet_address' => 'Vorschau Shop-Internet Adresse',
@ -50,6 +52,6 @@ return array (
'your_city' => 'Dein Ort',
'your_phone_number' => 'Deine Festnetz-Nummer',
'your_mobile_number' => 'Deine Mobil-Nummer',
'error_subdomain_exists' => 'Fehler: Subdomain existierts bereits, bitte einen neues Namen wählen'
'error_subdomain_exists' => 'Fehler: Subdomain existierts bereits, bitte einen neues Namen wählen',
'your_current_shop_name' => 'Dein aktueller Shop-Name lautet:'
);

View file

@ -0,0 +1,578 @@
@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">&times;</span>
</button>
</div>
`;
$('h4.font-weight-bold').after(alertHtml);
// Auto-hide after 5 seconds
setTimeout(function() {
$('.alert').alert('close');
}, 5000);
}
});
</script>
@endsection

View file

@ -0,0 +1,428 @@
@extends('layouts.layout-2')
@section('content')
<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-shipping-fast text-primary"></i>
DHL Sendung erstellen
</h4>
<a href="{{ route('admin.dhl.cockpit') }}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left"></i> Zurück zum Cockpit
</a>
</div>
<!-- Order Information Card -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-shopping-cart text-info"></i>
Bestellinformationen
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">Bestellungs-ID:</td>
<td>#{{ $order->id }}</td>
</tr>
<tr>
<td class="font-weight-semibold">Kunde:</td>
<td>
{{ $order->user->first_name ?? '' }} {{ $order->user->last_name ?? '' }}
<br>
<small class="text-muted">{{ $order->user->email ?? '' }}</small>
</td>
</tr>
<tr>
<td class="font-weight-semibold">Bestelldatum:</td>
<td>{{ $order->created_at->format('d.m.Y H:i') }}</td>
</tr>
<tr>
<td class="font-weight-semibold">Bestellwert:</td>
<td><strong>{{ number_format($order->order_total, 2) }} </strong></td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">Lieferadresse:</td>
<td>
{{ $order->shipping_first_name ?? $order->user->first_name }} {{ $order->shipping_last_name ?? $order->user->last_name }}<br>
{{ $order->shipping_street ?? $order->user->street }} {{ $order->shipping_house_number ?? $order->user->house_number }}<br>
{{ $order->shipping_postcode ?? $order->user->postcode }} {{ $order->shipping_city ?? $order->user->city }}<br>
{{ $order->shippingCountry->name ?? 'Deutschland' }}
</td>
</tr>
<tr>
<td class="font-weight-semibold">Status:</td>
<td>
<span class="badge badge-{{ $order->status == 'completed' ? 'success' : 'warning' }}">
{{ $order->status }}
</span>
</td>
</tr>
<tr>
<td class="font-weight-semibold">Artikel:</td>
<td>{{ $order->items->count() }} Artikel</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<!-- Order Items Card -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-list text-success"></i>
Artikel in der Bestellung
</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Artikel</th>
<th>Menge</th>
<th>Einzelpreis</th>
<th>Gesamtpreis</th>
<th>Gewicht (kg)</th>
</tr>
</thead>
<tbody>
@php $totalWeight = 0; @endphp
@foreach($order->items as $item)
@php
$itemWeight = ($item->product->weight ?? 0) * $item->qty;
$totalWeight += $itemWeight;
@endphp
<tr>
<td>
<strong>{{ $item->product->name ?? 'Unbekanntes Produkt' }}</strong>
@if($item->product->number)
<br>
<small class="text-muted">Art.-Nr: {{ $item->product->number }}</small>
@endif
</td>
<td>{{ $item->qty }}</td>
<td>{{ number_format($item->price, 2) }} </td>
<td>{{ number_format($item->price * $item->qty, 2) }} </td>
<td>{{ number_format($itemWeight, 3) }}</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr class="table-info font-weight-semibold">
<td colspan="4">Geschätztes Gesamtgewicht:</td>
<td>{{ number_format($totalWeight, 3) }} kg</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- Shipment Creation Form -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-plus-circle text-primary"></i>
Sendung konfigurieren
</h5>
</div>
<div class="card-body">
<form id="create-shipment-form">
@csrf
<input type="hidden" name="order_id" value="{{ $order->id }}">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="weight" class="font-weight-semibold">
<i class="fas fa-weight"></i>
Versandgewicht (kg) <span class="text-danger">*</span>
</label>
<input type="number"
class="form-control"
id="weight"
name="weight"
min="0.1"
max="31.5"
step="0.1"
value="{{ max(0.5, $totalWeight) }}"
required>
<small class="form-text text-muted">
Mindestens 0.1 kg, maximal 31.5 kg (DHL Paket Limit)
</small>
</div>
<div class="form-group">
<label for="product_code" class="font-weight-semibold">
<i class="fas fa-cube"></i>
DHL Produktcode
</label>
<select class="form-control" id="product_code" name="product_code">
<option value="V01PAK">V01PAK - DHL Paket</option>
<option value="V53WPAK">V53WPAK - DHL Paket International</option>
<option value="V54EPAK">V54EPAK - DHL Express</option>
</select>
<small class="form-text text-muted">
Standardmäßig DHL Paket für nationale Sendungen
</small>
</div>
<div class="form-group">
<label for="priority" class="font-weight-semibold">
<i class="fas fa-exclamation-triangle"></i>
Priorität
</label>
<select class="form-control" id="priority" name="priority">
<option value="normal">Normal</option>
<option value="high">Hoch (Express-Queue)</option>
</select>
<small class="form-text text-muted">
Hohe Priorität für dringende Sendungen
</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="font-weight-semibold">
<i class="fas fa-cog"></i>
Zusätzliche Optionen
</label>
<div class="custom-control custom-checkbox">
<input type="checkbox"
class="custom-control-input"
id="auto_track"
name="auto_track"
checked>
<label class="custom-control-label" for="auto_track">
Automatisches Tracking aktivieren
</label>
<small class="form-text text-muted">
Startet automatische Sendungsverfolgung nach Erstellung
</small>
</div>
</div>
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-info-circle text-info"></i>
Versandhinweise
</h6>
<ul class="mb-0 small">
<li>Die Sendung wird asynchron erstellt</li>
<li>Sie erhalten eine Benachrichtigung nach Fertigstellung</li>
<li>Das Versandlabel wird automatisch generiert</li>
<li>Bei aktiviertem Auto-Tracking wird die Sendung überwacht</li>
@if($totalWeight > 10)
<li class="text-warning">
<i class="fas fa-exclamation-triangle"></i>
Hohes Gewicht - prüfen Sie die Verpackung
</li>
@endif
</ul>
</div>
</div>
</div>
</div>
<hr>
<div class="form-group mb-0">
<div class="d-flex justify-content-between align-items-center">
<div>
<small class="text-muted">
* Pflichtfelder | Geschätzte Verarbeitungszeit: 2-5 Minuten
</small>
</div>
<div>
<button type="button"
class="btn btn-secondary mr-2"
onclick="window.location.href='{{ route('admin.dhl.cockpit') }}'">
<i class="fas fa-times"></i>
Abbrechen
</button>
<button type="submit"
class="btn btn-primary"
id="submit-btn">
<i class="fas fa-shipping-fast"></i>
Sendung erstellen
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- Progress Modal -->
<div class="modal fade" id="progress-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-cog fa-spin text-primary"></i>
Sendung wird erstellt
</h5>
</div>
<div class="modal-body text-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
<p class="mt-3 mb-0">
Bitte warten Sie, während die DHL-Sendung erstellt wird...<br>
<small class="text-muted">Dies kann einige Minuten dauern.</small>
</p>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
$(document).ready(function() {
// Form submission
$('#create-shipment-form').on('submit', function(e) {
e.preventDefault();
var formData = $(this).serialize();
var submitBtn = $('#submit-btn');
// Disable submit button and show loading
submitBtn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird erstellt...');
// Show progress modal
$('#progress-modal').modal('show');
$.ajax({
url: '{{ route("admin.dhl.store") }}',
method: 'POST',
data: formData,
success: function(response) {
$('#progress-modal').modal('hide');
if (response.success) {
// Show success alert
showAlert('success', response.message);
// Redirect to cockpit after 3 seconds
setTimeout(function() {
window.location.href = '{{ route("admin.dhl.cockpit") }}';
}, 3000);
} else {
showAlert('error', response.message);
resetForm();
}
},
error: function(xhr) {
$('#progress-modal').modal('hide');
var errorMessage = 'Fehler beim Erstellen der Sendung.';
if (xhr.responseJSON && xhr.responseJSON.message) {
errorMessage = xhr.responseJSON.message;
} else if (xhr.responseJSON && xhr.responseJSON.errors) {
var errors = xhr.responseJSON.errors;
errorMessage = Object.values(errors).flat().join('<br>');
}
showAlert('error', errorMessage);
resetForm();
}
});
});
// Reset form function
function resetForm() {
var submitBtn = $('#submit-btn');
submitBtn.prop('disabled', false).html('<i class="fas fa-shipping-fast"></i> Sendung erstellen');
}
// Weight input validation
$('#weight').on('input', function() {
var weight = parseFloat($(this).val());
var weightInput = $(this);
var feedback = weightInput.siblings('.invalid-feedback');
// Remove existing feedback
feedback.remove();
weightInput.removeClass('is-invalid');
if (weight < 0.1) {
weightInput.addClass('is-invalid');
weightInput.after('<div class="invalid-feedback">Mindestgewicht: 0.1 kg</div>');
} else if (weight > 31.5) {
weightInput.addClass('is-invalid');
weightInput.after('<div class="invalid-feedback">Maximalgewicht: 31.5 kg (DHL Paket Limit)</div>');
} else if (weight > 10) {
weightInput.after('<div class="text-warning small"><i class="fas fa-exclamation-triangle"></i> Hohes Gewicht - prüfen Sie die Verpackung</div>');
}
});
// Product code change handler
$('#product_code').change(function() {
var productCode = $(this).val();
var weightInput = $('#weight');
var maxWeight = 31.5;
// Adjust weight limits based on product
if (productCode === 'V54EPAK') {
maxWeight = 31.5;
} else if (productCode === 'V53WPAK') {
maxWeight = 20;
}
weightInput.attr('max', maxWeight);
// Validate current weight
$('#weight').trigger('input');
});
// Alert helper function
function showAlert(type, message) {
var alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
var iconClass = type === 'success' ? 'fas fa-check-circle' : 'fas fa-exclamation-circle';
var alertHtml = `
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">
<i class="${iconClass}"></i>
${message}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">&times;</span>
</button>
</div>
`;
$('.py-2.mb-4').after(alertHtml);
// Scroll to top
$('html, body').animate({ scrollTop: 0 }, 500);
// Auto-hide success alerts after 5 seconds
if (type === 'success') {
setTimeout(function() {
$('.alert-success').alert('close');
}, 5000);
}
}
// Prevent modal from closing on backdrop click
$('#progress-modal').modal({
backdrop: 'static',
keyboard: false
});
});
</script>
@endsection

View 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">&times;</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>

View file

@ -0,0 +1,600 @@
@extends('layouts.layout-2')
@section('content')
<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>
DHL Sendung #{{ $shipment->id }}
@if($shipment->type == 'return')
<span class="badge badge-info ml-2">
<i class="fas fa-undo"></i> Retoure
</span>
@endif
</h4>
<div>
<a href="{{ route('admin.dhl.cockpit') }}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left"></i> Zurück zum Cockpit
</a>
@if($shipment->shoppingOrder)
<a href="{{ route('admin_sales_customers_detail', $shipment->shoppingOrder->id) }}"
class="btn btn-outline-primary ml-2">
<i class="fas fa-shopping-cart"></i> Bestellung anzeigen
</a>
@endif
</div>
</div>
<!-- Status & Key Info Row -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-primary">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Status</div>
@switch($shipment->status)
@case('pending')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-warning">Wartend</span>
</div>
@break
@case('created')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-success">Erstellt</span>
</div>
@break
@case('shipped')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-primary">Versendet</span>
</div>
@break
@case('delivered')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-info">Zugestellt</span>
</div>
@break
@case('cancelled')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-secondary">Storniert</span>
</div>
@break
@case('failed')
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-danger">Fehler</span>
</div>
@break
@default
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span class="badge badge-light">{{ $shipment->status }}</span>
</div>
@endswitch
</div>
<div class="col-auto">
<i class="fas fa-flag fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-success">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Sendungsnummer</div>
<div class="h6 mb-0 font-weight-bold text-gray-800">
@if($shipment->shipment_number)
<code class="text-success">{{ $shipment->shipment_number }}</code>
@else
<span class="text-muted">Nicht verfügbar</span>
@endif
</div>
</div>
<div class="col-auto">
<i class="fas fa-hashtag fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-info">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tracking-Nummer</div>
<div class="h6 mb-0 font-weight-bold text-gray-800">
@if($shipment->tracking_number)
<code class="text-info">{{ $shipment->tracking_number }}</code>
<br>
<a href="{{ route('public.tracking') }}?tracking_number={{ $shipment->tracking_number }}"
target="_blank" class="text-muted small">
<i class="fas fa-external-link-alt"></i> Verfolgen
</a>
@else
<span class="text-muted">Nicht verfügbar</span>
@endif
</div>
</div>
<div class="col-auto">
<i class="fas fa-search fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-warning">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Gewicht</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
{{ number_format($shipment->weight, 2) }} kg
</div>
</div>
<div class="col-auto">
<i class="fas fa-weight fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Action Buttons -->
@if($shipment->status != 'cancelled')
<div class="card mb-4">
<div class="card-body">
<div class="d-flex flex-wrap gap-2">
@if($shipment->label_path)
<a href="{{ route('admin.dhl.download-label', $shipment) }}"
class="btn btn-success mr-2">
<i class="fas fa-download"></i> Label herunterladen
</a>
@endif
@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)
<button type="button"
class="btn btn-info mr-2"
id="create-return-btn"
data-shipment-id="{{ $shipment->id }}">
<i class="fas fa-undo"></i> Retourenlabel erstellen
</button>
@endif
@if($shipment->tracking_number)
<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>
@endif
</div>
</div>
</div>
@endif
<!-- Shipment Details -->
<div class="row">
<!-- Left Column -->
<div class="col-lg-8">
<!-- Shipment Information -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-info-circle text-primary"></i>
Sendungsinformationen
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">ID:</td>
<td>#{{ $shipment->id }}</td>
</tr>
<tr>
<td class="font-weight-semibold">Typ:</td>
<td>
@if($shipment->type == 'outbound')
<span class="badge badge-primary">
<i class="fas fa-arrow-right"></i> Ausgehend
</span>
@else
<span class="badge badge-info">
<i class="fas fa-undo"></i> Retoure
</span>
@if($shipment->relatedShipment)
<br>
<small class="text-muted">
Bezieht sich auf Sendung
<a href="{{ route('admin.dhl.show', $shipment->relatedShipment) }}">
#{{ $shipment->relatedShipment->id }}
</a>
</small>
@endif
@endif
</td>
</tr>
<tr>
<td class="font-weight-semibold">Produktcode:</td>
<td><code>{{ $shipment->product_code }}</code></td>
</tr>
<tr>
<td class="font-weight-semibold">Label-Format:</td>
<td>{{ strtoupper($shipment->label_format) }}</td>
</tr>
<tr>
<td class="font-weight-semibold">Label gedruckt:</td>
<td>
@if($shipment->label_printed)
<span class="badge badge-success">Ja</span>
@else
<span class="badge badge-secondary">Nein</span>
@endif
</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">Erstellt:</td>
<td>{{ $shipment->created_at->format('d.m.Y H:i:s') }}</td>
</tr>
<tr>
<td class="font-weight-semibold">Letzte Änderung:</td>
<td>{{ $shipment->updated_at->format('d.m.Y H:i:s') }}</td>
</tr>
@if($shipment->last_tracked_at)
<tr>
<td class="font-weight-semibold">Letztes Tracking:</td>
<td>{{ $shipment->last_tracked_at->format('d.m.Y H:i:s') }}</td>
</tr>
@endif
@if($shipment->length || $shipment->width || $shipment->height)
<tr>
<td class="font-weight-semibold">Abmessungen:</td>
<td>
{{ $shipment->length }}×{{ $shipment->width }}×{{ $shipment->height }} cm
</td>
</tr>
@endif
</table>
</div>
</div>
</div>
</div>
<!-- Order Information -->
@if($shipment->shoppingOrder)
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-shopping-cart text-success"></i>
Bestellinformationen
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">Bestellungs-ID:</td>
<td>
<a href="{{ route('admin_sales_customers_detail', $shipment->shoppingOrder->id) }}" class="text-primary">
#{{ $shipment->shoppingOrder->id }}
</a>
</td>
</tr>
<tr>
<td class="font-weight-semibold">Kunde:</td>
<td>
@if($shipment->shoppingOrder->shopping_user)
{{ $shipment->shoppingOrder->shopping_user->billing_firstname }} {{ $shipment->shoppingOrder->shopping_user->billing_lastname }}
<br>
<small class="text-muted">{{ $shipment->shoppingOrder->shopping_user->billing_email }}</small>
@else
<span class="text-muted">Unbekannt</span>
@endif
</td>
</tr>
<tr>
<td class="font-weight-semibold">Bestelldatum:</td>
<td>{{ $shipment->shoppingOrder->created_at->format('d.m.Y H:i') }}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td class="font-weight-semibold">Bestellwert:</td>
<td><strong>{{ number_format($shipment->shoppingOrder->total, 2) }} </strong></td>
</tr>
<tr>
<td class="font-weight-semibold">Status:</td>
<td>
<span class="badge badge-{{ $shipment->shoppingOrder->status == 'completed' ? 'success' : 'warning' }}">
{{ $shipment->shoppingOrder->status }}
</span>
</td>
</tr>
<tr>
<td class="font-weight-semibold">Artikel:</td>
<td>{{ $shipment->shoppingOrder->shopping_order_items->count() ?? 0 }} Artikel</td>
</tr>
</table>
</div>
</div>
</div>
</div>
@endif
<!-- Tracking Information -->
@if($shipment->tracking_status || $shipment->tracking_number)
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-route text-info"></i>
Tracking-Informationen
</h5>
</div>
<div class="card-body">
@if($shipment->tracking_status)
<div class="alert alert-info">
<h6 class="alert-heading">
<i class="fas fa-map-marker-alt"></i>
Aktueller Status: {{ $shipment->tracking_status }}
</h6>
@if($shipment->last_tracked_at)
<small class="text-muted">
Zuletzt aktualisiert: {{ $shipment->last_tracked_at->format('d.m.Y H:i') }}
</small>
@endif
</div>
@endif
@if($shipment->tracking_number)
<div class="text-center">
<p>Verfolgen Sie diese Sendung direkt bei DHL:</p>
<a href="https://www.dhl.de/de/privatkunden/pakete-empfangen/verfolgen.html?lang=de&idc={{ $shipment->tracking_number }}"
target="_blank"
class="btn btn-outline-warning">
<i class="fas fa-external-link-alt"></i>
Bei DHL verfolgen
</a>
<a href="{{ route('public.tracking') }}?tracking_number={{ $shipment->tracking_number }}"
target="_blank"
class="btn btn-outline-info ml-2">
<i class="fas fa-search"></i>
Lokales Tracking
</a>
</div>
@endif
</div>
</div>
@endif
</div>
<!-- Right Column -->
<div class="col-lg-4">
<!-- Related Shipments -->
@if($shipment->type == 'outbound' && $shipment->relatedShipments && $shipment->relatedShipments->count() > 0)
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-link text-warning"></i>
Verknüpfte Retouren
</h5>
</div>
<div class="card-body">
@foreach($shipment->relatedShipments as $relatedShipment)
<div class="d-flex justify-content-between align-items-center mb-2">
<div>
<a href="{{ route('admin.dhl.show', $relatedShipment) }}" class="text-primary">
Retoure #{{ $relatedShipment->id }}
</a>
<br>
<small class="text-muted">{{ $relatedShipment->created_at->format('d.m.Y H:i') }}</small>
</div>
<span class="badge badge-{{ $relatedShipment->status == 'created' ? 'success' : 'warning' }}">
{{ $relatedShipment->status }}
</span>
</div>
@endforeach
</div>
</div>
@endif
<!-- Additional Services -->
@if($shipment->services)
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-plus-circle text-success"></i>
Zusatzleistungen
</h5>
</div>
<div class="card-body">
@foreach($shipment->services as $service => $enabled)
@if($enabled)
<div class="badge badge-success mr-1 mb-1">{{ $service }}</div>
@endif
@endforeach
</div>
</div>
@endif
<!-- API Response Data -->
@if($shipment->api_response_data && auth()->user()->isSuperAdmin())
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-code text-muted"></i>
API Response (Debug)
</h5>
</div>
<div class="card-body">
<pre class="small text-muted" style="max-height: 300px; overflow-y: auto;">{{ json_encode($shipment->api_response_data, JSON_PRETTY_PRINT) }}</pre>
</div>
</div>
@endif
</div>
</div>
@endsection
@section('scripts')
<script>
$(document).ready(function() {
// Cancel shipment
$('#cancel-shipment-btn').click(function() {
var shipmentId = $(this).data('shipment-id');
if (!confirm('Möchten Sie diese Sendung wirklich stornieren?\n\nDieser Vorgang kann nicht rückgängig gemacht werden.')) {
return;
}
var btn = $(this);
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird storniert...');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/cancel`,
method: 'DELETE',
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-ban"></i> Sendung stornieren');
}
},
error: function(xhr) {
showAlert('error', 'Fehler beim Stornieren der Sendung.');
resetButton(btn, '<i class="fas fa-ban"></i> Sendung stornieren');
}
});
});
// Create return label
$('#create-return-btn').click(function() {
var shipmentId = $(this).data('shipment-id');
if (!confirm('Möchten Sie ein Retourenlabel für diese Sendung erstellen?')) {
return;
}
var btn = $(this);
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird erstellt...');
$.ajax({
url: `/admin/dhl/shipment/${shipmentId}/return-label`,
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-undo"></i> Retourenlabel erstellen');
}
},
error: function(xhr) {
showAlert('error', 'Fehler beim Erstellen des Retourenlabels.');
resetButton(btn, '<i class="fas fa-undo"></i> Retourenlabel erstellen');
}
});
});
// Update tracking
$('#update-tracking-btn').click(function() {
var shipmentId = $(this).data('shipment-id');
var btn = $(this);
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Wird aktualisiert...');
$.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();
}, 3000);
} else {
showAlert('error', response.message);
resetButton(btn, '<i class="fas fa-sync"></i> Tracking aktualisieren');
}
},
error: function(xhr) {
showAlert('error', 'Fehler beim Aktualisieren der Tracking-Informationen.');
resetButton(btn, '<i class="fas fa-sync"></i> Tracking aktualisieren');
}
});
});
// Helper functions
function resetButton(btn, originalText) {
btn.prop('disabled', false).html(originalText);
}
function showAlert(type, message) {
var alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
var iconClass = type === 'success' ? 'fas fa-check-circle' : 'fas fa-exclamation-circle';
var alertHtml = `
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">
<i class="${iconClass}"></i>
${message}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">&times;</span>
</button>
</div>
`;
$('.py-2.mb-4').after(alertHtml);
// Scroll to top
$('html, body').animate({ scrollTop: 0 }, 500);
// Auto-hide success alerts after 5 seconds
if (type === 'success') {
setTimeout(function() {
$('.alert-success').alert('close');
}, 5000);
}
}
});
</script>
@endsection

View file

@ -107,6 +107,220 @@
<button type="submit" name="action" value="save_prepayment" class="btn btn-primary btn-sm mb-2"><i class="ion ion-ios-save"></i> speichern</button>
</div>
</div>
<!-- DHL Configuration Section -->
<div class="card mb-2">
<div class="card-body">
<h4><i class="fas fa-truck"></i> DHL Versandeinstellungen</h4>
@if(Session::has('alert-save-dhl'))
<div class="alert alert-success" role="alert">
<i class="fas fa-check-circle"></i> {{ Session::get('alert-save-dhl') }}
</div>
@endif
<!-- DHL Standard-Einstellungen -->
<div class="form-row">
<div class="col-sm-12">
<h5>Standard-Einstellungen</h5>
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('API Basis URL') }}*</label>
{{ Form::text('settings[dhl_base_url][val]', \App\Models\Setting::getContentBySlug('dhl_base_url') ?: 'https://api-eu.dhl.com', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_base_url][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('API Schlüssel') }}*</label>
{{ Form::text('settings[dhl_api_key][val]', \App\Models\Setting::getContentBySlug('dhl_api_key'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_api_key][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Benutzername') }}*</label>
{{ Form::text('settings[dhl_username][val]', \App\Models\Setting::getContentBySlug('dhl_username'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_username][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Passwort') }}*</label>
{{ Form::password('settings[dhl_password][val]', array('class'=>'form-control', 'value' => \App\Models\Setting::getContentBySlug('dhl_password'))) }}
{{ Form::hidden('settings[dhl_password][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Standard Abrechnungsnummer') }}*</label>
{{ Form::text('settings[dhl_billing_number][val]', \App\Models\Setting::getContentBySlug('dhl_billing_number'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_billing_number][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Standard Produktcode') }}*</label>
{{ Form::select('settings[dhl_product][val]', [
'V01PAK' => 'V01PAK - DHL Paket National',
'V53PAK' => 'V53PAK - DHL Paket International',
'V62WP' => 'V62WP - Warenpost National'
], \App\Models\Setting::getContentBySlug('dhl_product') ?: 'V01PAK', array('class'=>'form-control custom-select')) }}
{{ Form::hidden('settings[dhl_product][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Label Format') }}*</label>
{{ Form::select('settings[dhl_label_format][val]', [
'PDF' => 'PDF',
'ZPL' => 'ZPL'
], \App\Models\Setting::getContentBySlug('dhl_label_format') ?: 'PDF', array('class'=>'form-control custom-select')) }}
{{ Form::hidden('settings[dhl_label_format][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="custom-control custom-checkbox mt-4">
{!! Form::checkbox('settings[dhl_use_queue][val]', 1, \App\Models\Setting::getContentBySlug('dhl_use_queue'), ['class'=>'custom-control-input']) !!}
<span class="custom-control-label">Queue für asynchrone Verarbeitung verwenden</span>
</label>
{{ Form::hidden('settings[dhl_use_queue][type]', 'bool') }}
<small class="form-text text-muted">
<strong>Aktiviert:</strong> Versandlabel werden im Hintergrund erstellt (erfordert Queue Worker)<br>
<strong>Deaktiviert:</strong> Versandlabel werden sofort erstellt (synchron)
</small>
</div>
</div>
<hr>
<!-- DHL Account Numbers -->
<div class="form-row">
<div class="col-sm-12">
<h5>Account Nummern für verschiedene Produkte</h5>
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('V01PAK - DHL Paket National') }}*</label>
{{ Form::text('settings[dhl_account_v01pak][val]', \App\Models\Setting::getContentBySlug('dhl_account_v01pak'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_account_v01pak][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('V07PAK - DHL Retoure Online') }}</label>
{{ Form::text('settings[dhl_account_v07pak][val]', \App\Models\Setting::getContentBySlug('dhl_account_v07pak'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_account_v07pak][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('V53PAK - DHL Paket International') }}</label>
{{ Form::text('settings[dhl_account_v53pak][val]', \App\Models\Setting::getContentBySlug('dhl_account_v53pak'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_account_v53pak][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('V62WP - Warenpost National') }}</label>
{{ Form::text('settings[dhl_account_v62wp][val]', \App\Models\Setting::getContentBySlug('dhl_account_v62wp'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_account_v62wp][type]', 'text') }}
</div>
</div>
<hr>
<!-- DHL Absenderadresse -->
<div class="form-row">
<div class="col-sm-12">
<h5>Absenderadresse</h5>
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Firmenname') }}*</label>
{{ Form::text('settings[dhl_sender_company][val]', \App\Models\Setting::getContentBySlug('dhl_sender_company') ?: 'mivita care gmbh', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_company][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Name (optional)') }}</label>
{{ Form::text('settings[dhl_sender_name][val]', \App\Models\Setting::getContentBySlug('dhl_sender_name'), array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_name][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Straße') }}*</label>
{{ Form::text('settings[dhl_sender_street][val]', \App\Models\Setting::getContentBySlug('dhl_sender_street') ?: 'Leinfeld', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_street][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Hausnummer') }}*</label>
{{ Form::text('settings[dhl_sender_house_number][val]', \App\Models\Setting::getContentBySlug('dhl_sender_house_number') ?: '2', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_house_number][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('PLZ') }}*</label>
{{ Form::text('settings[dhl_sender_postal_code][val]', \App\Models\Setting::getContentBySlug('dhl_sender_postal_code') ?: '87755', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_postal_code][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Stadt') }}*</label>
{{ Form::text('settings[dhl_sender_city][val]', \App\Models\Setting::getContentBySlug('dhl_sender_city') ?: 'Kirchhaslach', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_city][type]', 'text') }}
</div>
<div class="form-group col-sm-4">
<label class="form-label">{{ __('Land') }}*</label>
{{ Form::select('settings[dhl_sender_country][val]', [
'DE' => 'Deutschland',
'AT' => 'Österreich',
'CH' => 'Schweiz'
], \App\Models\Setting::getContentBySlug('dhl_sender_country') ?: 'DE', array('class'=>'form-control custom-select')) }}
{{ Form::hidden('settings[dhl_sender_country][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('E-Mail') }}*</label>
{{ Form::email('settings[dhl_sender_email][val]', \App\Models\Setting::getContentBySlug('dhl_sender_email') ?: 'versand@mivita.care', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_email][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Telefon') }}</label>
{{ Form::text('settings[dhl_sender_phone][val]', \App\Models\Setting::getContentBySlug('dhl_sender_phone') ?: '+49 123 456789', array('class'=>'form-control')) }}
{{ Form::hidden('settings[dhl_sender_phone][type]', 'text') }}
</div>
</div>
<!-- DHL Absenderadresse -->
<div class="form-row">
<div class="col-sm-12">
<h5>Papierformat</h5>
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Versandlabel') }}*</label>
{{ Form::select('settings[dhl_print_format][val]', [
'A4' => 'Common Label Laserdruck A4 Normalpapier',
'910-300-600' => 'Common Label Thermodruck 103 x 199 mm (910-300-600)',
'910-300-610' => 'Common Label Thermodruck 103 x 199 mm (910-300-610)',
'910-300-700' => 'Common Label Laserdruck 105 x 205 mm (DIN A5 Normalpapier, 910-300-700)',
'910-300-700-oz' => 'Common Label Laserdruck 105 x 205 mm (DIN A5 Normalpapier, 910-300-700) ohne Zusatzetiketten',
'910-300-710' => 'Common Label Laserdruck 105 x 208 mm (910-300-710)',
'910-300-300' => 'Common Label Laserdruck 105 x 148 mm (DIN A5 Normalpapier, 910-300-300)',
'910-300-300-oz' => 'Common Label Laserdruck 105 x 148 mm (DIN A5 Normalpapier, 910-300-300) ohne Zusatzetiketten',
'910-300-400' => 'Common Label Thermodruck 103 x 150 mm (910-300-400)',
'910-300-410' => 'Common Label Thermodruck 103 x 150 mm (910-300-410)',
'100x70mm' => '100x70mm',
], \App\Models\Setting::getContentBySlug('dhl_print_format') ?: 'A4', array('class'=>'form-control custom-select')) }}
{{ Form::hidden('settings[dhl_print_format][type]', 'text') }}
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ __('Retoure Label') }}*</label>
{{ Form::select('settings[dhl_retoure_print_format][val]', [
'A4' => 'Common Label Laserdruck A4 Normalpapier',
'910-300-600' => 'Common Label Thermodruck 103 x 199 mm (910-300-600)',
'910-300-610' => 'Common Label Thermodruck 103 x 199 mm (910-300-610)',
'910-300-700' => 'Common Label Laserdruck 105 x 205 mm (DIN A5 Normalpapier, 910-300-700)',
'910-300-700-oz' => 'Common Label Laserdruck 105 x 205 mm (DIN A5 Normalpapier, 910-300-700) ohne Zusatzetiketten',
'910-300-710' => 'Common Label Laserdruck 105 x 208 mm (910-300-710)',
'910-300-300' => 'Common Label Laserdruck 105 x 148 mm (DIN A5 Normalpapier, 910-300-300)',
'910-300-300-oz' => 'Common Label Laserdruck 105 x 148 mm (DIN A5 Normalpapier, 910-300-300) ohne Zusatzetiketten',
'910-300-400' => 'Common Label Thermodruck 103 x 150 mm (910-300-400)',
'910-300-410' => 'Common Label Thermodruck 103 x 150 mm (910-300-410)',
'100x70mm' => '100x70mm',
], \App\Models\Setting::getContentBySlug('dhl_retoure_print_format') ?: 'A4', array('class'=>'form-control custom-select')) }}
{{ Form::hidden('settings[dhl_retoure_print_format][type]', 'text') }}
</div>
</div>
<button type="submit" name="action" value="save_dhl" class="btn btn-primary btn-sm mb-2">
<i class="fas fa-truck"></i> DHL Einstellungen speichern
</button>
</div>
</div>
{!! Form::close() !!}

View file

@ -40,8 +40,8 @@
</form>
<div class="mt-1 text-center justify-content-center">
<button type="button" class="btn btn-outline-primary mt-2 btn-sm update_modal_data_load" data-url="{{ route('portal.loading_modal') }}" data-data="data_protection" data-target="#modal-loading">{{__('register.data_protection')}}</button>
<button type="button" class="btn btn-outline-primary mt-2 btn-sm update_modal_data_load" data-url="{{ route('portal.loading_modal') }}" data-data="imprint" data-target="#modal-loading">{{__('imprint')}}</button>
<button type="button" class="btn btn-outline-primary mt-2 btn-sm update_modal_data_load" data-url="{{ route('loading_modal') }}" data-data="data_protection" data-target="#modal-loading">{{__('register.data_protection')}}</button>
<button type="button" class="btn btn-outline-primary mt-2 btn-sm update_modal_data_load" data-url="{{ route('loading_modal') }}" data-data="imprint" data-target="#modal-loading">{{__('imprint')}}</button>
</div>
<div class="mt-1 text-center justify-content-center">
<a href="{{ Util::getMyMivitaShopUrl() }}" class="btn btn-secondary mt-2 btn-sm">{{__('portal.back_to_shop')}}</a>

View file

@ -212,6 +212,11 @@
</ul>
</li>
<li class="sidenav-item{{ Request::is('admin/dhl/*') ? ' active' : '' }}">
<a href="{{ route('admin.dhl.cockpit') }}" class="sidenav-link"><i class="sidenav-icon ion ion-md-send"></i><div>{{ __('navigation.dhl_cockpit') }}</div></a>
</li>
<li class="sidenav-item @if(Request::is('admin/payments/*')) open @endif">
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
<i class="sidenav-icon ion ion-md-cash"></i>
@ -302,6 +307,7 @@
</ul>
</li>
<li class="sidenav-item @if(Request::is('admin/sites/*')) open @endif">
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
<i class="sidenav-icon ion ion-md-albums"></i>

View file

@ -35,7 +35,7 @@
<a href="{{route('login')}}" class="btn btn-primary btn-block">{{ __('go to login') }}</a>
<a href="{{route('password.request')}}" class="btn btn-secondary btn-block">{{ __('create new password') }}</a>
<hr>
<a href="{{route('/')}}" class="btn btn-default btn-block">{{ __('back to the homepage') }}</a>
<a href="{{url('/')}}" class="btn btn-default btn-block">{{ __('back to the homepage') }}</a>
</div>
</div>

View file

@ -32,7 +32,7 @@
<p class="text-center text-big mb-4"><strong>{{ __('Page not available') }}</strong></p>
<a href="{{route('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
<a href="{{url('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
</div>
</div>

View file

@ -33,7 +33,7 @@
<p class="text-center text-big mb-4"><strong>{{ __('Thank you for your registration!') }}</strong></p>
<p class="text-center text-big mb-4">{{ __('We have sent you an e-mail with a link to activate your data.') }}</p>
<a href="{{route('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
<a href="{{url('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
</div>
</div>

View file

@ -33,7 +33,7 @@
<hr>
<p class="text-center text-big mb-4">{{ __('Now assign a password.') }}<br><br><a href="{{route('user_update_password_first')}}" class="btn btn btn-primary">{{ __('create new password') }}</a></p>
<hr>
<a href="{{route('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
<a href="{{url('/')}}" class="btn btn-primary btn-block">{{ __('back to the homepage') }}</a>
</div>
</div>

View file

@ -70,6 +70,17 @@
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
<div class="text-muted">{{ __('Status') }}</div>
<div class="text-right">
@if($user->shop->getSubdomainAvailable())
<span class="badge badge-pill badge-success"><i class="fa fa-check"> {{ __('shop.available') }} </i> </span>
@else
<span class="badge badge-pill badge-danger"><i class="fa fa-times"> {{ __('shop.not_available') }} </i> </span>
@endif
</div>
</li>
{{-- <li class="list-group-item d-flex justify-content-between align-items-center">
<div class="text-muted">{{ __('Status') }}</div>
<div class="text-right">
@if($user->shop->getSubdomainStatus())
@ -94,17 +105,13 @@
@endif
</div>
</li> --}}
<li class="list-group-item d-flex justify-content-between align-items-center">
<div class="text-muted">{{ __('shop.active_since') }}</div>
<div>
<a href="{{ route('user_shop_name_edit') }}" class="btn btn-xs btn-outline-primary"><i class="fa fa-edit"></i> Shop Name anpassen</a>
</div>
</li>
@if(!$user->shop->getSubdomainStatus() || !$user->shop->getSubdomainAvailable() || !$user->shop->getSubdomainSslSinActive())
<li class="list-group-item d-flex justify-content-between align-items-center">
<p class="text-danger">{{ __('shop.not_available_copy') }}
<a href="" class="btn icon-btn btn-xs btn-outline-primary">
<span class="lnr lnr-redo"></span>
</a>
</p>
</li>
@endif
<li class="list-group-item d-flex justify-content-between align-items-center">
<div class="text-muted">{{ __('shop.active_since') }}</div>
<div>

View file

@ -0,0 +1,174 @@
<div class="card-body" style="background: #fff; border: 1px solid rgba(24, 28, 33, 0.06);">
<h4>{{ __('shop.edit_your_shop') }}</h4>
{!! Form::open(['action' => route('user_shop_register_form'), 'class' => 'form-horizontal' , 'id'=>'data-shop-form-validations']) !!}
{{ Form::hidden('user_shop_id', $user_shop_id) }}
@php
$shop_name_btn_color = 'btn-secondary';
$shop_name_fa = '';
$shop_name_form_control = '';
@endphp
@if(Session::has('shop-name-error'))
@if(Session::get('shop-name-error') == 'check')
@php
$shop_name_btn_color = 'btn-success';
$shop_name_fa = 'fa-check';
$shop_name_form_control = ' is-valid';
@endphp
@endif
@if(Session::get('shop-name-error') == 'error')
@php
$shop_name_btn_color = 'btn-danger';
$shop_name_fa = 'fa-times';
$shop_name_form_control = ' is-invalid';
@endphp
@endif
@endif
<p class="mt-2">
{!! __('shop.open_copy_1') !!}
<br><br>
{!! __('shop.open_copy_2') !!}
<br><br>
<strong>{{ __('shop.open_note_hl') }}</strong><br>
{!! __('shop.open_note_1') !!}
<hr>
<span class="badge badge-pill badge-primary">{{ __('shop.your_current_shop_name') }}</span> <strong><a href="{{ $user_shop_domain }}" target="_blank">{{ $user_shop_domain }}</a></strong>
</p>
<div class="form-group">
<div class="input-group mt-2 mb-2 ">
{{ Form::text('user_shop_name', old('user_shop_name'), array('placeholder'=>__('shop.your_shop_name'), 'class'=>'form-control'.$shop_name_form_control.($errors->has('user_shop_name') ? ' is-invalid' : ''), 'id'=>'user_shop_name', 'tabindex' => 2)) }}
<span class="input-group-append">
<button class="btn {{ $shop_name_btn_color }}" type="submit" name="shop_submit" value="check"><i class="fa {{ $shop_name_fa }}"></i> {{ __('shop.check') }}!</button>
</span>
</div>
@if ($errors->has('user_shop_name'))
<span class="invalid-feedback" style="display: inline-block;">
<strong>{{ $errors->first('user_shop_name') }}</strong>
</span>
@endif
</div>
<div class="from-group mt-2 mb-2 ">
{{ Form::text('preview_user_shop_name', '', array('placeholder'=>__('shop.preview_shop_internet_address'), 'class'=>'form-control', 'id'=>'preview_user_shop_name', 'readonly')) }}
</div>
<div class="form-group">
<label class="custom-control custom-checkbox m-0">
<input type="checkbox" class="custom-control-input {{ $errors->has('user_shop_active') ? 'is-invalid' : '' }}" name="user_shop_active" id="user_shop_active" tabindex = "1">
<span class="custom-control-label">{!! __('shop.declaration_of_shop') !!}</span>
</label>
@if ($errors->has('user_shop_active'))
<span class="invalid-feedback" style="display: inline-block;">
<strong>{{ $errors->first('user_shop_active') }}</strong>
</span>
@endif
</div>
<hr>
<div class="text-left mt-3">
<button type="submit" class="btn btn-secondary" name="shop_submit" value="action">{{__('shop.accept_and_change') }}</button>&nbsp;
</div>
{!! Form::close() !!}
</div>
<script type="application/javascript">
$( document ).ready(function() {
$.extend( $.validator.messages, {
required: "{{__('account.validator_required')}}",
maxlength: $.validator.format( "{{__('account.validator_maxlength')}}" ),
minlength: $.validator.format( "{{__('account.validator_minlength')}}" ),
rangelength: $.validator.format( "{{__('account.validator_rangelength')}}" ),
email: "{{__('account.validator_email')}}",
url: "{{__('account.validator_url')}}",
date: "{{__('account.validator_date')}}",
number: "{{__('account.validator_number')}}",
digits: "{{__('account.validator_digits')}}",
equalTo: "{{__('account.validator_equalTo')}}",
range: $.validator.format( "{{__('account.validator_range')}}" ),
max: $.validator.format( "{{__('account.validator_max')}}" ),
min: $.validator.format( "{{__('account.validator_min')}}" ),
creditcard: "{{__('account.validator_creditcard')}}"
});
// Set up validator
var message = 'Default error message';
$('#data-shop-form-validations').validate({
rules: {
'user_shop_name': {
required: true,
remote:
{
url: "{{ route('user_shop_name_check') }}",
type: "post",
data:
{
user_shop_name: function()
{
return $('#data-shop-form-validations :input[name="user_shop_name"]').val();
}
},
encode: true,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
dataFilter: function(response) {
response = $.parseJSON(response);
console.log(response);
if (response.success === true){
$('#preview_user_shop_name').val(response.preview_user_shop_name);
return true;
}
else {
message = response.errors.user_shop_name;
$('#preview_user_shop_name').val('');
return false;
}
}
}
},
},
errorPlacement: function errorPlacement(error, element) {
$(element).parents('.form-group').find('.input-group').after(
error.addClass('invalid-feedback d-block font-weight-bold')
)
},
highlight: function (element) {
$(element).parent().find('button').removeClass('btn-success');
$(element).parent().find('button').addClass('btn-danger');
$(element).parent().find('button i').removeClass('fa-check');
$(element).parent().find('button i').addClass('fa-times');
$(element).removeClass('is-valid');
$(element).addClass('is-invalid');
},
unhighlight: function (element) {
$(element).removeClass('is-invalid');
$(element).addClass('is-valid');
$(element).parent().find('button').removeClass('btn-danger');
$(element).parent().find('button').addClass('btn-success');
$(element).parent().find('button i').removeClass('fa-times');
$(element).parent().find('button i').addClass('fa-check');
$(element).parents('.form-group').find('.is-invalid').removeClass('is-invalid');
},
messages : {
required: "{{__('This field is required.')}}",
user_shop_name: {
email: "{{ __('Please enter a valid email address.') }}",
remote : function(){ return message; }
},
},
onkeyup: function(element) {$(element).valid()},
});
});
</script>

View file

@ -27,9 +27,9 @@
<p class="mt-2">
{{ __('shop.open_copy_1') }}
{!! __('shop.open_copy_1') !!}
<br><br>
{{ __('shop.open_copy_2') }}
{!! __('shop.open_copy_2') !!}
<br><br>
<strong>{{ __('shop.open_note_hl') }}</strong><br>
{{ __('shop.open_note_1') }}

View file

@ -0,0 +1,23 @@
@extends('layouts.layout-2')
@section('content')
{{-- @if ($errors->any())
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
--}}
<h4 class="font-weight-bold py-2 mb-2">
{{ __('navigation.my_shop') }}
</h4>
@include('user.components.user_shop_edit_name')
@endsection

View file

@ -68,9 +68,10 @@
href="{{url('/geschaeftsmodell/karrierechancen')}}">{{ __('website.career_opportunities') }} </a></li>
<li class="{{ Request::is('kontakt') ? ' active' : '' }}"><a
href="{{url('/kontakt')}}">{{ __('website.contact') }} </a></li>
<li class="{{ Request::is('partner') ? ' register_user' : '' }}"><a
<li class="{{ Request::is('partner') ? ' active' : '' }}"><a
href="{{url('/partner')}}">{{ __('website.partner') }}</a></li>
<li class="{{ Request::is('register_user') ? ' active' : '' }}">
<li class="{{ Request::is('registrierung') ? ' active' : '' }}"><a
href="{{url('/registrierung')}}">{{ __('website.register') }}</a></li>
</ul>
<!-- /Links -->
</div>

View file

@ -101,7 +101,7 @@
<li class="{{ Request::is('partner') ? ' active' : '' }}"><a
href="{{url('/partner')}}">{{ __('website.partner') }}</a></li>
@if($user_shop)
<li class="{{ Request::is('register_user') ? ' active' : '' }}"><a
<li class="{{ Request::is('registrierung') ? ' active' : '' }}"><a
href="{{url('/registrierung')}}">{{ __('website.register') }}</a></li>
@endif
</ul>