Widerruf: Gesetzliche Online-Widerrufsfunktion (Formular, Bestätigungsmail, Admin-Verwaltung)

- Öffentliches Widerrufsformular /widerruf mit Bestell-Lookup (throttled)
- Bestätigungsmail an Kunde + Weiterleitung an bestellungen@ (config app.withdrawal_mail)
- Admin-Übersicht/-Detail unter /admin/withdrawals inkl. Sidenav-Eintrag
- Widerruf-Button in Portal-Bestellansicht und Footer-Links
- Model OrderWithdrawal + Migration + Factory + Tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-07-08 15:56:02 +00:00
parent 9dc138e45b
commit 83ef5f1e52
24 changed files with 1607 additions and 92 deletions

View file

@ -68,6 +68,7 @@ return [
'customerabo' => 'Kunden Abo',
'abo' => 'Abo',
'abos' => 'Abos',
'withdrawals' => 'Widerrufe',
'payment_links' => 'Bezahllinks',
'dashboard' => 'Dashboard',
'shop' => 'Shop',

View file

@ -0,0 +1,63 @@
<?php
return [
// Buttons / Navigation
'button_label' => 'Vertrag widerrufen',
'nav_title' => 'Widerruf',
// Identifikationsformular
'page_title' => 'Vertrag widerrufen',
'intro' => 'Hier kannst du deine online abgeschlossene Bestellung ganz einfach widerrufen. Bitte identifiziere zunächst deine Bestellung.',
'identify_hl' => 'Bestellung identifizieren',
'order_number' => 'Bestellnummer',
'order_number_placeholder' => 'z. B. 12345',
'order_number_help' => 'Die Bestellnummer findest du in deiner Bestellbestätigung.',
'email' => 'E-Mail-Adresse der Bestellung',
'email_placeholder' => 'deine@email.de',
'find_order' => 'Bestellung suchen',
// Bestellung gefunden / Auswahl
'order_found_hl' => 'Deine Bestellung',
'order_date' => 'Bestelldatum',
'choose_scope_hl' => 'Was möchtest du widerrufen?',
'scope_full' => 'Vollständiger Widerruf (gesamte Bestellung)',
'scope_partial' => 'Teilweiser Widerruf (einzelne Artikel)',
'select_items_hl' => 'Artikel auswählen',
'product' => 'Artikel',
'quantity' => 'Menge',
'withdraw_quantity' => 'Zu widerrufende Menge',
'reason' => 'Grund (optional)',
'reason_placeholder' => 'Du musst keinen Grund angeben. Falls du möchtest, kannst du uns hier deinen Grund mitteilen.',
'submit' => 'Widerruf verbindlich absenden',
'back' => 'Zurück',
'legal_note' => 'Mit dem Absenden erklärst du den Widerruf deines Vertrags gegenüber der mivita care gmbh, Leinfeld 2, 87755 Kirchhaslach. Du erhältst umgehend eine Eingangsbestätigung per E-Mail mit Datum und Uhrzeit.',
// Fehler
'not_found' => 'Wir konnten keine passende Bestellung zu diesen Angaben finden. Bitte prüfe Bestellnummer und E-Mail-Adresse.',
'no_items_selected' => 'Bitte wähle mindestens einen Artikel für den teilweisen Widerruf aus.',
// Erfolg / Eingangsbestätigung
'success_hl' => 'Dein Widerruf ist bei uns eingegangen',
'success_intro' => 'Vielen Dank. Wir haben deinen Widerruf erhalten und bearbeiten ihn schnellstmöglich.',
'clock' => 'Uhr',
'success_received_at' => 'Eingang deines Widerrufs',
'success_reference' => 'Vorgangsnummer',
'success_email_sent' => 'Eine Eingangsbestätigung haben wir zusätzlich an :email gesendet.',
'success_full' => 'Du hast die gesamte Bestellung widerrufen.',
'success_partial' => 'Du hast einzelne Artikel deiner Bestellung widerrufen.',
// E-Mail
'mail_subject' => 'Eingangsbestätigung deines Widerrufs',
'mail_hello' => 'Hallo',
'mail_intro' => 'wir bestätigen den Eingang deines Widerrufs zu folgender Bestellung. Dein Widerruf ist zum genannten Zeitpunkt bei uns eingegangen:',
'mail_received_at' => 'Eingegangen am',
'mail_order_number' => 'Bestellnummer',
'mail_reference' => 'Vorgangsnummer',
'mail_scope' => 'Umfang des Widerrufs',
'mail_items_hl' => 'Widerrufene Artikel',
'mail_outro' => 'Wir kümmern uns um die weitere Abwicklung und melden uns bei Bedarf bei dir.',
'mail_greetings' => 'Beste Grüße',
'mail_sender' => 'Dein mivita.care Team',
];

View file

@ -3,6 +3,7 @@
return [
'abo' => 'Subscription',
'abos' => 'Subscriptions',
'withdrawals' => 'Withdrawals',
'add' => 'add',
'attribute' => 'attributes',
'business' => 'business',

View file

@ -0,0 +1,63 @@
<?php
return [
// Buttons / Navigation
'button_label' => 'Withdraw contract',
'nav_title' => 'Withdrawals',
// Identification form
'page_title' => 'Withdraw your contract',
'intro' => 'Here you can easily withdraw the contract for an order you concluded online. Please identify your order first.',
'identify_hl' => 'Identify your order',
'order_number' => 'Order number',
'order_number_placeholder' => 'e.g. 12345',
'order_number_help' => 'You can find the order number in your order confirmation.',
'email' => 'E-mail address of the order',
'email_placeholder' => 'your@email.com',
'find_order' => 'Find order',
// Order found / selection
'order_found_hl' => 'Your order',
'order_date' => 'Order date',
'choose_scope_hl' => 'What would you like to withdraw?',
'scope_full' => 'Full withdrawal (entire order)',
'scope_partial' => 'Partial withdrawal (individual items)',
'select_items_hl' => 'Select items',
'product' => 'Item',
'quantity' => 'Quantity',
'withdraw_quantity' => 'Quantity to withdraw',
'reason' => 'Reason (optional)',
'reason_placeholder' => 'You do not have to provide a reason. If you like, you can let us know your reason here.',
'submit' => 'Submit withdrawal',
'back' => 'Back',
'legal_note' => 'By submitting, you declare the withdrawal of your contract with mivita care gmbh, Leinfeld 2, 87755 Kirchhaslach, Germany. You will immediately receive a confirmation of receipt by e-mail including date and time.',
// Errors
'not_found' => 'We could not find a matching order for these details. Please check the order number and e-mail address.',
'no_items_selected' => 'Please select at least one item for the partial withdrawal.',
// Success / confirmation
'success_hl' => 'We have received your withdrawal',
'success_intro' => 'Thank you. We have received your withdrawal and will process it as soon as possible.',
'clock' => '',
'success_received_at' => 'Receipt of your withdrawal',
'success_reference' => 'Reference number',
'success_email_sent' => 'We have also sent a confirmation of receipt to :email.',
'success_full' => 'You have withdrawn the entire order.',
'success_partial' => 'You have withdrawn individual items of your order.',
// E-mail
'mail_subject' => 'Confirmation of receipt of your withdrawal',
'mail_hello' => 'Hello',
'mail_intro' => 'we confirm receipt of your withdrawal for the following order. Your withdrawal was received by us at the time stated:',
'mail_received_at' => 'Received on',
'mail_order_number' => 'Order number',
'mail_reference' => 'Reference number',
'mail_scope' => 'Scope of withdrawal',
'mail_items_hl' => 'Withdrawn items',
'mail_outro' => 'We will take care of the further processing and will contact you if necessary.',
'mail_greetings' => 'Best regards',
'mail_sender' => 'Your mivita.care team',
];

View file

@ -0,0 +1,98 @@
@extends('layouts.layout-2')
@section('content')
<h4 class="font-weight-bold py-2 mb-2">
<a href="{{ route('admin_withdrawals') }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
{{ __('navigation.withdrawals') }} <span class="text-muted">#{{ $withdrawal->id }}</span>
</h4>
@if (Session::has('alert-success'))
<div class="alert alert-success p-2 mt-2">{{ Session::get('alert-success') }}</div>
@endif
@if (Session::has('alert-error'))
<div class="alert alert-danger p-2 mt-2">{{ Session::get('alert-error') }}</div>
@endif
<div class="row">
<div class="col-md-7">
<div class="card mb-4">
<div class="card-body">
<table class="table table-borderless mb-0">
<tr>
<th>{{ __('withdrawal.success_received_at') }}</th>
<td>{{ optional($withdrawal->declared_at)->format('d.m.Y H:i') }} {{ __('withdrawal.clock') }}</td>
</tr>
<tr>
<th>{{ __('withdrawal.order_number') }}</th>
<td>
#{{ $withdrawal->order_reference }}
@if ($withdrawal->shopping_order_id)
<a href="{{ route('admin_sales_customers_detail', [$withdrawal->shopping_order->shopping_user_id ?? 0]) }}"
class="btn btn-xs btn-outline-primary ml-1"><i class="fa fa-external-link-alt"></i></a>
@endif
</td>
</tr>
<tr>
<th>{{ __('withdrawal.choose_scope_hl') }}</th>
<td>
@if ($withdrawal->isFullWithdrawal())
{{ __('withdrawal.scope_full') }}
@else
{{ __('withdrawal.scope_partial') }}
@endif
</td>
</tr>
<tr>
<th>Kunde</th>
<td>{{ $withdrawal->customer_name }}<br><small>{{ $withdrawal->customer_email }}</small></td>
</tr>
@if ($withdrawal->user_shop)
<tr>
<th>Shop</th>
<td>{{ $withdrawal->user_shop->name }}</td>
</tr>
@endif
@if ($withdrawal->reason)
<tr>
<th>{{ __('withdrawal.reason') }}</th>
<td>{{ $withdrawal->reason }}</td>
</tr>
@endif
</table>
</div>
</div>
@if (! empty($withdrawal->items))
<div class="card mb-4">
<div class="card-header font-weight-bold">{{ __('withdrawal.mail_items_hl') }}</div>
<div class="card-body">
<ul class="mb-0">
@foreach ($withdrawal->items as $item)
<li>{{ $item['qty'] }} &times; {{ $item['name'] }}</li>
@endforeach
</ul>
</div>
</div>
@endif
</div>
<div class="col-md-5">
<div class="card mb-4">
<div class="card-header font-weight-bold">Status &amp; Notiz</div>
<div class="card-body">
{!! Form::open(['route' => ['admin_withdrawals_update', $withdrawal->id], 'method' => 'post']) !!}
<div class="form-group">
{!! Form::label('status', 'Status') !!}
{!! Form::select('status', collect($statuses)->mapWithKeys(fn ($s) => [$s => ucfirst($s)])->all(), $withdrawal->status, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('admin_note', 'Interne Notiz') !!}
{!! Form::textarea('admin_note', $withdrawal->admin_note, ['class' => 'form-control', 'rows' => 5]) !!}
</div>
<button type="submit" class="btn btn-primary"><i class="fa fa-save"></i> {{ __('save') }}</button>
{!! Form::close() !!}
</div>
</div>
</div>
</div>
@endsection

View file

@ -0,0 +1,57 @@
@extends('layouts.layout-2')
@section('content')
<h4 class="font-weight-bold py-2 mb-2">
{{ __('navigation.withdrawals') }}
</h4>
<div class="row">
<div class="col-12">
<div class="card mb-4">
<div class="card-datatable table-responsive">
<table class="datatables-withdrawals table table-striped table-bordered" id="datatables-withdrawals">
<thead>
<tr>
<th>ID</th>
<th>{{ __('withdrawal.success_received_at') }}</th>
<th>{{ __('withdrawal.order_number') }}</th>
<th>Kunde</th>
<th>{{ __('withdrawal.choose_scope_hl') }}</th>
<th>Status</th>
<th>#</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#datatables-withdrawals').DataTable({
"processing": true,
"serverSide": true,
ajax: {
url: '{!! route('admin_withdrawals_datatable') !!}',
data: function (d) {}
},
"order": [[0, "desc"]],
"columns": [
{data: 'id', name: 'id'},
{data: 'declared_at', name: 'declared_at'},
{data: 'order_reference', name: 'order_reference'},
{data: 'customer', name: 'customer'},
{data: 'type', name: 'type', searchable: false, orderable: false},
{data: 'status', name: 'status'},
{data: 'action', name: 'action', searchable: false, orderable: false},
],
"bLengthChange": false,
"iDisplayLength": 100,
"language": {
"url": "/js/datatables-{{ \App::getLocale() }}.json"
}
});
});
</script>
@endsection

