gruene-seele/resources/views/admin/inventory/orders/index.blade.php
Kevin Adametz 4c73e64446 Warenwirtschaft: AP-33a — Abwicklungs-Tabelle für iPad optimiert
9 → 6 Spalten (Datum unter Bestellnr., Gewicht in die Packliste, Zahlung in
die Status-Spalte); Aktionen-Spalte sticky am rechten Rand (bleibt beim
horizontalen Scrollen sichtbar); unterhalb Desktop-Breite Icon-Buttons ohne
Beschriftung (Tooltip bleibt).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:48:52 +00:00

253 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.layout-2')
@section('content')
@include('admin.inventory.partials.wawi-ui')
<style>
/* AP-33a: iPad-Optimierung — Aktionen bleiben beim horizontalen Scrollen sichtbar */
#of-table th.of-actions,
#of-table td.of-actions {
position: sticky;
right: 0;
background: #fff;
box-shadow: -6px 0 6px -6px rgba(24, 28, 33, .15);
white-space: nowrap;
}
#of-table td { vertical-align: middle; }
@media (max-width: 1199.98px) {
.of-btn-text { display: none; }
#of-table .btn .mr-1 { margin-right: 0 !important; }
}
</style>
<div class="wawi-page">
<div class="wawi-page-head">
<div>
<h1 class="wawi-page-head__title">{{ __('Bestell-Abwicklung') }}</h1>
<p class="wawi-page-head__subtitle">{{ __('Tagesübersicht: konfektionieren, Dokumente drucken, versenden — versandfertig = bezahlt (Rechnung sofort, Vorkasse nach Zahlungseingang, API immer)') }}</p>
</div>
<div class="wawi-page-head__actions">
<a href="{{ route('admin.inventory.api-orders.index') }}" class="btn btn-outline-secondary btn-sm">
<span class="fas fa-cloud-download-alt mr-1"></span>{{ __('API-Bestellungen') }}
</a>
</div>
</div>
<div class="wawi-stats">
<a class="wawi-stat is-clickable text-reset" href="{{ route('admin.inventory.orders.index', ['filter' => 'today']) }}">
<div class="wawi-stat__icon"><span class="fas fa-inbox"></span></div>
<div class="wawi-stat__body">
<div class="wawi-stat__value">{{ $counts['today'] }}</div>
<div class="wawi-stat__label">{{ __('Heute eingegangen') }}</div>
</div>
</a>
<a class="wawi-stat wawi-stat--warning is-clickable text-reset" href="{{ route('admin.inventory.orders.index', ['filter' => 'pick']) }}">
<div class="wawi-stat__icon"><span class="fas fa-box-open"></span></div>
<div class="wawi-stat__body">
<div class="wawi-stat__value">{{ $counts['pick'] }}</div>
<div class="wawi-stat__label">{{ __('Zu konfektionieren') }}</div>
</div>
</a>
<a class="wawi-stat wawi-stat--ok is-clickable text-reset" href="{{ route('admin.inventory.orders.index', ['filter' => 'ready']) }}">
<div class="wawi-stat__icon"><span class="fas fa-truck-loading"></span></div>
<div class="wawi-stat__body">
<div class="wawi-stat__value">{{ $counts['ready'] }}</div>
<div class="wawi-stat__label">{{ __('Versandfertig') }}</div>
</div>
</a>
<a class="wawi-stat is-clickable text-reset" href="{{ route('admin.inventory.orders.index', ['filter' => 'shipped_today']) }}">
<div class="wawi-stat__icon"><span class="fas fa-shipping-fast"></span></div>
<div class="wawi-stat__body">
<div class="wawi-stat__value">{{ $counts['shipped_today'] }}</div>
<div class="wawi-stat__label">{{ __('Heute versendet') }}</div>
</div>
</a>
</div>
<div class="wawi-card">
<div class="wawi-toolbar">
<div class="d-flex align-items-center" style="gap:.75rem;">
@if ($filter !== '')
<a href="{{ route('admin.inventory.orders.index') }}" class="btn btn-sm btn-outline-secondary">
<span class="fas fa-times mr-1"></span>{{ __('Filter zurücksetzen') }}
</a>
@endif
<input type="search" id="of-search" class="form-control form-control-sm" style="width:240px"
placeholder="{{ __('Suche Bestellnr. / Kunde …') }}">
</div>
</div>
<div class="table-responsive">
<table class="table wawi-table" id="of-table">
<thead>
<tr>
<th>{{ __('Bestellung') }}</th>
<th>{{ __('Kunde') }}</th>
<th class="text-center">{{ __('Positionen') }}</th>
<th>{{ __('Status') }}</th>
<th>{{ __('Dokumente') }}</th>
<th class="text-right of-actions">{{ __('Aktionen') }}</th>
</tr>
</thead>
<tbody>
@forelse ($orders as $order)
@php
$customer = $order->shopping_user
? trim(($order->shopping_user->shipping_firstname ?: $order->shopping_user->billing_firstname ?? '').' '.($order->shopping_user->shipping_lastname ?: $order->shopping_user->billing_lastname ?? ''))
: '';
$clearingtype = $order->shopping_payment_last?->clearingtype;
$readyToShip = $order->isReadyToShip();
$itemCount = $order->shopping_order_items->sum('qty');
@endphp
<tr class="of-row" data-search="{{ mb_strtolower($order->id.' '.$customer) }}">
<td>
<a href="{{ route('admin_sales_detail', $order->id) }}">#{{ $order->id }}</a>
@if ($order->isApiOrder())
<span class="wawi-pill" style="background:rgba(24,28,33,.06);color:#6c757d;">API</span>
@elseif ($order->user_shop_id)
<span class="wawi-pill" style="background:rgba(24,28,33,.06);color:#6c757d;">{{ __('Shop') }}</span>
@elseif ($order->promotion_user_id)
<span class="wawi-pill" style="background:rgba(24,28,33,.06);color:#6c757d;">{{ __('Promo') }}</span>
@endif
<div class="small text-muted">{{ $order->created_at->format('d.m.Y H:i') }}</div>
</td>
<td>
<span class="wawi-item-name">{{ $customer !== '' ? $customer : '—' }}</span>
@if ($order->shipping_country?->country)
<span class="text-muted small">{{ strtoupper($order->shipping_country->country->code) }}</span>
@endif
</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-link p-0 js-of-toggle" data-target="of-items-{{ $order->id }}">
{{ $itemCount }} <span class="fas fa-chevron-down small"></span>
</button>
</td>
<td>
@if ((int) $order->shipped === 0)
<span class="wawi-pill wawi-pill--warning">{{ __('offen') }}</span>
@else
<span class="wawi-pill" style="background:rgba(3,155,229,.12);color:#0277bd;">{{ $order->getShippedType() }}</span>
@endif
<div class="small mt-1">
@if ($readyToShip)
<span class="wawi-pill wawi-pill--ok">{{ __('versandfertig') }}</span>
@else
<span class="wawi-pill wawi-pill--danger">{{ __('wartet auf Zahlung') }}</span>
@endif
@if ($clearingtype === 'fnc')
<span class="text-muted">{{ __('Rechnung') }}</span>
@elseif ($clearingtype === 'vor')
<span class="text-muted">{{ __('Vorkasse') }}</span>
@endif
</div>
</td>
<td style="white-space:nowrap;">
@if ($order->isApiOrder())
@if ($order->wp_invoice_path)
<a href="{{ $order->wp_invoice_path }}" target="_blank" rel="noopener" title="{{ __('Externe Rechnung (Shop)') }}">
<span class="fas fa-external-link-alt"></span> {{ __('Extern') }}
</a>
@else
<span class="text-muted small">{{ __('extern') }}</span>
@endif
@elseif (\App\Services\Invoice::isInvoice($order))
<a href="{{ route('admin.inventory.orders.document', [$order->id, 'invoice']) }}" target="_blank" title="{{ __('Rechnung') }}" class="mr-1"><span class="far fa-file-alt"></span> {{ __('Re.') }}</a>
<a href="{{ route('admin.inventory.orders.document', [$order->id, 'delivery']) }}" target="_blank" title="{{ __('Lieferschein') }}" class="mr-1"><span class="fas fa-dolly"></span> {{ __('LS') }}</a>
<a href="{{ route('admin.inventory.orders.document', [$order->id, 'combined']) }}" target="_blank" title="{{ __('Rechnung + Lieferschein') }}"><span class="fas fa-print"></span></a>
@else
<form action="{{ route('admin.inventory.orders.documents', $order->id) }}" method="post" class="d-inline">
@csrf
<input type="hidden" name="back_filter" value="{{ $filter }}">
<button type="submit" class="btn btn-sm btn-outline-secondary" title="{{ __('Rechnung + Lieferschein erstellen (ohne E-Mail-Versand)') }}"
onclick="return confirm(@json(__('Rechnung + Lieferschein jetzt erstellen? (Es wird keine E-Mail versendet — Versand wie gewohnt über die Bestell-Details.)')));">
<span class="fas fa-file-medical mr-1"></span><span class="of-btn-text">{{ __('erstellen') }}</span>
</button>
</form>
@endif
</td>
<td class="text-right of-actions">
@if ((int) $order->shipped === 0)
<form action="{{ route('admin.inventory.orders.status', $order->id) }}" method="post" class="d-inline">
@csrf
<input type="hidden" name="shipped" value="1">
<input type="hidden" name="back_filter" value="{{ $filter }}">
<button type="submit" class="btn btn-sm btn-outline-primary" title="{{ __('Als konfektioniert (in Bearbeitung) markieren') }}">
<span class="fas fa-box mr-1"></span><span class="of-btn-text">{{ __('Konfektioniert') }}</span>
</button>
</form>
@endif
@if (in_array((int) $order->shipped, [0, 1], true))
<form action="{{ route('admin.inventory.orders.status', $order->id) }}" method="post" class="d-inline"
onsubmit="return confirm(@json(__('Bestellung als versendet buchen? Der Produktbestand wird abgezogen.')));">
@csrf
<input type="hidden" name="shipped" value="2">
<input type="hidden" name="back_filter" value="{{ $filter }}">
<button type="submit" class="btn btn-sm btn-primary" title="{{ __('Als versendet buchen (Bestandsabzug)') }}">
<span class="fas fa-shipping-fast mr-1"></span><span class="of-btn-text">{{ __('Versendet') }}</span>
</button>
</form>
@endif
</td>
</tr>
<tr class="of-items d-none" id="of-items-{{ $order->id }}">
<td colspan="6" class="pl-4" style="background:rgba(24,28,33,.02);">
<strong class="small text-muted">{{ __('Packliste') }}</strong>
@if ($order->weight)
<span class="small text-muted">· {{ __('Gewicht') }}: {{ number_format($order->weight / 1000, 2, ',', '.') }} kg</span>
@endif
<ul class="mb-1 small">
@foreach ($order->shopping_order_items as $item)
<li>
{{ $item->qty }} × {{ $item->product?->name ?? __('(Produkt gelöscht)') }}
@if ($item->product?->is_set)
<span class="wawi-pill" style="background:rgba(24,28,33,.06);color:#6c757d;">SET</span>
<ul class="text-muted">
@foreach ($item->product->setItems as $component)
<li>{{ $item->qty * $component->pivot->quantity }} × {{ $component->name }}</li>
@endforeach
</ul>
@endif
</li>
@endforeach
</ul>
</td>
</tr>
@empty
<tr>
<td colspan="6">
<div class="wawi-empty">
<div><span class="fas fa-mug-hot"></span></div>
{{ __('Nichts zu tun — keine Bestellungen in diesem Filter.') }}
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if (($listLimit ?? null) !== null && $orders->count() >= $listLimit)
<p class="text-muted small px-3 pb-2 mb-0">
{{ __('Es werden die neuesten :n Bestellungen angezeigt.', ['n' => $listLimit]) }}
<a href="{{ route('admin.inventory.orders.index', array_filter(['all' => 1, 'filter' => $filter])) }}">{{ __('Alle anzeigen') }}</a>
</p>
@endif
</div>
</div>
<script>
$(function () {
$('.js-of-toggle').on('click', function () {
$('#' + $(this).data('target')).toggleClass('d-none');
});
$('#of-search').on('input', function () {
var term = ($(this).val() || '').toLowerCase().trim();
$('#of-table tbody tr.of-row').each(function () {
var show = term === '' || ($(this).data('search') || '').toString().indexOf(term) !== -1;
$(this).toggle(show);
if (!show) {
$('#of-items-' + $(this).find('a').first().text().replace('#', '')).addClass('d-none');
}
});
});
});
</script>
@endsection