View file

@ -0,0 +1,131 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>mivita.care</title>
<style type="text/css">
body {
-webkit-font-smoothing: antialiased;
width: 100%;
color: #37302d;
background: #f8f8f8;
font-size: 15px;
line-height: 26px;
}
td, h1, h2, h3 {
font-family: Helvetica, Verdana, Arial, sans-serif;
font-weight: 400;
}
.headline {
color: #37302d;
font-size: 18px;
}
.sub_headline {
color: #788662;
font-size: 15px;
}
hr {
border: none;
border-top: 1px solid #b7c59e;
}
.info-box {
padding: 20px;
border: 1px solid #eee;
background-color: #f6fdf5;
line-height: 1.6em;
}
</style>
</head>
<body style="padding:0; margin:0; background:#f8f8f8;" bgcolor="#f8f8f8">
<table align="left" cellpadding="0" cellspacing="0" width="100%" height="100%">
<tr>
<td align="left" valign="top" bgcolor="#f8f8f8" width="100%">
<br>
<table style="margin: 0 auto;" cellpadding="0" cellspacing="0" width="700">
<tr>
<td align="center" valign="top">
<img src="https://my.mivita.care/images/logo_mivita.png" alt="mivita.care" style="border:none" width="230">
<br><br>
</td>
</tr>
<tr>
<td>
<table cellpadding="10" style="padding: 10px;" cellspacing="0" border="0" width="100%" bgcolor="#ffffff">
<tr>
<td class="headline">
<b>{{ __('withdrawal.mail_hello') }} {{ $withdrawal->customer_name ?: '' }},</b>
</td>
</tr>
<tr>
<td style="color:#37302d; line-height:1.6em;">
{{ __('withdrawal.mail_intro') }}
</td>
</tr>
<tr>
<td>
<table class="info-box" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td>
<b>{{ __('withdrawal.mail_received_at') }}:</b>
{{ optional($withdrawal->declared_at)->format('d.m.Y H:i') }} {{ __('withdrawal.clock') }}<br>
<b>{{ __('withdrawal.mail_order_number') }}:</b> #{{ $withdrawal->order_reference }}<br>
<b>{{ __('withdrawal.mail_reference') }}:</b> {{ $withdrawal->id }}<br>
<b>{{ __('withdrawal.mail_scope') }}:</b>
@if ($withdrawal->isFullWithdrawal())
{{ __('withdrawal.scope_full') }}
@else
{{ __('withdrawal.scope_partial') }}
@endif
</td>
</tr>
</table>
</td>
</tr>
@if (! empty($withdrawal->items))
<tr>
<td class="sub_headline"><hr><b>{{ __('withdrawal.mail_items_hl') }}</b></td>
</tr>
<tr>
<td>
<table class="info-box" cellpadding="2" cellspacing="0" width="100%">
@foreach ($withdrawal->items as $item)
<tr>
<td>{{ $item['qty'] }} &times; {{ $item['name'] }}</td>
</tr>
@endforeach
</table>
</td>
</tr>
@endif
@if ($withdrawal->reason)
<tr>
<td style="color:#37302d; line-height:1.6em;">
<hr>{{ $withdrawal->reason }}
</td>
</tr>
@endif
<tr>
<td style="color:#37302d; line-height:1.6em;">
<hr>{{ __('withdrawal.mail_outro') }}
<br><br>
{{ __('withdrawal.mail_greetings') }}<br>
<b>{{ __('withdrawal.mail_sender') }}</b>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="color:#7B7B7E; font-size:12px; text-align: center; padding-top: 16px;" align="center">
mivita care gmbh &bull; Leinfeld 2 &bull; 87755 Kirchhaslach<br>
<a href="https://www.mivita.care" style="color: #7B7B7E;">www.mivita.care</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View file

@ -315,7 +315,7 @@
<div>{{ __('navigation.clients') }}</div>
</a>
</li>
<li class="sidenav-item @if (Request::is('admin/sales/*', 'admin/abos', 'admin/abos/*')) open @endif">
<li class="sidenav-item @if (Request::is('admin/sales/*', 'admin/abos', 'admin/abos/*', 'admin/withdrawals', 'admin/withdrawals/*')) open @endif">
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
<i class="sidenav-icon ion ion-ios-cart"></i>
<div>{{ __('navigation.orders') }}</div>
@ -341,6 +341,12 @@
<div>{{ __('navigation.abos') }}</div>
</a>
</li>
<li class="sidenav-item{{ Request::is('admin/withdrawals', 'admin/withdrawals/*') ? ' active' : '' }}">
<a href="{{ route('admin_withdrawals') }}" class="sidenav-link"><i
class="sidenav-icon ion ion-md-undo"></i>
<div>{{ __('navigation.withdrawals') }}</div>
</a>
</li>
</ul>
</li>
<li class="sidenav-item{{ Request::is('admin/dhl/*') ? ' active' : '' }}">

View file

@ -16,6 +16,16 @@
{{ __('shop.order_customer') }} <span class="text-muted">#{{$shopping_order->id}}</span>
</h4>
@include('portal.order._detail')
<a href="{{route('portal.my_orders')}}" class="btn btn-sm btn-default mt-2 float-right">{{ __('back') }}</a>
<div class="mt-2 d-flex justify-content-between align-items-center">
@if($shopping_order->payment_for === 6)
<a href="{{ route('withdrawal.create', ['order' => $shopping_order->id, 'email' => optional($shopping_order->shopping_user)->billing_email]) }}"
class="btn btn-sm btn-outline-danger">
<i class="fa fa-undo"></i> {{ __('withdrawal.button_label') }}
</a>
@else
<span></span>
@endif
<a href="{{route('portal.my_orders')}}" class="btn btn-sm btn-default">{{ __('back') }}</a>
</div>
@endsection

View file

@ -97,6 +97,9 @@
<li class=""><a target="_blank"
href="{{ asset('download/mivita_widerruf_formular.pdf') }}">{{ __('website.cancellation_policy') }} </a></li>
<li>&bull;</li>
<li class="{{ Request::is('widerruf') ? ' active' : '' }}"><a
href="{{ route('withdrawal.create') }}">{{ __('withdrawal.button_label') }} </a></li>
<li>&bull;</li>
<li class="{{ Request::is('datenschutz') ? ' active' : '' }}"><a
href="{{ url('/datenschutz') }}">{{ __('website.privacy_policy') }} </a></li>
<li>&bull;</li>

View file

@ -0,0 +1,49 @@
@extends($user_shop ? 'web.user.layouts.layout' : 'web.layouts.layout')
@section('content')
<section class="page-header page-header-xlg parallax parallax-3"
style="background-image:url('/assets/images/vision-min.jpg')">
<div class="overlay dark-1"></div>
<div class="container"></div>
</section>
<section>
<div class="container">
<div class="panel panel-default" style="max-width: 760px; margin: 0 auto;">
<div class="panel-body">
<h3><i class="fa fa-check-circle text-success"></i> {{ __('withdrawal.success_hl') }}</h3>
<p>{{ __('withdrawal.success_intro') }}</p>
<hr>
<p>
<strong>{{ __('withdrawal.success_received_at') }}:</strong>
{{ optional($withdrawal->declared_at)->format('d.m.Y H:i') }} {{ __('withdrawal.clock') }}<br>
<strong>{{ __('withdrawal.order_number') }}:</strong> #{{ $withdrawal->order_reference }}<br>
<strong>{{ __('withdrawal.success_reference') }}:</strong> {{ $withdrawal->id }}
</p>
<p>
@if ($withdrawal->isFullWithdrawal())
{{ __('withdrawal.success_full') }}
@else
{{ __('withdrawal.success_partial') }}
@endif
</p>
@if (! empty($withdrawal->items))
<ul>
@foreach ($withdrawal->items as $item)
<li>{{ $item['qty'] }} &times; {{ $item['name'] }}</li>
@endforeach
</ul>
@endif
<hr>
<p>{{ __('withdrawal.success_email_sent', ['email' => $withdrawal->customer_email]) }}</p>
</div>
</div>
</div>
</section>
@endsection

View file

@ -0,0 +1,160 @@
@extends($user_shop ? 'web.user.layouts.layout' : 'web.layouts.layout')
@section('content')
<section class="page-header page-header-xlg parallax parallax-3"
style="background-image:url('/assets/images/vision-min.jpg')">
<div class="overlay dark-1"></div>
<div class="container"></div>
</section>
<style type="text/css">
.withdrawal-box {
max-width: 760px;
margin: 0 auto;
}
.withdrawal-box .alert.error {
font-weight: bold;
}
.withdrawal-scope label {
display: block;
font-size: 15px;
margin-bottom: 8px;
}
.withdrawal-items .qty-input {
max-width: 90px;
}
.legal-note {
font-size: 13px;
color: #6b7758;
}
</style>
<section>
<div class="container">
<div class="withdrawal-box box-static box-transparent box-bordered padding-20">
<h1>{{ __('withdrawal.page_title') }}</h1>
<p>{{ __('withdrawal.intro') }}</p>
@if (session('alert-error'))
<div class="alert alert-danger error">{{ session('alert-error') }}</div>
@endif
@if (! $order)
{{-- Phase 1: Bestellung identifizieren --}}
<hr>
<h3>{{ __('withdrawal.identify_hl') }}</h3>
{!! Form::open(['route' => 'withdrawal.lookup', 'method' => 'post']) !!}
<div class="form-group">
{!! Form::label('order_number', __('withdrawal.order_number') . '*') !!}
{!! Form::text('order_number', old('order_number', $prefill_order), ['class' => 'form-control ' . ($errors->has('order_number') ? 'error is-invalid' : ''), 'placeholder' => __('withdrawal.order_number_placeholder')]) !!}
<small class="form-text text-muted">{{ __('withdrawal.order_number_help') }}</small>
@if ($errors->has('order_number'))
<div class="alert alert-danger error">{{ $errors->first('order_number') }}</div>
@endif
</div>
<div class="form-group">
{!! Form::label('email', __('withdrawal.email') . '*') !!}
{!! Form::email('email', old('email', $prefill_email), ['class' => 'form-control ' . ($errors->has('email') ? 'error is-invalid' : ''), 'placeholder' => __('withdrawal.email_placeholder')]) !!}
@if ($errors->has('email'))
<div class="alert alert-danger error">{{ $errors->first('email') }}</div>
@endif
</div>
<button type="submit" class="btn btn-primary btn-text-500">
<i class="fa fa-search"></i> {{ __('withdrawal.find_order') }}
</button>
{!! Form::close() !!}
@else
{{-- Phase 2: Umfang wählen und absenden --}}
<hr>
<h3>{{ __('withdrawal.order_found_hl') }}</h3>
<p>
<strong>{{ __('withdrawal.order_number') }}:</strong> #{{ $order->id }}<br>
<strong>{{ __('withdrawal.order_date') }}:</strong> {{ optional($order->created_at)->format('d.m.Y H:i') }}
</p>
{!! Form::open(['route' => 'withdrawal.store', 'method' => 'post']) !!}
{!! Form::hidden('order_number', $order->id) !!}
{!! Form::hidden('email', $prefill_email) !!}
<hr>
<h4>{{ __('withdrawal.choose_scope_hl') }}</h4>
<div class="withdrawal-scope">
<label class="radio">
{!! Form::radio('scope', \App\Models\OrderWithdrawal::TYPE_FULL, old('scope', 'full') === 'full', ['id' => 'scope_full']) !!}
<i></i> {{ __('withdrawal.scope_full') }}
</label>
<label class="radio">
{!! Form::radio('scope', \App\Models\OrderWithdrawal::TYPE_PARTIAL, old('scope') === 'partial', ['id' => 'scope_partial']) !!}
<i></i> {{ __('withdrawal.scope_partial') }}
</label>
@if ($errors->has('scope'))
<div class="alert alert-danger error">{{ $errors->first('scope') }}</div>
@endif
</div>
<div id="withdrawal_items" class="withdrawal-items" style="display: none;">
<hr>
<h4>{{ __('withdrawal.select_items_hl') }}</h4>
<table class="table table-striped">
<thead>
<tr>
<th>{{ __('withdrawal.product') }}</th>
<th class="text-center">{{ __('withdrawal.quantity') }}</th>
<th class="text-center">{{ __('withdrawal.withdraw_quantity') }}</th>
</tr>
</thead>
<tbody>
@foreach ($order->shopping_order_items as $item)
<tr>
<td>{{ $item->product?->getLang('name') ?? ('#' . $item->product_id) }}</td>
<td class="text-center">{{ (int) $item->qty }}</td>
<td class="text-center">
{!! Form::number('items[' . $item->id . ']', old('items.' . $item->id, 0), ['class' => 'form-control qty-input mx-auto', 'min' => 0, 'max' => (int) $item->qty]) !!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<hr>
<div class="form-group">
{!! Form::label('reason', __('withdrawal.reason')) !!}
{!! Form::textarea('reason', old('reason'), ['class' => 'form-control', 'rows' => 3, 'placeholder' => __('withdrawal.reason_placeholder')]) !!}
</div>
<p class="legal-note">{{ __('withdrawal.legal_note') }}</p>
<div class="mt-3">
<a href="{{ route('withdrawal.create') }}" class="btn btn-default btn-text-500">
<i class="fa fa-angle-left"></i> {{ __('withdrawal.back') }}
</a>
<button type="submit" class="btn btn-primary btn-text-500">
<i class="fa fa-check"></i> {{ __('withdrawal.submit') }}
</button>
</div>
{!! Form::close() !!}
@endif
</div>
</div>
</section>
@endsection
@section('scripts')
<script>
$(document).ready(function () {
function toggleItems() {
if ($('#scope_partial').is(':checked')) {
$('#withdrawal_items').show();
} else {
$('#withdrawal_items').hide();
}
}
$('input[type=radio][name=scope]').on('change', toggleItems);
toggleItems();
});
</script>
@endsection

View file

@ -138,6 +138,9 @@
<li class=""><a target="_blank"
href="{{ asset('download/mivita_widerruf_formular.pdf') }}">{{ __('website.cancellation_policy') }}</a></li>
<li>&bull;</li>
<li class="{{ Request::is('widerruf') ? ' active' : '' }}"><a
href="{{ route('withdrawal.create') }}">{{ __('withdrawal.button_label') }}</a></li>
<li>&bull;</li>
<li class="{{ Request::is('datenschutz') ? ' active' : '' }}"><a
href="{{ legal_url('/datenschutz') }}">{{ __('website.privacy_policy') }}</a></li>
<li>&bull;</li>