10.April 2026
This commit is contained in:
parent
a00c42e770
commit
f58c709945
208 changed files with 19280 additions and 2914 deletions
|
|
@ -1,22 +1,30 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
<a href="{{route('admin_abos')}}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
{{ __('navigation.abo') }} <span class="text-muted">{{ '#'.$user_abo->payone_userid }}</span>
|
||||
<a href="{{ route('admin_abos') }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
{{ __('navigation.abo') }} <span class="text-muted">{{ '#' . $user_abo->payone_userid }}</span>
|
||||
</h4>
|
||||
|
||||
|
||||
@if(Session::has('alert-error'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-error') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if (Session::has('alert-error'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-error') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if (Session::has('alert-warning'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-warning p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-warning') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card">
|
||||
@include('admin.abo._detail')
|
||||
</div>
|
||||
|
|
@ -27,20 +35,24 @@
|
|||
@include('admin.customer._customer_detail', ['shopping_user' => $customer_detail])
|
||||
</div>
|
||||
|
||||
{!! Form::open(['action' => route('user_abos_update', [$view, $user_abo->id]), 'class' => 'form-horizontal', 'id'=>'cart-order-form']) !!}
|
||||
<input type="hidden" name="is_for" value="{{ $user_abo->is_for }}">
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._order_abo')
|
||||
{!! Form::open([
|
||||
'action' => route('user_abos_update', [$view, $user_abo->id]),
|
||||
'class' => 'form-horizontal',
|
||||
'id' => 'cart-order-form',
|
||||
]) !!}
|
||||
<input type="hidden" name="is_for" value="{{ $user_abo->is_for }}">
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._order_abo')
|
||||
</div>
|
||||
|
||||
@if ($comp_products && Yard::instance('shopping')->getNumComp() > 0)
|
||||
<div id="holder_html_view_comp_product">
|
||||
@include('user.order.comp_product')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($comp_products && Yard::instance('shopping')->getNumComp() > 0)
|
||||
<div id="holder_html_view_comp_product">
|
||||
@include('user.order.comp_product')
|
||||
</div>
|
||||
@endif
|
||||
{{ Form::close() }}
|
||||
|
||||
{{ Form::close() }}
|
||||
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._initial_composition')
|
||||
</div>
|
||||
|
|
@ -54,48 +66,49 @@
|
|||
</div>
|
||||
|
||||
|
||||
<a href="{{route('admin_abos')}}" class="btn btn-sm btn-default mt-2 float-right">{{ __('back') }}</a>
|
||||
<a href="{{ route('admin_abos') }}" class="btn btn-sm btn-default mt-2 float-right">{{ __('back') }}</a>
|
||||
|
||||
<div class="modal fade" id="modal-confirm-add" tabindex="-1" role="dialog" aria-labelledby="modal-confirm-add-label" aria-hidden="true"
|
||||
data-title-add-only="{{ __('abo.confirm_add_title') }}"
|
||||
data-title-normal="{{ __('abo.confirm_add_title_normal') }}"
|
||||
data-warning-add-only="{{ __('abo.confirm_add_warning') }}"
|
||||
data-warning-normal="{{ __('abo.confirm_add_warning_normal') }}">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modal-confirm-add-label"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning mb-3">
|
||||
<i class="fa fa-exclamation-triangle"></i> <span id="confirm-add-warning-text"></span>
|
||||
<div class="modal fade" id="modal-confirm-add" tabindex="-1" role="dialog" aria-labelledby="modal-confirm-add-label"
|
||||
aria-hidden="true" data-title-add-only="{{ __('abo.confirm_add_title') }}"
|
||||
data-title-normal="{{ __('abo.confirm_add_title_normal') }}"
|
||||
data-warning-add-only="{{ __('abo.confirm_add_warning') }}"
|
||||
data-warning-normal="{{ __('abo.confirm_add_warning_normal') }}">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modal-confirm-add-label"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning mb-3">
|
||||
<i class="fa fa-exclamation-triangle"></i> <span id="confirm-add-warning-text"></span>
|
||||
</div>
|
||||
<table class="table table-sm mb-0">
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('order.article') }}:</td>
|
||||
<td id="confirm-add-product-name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.price') }}:</td>
|
||||
<td id="confirm-add-product-price"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.quantity') }}:</td>
|
||||
<td id="confirm-add-qty-info"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default"
|
||||
data-dismiss="modal">{{ __('abo.confirm_add_cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary"
|
||||
id="confirm-add-btn">{{ __('abo.confirm_add_ok') }}</button>
|
||||
</div>
|
||||
<table class="table table-sm mb-0">
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('order.article') }}:</td>
|
||||
<td id="confirm-add-product-name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.price') }}:</td>
|
||||
<td id="confirm-add-product-price"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.quantity') }}:</td>
|
||||
<td id="confirm-add-qty-info"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('abo.confirm_add_cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary" id="confirm-add-btn">{{ __('abo.confirm_add_ok') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
|
|
@ -107,4 +120,4 @@
|
|||
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -9,33 +9,48 @@
|
|||
<div class="card mb-4">
|
||||
<h5 class="card-header">Struktur</h5>
|
||||
<div class="card-body">
|
||||
<button type="button" id="" data-save="navigation-structure" class="btn btn-primary nestable_list_menu_save">{{ __('save') }}</button>
|
||||
<button type="button" id="" data-save="navigation-structure"
|
||||
class="btn btn-primary nestable_list_menu_save">{{ __('save') }}</button>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="white-box">
|
||||
<div class="custom-dd dd" id="nestable_list_1" data-href-save="{{ route('admin_downloadcenter_item_store', ['structure'])}}">
|
||||
<div class="custom-dd dd" id="nestable_list_1"
|
||||
data-href-save="{{ route('admin_downloadcenter_item_store', ['structure']) }}">
|
||||
<ol class="dd-list">
|
||||
@if(count($category_active))
|
||||
@foreach($category_active as $category)
|
||||
<li class="dd-item" data-id="{{ $category->id }}" data-name="{{ $category->slug }}">
|
||||
<span class="pull-right">
|
||||
<a href="#" class="btn btn-sm mt-1 nestable_update_btn" data-action="update-category-active" data-target="self" data-id="{{ $category->id }}" data-url="{{ route('admin_downloadcenter_item_store', ['update_ajax']) }}">
|
||||
@if($category->active) <i class="fa fa-eye text-success"></i> @else <i class="fa fa-eye-slash text-danger"></i> @endif
|
||||
</a>
|
||||
<a href="{{ route('admin_downloadcenter_item_delete', ['obj' => 'category', 'id'=> $category->id])}}" class="btn btn-sm mt-1 nestable_list_delete"><i class="fa fa-trash text-danger"></i></a>
|
||||
</span>
|
||||
@if (count($category_active))
|
||||
@foreach ($category_active as $category)
|
||||
<li class="dd-item" data-id="{{ $category->id }}"
|
||||
data-name="{{ $category->slug }}">
|
||||
<div style="display: inline-block;">
|
||||
<div class="ml-4">
|
||||
<a href="#"
|
||||
class="btn btn-sm mt-1 mt-0 nestable_update_btn"
|
||||
data-action="update-category-active" data-target="self"
|
||||
data-id="{{ $category->id }}"
|
||||
data-url="{{ route('admin_downloadcenter_item_store', ['update_ajax']) }}">
|
||||
@if ($category->active)
|
||||
<i class="fa fa-eye text-success"></i>
|
||||
@else
|
||||
<i class="fa fa-eye-slash text-danger"></i>
|
||||
@endif
|
||||
</a>
|
||||
<a href="{{ route('admin_downloadcenter_item_delete', ['obj' => 'category', 'id' => $category->id]) }}"
|
||||
class="btn btn-sm mt-1 mt-0 nestable_list_delete"><i
|
||||
class="fa fa-trash text-danger"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dd-handle">
|
||||
<strong> {{ $category->name }} </strong>
|
||||
<strong> {{ $category->name }} </strong>
|
||||
</div>
|
||||
<ol class="dd-list">
|
||||
{!! \App\Services\DcHelper::makeNestableList($category->id) !!}
|
||||
{!! \App\Services\DcHelper::makeNestableList($category->id) !!}
|
||||
<li class="dd-item" data-id="0">
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,23 +62,27 @@
|
|||
<ol class="dd-list">
|
||||
<li class="dd-item" data-id="0">
|
||||
<div class="dd-handle dd-nodrag">
|
||||
<strong><em> Neue Tags </em></strong>
|
||||
<strong><em> Neue Tags </em></strong>
|
||||
</div>
|
||||
<ol class="dd-list">
|
||||
@if(count($tags_inactive))
|
||||
@foreach($tags_inactive as $tag)
|
||||
<li class="dd-item" data-id="{{ $tag->id }}">
|
||||
<span class="pull-right">
|
||||
<a href="{{ route('admin_downloadcenter_item_delete', ['obj' => 'tag', 'id'=> $tag->id])}}" class="btn btn-sm nestable_list_delete"><i class="fa fa-trash text-danger"></i></a>
|
||||
</span>
|
||||
<div class="dd-handle">
|
||||
{{ $tag->name }}
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
@if (count($tags_inactive))
|
||||
@foreach ($tags_inactive as $tag)
|
||||
<li class="dd-item" data-id="{{ $tag->id }}">
|
||||
<div style="display: inline-block; width: 100%;">
|
||||
<div class="float-right">
|
||||
<a href="{{ route('admin_downloadcenter_item_delete', ['obj' => 'tag', 'id' => $tag->id]) }}"
|
||||
class="btn btn-sm nestable_list_delete"><i
|
||||
class="fa fa-trash text-danger"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dd-handle">
|
||||
{{ $tag->name }}
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
<li class="dd-item " data-id="0">
|
||||
|
||||
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
|
|
@ -73,16 +92,20 @@
|
|||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" id="" data-save="navigation-structure" class="btn btn-primary nestable_list_menu_save">{{ __('save') }}</button>
|
||||
<button type="button" id="" data-save="navigation-structure"
|
||||
class="btn btn-primary nestable_list_menu_save">{{ __('save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
{!! Form::open(['action' => route('admin_downloadcenter_item_store', ['category']), 'class' => 'form-horizontal']) !!}
|
||||
{!! Form::open([
|
||||
'action' => route('admin_downloadcenter_item_store', ['category']),
|
||||
'class' => 'form-horizontal',
|
||||
]) !!}
|
||||
<label class="form-label" for="dc_category_name">Neue Katagorie anlegen</label>
|
||||
{{ Form::text('dc_category_name', '', array('placeholder'=>'Bezeichung Katagorie', 'class'=>'form-control', 'id'=>'dc_category_name')) }}
|
||||
{{ Form::text('dc_category_name', '', ['placeholder' => 'Bezeichung Katagorie', 'class' => 'form-control', 'id' => 'dc_category_name']) }}
|
||||
<button type="submit" class="btn btn-submit mt-4">{{ __('save') }}</button>
|
||||
{!! Form::close() !!}
|
||||
<br>
|
||||
|
|
@ -90,7 +113,7 @@
|
|||
<br>
|
||||
{!! Form::open(['action' => route('admin_downloadcenter_item_store', ['tag']), 'class' => 'form-horizontal']) !!}
|
||||
<label class="form-label" for="dc_tag_name">Neuen Tag anlegen</label>
|
||||
{{ Form::text('dc_tag_name', '', array('placeholder'=>'Bezeichung Tag', 'class'=>'form-control', 'id'=>'dc_tag_name')) }}
|
||||
{{ Form::text('dc_tag_name', '', ['placeholder' => 'Bezeichung Tag', 'class' => 'form-control', 'id' => 'dc_tag_name']) }}
|
||||
<button type="submit" class="btn btn-submit mt-4">{{ __('save') }}</button>
|
||||
{!! Form::close() !!}
|
||||
<br>
|
||||
|
|
@ -101,19 +124,18 @@
|
|||
@endsection
|
||||
|
||||
@section('styles')
|
||||
<link rel="stylesheet" href="/vendor/libs/nestable/nestable.css">
|
||||
<style>
|
||||
.dd-list {
|
||||
min-width: auto;
|
||||
}
|
||||
.dd-nodrag{
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/vendor/libs/nestable/nestable.css">
|
||||
<style>
|
||||
.dd-list {
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.dd-nodrag {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
@section('scripts')
|
||||
|
||||
<script src="/vendor/libs/nestable/jquery-nestable-full.js?v=1"></script>
|
||||
<script src="/js/nestable-init.js?v=1"></script>
|
||||
|
||||
@endsection
|
||||
<script src="/vendor/libs/nestable/jquery-nestable-full.js?v=1"></script>
|
||||
<script src="/js/nestable-init.js?v=1"></script>
|
||||
@endsection
|
||||
|
|
|
|||
214
resources/views/admin/incentive/_form.blade.php
Normal file
214
resources/views/admin/incentive/_form.blade.php
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- ===== KONFIGURATION ===== --}}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="ion ion-md-settings mr-1"></i>
|
||||
<strong>{{ __('incentive.configuration') }}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-8">
|
||||
<label for="name">{{ __('incentive.name') }} *</label>
|
||||
<input type="text" class="form-control" id="name" name="name"
|
||||
value="{{ old('name', $incentive->name ?? '') }}" required>
|
||||
<small class="form-text text-muted">{{ __('incentive.name_help') }}</small>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="status">{{ __('incentive.status') }} *</label>
|
||||
<select class="custom-select" id="status" name="status" required>
|
||||
@foreach (\App\Models\Incentive::$statusTypes as $key => $label)
|
||||
<option value="{{ $key }}" @if (old('status', $incentive->status ?? 0) == $key) selected @endif>
|
||||
{{ __('incentive.status_' . $label) }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="qualification_start">{{ __('incentive.qualification_start') }} *</label>
|
||||
{!! Form::text(
|
||||
'qualification_start',
|
||||
old(
|
||||
'qualification_start',
|
||||
isset($incentive->qualification_start) ? $incentive->qualification_start->format('d.m.Y') : '',
|
||||
),
|
||||
[
|
||||
'class' => 'form-control datepicker-base',
|
||||
'required' => true,
|
||||
],
|
||||
) !!}
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="qualification_end">{{ __('incentive.qualification_end') }} *</label>
|
||||
{!! Form::text(
|
||||
'qualification_end',
|
||||
old(
|
||||
'qualification_end',
|
||||
isset($incentive->qualification_end) ? $incentive->qualification_end->format('d.m.Y') : '',
|
||||
),
|
||||
[
|
||||
'class' => 'form-control datepicker-base',
|
||||
'required' => true,
|
||||
],
|
||||
) !!}
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="calculation_end">{{ __('incentive.calculation_end') }} *</label>
|
||||
{!! Form::text(
|
||||
'calculation_end',
|
||||
old('calculation_end', isset($incentive->calculation_end) ? $incentive->calculation_end->format('d.m.Y') : ''),
|
||||
[
|
||||
'class' => 'form-control datepicker-base',
|
||||
'required' => true,
|
||||
],
|
||||
) !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="points_partner_onetime">{{ __('incentive.points_partner_onetime') }} *</label>
|
||||
<input type="number" class="form-control" id="points_partner_onetime" name="points_partner_onetime"
|
||||
value="{{ old('points_partner_onetime', $incentive->points_partner_onetime ?? 600) }}"
|
||||
min="0" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="points_abo_onetime">{{ __('incentive.points_abo_onetime') }} *</label>
|
||||
<input type="number" class="form-control" id="points_abo_onetime" name="points_abo_onetime"
|
||||
value="{{ old('points_abo_onetime', $incentive->points_abo_onetime ?? 400) }}" min="0"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="max_winners">{{ __('incentive.max_winners') }} *</label>
|
||||
<input type="number" class="form-control" id="max_winners" name="max_winners"
|
||||
value="{{ old('max_winners', $incentive->max_winners ?? 30) }}" min="1" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="min_direct_partners">{{ __('incentive.min_direct_partners') }} *</label>
|
||||
<input type="number" class="form-control" id="min_direct_partners" name="min_direct_partners"
|
||||
value="{{ old('min_direct_partners', $incentive->min_direct_partners ?? 4) }}" min="0"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="min_customer_abos">{{ __('incentive.min_customer_abos') }} *</label>
|
||||
<input type="number" class="form-control" id="min_customer_abos" name="min_customer_abos"
|
||||
value="{{ old('min_customer_abos', $incentive->min_customer_abos ?? 6) }}" min="0" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-0">
|
||||
<label for="image">{{ __('incentive.image') }}</label>
|
||||
<input type="text" class="form-control" id="image" name="image"
|
||||
value="{{ old('image', $incentive->image ?? '') }}">
|
||||
<small class="form-text text-muted">{{ __('incentive.image_help') }}</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ===== INHALTE: DEUTSCH (Standard) ===== --}}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<i class="ion ion-md-flag mr-1"></i>
|
||||
<strong>{{ __('incentive.content_lang_de') }}</strong>
|
||||
<span class="badge badge-light ml-1">{{ __('incentive.default_language') }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="subtitle">{{ __('incentive.subtitle') }}</label>
|
||||
<input type="text" class="form-control" id="subtitle" name="subtitle"
|
||||
value="{{ old('subtitle', $incentive->subtitle ?? '') }}"
|
||||
placeholder="{{ __('incentive.subtitle_placeholder') }}">
|
||||
<small class="form-text text-muted">{{ __('incentive.subtitle_help') }}</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">
|
||||
<i class="ion ion-md-text mr-1"></i>
|
||||
{{ __('incentive.description') }}
|
||||
</label>
|
||||
<textarea class="form-control summernote-small" id="description" name="description" rows="6">{{ old('description', $incentive->description ?? '') }}</textarea>
|
||||
<small class="form-text text-muted">{{ __('incentive.description_help') }}</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-0">
|
||||
<label for="terms">
|
||||
<i class="ion ion-md-document mr-1"></i>
|
||||
{{ __('incentive.terms') }}
|
||||
</label>
|
||||
<textarea class="form-control summernote-small" id="terms" name="terms" rows="8">{{ old('terms', $incentive->terms ?? '') }}</textarea>
|
||||
<small class="form-text text-muted">{{ __('incentive.terms_help') }}</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ===== INHALTE: WEITERE SPRACHEN ===== --}}
|
||||
@foreach ($languages as $locale => $localeData)
|
||||
@if ($locale !== 'de')
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="ion ion-md-flag mr-1"></i>
|
||||
<strong>{{ $localeData['native'] }}</strong>
|
||||
<span class="badge badge-secondary ml-1">{{ strtoupper($locale) }}</span>
|
||||
<small class="text-muted ml-2">{{ __('incentive.lang_fallback_hint') }}</small>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@php $existingIncentive = $incentive ?? null; @endphp
|
||||
|
||||
<div class="form-group">
|
||||
<label for="trans_name_{{ $locale }}">{{ __('incentive.name') }}</label>
|
||||
<input type="text" class="form-control" id="trans_name_{{ $locale }}"
|
||||
name="trans_name_{{ $locale }}"
|
||||
value="{{ old('trans_name_' . $locale, $existingIncentive ? $existingIncentive->getTrans('name', $locale) : '') }}"
|
||||
placeholder="{{ $existingIncentive->name ?? '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="trans_subtitle_{{ $locale }}">{{ __('incentive.subtitle') }}</label>
|
||||
<input type="text" class="form-control" id="trans_subtitle_{{ $locale }}"
|
||||
name="trans_subtitle_{{ $locale }}"
|
||||
value="{{ old('trans_subtitle_' . $locale, $existingIncentive ? $existingIncentive->getTrans('subtitle', $locale) : '') }}"
|
||||
placeholder="{{ $existingIncentive->subtitle ?? __('incentive.subtitle_placeholder') }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="trans_description_{{ $locale }}">
|
||||
<i class="ion ion-md-text mr-1"></i>
|
||||
{{ __('incentive.description') }}
|
||||
</label>
|
||||
<textarea class="form-control summernote-small" id="trans_description_{{ $locale }}"
|
||||
name="trans_description_{{ $locale }}" rows="6">{{ old('trans_description_' . $locale, $existingIncentive ? $existingIncentive->getTrans('description', $locale) : '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-0">
|
||||
<label for="trans_terms_{{ $locale }}">
|
||||
<i class="ion ion-md-document mr-1"></i>
|
||||
{{ __('incentive.terms') }}
|
||||
</label>
|
||||
<textarea class="form-control summernote-small" id="trans_terms_{{ $locale }}" name="trans_terms_{{ $locale }}"
|
||||
rows="8">{{ old('trans_terms_' . $locale, $existingIncentive ? $existingIncentive->getTrans('terms', $locale) : '') }}</textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
<hr class="mb-3">
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
{{-- Zusammenfassung --}}
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center bg-light">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">{{ __('incentive.total_points') }}</small>
|
||||
<h4 class="mb-0 font-weight-bold">{{ number_format($participant->total_points, 0, ',', '.') }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center bg-light">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">{{ __('incentive.rank') }}</small>
|
||||
<h4 class="mb-0 font-weight-bold">{{ $participant->rank ?? '-' }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center bg-light">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">{{ __('incentive.partners') }}</small>
|
||||
<h4 class="mb-0 font-weight-bold {{ $participant->qualified_partners >= $incentive->min_direct_partners ? 'text-success' : 'text-danger' }}">
|
||||
{{ $participant->qualified_partners }}/{{ $incentive->min_direct_partners }}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center bg-light">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">{{ __('incentive.abos') }}</small>
|
||||
<h4 class="mb-0 font-weight-bold {{ $participant->qualified_abos >= $incentive->min_customer_abos ? 'text-success' : 'text-danger' }}">
|
||||
{{ $participant->qualified_abos }}/{{ $incentive->min_customer_abos }}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Sektion A: Neupartner-Punkte --}}
|
||||
<h6 class="font-weight-bold">{{ __('incentive.section_partners') }}</h6>
|
||||
<div class="mb-3">
|
||||
@include('partials.incentive._source_table', [
|
||||
'sources' => $partner_sources,
|
||||
'type' => 'partner',
|
||||
'label_header' => __('incentive.new_partner'),
|
||||
'date_header' => __('incentive.entry_date'),
|
||||
'empty_message' => __('incentive.no_partners_yet'),
|
||||
])
|
||||
</div>
|
||||
|
||||
{{-- Sektion B: Kundenabo-Punkte --}}
|
||||
<h6 class="font-weight-bold">{{ __('incentive.section_abos') }}</h6>
|
||||
@include('partials.incentive._source_table', [
|
||||
'sources' => $abo_sources,
|
||||
'type' => 'abo',
|
||||
'label_header' => __('incentive.customer_abo'),
|
||||
'date_header' => __('incentive.abo_date'),
|
||||
'empty_message' => __('incentive.no_abos_yet'),
|
||||
])
|
||||
18
resources/views/admin/incentive/create.blade.php
Normal file
18
resources/views/admin/incentive/create.blade.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
{{ __('incentive.create') }}
|
||||
</h4>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin_incentive_store') }}" method="POST">
|
||||
@csrf
|
||||
@include('admin.incentive._form')
|
||||
<button type="submit" class="btn btn-success">{{ __('incentive.save') }}</button>
|
||||
<a href="{{ route('admin_incentives') }}" class="btn btn-default">{{ __('incentive.cancel') }}</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
18
resources/views/admin/incentive/edit.blade.php
Normal file
18
resources/views/admin/incentive/edit.blade.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
{{ __('incentive.edit') }}: {{ $incentive->name }}
|
||||
</h4>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin_incentive_update', [$incentive->id]) }}" method="POST">
|
||||
@csrf
|
||||
@include('admin.incentive._form', ['incentive' => $incentive])
|
||||
<button type="submit" class="btn btn-success">{{ __('incentive.save') }}</button>
|
||||
<a href="{{ route('admin_incentive_show', [$incentive->id]) }}" class="btn btn-default">{{ __('incentive.cancel') }}</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
51
resources/views/admin/incentive/index.blade.php
Normal file
51
resources/views/admin/incentive/index.blade.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
{{ __('incentive.incentives') }}
|
||||
<a href="{{ route('admin_incentive_create') }}" class="btn btn-sm btn-success float-right">
|
||||
<span class="fa fa-plus"></span> {{ __('incentive.create') }}
|
||||
</a>
|
||||
</h4>
|
||||
<div class="card">
|
||||
<div class="card-datatable table-responsive">
|
||||
<table class="table table-striped table-bordered" id="datatable-incentives">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ __('incentive.name') }}</th>
|
||||
<th>{{ __('incentive.status') }}</th>
|
||||
<th>{{ __('incentive.period') }}</th>
|
||||
<th>{{ __('incentive.participants') }}</th>
|
||||
<th>{{ __('incentive.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#datatable-incentives').DataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
ajax: {
|
||||
url: '{!! route('admin_incentives_datatable') !!}'
|
||||
},
|
||||
"order": [[0, "desc"]],
|
||||
"columns": [
|
||||
{ data: 'id', name: 'id' },
|
||||
{ data: 'name', name: 'name' },
|
||||
{ data: 'status_label', name: 'status_label', searchable: false },
|
||||
{ data: 'period', name: 'period', searchable: false, orderable: false },
|
||||
{ data: 'participants_count', name: 'participants_count', searchable: false, orderable: false },
|
||||
{ data: 'action', name: 'action', searchable: false, orderable: false }
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 50,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
191
resources/views/admin/incentive/show.blade.php
Normal file
191
resources/views/admin/incentive/show.blade.php
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
{{ $incentive->name }}
|
||||
<span class="badge badge-{{ $incentive->getStatusColor() }}">{{ $incentive->getStatusType() }}</span>
|
||||
<div class="float-right">
|
||||
<a href="{{ route('admin_incentive_edit', [$incentive->id]) }}" class="btn btn-sm btn-warning">
|
||||
<span class="fa fa-edit"></span> {{ __('incentive.edit') }}
|
||||
</a>
|
||||
{{-- <form action="{{ route('admin_incentive_recalculate', [$incentive->id]) }}" method="POST" class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-info" onclick="return confirm('{{ __('incentive.recalculate_confirm') }}')">
|
||||
<span class="fa fa-sync"></span> {{ __('incentive.recalculate') }}
|
||||
</button>
|
||||
</form>
|
||||
<form action="{{ route('admin_incentive_recalculate', [$incentive->id]) }}" method="POST" class="d-inline">
|
||||
@csrf
|
||||
<input type="hidden" name="force" value="1">
|
||||
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('{{ __('incentive.force_recalculate_confirm') }}')">
|
||||
<span class="fa fa-redo"></span> {{ __('incentive.force_recalculate') }}
|
||||
</button>
|
||||
</form> --}}
|
||||
</div>
|
||||
</h4>
|
||||
|
||||
{{-- Konfiguration --}}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">{{ __('incentive.configuration') }}</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<strong>{{ __('incentive.qualification_start') }}:</strong>
|
||||
{{ $incentive->qualification_start->format('d.m.Y') }}<br>
|
||||
<strong>{{ __('incentive.qualification_end') }}:</strong>
|
||||
{{ $incentive->qualification_end->format('d.m.Y') }}<br>
|
||||
<strong>{{ __('incentive.calculation_end') }}:</strong>
|
||||
{{ $incentive->calculation_end->format('d.m.Y') }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>{{ __('incentive.points_partner_onetime') }}:</strong>
|
||||
{{ $incentive->points_partner_onetime }}<br>
|
||||
<strong>{{ __('incentive.points_abo_onetime') }}:</strong> {{ $incentive->points_abo_onetime }}<br>
|
||||
<strong>{{ __('incentive.max_winners') }}:</strong> {{ $incentive->max_winners }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>{{ __('incentive.min_direct_partners') }}:</strong> {{ $incentive->min_direct_partners }}<br>
|
||||
<strong>{{ __('incentive.min_customer_abos') }}:</strong> {{ $incentive->min_customer_abos }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Ranking --}}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{{ __('incentive.ranking') }} ({{ $participants->count() }} {{ __('incentive.participants') }})
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<table class="table table-striped table-bordered mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('incentive.rank') }}</th>
|
||||
<th>{{ __('incentive.consultant') }}</th>
|
||||
<th>E-Mail</th>
|
||||
<th>{{ __('incentive.admin_terms_accepted') }}</th>
|
||||
<th>{{ __('incentive.total_points') }}</th>
|
||||
<th>{{ __('incentive.partners') }}</th>
|
||||
<th>{{ __('incentive.abos') }}</th>
|
||||
<th>{{ __('incentive.qualified') }}</th>
|
||||
<th>{{ __('incentive.status') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($participants as $p)
|
||||
@php
|
||||
$isWinner = $p->is_qualified && $p->rank && $p->rank <= $incentive->max_winners;
|
||||
@endphp
|
||||
<tr
|
||||
class="{{ $isWinner ? 'table-success font-weight-bold' : ($p->is_qualified ? 'font-weight-bold' : '') }}">
|
||||
<td>{{ $p->rank ?? '—' }}</td>
|
||||
<td>
|
||||
@if ($p->user && $p->user->account)
|
||||
{{ $p->user->account->first_name }} {{ $p->user->account->last_name }}
|
||||
@else
|
||||
{{ $p->user->email ?? 'N/A' }}
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $p->user->email ?? '' }}</td>
|
||||
<td>
|
||||
@if ($p->accepted_terms_at)
|
||||
<span class="badge badge-success">{{ __('incentive.yes') }}</span>
|
||||
<span class="text-muted small d-block"
|
||||
title="{{ __('incentive.admin_terms_accepted_at_tooltip') }}">{{ $p->accepted_terms_at->format('d.m.Y H:i') }}</span>
|
||||
@else
|
||||
<span class="badge badge-secondary">{{ __('incentive.admin_terms_pending') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ number_format($p->total_points, 0, ',', '.') }}</td>
|
||||
<td>
|
||||
{{ $p->qualified_partners }}/{{ $incentive->min_direct_partners }}
|
||||
@if ($p->qualified_partners >= $incentive->min_direct_partners)
|
||||
<span class="text-success">✓</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $p->qualified_abos }}/{{ $incentive->min_customer_abos }}
|
||||
@if ($p->qualified_abos >= $incentive->min_customer_abos)
|
||||
<span class="text-success">✓</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($p->is_qualified)
|
||||
<span class="badge badge-success">{{ __('incentive.yes') }}</span>
|
||||
@else
|
||||
<span class="badge badge-secondary">{{ __('incentive.no') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($isWinner)
|
||||
<span class="badge badge-warning">{{ __('incentive.winner') }}</span>
|
||||
@elseif($p->is_qualified)
|
||||
<span class="badge badge-info">{{ __('incentive.qualified') }}</span>
|
||||
@else
|
||||
<span class="badge badge-secondary">{{ __('incentive.open') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary btn-participant-details"
|
||||
data-participant-id="{{ $p->id }}"
|
||||
data-participant-name="{{ $p->user && $p->user->account ? $p->user->account->first_name . ' ' . $p->user->account->last_name : ($p->user->email ?? 'N/A') }}">
|
||||
<span class="fa fa-eye"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="10" class="text-center text-muted">{{ __('incentive.no_participants') }}</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Modal: Teilnehmer-Details --}}
|
||||
<div class="modal fade" id="participantDetailsModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ __('incentive.calculation_details') }}: <span
|
||||
id="modalParticipantName"></span></h5>
|
||||
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
||||
</div>
|
||||
<div class="modal-body" id="modalParticipantBody">
|
||||
<div class="text-center py-4">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary"
|
||||
data-dismiss="modal">{{ __('incentive.close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
$(document).on('click', '.btn-participant-details', function() {
|
||||
var participantId = $(this).data('participant-id');
|
||||
var participantName = $(this).data('participant-name');
|
||||
|
||||
$('#modalParticipantName').text(participantName);
|
||||
$('#modalParticipantBody').html(
|
||||
'<div class="text-center py-4"><div class="spinner-border text-primary" role="status"><span class="sr-only">Loading...</span></div></div>'
|
||||
);
|
||||
$('#participantDetailsModal').modal('show');
|
||||
|
||||
$.get('{{ url('/admin/incentives/participant') }}/' + participantId + '/details', function(html) {
|
||||
$('#modalParticipantBody').html(html);
|
||||
}).fail(function() {
|
||||
$('#modalParticipantBody').html(
|
||||
'<div class="alert alert-danger">Fehler beim Laden der Details.</div>');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -1,50 +1,47 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.td-entry-table-margin {
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid rgb(221, 221, 221);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.td-entry-table-margin {
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid rgb(221, 221, 221);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Guthaben offen
|
||||
<div class="float-right">
|
||||
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#modals-load-content"
|
||||
data-id="new"
|
||||
data-action="add-user-credit"
|
||||
data-back="{{url()->current()}}"
|
||||
data-id="new" data-action="add-user-credit" data-back="{{ url()->current() }}"
|
||||
data-route="{{ route('modal_load') }}"><span class="fa fa-plus-circle"></span> Guthaben hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
</h5>
|
||||
|
||||
@if(isset($add_credit_error) && $add_credit_error)
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ $add_credit_error }}</li>
|
||||
</ul>
|
||||
@if (isset($add_credit_error) && $add_credit_error)
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ $add_credit_error }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-datatable table-responsive pt-0">
|
||||
<table class="datatables-style table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__('Account ID')}}</th>
|
||||
<th>{{__('First name')}}</th>
|
||||
<th>{{__('Last name') }}</th>
|
||||
<th>{{__('E-Mail') }}</th>
|
||||
<th>{{__('Betrag') }}</th>
|
||||
<th>{{__('Guthaben')}}</th>
|
||||
<th>{{__('#')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ __('Account ID') }}</th>
|
||||
<th>{{ __('First name') }}</th>
|
||||
<th>{{ __('Last name') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>{{ __('Betrag') }}</th>
|
||||
<th>{{ __('Guthaben') }}</th>
|
||||
<th>{{ __('#') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($user_credit_items as $user_credit_item)
|
||||
|
|
@ -57,28 +54,29 @@
|
|||
<td>
|
||||
@foreach ($user_credit_item['entries'] as $key => $credit)
|
||||
<div class="td-entry-table-margin">
|
||||
<i class="fa fa-plus-circle text-secondary"></i>
|
||||
{!! formatNumber($credit->credit) !!} € |
|
||||
<i class="fa fa-plus-circle text-secondary"></i>
|
||||
{!! formatNumber($credit->credit) !!} € |
|
||||
{{ formatTextWithLineBreaks($credit->message, true) }}
|
||||
/ {{ $credit->created_at->format("d.m.Y") }}
|
||||
@if($deleteTime = $credit->deleteTime())
|
||||
/ <span class="no-line-break">
|
||||
<a class="btn btn-danger btn-xs" href="{{ route('admin_payments_credit_delete', [$credit->id, 'user_credit_item']) }}" onclick="return confirm('Wirklich löschen?');">
|
||||
<i class="ion ion-ios-trash"></i>
|
||||
</a> noch {{ $deleteTime }} min.
|
||||
</span>
|
||||
@endif
|
||||
/ {{ $credit->created_at->format('d.m.Y') }}
|
||||
@if ($deleteTime = $credit->deleteTime())
|
||||
/ <span class="no-line-break">
|
||||
<a class="btn btn-danger btn-xs"
|
||||
href="{{ route('admin_payments_credit_delete', [$credit->id, 'user_credit_item']) }}"
|
||||
onclick="return confirm('Wirklich löschen?');">
|
||||
<i class="ion ion-ios-trash"></i>
|
||||
</a> noch {{ $deleteTime }} min.
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-toggle="modal" data-target="#modals-credit"
|
||||
data-userid="{{ $user_credit_item['user_id'] }}"
|
||||
data-email="{{ $user_credit_item['email'] }}"
|
||||
data-back="{{url()->current()}}"
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-toggle="modal"
|
||||
data-target="#modals-credit" data-userid="{{ $user_credit_item['user_id'] }}"
|
||||
data-email="{{ $user_credit_item['email'] }}" data-back="{{ url()->current() }}"
|
||||
data-action="create_credit">
|
||||
<span class="fa fa-dollar-sign"></span> <strong>Guthaben auszahlen</strong>
|
||||
</button>
|
||||
<span class="fa fa-dollar-sign"></span> <strong>Guthaben auszahlen</strong>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
@ -88,147 +86,242 @@
|
|||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card mt-3">
|
||||
|
||||
<div class="card mt-3 mb-3" id="credit-stats-card">
|
||||
<div class="card-body py-3">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto text-muted small">
|
||||
<i class="fa fa-chart-bar mr-1"></i> Statistik:
|
||||
<span class="font-weight-bold text-dark" id="stats-credit-period">
|
||||
{{ $filter_months[session('credit_filter_month')] ?? '' }} {{ session('credit_filter_year') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col text-right d-flex justify-content-end">
|
||||
<div class="mr-4 text-center">
|
||||
<div class="text-muted" style="font-size:0.75rem;">Anzahl Gutschriften</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-primary" id="stats-credit-count">
|
||||
<i class="fa fa-spinner fa-spin fa-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-muted" style="font-size:0.75rem;">Gesamtsumme</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-success" id="stats-credit-total">
|
||||
<i class="fa fa-spinner fa-spin fa-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-0">
|
||||
<h5 class="card-header">
|
||||
Gutschriften / Auszahlungen
|
||||
Gutschriften / Auszahlungen
|
||||
</h5>
|
||||
<div class="card-body p-0">
|
||||
{!! Form::open(['action' => route('admin_payments_credit'), 'class' => 'form-horizontal', 'id'=>'form_filter_payment_credits']) !!}
|
||||
{!! Form::open([
|
||||
'action' => route('admin_payments_credit'),
|
||||
'class' => 'form-horizontal',
|
||||
'id' => 'form_filter_payment_credits',
|
||||
]) !!}
|
||||
|
||||
<div class="form-row align-items-center px-4 pb-2 pt-3">
|
||||
<div class="col-12 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<input class="form-control on_keyup_credits" name="credit_filter_name" type="text" value="{{session('credit_filter_name')}}" placeholder="Name">
|
||||
<input class="form-control on_keyup_credits" name="credit_filter_name" type="text"
|
||||
value="{{ session('credit_filter_name') }}" placeholder="Name">
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_credits" name="credit_filter_month">
|
||||
@foreach($filter_months as $key=>$value)
|
||||
<option value="{{$key}}" @if(session('credit_filter_month') == $key) selected @endif>{{$value}}</option>
|
||||
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_credits" name="credit_filter_month">
|
||||
@foreach ($filter_months as $key => $value)
|
||||
<option value="{{ $key }}" @if (session('credit_filter_month') == $key) selected @endif>
|
||||
{{ $value }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_credits" name="credit_filter_year">
|
||||
@foreach($filter_years as $key=>$value)
|
||||
<option value="{{$value}}" @if(session('credit_filter_year') == $value) selected @endif>{{$value}}</option>
|
||||
@foreach ($filter_years as $key => $value)
|
||||
<option value="{{ $value }}" @if (session('credit_filter_year') == $value) selected @endif>
|
||||
{{ $value }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
|
||||
<div class="card-datatable table-responsive pt-0">
|
||||
<table class="datatables-style table table-striped table-bordered" id="datatable-credit">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>{{__('G.Nr.')}}</th>
|
||||
<th>{{__('Gutschrift')}}</th>
|
||||
<th>{{__('First name')}}</th>
|
||||
<th>{{__('Last name') }}</th>
|
||||
<th>{{__('E-Mail') }}</th>
|
||||
<th>{{__('Betrag') }}</th>
|
||||
<th>{{__('Datum') }}</th>
|
||||
<th>{{__('Zahlung')}}</th>
|
||||
<th>{{__('aus Guthaben')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="card-datatable table-responsive pt-0">
|
||||
<table class="datatables-style table table-striped table-bordered" id="datatable-credit">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>{{ __('G.Nr.') }}</th>
|
||||
<th>{{ __('Gutschrift') }}</th>
|
||||
<th>{{ __('First name') }}</th>
|
||||
<th>{{ __('Last name') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>{{ __('Betrag') }}</th>
|
||||
<th>{{ __('Datum') }}</th>
|
||||
<th>{{ __('Zahlung') }}</th>
|
||||
<th>{{ __('aus Guthaben') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modals-credit">
|
||||
<div class="modal-dialog">
|
||||
<form class="modal-content form-prevent-multiple-submits" action="{{ route('admin_payments_credit_create') }}" method="post">
|
||||
<form class="modal-content form-prevent-multiple-submits" action="{{ route('admin_payments_credit_create') }}"
|
||||
method="post">
|
||||
@csrf
|
||||
<input type="hidden" name="userid" value="">
|
||||
<input type="hidden" name="action" value="create_credit">
|
||||
<input type="hidden" name="back" value="{{url()->current()}}">
|
||||
<input type="hidden" name="back" value="{{ url()->current() }}">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{__('Gutschrift')}}</h5>
|
||||
<h5 class="modal-title">{{ __('Gutschrift') }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group col-sm-12">
|
||||
{{ Form::select('credit_option', ['create'=>'Gutschrift erstellen'], false, array('data-live-search'=>'false', 'class'=>'selectpicker')) }}
|
||||
{{ Form::select('credit_option', ['create' => 'Gutschrift erstellen'], false, ['data-live-search' => 'false', 'class' => 'selectpicker']) }}
|
||||
</div>
|
||||
<div class="form-group col-sm-12">
|
||||
<label class="form-label" for="credit_date">{{ __('Gutschriftsdatum') }}</label>
|
||||
{!! Form::text('credit_date', \Carbon::now()->format("d.m.Y"), ['class'=>'form-control datepicker-base']) !!}
|
||||
{!! Form::text('credit_date', \Carbon::now()->format('d.m.Y'), ['class' => 'form-control datepicker-base']) !!}
|
||||
</div>
|
||||
<div class="form-group col-sm-12">
|
||||
<label class="form-label" for="credit_number">{{ __('Gutschriftsnummer') }}</label>
|
||||
{!! Form::text('credit_number', App\Services\Credit::getCreditNumber(), ['class'=>'form-control', 'disabled']) !!}
|
||||
<em> nächste Gutschriftsnummer <a href="{{ route('admin_settings') }}"><i class="fa fa-edit"></i></a></em>
|
||||
{!! Form::text('credit_number', App\Services\Credit::getCreditNumber(), ['class' => 'form-control', 'disabled']) !!}
|
||||
<em> nächste Gutschriftsnummer <a href="{{ route('admin_settings') }}"><i
|
||||
class="fa fa-edit"></i></a></em>
|
||||
</div>
|
||||
<div class="form-group col-sm-12">
|
||||
<label class="custom-control custom-checkbox">
|
||||
{!! Form::checkbox('credit_send_mail', 1, true, ['class'=>'custom-control-input']) !!}
|
||||
<span class="custom-control-label">Gutschrift an <span id="set_credit_send_mail">mail</span></span>
|
||||
{!! Form::checkbox('credit_send_mail', 1, true, ['class' => 'custom-control-input']) !!}
|
||||
<span class="custom-control-label">Gutschrift an <span
|
||||
id="set_credit_send_mail">mail</span></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{__('close')}}</button>
|
||||
<button type="submit" class="btn btn-primary button-prevent-multiple-submits"><i class="spinner fa fa-spinner fa-spin"></i> {{ __('save')}}</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
|
||||
<button type="submit" class="btn btn-primary button-prevent-multiple-submits"><i
|
||||
class="spinner fa fa-spinner fa-spin"></i> {{ __('save') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
function loadCreditStats() {
|
||||
var month = $('select[name=credit_filter_month]').val();
|
||||
var year = $('select[name=credit_filter_year]').val();
|
||||
var name = $('input[name=credit_filter_name]').val();
|
||||
$.getJSON('{!! route('admin_payments_credit_stats') !!}', {
|
||||
credit_filter_month: month,
|
||||
credit_filter_year: year,
|
||||
credit_filter_name: name
|
||||
}, function(data) {
|
||||
$('#stats-credit-count').text(data.count);
|
||||
$('#stats-credit-total').text(data.total + ' €');
|
||||
var monthName = $('select[name=credit_filter_month] option:selected').text();
|
||||
$('#stats-credit-period').text(monthName + ' ' + year);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
loadCreditStats();
|
||||
|
||||
var oTable = $('#datatable-credit').DataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
ajax: {
|
||||
url: '{!! route( 'admin_payments_credit_datatable') !!}',
|
||||
data: function(d) {
|
||||
d.credit_filter_name = $('input[name=credit_filter_name]').val();
|
||||
d.credit_filter_month = $('select[name=credit_filter_month]').val();
|
||||
d.credit_filter_year = $('select[name=credit_filter_year]').val();
|
||||
}
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
ajax: {
|
||||
url: '{!! route('admin_payments_credit_datatable') !!}',
|
||||
data: function(d) {
|
||||
d.credit_filter_name = $('input[name=credit_filter_name]').val();
|
||||
d.credit_filter_month = $('select[name=credit_filter_month]').val();
|
||||
d.credit_filter_year = $('select[name=credit_filter_year]').val();
|
||||
}
|
||||
},
|
||||
"order": [
|
||||
[0, "desc"]
|
||||
],
|
||||
"columns": [{
|
||||
data: 'id',
|
||||
searchable: false
|
||||
},
|
||||
"order": [[0, "desc" ]],
|
||||
"columns": [
|
||||
{ data: 'id', searchable: false },
|
||||
{ data: 'full_number', name: 'full_number' },
|
||||
{ data: 'view', name: 'view' },
|
||||
{ data: 'user.account.first_name', name: 'user.account.first_name', orderable: false },
|
||||
{ data: 'user.account.last_name', name: 'user.account.last_name', orderable: false },
|
||||
{ data: 'user.email', name: 'user.email', orderable: false },
|
||||
{ data: 'total', name: 'total' },
|
||||
{ data: 'date', name: 'date' },
|
||||
{ data: 'status', name: 'status', searchable: false },
|
||||
{ data: 'credits', name: 'credits', orderable: false },
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 100,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
$('select.on_change_credits').on('change', function(){
|
||||
oTable.draw();
|
||||
});
|
||||
|
||||
$('input.on_keyup_credits').on('keyup', function(){
|
||||
oTable.draw();
|
||||
});
|
||||
$( document ).ready(function() {
|
||||
$('#modals-credit').on('show.bs.modal', function (event) {
|
||||
{
|
||||
data: 'full_number',
|
||||
name: 'full_number'
|
||||
},
|
||||
{
|
||||
data: 'view',
|
||||
name: 'view'
|
||||
},
|
||||
{
|
||||
data: 'user.account.first_name',
|
||||
name: 'user.account.first_name',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'user.account.last_name',
|
||||
name: 'user.account.last_name',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'user.email',
|
||||
name: 'user.email',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'total',
|
||||
name: 'total'
|
||||
},
|
||||
{
|
||||
data: 'date',
|
||||
name: 'date'
|
||||
},
|
||||
{
|
||||
data: 'status',
|
||||
name: 'status',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'credits',
|
||||
name: 'credits',
|
||||
orderable: false
|
||||
},
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 100,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
$('select.on_change_credits').on('change', function() {
|
||||
oTable.draw();
|
||||
loadCreditStats();
|
||||
});
|
||||
|
||||
$('input.on_keyup_credits').on('keyup', function() {
|
||||
oTable.draw();
|
||||
loadCreditStats();
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$('#modals-credit').on('show.bs.modal', function(event) {
|
||||
var button = $(event.relatedTarget);
|
||||
if(event.relatedTarget){
|
||||
$(this).find(".modal-content input[name='userid']").val(button.data('userid'));
|
||||
$(this).find(".modal-body #set_credit_send_mail").html(button.data('email'));
|
||||
if (event.relatedTarget) {
|
||||
$(this).find(".modal-content input[name='userid']").val(button.data(
|
||||
'userid'));
|
||||
$(this).find(".modal-body #set_credit_send_mail").html(button.data(
|
||||
'email'));
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,50 +1,84 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<div class="card mb-3" id="invoice-stats-card">
|
||||
<div class="card-body py-3">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto text-muted small">
|
||||
<i class="fa fa-chart-bar mr-1"></i> Statistik:
|
||||
<span class="font-weight-bold text-dark" id="stats-invoice-period">
|
||||
{{ $filter_months[session('invoice_filter_month')] ?? '' }} {{ session('invoice_filter_year') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col text-right d-flex justify-content-end">
|
||||
<div class="mr-4 text-center">
|
||||
<div class="text-muted" style="font-size:0.75rem;">Anzahl Rechnungen</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-primary" id="stats-invoice-count">
|
||||
<i class="fa fa-spinner fa-spin fa-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-muted" style="font-size:0.75rem;">Gesamtsumme</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-success" id="stats-invoice-total">
|
||||
<i class="fa fa-spinner fa-spin fa-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Finanzen / Rechnungen
|
||||
</h5>
|
||||
<div class="card-body p-0">
|
||||
{!! Form::open(['action' => route('admin_payments_invoice'), 'class' => 'form-horizontal', 'id'=>'form_filter_payment_invoices']) !!}
|
||||
{!! Form::open([
|
||||
'action' => route('admin_payments_invoice'),
|
||||
'class' => 'form-horizontal',
|
||||
'id' => 'form_filter_payment_invoices',
|
||||
]) !!}
|
||||
|
||||
<div class="form-row align-items-center px-4 pb-2 pt-3">
|
||||
<div class="col-12 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<input class="form-control on_keyup_invoice" name="invoice_filter_name" type="text" value="{{session('invoice_filter_name')}}" placeholder="Name">
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_invoice" name="invoice_filter_month">
|
||||
@foreach($filter_months as $key=>$value)
|
||||
<option value="{{$key}}" @if(session('invoice_filter_month') == $key) selected @endif>{{$value}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_invoice" name="invoice_filter_year">
|
||||
@foreach($filter_years as $key=>$value)
|
||||
<option value="{{$value}}" @if(session('invoice_filter_year') == $value) selected @endif>{{$value}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row align-items-center px-4 pb-2 pt-3">
|
||||
<div class="col-12 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<input class="form-control on_keyup_invoice" name="invoice_filter_name" type="text"
|
||||
value="{{ session('invoice_filter_name') }}" placeholder="Name">
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_invoice" name="invoice_filter_month">
|
||||
@foreach ($filter_months as $key => $value)
|
||||
<option value="{{ $key }}" @if (session('invoice_filter_month') == $key) selected @endif>
|
||||
{{ $value }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
||||
<select class="custom-select on_change_invoice" name="invoice_filter_year">
|
||||
@foreach ($filter_years as $key => $value)
|
||||
<option value="{{ $value }}" @if (session('invoice_filter_year') == $value) selected @endif>
|
||||
{{ $value }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
|
||||
<div class="card-datatable table-responsive pt-0">
|
||||
<table class="datatables-style table table-striped table-bordered" id="datatable-invoice">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{__('tables.in_no')}}</th>
|
||||
<th>{{__('tables.invoice')}}</th>
|
||||
<th>{{__('tables.amount') }}</th>
|
||||
<th>{{__('tables.status')}}</th>
|
||||
<th>{{__('First name')}}</th>
|
||||
<th>{{__('Last name') }}</th>
|
||||
<th>{{__('E-Mail') }}</th>
|
||||
<th>{{__('tables.date') }}</th>
|
||||
<th>{{__('tables.art')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ __('tables.in_no') }}</th>
|
||||
<th>{{ __('tables.invoice') }}</th>
|
||||
<th>{{ __('tables.amount') }}</th>
|
||||
<th>{{ __('tables.status') }}</th>
|
||||
<th>{{ __('First name') }}</th>
|
||||
<th>{{ __('Last name') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>{{ __('tables.date') }}</th>
|
||||
<th>{{ __('tables.art') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
|
|
@ -54,45 +88,106 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
function loadInvoiceStats() {
|
||||
var month = $('select[name=invoice_filter_month]').val();
|
||||
var year = $('select[name=invoice_filter_year]').val();
|
||||
var name = $('input[name=invoice_filter_name]').val();
|
||||
$.getJSON('{!! route('admin_payments_invoice_stats') !!}', {
|
||||
invoice_filter_month: month,
|
||||
invoice_filter_year: year,
|
||||
invoice_filter_name: name
|
||||
}, function(data) {
|
||||
$('#stats-invoice-count').text(data.count);
|
||||
$('#stats-invoice-total').text(data.total + ' €');
|
||||
var monthName = $('select[name=invoice_filter_month] option:selected').text();
|
||||
$('#stats-invoice-period').text(monthName + ' ' + year);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
loadInvoiceStats();
|
||||
|
||||
var oTable = $('#datatable-invoice').DataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"stateSave": true,
|
||||
"searching": false,
|
||||
ajax: {
|
||||
url: '{!! route('admin_payments_invoice_datatable') !!}',
|
||||
data: function(d) {
|
||||
d.invoice_filter_name = $('input[name=invoice_filter_name]').val();
|
||||
d.invoice_filter_month = $('select[name=invoice_filter_month]').val();
|
||||
d.invoice_filter_year = $('select[name=invoice_filter_year]').val();
|
||||
}
|
||||
},
|
||||
"order": [[0, "desc" ]],
|
||||
"columns": [
|
||||
{ data: 'id', searchable: false },
|
||||
{ data: 'full_number', name: 'full_number' },
|
||||
{ data: 'invoice', name: 'invoice', orderable: false, searchable: false },
|
||||
{ data: 'total_shipping', name: 'total_shipping', orderable: false, searchable: false },
|
||||
{ data: 'txaction', name: 'txaction', orderable: false, searchable: false },
|
||||
{ data: 'shopping_order.shopping_user.billing_firstname', name: 'shopping_order.shopping_user.billing_firstname', orderable: false },
|
||||
{ data: 'shopping_order.shopping_user.billing_lastname', name: 'shopping_order.shopping_user.billing_lastname', orderable: false },
|
||||
{ data: 'shopping_order.shopping_user.billing_email', name: 'shopping_order.shopping_user.billing_email', orderable: false },
|
||||
{ data: 'created_at', name: 'created_at' },
|
||||
{ data: 'status', name: 'status', searchable: false },
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 100,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"stateSave": true,
|
||||
"searching": false,
|
||||
ajax: {
|
||||
url: '{!! route('admin_payments_invoice_datatable') !!}',
|
||||
data: function(d) {
|
||||
d.invoice_filter_name = $('input[name=invoice_filter_name]').val();
|
||||
d.invoice_filter_month = $('select[name=invoice_filter_month]').val();
|
||||
d.invoice_filter_year = $('select[name=invoice_filter_year]').val();
|
||||
}
|
||||
});
|
||||
$('select.on_change_invoice').on('change', function(){
|
||||
},
|
||||
"order": [
|
||||
[0, "desc"]
|
||||
],
|
||||
"columns": [{
|
||||
data: 'id',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'full_number',
|
||||
name: 'full_number'
|
||||
},
|
||||
{
|
||||
data: 'invoice',
|
||||
name: 'invoice',
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'total_shipping',
|
||||
name: 'total_shipping',
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'txaction',
|
||||
name: 'txaction',
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'shopping_order.shopping_user.billing_firstname',
|
||||
name: 'shopping_order.shopping_user.billing_firstname',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'shopping_order.shopping_user.billing_lastname',
|
||||
name: 'shopping_order.shopping_user.billing_lastname',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'shopping_order.shopping_user.billing_email',
|
||||
name: 'shopping_order.shopping_user.billing_email',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
data: 'created_at',
|
||||
name: 'created_at'
|
||||
},
|
||||
{
|
||||
data: 'status',
|
||||
name: 'status',
|
||||
searchable: false
|
||||
},
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 100,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
$('select.on_change_invoice').on('change', function() {
|
||||
oTable.draw();
|
||||
loadInvoiceStats();
|
||||
});
|
||||
|
||||
$('input.on_keyup_invoice').on('keyup', function(){
|
||||
$('input.on_keyup_invoice').on('keyup', function() {
|
||||
oTable.draw();
|
||||
loadInvoiceStats();
|
||||
});
|
||||
});
|
||||
/*$('#filter_sales_year').on('change', function(){
|
||||
|
|
|
|||
327
resources/views/dashboard/_incentive.blade.php
Normal file
327
resources/views/dashboard/_incentive.blade.php
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
@if (isset($activeIncentive) && $activeIncentive)
|
||||
<div class="d-flex col-xl-12 align-items-stretch">
|
||||
<div class="w-100 mb-4 inc-dash-widget">
|
||||
|
||||
{{-- Hero-Bild mit Overlay --}}
|
||||
@if ($activeIncentive->image)
|
||||
<div class="inc-dash-hero">
|
||||
<img src="{{ asset('img/incentive/' . $activeIncentive->image) }}" alt="{{ $activeIncentive->name }}">
|
||||
<div class="inc-dash-hero-overlay"></div>
|
||||
<div class="inc-dash-hero-content">
|
||||
<span class="inc-dash-badge">
|
||||
<i class="ion ion-md-trophy mr-1"></i> Incentive VIP
|
||||
</span>
|
||||
<h4 class="inc-dash-title">
|
||||
{{ $activeIncentive->getLang('name') ?: $activeIncentive->name }}
|
||||
</h4>
|
||||
@if ($activeIncentive->getLang('subtitle'))
|
||||
<p class="inc-dash-subtitle">{{ $activeIncentive->getLang('subtitle') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="inc-dash-header-plain">
|
||||
<span class="inc-dash-badge">
|
||||
<i class="ion ion-md-trophy mr-1"></i> Incentive VIP
|
||||
</span>
|
||||
<h4 class="font-weight-bold mb-1">
|
||||
{{ $activeIncentive->getLang('name') ?: $activeIncentive->name }}
|
||||
</h4>
|
||||
@if ($activeIncentive->getLang('subtitle'))
|
||||
<p class="text-muted mb-0">{{ $activeIncentive->getLang('subtitle') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Inhaltsbereich --}}
|
||||
<div class="inc-dash-body">
|
||||
|
||||
{{-- Status-Leiste (nur fuer Teilnehmer) --}}
|
||||
@if ($incentiveParticipant)
|
||||
<div class="inc-dash-stats">
|
||||
@if ($incentiveParticipant->rank)
|
||||
<div class="inc-dash-stat">
|
||||
<span class="inc-dash-stat-value">{{ $incentiveParticipant->rank }}</span>
|
||||
<span class="inc-dash-stat-label">{{ __('incentive.your_rank') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
<div class="inc-dash-stat">
|
||||
<span
|
||||
class="inc-dash-stat-value">{{ number_format($incentiveParticipant->total_points, 0, ',', '.') }}</span>
|
||||
<span class="inc-dash-stat-label">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<div class="inc-dash-stat">
|
||||
@if ($incentiveParticipant->is_qualified)
|
||||
<span class="inc-dash-qual-yes">{{ __('incentive.qualified') }}</span>
|
||||
@else
|
||||
<span class="inc-dash-qual-no">{{ __('incentive.open') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Bilder-Leiste --}}
|
||||
@php
|
||||
$dashGallery = [];
|
||||
$galleryDir = public_path('img/incentive');
|
||||
if (is_dir($galleryDir)) {
|
||||
$galleryFiles = glob($galleryDir . '/*.{jpg,jpeg,png,webp}', GLOB_BRACE) ?: [];
|
||||
$heroImg = $activeIncentive->image;
|
||||
foreach ($galleryFiles as $gf) {
|
||||
$bn = basename($gf);
|
||||
if ($bn !== $heroImg) {
|
||||
$dashGallery[] = 'img/incentive/' . $bn;
|
||||
}
|
||||
}
|
||||
sort($dashGallery);
|
||||
$dashGallery = array_slice($dashGallery, 0, 4);
|
||||
}
|
||||
@endphp
|
||||
@if (count($dashGallery) > 0)
|
||||
<div class="inc-dash-gallery">
|
||||
@foreach ($dashGallery as $gi)
|
||||
<div class="inc-dash-gallery-thumb">
|
||||
<img src="{{ asset($gi) }}" alt="Impression" loading="lazy">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Buttons --}}
|
||||
<div class="inc-dash-actions">
|
||||
<a href="{{ route('user_incentive_teaser', [$activeIncentive->slug]) }}"
|
||||
class="btn inc-dash-btn-primary">
|
||||
<i class="ion ion-md-trophy mr-1"></i>
|
||||
{{ __('incentive.dashboard_btn_teaser') }}
|
||||
</a>
|
||||
<a href="{{ route('user_incentive_show', [$activeIncentive->slug]) }}"
|
||||
class="btn inc-dash-btn-secondary">
|
||||
<i class="ion ion-md-list mr-1"></i>
|
||||
{{ __('incentive.dashboard_btn_ranking') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.inc-dash-widget {
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.10);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.inc-dash-hero {
|
||||
position: relative;
|
||||
height: 180px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-dash-hero img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inc-dash-hero-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(to bottom,
|
||||
rgba(0, 0, 0, 0.05) 0%,
|
||||
rgba(0, 0, 0, 0.20) 40%,
|
||||
rgba(0, 0, 0, 0.70) 100%);
|
||||
}
|
||||
|
||||
.inc-dash-hero-content {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: 1.5rem 2rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.inc-dash-badge {
|
||||
display: inline-block;
|
||||
background: rgba(215, 215, 0, 0.92);
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
padding: .25rem .8rem;
|
||||
border-radius: 50px;
|
||||
font-size: .75rem;
|
||||
letter-spacing: .04em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: .6rem;
|
||||
}
|
||||
|
||||
.inc-dash-title {
|
||||
color: #fff;
|
||||
font-weight: 800;
|
||||
font-size: 1.6rem;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
margin: 0 0 .25rem 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.inc-dash-subtitle {
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
font-size: .95rem;
|
||||
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.inc-dash-header-plain {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
color: #fff;
|
||||
padding: 1.5rem 2rem;
|
||||
}
|
||||
|
||||
.inc-dash-header-plain h4 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.inc-dash-body {
|
||||
padding: 1.2rem 1.5rem 1.5rem;
|
||||
}
|
||||
|
||||
.inc-dash-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
padding: .8rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
background: #f4f5f0;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
|
||||
.inc-dash-stat {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inc-dash-stat-value {
|
||||
display: block;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 800;
|
||||
color: #6b7758;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.inc-dash-stat-label {
|
||||
font-size: .7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .04em;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.inc-dash-qual-yes {
|
||||
display: inline-block;
|
||||
background: linear-gradient(135deg, #b8b800, #d7d700);
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
padding: .3rem .8rem;
|
||||
border-radius: 50px;
|
||||
font-size: .78rem;
|
||||
}
|
||||
|
||||
.inc-dash-qual-no {
|
||||
display: inline-block;
|
||||
background: #e8e8e8;
|
||||
color: #777;
|
||||
font-weight: 600;
|
||||
padding: .3rem .8rem;
|
||||
border-radius: 50px;
|
||||
font-size: .78rem;
|
||||
}
|
||||
|
||||
.inc-dash-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: .4rem;
|
||||
margin-bottom: 1rem;
|
||||
border-radius: .5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-dash-gallery-thumb {
|
||||
aspect-ratio: 16/10;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-dash-gallery-thumb img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
transition: transform .3s ease;
|
||||
}
|
||||
|
||||
.inc-dash-gallery-thumb:hover img {
|
||||
transform: scale(1.06);
|
||||
}
|
||||
|
||||
.inc-dash-actions {
|
||||
display: flex;
|
||||
gap: .6rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.inc-dash-btn-primary {
|
||||
background: linear-gradient(135deg, #6b7758, #4a5340);
|
||||
color: #fff !important;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
padding: .55rem 1.8rem;
|
||||
font-weight: 700;
|
||||
font-size: .9rem;
|
||||
transition: transform .2s, box-shadow .2s;
|
||||
}
|
||||
|
||||
.inc-dash-btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 14px rgba(107, 119, 88, 0.35);
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.inc-dash-btn-secondary {
|
||||
background: transparent;
|
||||
color: #6b7758 !important;
|
||||
border: 2px solid #6b7758;
|
||||
border-radius: 50px;
|
||||
padding: .55rem 1.8rem;
|
||||
font-weight: 600;
|
||||
font-size: .9rem;
|
||||
transition: background .2s, color .2s;
|
||||
}
|
||||
|
||||
.inc-dash-btn-secondary:hover {
|
||||
background: #6b7758;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.inc-dash-hero {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.inc-dash-hero-content {
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
|
||||
.inc-dash-title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.inc-dash-gallery {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.inc-dash-stats {
|
||||
gap: .8rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@endif
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@if($user->active == 1)
|
||||
@if($user->active == 1 || ($user->payment_account && ! $user->isActiveAccount()))
|
||||
@if($user->payment_account && $user->daysActiveAccount() <= config('mivita.remind_first_days'))
|
||||
<div class="d-flex col-xl-12 align-items-stretch">
|
||||
<div class="card w-100 mb-4">
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
@php
|
||||
$selectedMonth = request()->get('stats_month', date('n'));
|
||||
$selectedYear = request()->get('stats_year', date('Y'));
|
||||
|
||||
|
||||
// Start- und Enddatum für den Monat
|
||||
$startDate = \Carbon\Carbon::createFromDate($selectedYear, $selectedMonth, 1)->startOfMonth();
|
||||
$endDate = \Carbon\Carbon::createFromDate($selectedYear, $selectedMonth, 1)->endOfMonth();
|
||||
|
||||
|
||||
// UserBusiness für den Monat laden (enthält Payline-Punkte)
|
||||
$userBusiness = \App\Models\UserBusiness::where('user_id', $user->id)
|
||||
->where('month', $selectedMonth)
|
||||
->where('year', $selectedYear)
|
||||
->first();
|
||||
|
||||
|
||||
// UserSalesVolume für KP-Punkte
|
||||
$userSalesVolume = $user->getUserSalesVolume($selectedMonth, $selectedYear, 'first');
|
||||
|
||||
|
||||
// Kunden-Umsatz Punkte (KP - Eigene Punkte + Shop)
|
||||
$customerPoints = $userSalesVolume ? $userSalesVolume->getPointsKPSum() : 0;
|
||||
|
||||
|
||||
// Team-Umsatz Punkte (Payline) - Live-Berechnung wenn UserBusiness nicht verfügbar
|
||||
$teamPaylinePoints = 0;
|
||||
$isLiveCalculation = false;
|
||||
|
||||
|
||||
if ($userBusiness) {
|
||||
// Gespeicherte Daten aus UserBusiness verwenden
|
||||
$teamPaylinePoints = $userBusiness->payline_points ?? 0;
|
||||
|
|
@ -29,9 +29,13 @@
|
|||
// Live-Berechnung über TreeCalcBot (für aktuellen Monat)
|
||||
$isLiveCalculation = true;
|
||||
try {
|
||||
$treeCalcBot = new \App\Services\BusinessPlan\TreeCalcBot((int)$selectedMonth, (int)$selectedYear, 'member');
|
||||
$treeCalcBot = new \App\Services\BusinessPlan\TreeCalcBot(
|
||||
(int) $selectedMonth,
|
||||
(int) $selectedYear,
|
||||
'member',
|
||||
);
|
||||
$treeCalcBot->initBusinesslUserDetail($user);
|
||||
|
||||
|
||||
if ($treeCalcBot->business_user) {
|
||||
$teamPaylinePoints = $treeCalcBot->business_user->payline_points ?? 0;
|
||||
}
|
||||
|
|
@ -40,48 +44,50 @@
|
|||
$teamPaylinePoints = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Direkte Neupartner (Firstlines) in diesem Monat
|
||||
$directNewPartners = \App\User::where('m_sponsor', $user->id)
|
||||
->whereColumn('id', '!=', 'm_sponsor')
|
||||
->where('active_date', '>=', $startDate)
|
||||
->where('active_date', '<=', $endDate)
|
||||
->where('m_level', '!=', null)
|
||||
->where('payment_account', '!=', null)
|
||||
->count();
|
||||
|
||||
|
||||
// ===== REKURSIVE TEAM-STRUKTUR =====
|
||||
// Hilfsfunktion um alle Team-Mitglieder rekursiv zu sammeln (inkl. Sponsor-Kette)
|
||||
$getAllTeamMemberIds = function($sponsorId, $maxDepth = 20) use (&$getAllTeamMemberIds) {
|
||||
$getAllTeamMemberIds = function ($sponsorId, $maxDepth = 20) use (&$getAllTeamMemberIds) {
|
||||
static $cache = [];
|
||||
|
||||
|
||||
if (isset($cache[$sponsorId])) {
|
||||
return $cache[$sponsorId];
|
||||
}
|
||||
|
||||
|
||||
$teamIds = [];
|
||||
$currentLevel = [$sponsorId];
|
||||
$depth = 0;
|
||||
|
||||
|
||||
while (!empty($currentLevel) && $depth < $maxDepth) {
|
||||
$children = \App\User::whereIn('m_sponsor', $currentLevel)
|
||||
->whereColumn('id', '!=', 'm_sponsor')
|
||||
->where('m_level', '!=', null)
|
||||
->where('payment_account', '!=', null)
|
||||
->whereNull('deleted_at')
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
|
||||
|
||||
$teamIds = array_merge($teamIds, $children);
|
||||
$currentLevel = $children;
|
||||
$depth++;
|
||||
}
|
||||
|
||||
|
||||
$cache[$sponsorId] = $teamIds;
|
||||
return $teamIds;
|
||||
};
|
||||
|
||||
|
||||
// Alle Team-Mitglieder rekursiv laden
|
||||
$allTeamMemberIds = $getAllTeamMemberIds($user->id);
|
||||
|
||||
|
||||
// Neupartner im gesamten Team (rekursiv im Marketingplan)
|
||||
$teamNewPartners = 0;
|
||||
if (!empty($allTeamMemberIds)) {
|
||||
|
|
@ -90,21 +96,21 @@
|
|||
->where('active_date', '<=', $endDate)
|
||||
->count();
|
||||
}
|
||||
|
||||
|
||||
// Kundenabos (is_for = 'customer' oder shop-bezogen)
|
||||
$customerAbos = \App\Models\UserAbo::where('member_id', $user->id)
|
||||
->where('is_for', 'customer')
|
||||
->where('is_for', 'ot')
|
||||
->whereIn('status', [1, 2]) // aktive Abos
|
||||
->where('active', true)
|
||||
->count();
|
||||
|
||||
|
||||
// Eigene Abos
|
||||
$ownAbos = \App\Models\UserAbo::where('user_id', $user->id)
|
||||
->where('is_for', 'me')
|
||||
->whereIn('status', [1, 2])
|
||||
->where('active', true)
|
||||
->count();
|
||||
|
||||
|
||||
// Team-Abos (rekursiv über gesamtes Team im Marketingplan)
|
||||
$teamAbos = 0;
|
||||
if (!empty($allTeamMemberIds)) {
|
||||
|
|
@ -116,131 +122,152 @@
|
|||
}
|
||||
@endphp
|
||||
|
||||
@if($user->isActiveAccount())
|
||||
<div class="d-flex col-xl-12 align-items-stretch">
|
||||
<div class="card w-100 mb-4">
|
||||
<h5 class="card-header with-elements d-flex justify-content-between align-items-center flex-wrap">
|
||||
<div class="card-header-title">
|
||||
<i class="ion ion-md-stats mr-2"></i>{{__('home.monthly_statistics') }} - {{ HTMLHelper::getMonth($selectedMonth) }} {{ $selectedYear }}
|
||||
</div>
|
||||
<div class="d-flex align-items-center mt-2 mt-md-0">
|
||||
<select id="stats-month-filter" class="form-control custom-select form-control-sm mr-2" style="width: auto;">
|
||||
@foreach(HTMLHelper::getTransMonths() as $monthNum => $monthName)
|
||||
<option value="{{ $monthNum }}" {{ $selectedMonth == $monthNum ? 'selected' : '' }}>{{ $monthName }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select id="stats-year-filter" class="form-control custom-select form-control-sm" style="width: auto;">
|
||||
@foreach(HTMLHelper::getYearRange() as $year)
|
||||
<option value="{{ $year }}" {{ $selectedYear == $year ? 'selected' : '' }}>{{ $year }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
{{-- Kunden-Umsatz Punkte --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-cart" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.customer_turnover_points') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ number_format($customerPoints, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@if ($user->isActiveAccount())
|
||||
<div class="d-flex col-xl-12 align-items-stretch">
|
||||
<div class="card w-100 mb-4">
|
||||
<h5 class="card-header with-elements d-flex justify-content-between align-items-center flex-wrap">
|
||||
<div class="card-header-title">
|
||||
<i class="ion ion-md-stats mr-2"></i>{{ __('home.monthly_statistics') }} -
|
||||
{{ HTMLHelper::getMonth($selectedMonth) }} {{ $selectedYear }}
|
||||
</div>
|
||||
|
||||
{{-- Team-Umsatz Punkte (Payline) --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-success text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-people" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">
|
||||
{{ __('home.team_turnover_points') }} (Payline)
|
||||
@if($isLiveCalculation)
|
||||
<span class="badge badge-pill badge-info ml-1" title="{{ __('home.live_calculation_hint') }}">Live</span>
|
||||
@endif
|
||||
<div class="d-flex align-items-center mt-2 mt-md-0">
|
||||
<select id="stats-month-filter" class="form-control custom-select form-control-sm mr-2"
|
||||
style="width: auto;">
|
||||
@foreach (HTMLHelper::getTransMonths() as $monthNum => $monthName)
|
||||
<option value="{{ $monthNum }}" {{ $selectedMonth == $monthNum ? 'selected' : '' }}>
|
||||
{{ $monthName }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select id="stats-year-filter" class="form-control custom-select form-control-sm"
|
||||
style="width: auto;">
|
||||
@foreach (HTMLHelper::getYearRange() as $year)
|
||||
<option value="{{ $year }}" {{ $selectedYear == $year ? 'selected' : '' }}>
|
||||
{{ $year }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
{{-- Kunden-Umsatz Punkte --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-cart" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.customer_turnover_points') }}</div>
|
||||
<div class="font-weight-bold text-large">
|
||||
{{ number_format($customerPoints, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
<div class="font-weight-bold text-large">{{ number_format($teamPaylinePoints, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Direkte Neupartner --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-info text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-person-add" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.direct_new_partners') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $directNewPartners }}</div>
|
||||
{{-- Team-Umsatz Punkte (Payline) --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-success text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-people" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">
|
||||
{{ __('home.team_turnover_points') }} (Payline)
|
||||
@if ($isLiveCalculation)
|
||||
<span class="badge badge-pill badge-info ml-1"
|
||||
title="{{ __('home.live_calculation_hint') }}">Live</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="font-weight-bold text-large">
|
||||
|
||||
{{ number_format($teamPaylinePoints, 0, ',', '.') }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Neupartner im Team --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-warning text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-contacts" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.team_new_partners') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $teamNewPartners }}</div>
|
||||
|
||||
{{-- Direkte Neupartner --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-info text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-person-add" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.direct_new_partners') }}
|
||||
</div>
|
||||
<div class="font-weight-bold text-large">{{ $directNewPartners }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Kundenabos --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-secondary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-repeat" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.customer_subscriptions') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $customerAbos }} + {{ $ownAbos }} {{ __('home.own') }}</div>
|
||||
{{-- Neupartner im Team --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-warning text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-contacts" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.team_new_partners') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $teamNewPartners }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Team-Abos --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-dark text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-sync" style="font-size: 1.5rem;"></i>
|
||||
{{-- Kundenabos --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-secondary text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-repeat" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.customer_subscriptions') }}
|
||||
</div>
|
||||
<div class="font-weight-bold text-large">{{ $customerAbos }} +
|
||||
{{ $ownAbos }}
|
||||
{{ __('home.own') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.team_subscriptions') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $teamAbos }}</div>
|
||||
</div>
|
||||
|
||||
{{-- Team-Abos --}}
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-dark text-white rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="ion ion-md-sync" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-muted small">{{ __('home.team_subscriptions') }}</div>
|
||||
<div class="font-weight-bold text-large">{{ $teamAbos }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Filter für Monat/Jahr - Statistiken
|
||||
function updateStatsFilter() {
|
||||
var month = $('#stats-month-filter').val();
|
||||
var year = $('#stats-year-filter').val();
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set('stats_month', month);
|
||||
url.searchParams.set('stats_year', year);
|
||||
window.location.href = url.toString();
|
||||
}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Filter für Monat/Jahr - Statistiken
|
||||
function updateStatsFilter() {
|
||||
var month = $('#stats-month-filter').val();
|
||||
var year = $('#stats-year-filter').val();
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set('stats_month', month);
|
||||
url.searchParams.set('stats_year', year);
|
||||
window.location.href = url.toString();
|
||||
}
|
||||
|
||||
$('#stats-month-filter, #stats-year-filter').on('change', function() {
|
||||
updateStatsFilter();
|
||||
$('#stats-month-filter, #stats-year-filter').on('change', function() {
|
||||
updateStatsFilter();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
@endif
|
||||
|
||||
|
|
|
|||
|
|
@ -15,35 +15,42 @@
|
|||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<h4 class="media align-items-center font-weight-bold py-3 mb-2">
|
||||
{{-- <img src="assets/img/avatars/1.png" alt="" class="ui-w-50 rounded-circle"> --}}
|
||||
<div class="media-body ml-3">
|
||||
{{ __('home.welcome_back') }}, {{$user->account->first_name}}!
|
||||
<div class="text-muted text-tiny mt-1"><small class="font-weight-normal">{{ __('home.today_is') }} {{__('cal.weekdays.'.$now->format('l'))}}, {{$now->format('j')}}. {{__('cal.months.'.$now->format('F'))}} {{$now->format('Y')}}</small></div>
|
||||
</div>
|
||||
</h4>
|
||||
<h4 class="media align-items-center font-weight-bold py-3 mb-2">
|
||||
{{-- <img src="assets/img/avatars/1.png" alt="" class="ui-w-50 rounded-circle"> --}}
|
||||
<div class="media-body ml-3">
|
||||
{{ __('home.welcome_back') }}, {{ $user->account->first_name }}!
|
||||
<div class="text-muted text-tiny mt-1"><small class="font-weight-normal">{{ __('home.today_is') }}
|
||||
{{ __('cal.weekdays.' . $now->format('l')) }}, {{ $now->format('j') }}.
|
||||
{{ __('cal.months.' . $now->format('F')) }} {{ $now->format('Y') }}</small></div>
|
||||
</div>
|
||||
</h4>
|
||||
|
||||
<hr class="container-m-nx mt-0 mb-4">
|
||||
<hr class="container-m-nx mt-0 mb-4">
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="row">
|
||||
|
||||
@if (Auth::user()->isActiveAccount())
|
||||
@include('dashboard._news')
|
||||
|
||||
@include('dashboard._reminder')
|
||||
@include('dashboard._incentive')
|
||||
@endif
|
||||
|
||||
@include('dashboard._membership')
|
||||
|
||||
@include('dashboard._shop')
|
||||
@include('dashboard._reminder')
|
||||
|
||||
@include('dashboard._membership')
|
||||
@include('dashboard._shop')
|
||||
|
||||
@if (Auth::user()->isActiveAccount())
|
||||
@include('dashboard._statistics')
|
||||
|
||||
@include('dashboard._points')
|
||||
|
||||
@include('dashboard._activities')
|
||||
@endif
|
||||
@include('dashboard._settings')
|
||||
|
||||
@include('dashboard._settings')
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="container-m-nx mt-0 mb-4">
|
||||
<hr class="container-m-nx mt-0 mb-4">
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -200,12 +200,20 @@
|
|||
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidenav-item{{ Request::is('user/abos/team/*') ? ' active' : '' }}">
|
||||
<li class="sidenav-item{{ Request::is('user/abos/team/show') ? ' active' : '' }}">
|
||||
<a href="{{ route('user_abos_team_show') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-refresh-circle"></i>
|
||||
<div>{{ __('navigation.teamabos') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="sidenav-item{{ Request::is('user/abos/team/customers', 'user/abos/team/customers/*') ? ' active' : '' }}">
|
||||
<a href="{{ route('user_abos_team_customers') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-refresh-circle"></i>
|
||||
<div>{{ __('navigation.team_customers') }}</div>
|
||||
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="sidenav-item{{ Request::is('user/abos/me', 'user/abos/detail/me/*') ? ' active' : '' }}">
|
||||
<a href="{{ route('user_abos', ['me']) }}" class="sidenav-link"><i
|
||||
|
|
@ -259,6 +267,15 @@
|
|||
<div>{{ __('navigation.downloadcenter') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
@php $activeIncentive = \App\Models\Incentive::active()->first(); @endphp
|
||||
@if ($activeIncentive)
|
||||
<li class="sidenav-item{{ Request::is('incentive/*') ? ' active' : '' }}">
|
||||
<a href="{{ route('user_incentive_teaser', [$activeIncentive->slug]) }}"
|
||||
class="sidenav-link"><i class="text-secondary sidenav-icon ion ion-md-trophy"></i>
|
||||
<div>{{ __('navigation.incentive') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@endif
|
||||
@endif
|
||||
|
||||
|
|
@ -397,6 +414,27 @@
|
|||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="sidenav-item @if (Request::is('admin/incentives*')) open @endif">
|
||||
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
|
||||
<i class="sidenav-icon ion ion-md-trophy"></i>
|
||||
<div>{{ __('navigation.incentives') }}</div>
|
||||
</a>
|
||||
<ul class="sidenav-menu">
|
||||
<li class="sidenav-item{{ Request::is('admin/incentives') ? ' active' : '' }}">
|
||||
<a href="{{ route('admin_incentives') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-list"></i>
|
||||
<div>{{ __('navigation.overview') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidenav-item{{ Request::is('admin/incentives/create') ? ' active' : '' }}">
|
||||
<a href="{{ route('admin_incentive_create') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-add-circle"></i>
|
||||
<div>{{ __('navigation.create') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="sidenav-item @if (Request::is('admin/product/*')) open @endif">
|
||||
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
|
||||
<i class="sidenav-icon ion ion-md-cube"></i>
|
||||
|
|
@ -573,6 +611,12 @@
|
|||
<div>{{ __('navigation.user_cleanup') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidenav-item{{ Request::is('superadmin/tools', 'superadmin/tool/*') ? ' active' : '' }}">
|
||||
<a href="{{ route('superadmin_tools') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-ios-cog"></i>
|
||||
<div>{{ __('navigation.tools') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@if (Auth::user()->isSySAdmin())
|
||||
<li class="sidenav-divider mb-1"></li>
|
||||
|
|
|
|||
89
resources/views/partials/incentive/_source_table.blade.php
Normal file
89
resources/views/partials/incentive/_source_table.blade.php
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
@php $total = 0; $colspan = 3 + count($calculation_months); @endphp
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped table-bordered mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $label_header }}</th>
|
||||
<th>{{ $date_header }}</th>
|
||||
<th class="text-right">{{ __('incentive.onetime') }}</th>
|
||||
@foreach($calculation_months as $period)
|
||||
<th class="text-right">{{ str_pad($period['month'], 2, '0', STR_PAD_LEFT) }}/{{ $period['year'] }}</th>
|
||||
@endforeach
|
||||
<th class="text-right font-weight-bold">{{ __('incentive.sum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($sources as $idx => $source)
|
||||
<tr class="{{ count($source['transactions']) > 0 ? 'cursor-pointer' : '' }}"
|
||||
@if(count($source['transactions']) > 0)
|
||||
data-toggle="collapse" data-target="#transactions-{{ $type }}-{{ $source['id'] }}" aria-expanded="false"
|
||||
@endif
|
||||
>
|
||||
<td>
|
||||
@if(count($source['transactions']) > 0)
|
||||
<i class="fa fa-chevron-right fa-xs text-muted mr-1 toggle-icon" id="icon-{{ $type }}-{{ $source['id'] }}"></i>
|
||||
@endif
|
||||
{{ $source['label'] }}
|
||||
</td>
|
||||
<td>{{ str_pad($source['month'], 2, '0', STR_PAD_LEFT) }}/{{ $source['year'] }}</td>
|
||||
<td class="text-right">{{ number_format($source['onetime'], 0, ',', '.') }}</td>
|
||||
@foreach($source['monthly'] as $mp)
|
||||
<td class="text-right">{{ $mp > 0 ? number_format($mp, 0, ',', '.') : '-' }}</td>
|
||||
@endforeach
|
||||
<td class="text-right font-weight-bold">{{ number_format($source['total'], 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@if(count($source['transactions']) > 0)
|
||||
<tr class="collapse" id="transactions-{{ $type }}-{{ $source['id'] }}">
|
||||
<td colspan="{{ $colspan + 1 }}" class="p-0 border-0">
|
||||
<table class="table table-sm mb-0 bg-light">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th class="pl-4">{{ __('incentive.transaction_date') }}</th>
|
||||
<th>{{ __('incentive.transaction_description') }}</th>
|
||||
<th>{{ __('incentive.transaction_period') }}</th>
|
||||
<th class="text-right">{{ __('incentive.transaction_type') }}</th>
|
||||
<th class="text-right pr-4">{{ __('incentive.transaction_points') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($source['transactions'] as $tx)
|
||||
<tr class="small">
|
||||
<td class="pl-4">{{ $tx['date'] }}</td>
|
||||
<td>{{ $tx['label'] }}</td>
|
||||
<td>{{ str_pad($tx['month'], 2, '0', STR_PAD_LEFT) }}/{{ $tx['year'] }}</td>
|
||||
<td class="text-right">
|
||||
@if($tx['type'] === 'onetime')
|
||||
<span class="badge badge-primary">{{ __('incentive.onetime') }}</span>
|
||||
@else
|
||||
<span class="badge badge-info">{{ __('incentive.accumulated') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right pr-4 font-weight-bold">{{ number_format($tx['points'], 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@php $total += $source['total']; @endphp
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="{{ $colspan + 1 }}" class="text-center text-muted">{{ $empty_message }}</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
@if(count($sources) > 0)
|
||||
<tr class="font-weight-bold table-secondary">
|
||||
<td colspan="{{ $colspan }}">{{ __('incentive.subtotal') }}</td>
|
||||
<td class="text-right">{{ number_format($total, 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<style>
|
||||
.cursor-pointer { cursor: pointer; }
|
||||
.cursor-pointer:hover { background-color: rgba(0,0,0,.05) !important; }
|
||||
.toggle-icon { transition: transform .2s; }
|
||||
tr[aria-expanded="true"] .toggle-icon { transform: rotate(90deg); }
|
||||
</style>
|
||||
|
|
@ -1,196 +1,278 @@
|
|||
{!! Form::open(['action' => route('portal.my_subscriptions.create', 5), 'method' => 'POST', 'class' => '']) !!}
|
||||
|
||||
<div class="card-body">
|
||||
@if(Yard::instance('subscription')->content()->count())
|
||||
<style>
|
||||
.cart-item {
|
||||
position: relative;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.cart-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.cart-item .product-image {
|
||||
max-width: 80px;
|
||||
}
|
||||
.cart-item .product-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
color: #393939;
|
||||
}
|
||||
.cart-item .product-details {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
.cart-item .quantity-input {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
.cart-summary {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.cart-summary .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.cart-summary .table td {
|
||||
border-top: none;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.cart-summary .total-row {
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
@if (Yard::instance('subscription')->content()->count())
|
||||
<style>
|
||||
.cart-item {
|
||||
position: relative;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.cart-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cart-item .product-image {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.cart-item .product-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
color: #393939;
|
||||
}
|
||||
|
||||
.cart-item .product-details {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cart-item .quantity-input {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cart-summary {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.cart-summary .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.cart-summary .table td {
|
||||
border-top: none;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.cart-summary .total-row {
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="cart-overview">
|
||||
<h4 class="mb-4">{{ __('abo.abo_order_hl') }}</h4>
|
||||
@if (isset($error))
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ $error }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
@foreach (Yard::instance('subscription')->getContentByOrder() as $row)
|
||||
@php($product = \App\Models\Product::find($row->id))
|
||||
<div class="cart-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-3 col-sm-2">
|
||||
@if ($row->options->has('image'))
|
||||
<img src="{{ route('product_image', [$row->options->image]) }}" class="product-image"
|
||||
alt="{{ $row->name }}">
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7">
|
||||
<div class="product-title">
|
||||
{{ $row->name }}
|
||||
|
||||
<div class="cart-overview">
|
||||
<h4 class="mb-4">{{ __('abo.abo_order_hl') }}</h4>
|
||||
@if(isset($error))
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ $error }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
@foreach(Yard::instance('subscription')->getContentByOrder() as $row)
|
||||
@php($product = \App\Models\Product::find($row->id))
|
||||
<div class="cart-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-3 col-sm-2">
|
||||
@if($row->options->has('image'))
|
||||
<img src="{{ route('product_image', [$row->options->image]) }}" class="product-image" alt="{{ $row->name }}">
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7">
|
||||
<div class="product-title">
|
||||
{{ $row->name }}
|
||||
|
||||
{!! get_abo_type_badge_by_product($product) !!}
|
||||
|
||||
|
||||
</div>
|
||||
<div class="product-details">
|
||||
<div>{{ __('order.content') }}: {{ $product->contents }}</div>
|
||||
<div>{{ __('order.art_no') }}: {{ $product->number }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-details">
|
||||
<div>{{ __('order.content') }}: {{ $product->contents }}</div>
|
||||
<div>{{ __('order.art_no') }}: {{ $product->number }}</div>
|
||||
<div class="col-6 col-sm-3 col-md-2">
|
||||
<div class="price-single">
|
||||
<div style="">{{ $row->price() }} €
|
||||
{{ Yard::instance('subscription')->getUserTaxFree() }}</div>
|
||||
@if (Yard::instance('subscription')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('price', $row, 2) }}
|
||||
{{ Yard::instance('subscription')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-2">
|
||||
<div class="price-single">
|
||||
<div style="">{{ $row->price() }} € {{ Yard::instance('subscription')->getUserTaxFree() }}</div>
|
||||
@if(Yard::instance('subscription')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('price', $row, 2) }} {{ Yard::instance('subscription')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-3">
|
||||
<div class="quantity-select text-right">
|
||||
@if($row->options->comp)
|
||||
<span class="text-right">1 x</span>
|
||||
@else
|
||||
<span class="text-right">{{ $row->qty }} x</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="price-total text-right mt-2">
|
||||
<span class="font-bold text-price-total"><strong>{{ $row->subtotal() }} € </strong></span>
|
||||
@if(Yard::instance('subscription')->isPriceCurrency())
|
||||
<br>
|
||||
<span class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('subtotal', $row, 2) }} {{ Yard::instance('subscription')->getPriceCurrencyUnit() }} </span> @endif
|
||||
<div class="col-6 col-sm-3 col-md-3">
|
||||
<div class="quantity-select text-right">
|
||||
@if ($row->options->comp)
|
||||
<span class="text-right">1 x</span>
|
||||
@else
|
||||
<span class="text-right">{{ $row->qty }} x</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="price-total text-right mt-2">
|
||||
<span class="font-bold text-price-total"><strong>{{ $row->subtotal() }} €
|
||||
</strong></span>
|
||||
@if (Yard::instance('subscription')->isPriceCurrency())
|
||||
<br>
|
||||
<span
|
||||
class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('subtotal', $row, 2) }}
|
||||
{{ Yard::instance('subscription')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endforeach
|
||||
|
||||
<div class="cart-summary mt-4">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ __('order.subtotal') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->total() }} €
|
||||
@if(Yard::instance('subscription')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('subtotal') }} {{ Yard::instance('subscription')->getPriceCurrencyUnit() }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ __('Delivery country') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->getShippingCountryName() }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ __('order.shipping_costs') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->shipping() }} €
|
||||
</td>
|
||||
</tr>
|
||||
@if(Yard::instance('subscription')->getUserTaxFree())
|
||||
<tr>
|
||||
<td class="">{{ __('order.sum_net') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->subtotalWithShipping() }} €</td>
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
<td class="">{{ __('order.total_without_VAT') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->subtotalWithShipping() }} €</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="">{{ __('order.plus_VAT') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->taxWithShipping() }} €</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
||||
<tr class="total-row">
|
||||
<td>
|
||||
@if(Yard::instance('subscription')->getUserTaxFree())
|
||||
{{ __('order.total_net') }}:
|
||||
@else
|
||||
{{ __('order.total_gross') }}:
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->totalWithShipping() }} €
|
||||
@if(Yard::instance('subscription')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('totalWithShipping') }} {{ Yard::instance('subscription')->getPriceCurrencyUnit() }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="cart-summary mt-4">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ __('order.subtotal') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->total() }} €
|
||||
@if (Yard::instance('subscription')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('subtotal') }}
|
||||
{{ Yard::instance('subscription')->getPriceCurrencyUnit() }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ __('Delivery country') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->getShippingCountryName() }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ __('order.shipping_costs') }}:</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->shipping() }} €
|
||||
</td>
|
||||
</tr>
|
||||
@if (Yard::instance('subscription')->getUserTaxFree())
|
||||
<tr>
|
||||
<td class="">{{ __('order.sum_net') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->subtotalWithShipping() }} €
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
<td class="">{{ __('order.total_without_VAT') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->subtotalWithShipping() }} €
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="">{{ __('order.plus_VAT') }}:</td>
|
||||
<td class="text-right">{{ Yard::instance('subscription')->taxWithShipping() }} €</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
||||
<tr class="total-row">
|
||||
<td>
|
||||
@if (Yard::instance('subscription')->getUserTaxFree())
|
||||
{{ __('order.total_net') }}:
|
||||
@else
|
||||
{{ __('order.total_gross') }}:
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ Yard::instance('subscription')->totalWithShipping() }} €
|
||||
@if (Yard::instance('subscription')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('subscription')->getCurrencyByKey('totalWithShipping') }}
|
||||
{{ Yard::instance('subscription')->getPriceCurrencyUnit() }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="abo-settings mt-4 text-right">
|
||||
<div class="alert alert-info text-left">
|
||||
<h4>{{ __('abo.abo_settings') }}</h4>
|
||||
<div class="form-row">
|
||||
<div class="col-6 col-sm-8 col-md-9 col-lg-9 mb-1"></div>
|
||||
<div class="col-12 col-sm-4 col-md-3 col-lg-3 mb-1 text-right">
|
||||
<label class="form-label">{{ __('abo.delivery_day') }}*</label>
|
||||
<select class="custom-select" name="abo_interval" id="abo_interval_select">
|
||||
{!! HTMLHelper::getAboDeliveryOptions() !!}
|
||||
</select>
|
||||
<div id="abo_interval_info" class="alert alert-info mt-2 small d-none"></div>
|
||||
<div id="abo_interval_warning" class="alert alert-warning mt-2 small d-none"></div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var select = document.getElementById('abo_interval_select');
|
||||
var info = document.getElementById('abo_interval_info');
|
||||
var warning = document.getElementById('abo_interval_warning');
|
||||
if (!select || !info || !warning) return;
|
||||
|
||||
var infoTpl = @json(__('abo.info_next_execution_select', ['placeholder_days' => '__DAYS__', 'placeholder_date' => '__DATE__']));
|
||||
var warnTpl = @json(__('abo.warning_next_date_soon_select', ['placeholder_days' => '__DAYS__', 'placeholder_date' => '__DATE__']));
|
||||
|
||||
function checkDays() {
|
||||
var option = select.options[select.selectedIndex];
|
||||
var days = parseInt(option.getAttribute('data-days'), 10);
|
||||
var date = option.getAttribute('data-date') || '';
|
||||
if (isNaN(days)) {
|
||||
return;
|
||||
}
|
||||
var showWarning = days < 20;
|
||||
if (showWarning) {
|
||||
info.innerHTML = '';
|
||||
info.classList.add('d-none');
|
||||
warning.innerHTML =
|
||||
'<i class="fa fa-exclamation-triangle"></i> ' +
|
||||
warnTpl.replace('__DAYS__', days).replace('__DATE__', date);
|
||||
warning.classList.remove('d-none');
|
||||
} else {
|
||||
warning.classList.add('d-none');
|
||||
info.innerHTML =
|
||||
'<i class="fa fa-info-circle"></i> ' +
|
||||
infoTpl.replace('__DAYS__', days).replace('__DATE__', date);
|
||||
info.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
select.addEventListener('change', checkDays);
|
||||
checkDays();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-4 col-lg-6 mb-1"></div>
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 mb-1">
|
||||
<div class="text-right">
|
||||
<em class="small"><i>{!! __('abo.abo_order_info_check') !!}</i></em>
|
||||
<hr class="my-2" style="border-color: #b4b4b4;">
|
||||
<em class="font-weight-bold"><i>{!! __('abo.abo_order_info_check_2') !!}</i></em>
|
||||
<hr class="my-2" style="border-color: #b4b4b4;">
|
||||
<em class="small"><i>{!! __('abo.abo_order_info_check_3', [
|
||||
'abo-min-duration' => \App\Models\Setting::getContentBySlug('abo-min-duration'),
|
||||
]) !!}</i></em>
|
||||
<hr class="my-2" style="border-color: #b4b4b4;">
|
||||
<label class="switcher switcher-success d-inline-flex align-items-center">
|
||||
<input type="checkbox" class="switcher-input" name="abo_order_info_checkbox"
|
||||
value="true" required>
|
||||
<span class="switcher-indicator">
|
||||
<span class="switcher-yes"><span class="ion ion-md-checkmark"></span></span>
|
||||
<span class="switcher-no"><span class="ion ion-md-close"></span></span>
|
||||
</span>
|
||||
<span class="switcher-label"><strong>{{ __('abo.abo_order_info_checkbox') }}</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="abo-settings mt-4">
|
||||
<h5>{{ __('abo.abo_settings') }}</h5>
|
||||
<div class="form-group">
|
||||
<label>{{ __('abo.delivery_day') }}*</label>
|
||||
<select class="form-control custom-select" name="abo_interval">
|
||||
{!! HTMLHelper::getAboDeliveryOptions() !!}
|
||||
</select>
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle"></i> {!! __('abo.abo_order_info_check') !!}
|
||||
<hr>
|
||||
<i class="fa fa-info-circle"></i> {!! __('abo.abo_order_info_check_2') !!}
|
||||
<hr>
|
||||
<i class="fa fa-info-circle"></i> {!! __('abo.abo_order_info_check_3', ['abo-min-duration' => \App\Models\Setting::getContentBySlug('abo-min-duration')]) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-default" name="action" value="back">{{ __('abo.back') }}</button>
|
||||
<div class="float-right">
|
||||
<button type="submit" class="btn btn-secondary" name="action" value="checkout"><i class="ion ion-ios-redo"></i> {{ __('order.confirm_and_proceed_to_checkout') }}</button>
|
||||
<button type="submit" class="btn btn-secondary" name="action" value="checkout"><i
|
||||
class="ion ion-ios-redo"></i> {{ __('order.confirm_and_send_order') }}</button>
|
||||
</div>
|
||||
<br><br>
|
||||
<div class="text-right">
|
||||
<em class="small"> <i class="fa fa-lock"></i> {!! __('payment.checkout_ssl_server') !!}</em>
|
||||
<em class="small"><i class="fa fa-info-circle"></i> {!! __('order.confirm_send_order_info') !!}</em>
|
||||
</div>
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
<ul class="sidenav-inner{{ empty($layout_sidenav_horizontal) ? ' py-1' : '' }}">
|
||||
|
||||
@if (Auth::guard('customers')->check())
|
||||
|
||||
<li class="sidenav-item{{ Request::is('portal/dashboard') ? ' active' : '' }}">
|
||||
<a href="{{ route('portal.dashboard') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-ios-home"></i>
|
||||
|
|
@ -26,14 +25,12 @@
|
|||
<div>{{ __('navigation.my_orders') }}</div>
|
||||
</a>
|
||||
</li>
|
||||
@if (Auth::user()->is_admin || Util::isTestSystem(true))
|
||||
<li class="sidenav-item{{ Request::is('portal/subscriptions') ? ' active' : '' }}">
|
||||
<a href="{{ route('portal.my_subscriptions') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-refresh-circle"></i>
|
||||
<div>{{ __('navigation.myabo') }} <span class="badge badge-warning">DEV</span></div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<li class="sidenav-item{{ Request::is('portal/subscriptions') ? ' active' : '' }}">
|
||||
<a href="{{ route('portal.my_subscriptions') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-md-refresh-circle"></i>
|
||||
<div>{{ __('navigation.myabo') }} </div>
|
||||
</a>
|
||||
</li>
|
||||
{{--
|
||||
<li class="sidenav-item{{ Request::is('portal/settings') ? ' active' : '' }}">
|
||||
<a href="{{ route('portal.settings') }}" class="sidenav-link"><i class="sidenav-icon ion ion-md-settings"></i><div>{{ __('navigation.settings') }}</div></a>
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@
|
|||
@endif
|
||||
</div>
|
||||
<hr class="m-0">
|
||||
@if (! $shopping_order->is_abo)
|
||||
<div class="card-body">
|
||||
<h6 class="font-weight-semibold">
|
||||
{{ __('order.reorder') }}
|
||||
|
|
@ -288,6 +289,7 @@
|
|||
|
||||
</div>
|
||||
<hr class="m-0">
|
||||
@endif
|
||||
|
||||
<div class="card-body">
|
||||
<h6 class="font-weight-semibold">
|
||||
|
|
|
|||
|
|
@ -1,29 +1,61 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card mt-5">
|
||||
<h5 class="card-header py-4 px-5">Sys Admin Tools</h5>
|
||||
<h5 class="card-header py-4 px-5">
|
||||
@if (Auth::user()->isSuperAdmin())
|
||||
Super
|
||||
@else
|
||||
Sys
|
||||
@endif
|
||||
Admin Tools
|
||||
</h5>
|
||||
<div class="row no-gutters row-bordered">
|
||||
<div class="col-md-12 p-5">
|
||||
<a href="{{ route('sysadmin_tool', ['buyings_products']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Add Buyings Products from Order</a>
|
||||
<a href="{{ route('sysadmin_tool', ['business_structur']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Business Strukrur speichern</a>
|
||||
<a href="{{ route('sysadmin_tool', ['sales_members']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Buchnungen Pakete Berater nach Jahren</a>
|
||||
<a href="{{ route('sysadmin_tool', ['customers']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Kundenhoheit prüfen</a>
|
||||
<a href="{{ route('sysadmin_tool', ['cronjobs']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Cron Jobs</a>
|
||||
<a href="{{ route('sysadmin_tool', ['domainssl']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Subdomains prüfen SSL/Aktiv</a>
|
||||
<a href="{{ route('sysadmin_tool', ['shopping_orders']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Shopping Orders Käufe</a>
|
||||
<a href="{{ route('sysadmin_tool', ['import']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Import</a>
|
||||
<a href="{{ route('sysadmin_tool', ['corrections']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Corrections Points / Payment / Price / Tax / Tax Spit / Points / Discount </a>
|
||||
<a href="{{ route('sysadmin_tool', ['change_user_businesses']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Change user level qual_pp in UserBusiness </a>
|
||||
<a href="{{ route('sysadmin_tool', ['repair_sales_volume_invoice']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Repair Sales Volume save InvoiceID </a>
|
||||
<a href="{{ route('sysadmin_tool', ['user_credit_items_change_message']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> User Credit items Change Message </a>
|
||||
<a href="{{ route('sysadmin_tool', ['clean_html_product_description']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> clean_html_product_description </a>
|
||||
<a href="{{ route('sysadmin_tool', ['user_credit_items_add_from']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> user_credit_items add from month year </a>
|
||||
<a href="{{ route('sysadmin_tool', ['import_dbip_country_lite']) }}" class="d-block mb-3"><i class="ion ion-ios-arrow-forward"></i> Import dbip-country-lite </a>
|
||||
<div class="col-md-12 p-5">
|
||||
@if (Auth::user()->isSysAdmin())
|
||||
<a href="{{ route('sysadmin_tool', ['buyings_products']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Add Buyings Products from Order</a>
|
||||
<a href="{{ route('sysadmin_tool', ['business_structur']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Business Strukrur speichern</a>
|
||||
<a href="{{ route('sysadmin_tool', ['sales_members']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Buchnungen Pakete Berater nach Jahren</a>
|
||||
<a href="{{ route('sysadmin_tool', ['customers']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Kundenhoheit prüfen</a>
|
||||
<a href="{{ route('sysadmin_tool', ['cronjobs']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Cron Jobs</a>
|
||||
<a href="{{ route('sysadmin_tool', ['domainssl']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Subdomains prüfen SSL/Aktiv</a>
|
||||
<a href="{{ route('sysadmin_tool', ['shopping_orders']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Shopping Orders Käufe</a>
|
||||
<a href="{{ route('sysadmin_tool', ['import']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Import</a>
|
||||
<a href="{{ route('sysadmin_tool', ['corrections']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Corrections Points / Payment / Price / Tax / Tax
|
||||
Spit /
|
||||
Points / Discount </a>
|
||||
<a href="{{ route('sysadmin_tool', ['change_user_businesses']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Change user level qual_pp in UserBusiness </a>
|
||||
<a href="{{ route('sysadmin_tool', ['repair_sales_volume_invoice']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Repair Sales Volume save InvoiceID </a>
|
||||
<a href="{{ route('sysadmin_tool', ['user_credit_items_change_message']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> User Credit items Change Message </a>
|
||||
<a href="{{ route('sysadmin_tool', ['clean_html_product_description']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> clean_html_product_description </a>
|
||||
<a href="{{ route('sysadmin_tool', ['user_credit_items_add_from']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> user_credit_items add from month year </a>
|
||||
<a href="{{ route('sysadmin_tool', ['import_dbip_country_lite']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> Import dbip-country-lite </a>
|
||||
<a href="{{ route('sysadmin_tool', ['payone_callback_testbench']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> <strong>Payone-Callback Testbench</strong>
|
||||
({{ parse_url(route('api.payment_status', [], true), PHP_URL_HOST) }}/payment/status) </a>
|
||||
@endif
|
||||
@if (Auth::user()->isSuperAdmin())
|
||||
<a href="{{ route('sysadmin_tool', ['abo_orders_overview']) }}" class="d-block mb-3"><i
|
||||
class="ion ion-ios-arrow-forward"></i> <strong class="text-danger">Abo-Bestellungen
|
||||
Zahlungsdifferenzen</strong> </a>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
135
resources/views/sys/tools/abo-orders-overview.blade.php
Normal file
135
resources/views/sys/tools/abo-orders-overview.blade.php
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold mb-4">
|
||||
Abo-Bestellungen – Soll-Brutto vs. tatsächlich eingezogen (ShoppingPayment)
|
||||
</h4>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="btn-group mb-3" role="group">
|
||||
<a href="{{ route('sysadmin_tool', ['abo_orders_overview']) }}"
|
||||
class="btn btn-{{ $filter === 'all' ? 'primary' : 'outline-primary' }}">Alle</a>
|
||||
<a href="{{ route('sysadmin_tool', ['abo_orders_overview']) }}?filter=berater"
|
||||
class="btn btn-{{ $filter === 'berater' ? 'warning' : 'outline-warning' }}">Berater</a>
|
||||
<a href="{{ route('sysadmin_tool', ['abo_orders_overview']) }}?filter=kunde"
|
||||
class="btn btn-{{ $filter === 'kunde' ? 'info' : 'outline-info' }}">Kunden</a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="alert alert-info mb-0">
|
||||
<strong>Gesamt Bestellungen:</strong> {{ $summary['total_orders'] }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="alert alert-{{ $summary['affected_orders'] > 0 ? 'danger' : 'success' }} mb-0">
|
||||
<strong>Betroffene Bestellungen:</strong> {{ $summary['affected_orders'] }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="alert alert-{{ $summary['total_diff'] != 0 ? 'danger' : 'success' }} mb-0">
|
||||
<strong>Fehlbetrag gesamt:</strong> {{ number_format($summary['total_diff'], 2, ',', '.') }} €
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="alert alert-warning mb-0">
|
||||
<strong>Hinweis:</strong> Eingezogen = Summe <code>shopping_payments.amount</code> bei TX
|
||||
paid / extern_paid / invoice_paid. Soll = <code>total_shipping</code> (Brutto).
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered table-sm">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Abo-Order ID</th>
|
||||
<th>Abo ID</th>
|
||||
<th>Order ID</th>
|
||||
<th>User</th>
|
||||
<th>Typ</th>
|
||||
<th class="text-right">Netto+Versand (subtotal_ws)</th>
|
||||
<th class="text-right">MwSt</th>
|
||||
<th class="text-right">Soll Brutto (total_shipping)</th>
|
||||
<th class="text-right">Eingezogen (Zahlung)</th>
|
||||
<th>Zahlungs-TX</th>
|
||||
<th class="text-right text-danger">Differenz (Soll − Ist)</th>
|
||||
<th>Status</th>
|
||||
<th>Bezahlt</th>
|
||||
<th>TX-Action</th>
|
||||
<th>Datum</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($rows as $row)
|
||||
<tr class="{{ isset($row['diff']) && $row['diff'] != 0 ? 'table-danger' : '' }}">
|
||||
<td>{{ $row['abo_order_id'] }}</td>
|
||||
<td>{{ $row['abo_id'] }}</td>
|
||||
<td>{!! $row['order_id'] !!}</td>
|
||||
<td>
|
||||
<small>
|
||||
@if ($row['user_id'])
|
||||
<strong>#{{ $row['user_id'] }}</strong>
|
||||
@endif
|
||||
{{ $row['user_name'] }}<br>
|
||||
{{ $row['user_email'] }}
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
@if ($row['is_for'] === 'me')
|
||||
<span class="badge badge-outline-warning-dark">Berater</span>
|
||||
@else
|
||||
<span class="badge badge-outline-info">Kunde</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right">{{ number_format($row['subtotal_ws'], 2, ',', '.') }} €</td>
|
||||
<td class="text-right">{{ number_format($row['tax'], 2, ',', '.') }} €</td>
|
||||
<td class="text-right">{{ number_format($row['total_shipping'], 2, ',', '.') }} €</td>
|
||||
<td class="text-right">
|
||||
@if ($row['actual_charged_eur'] !== null)
|
||||
{{ number_format($row['actual_charged_eur'], 2, ',', '.') }} €
|
||||
@else
|
||||
<span class="text-muted"
|
||||
title="Keine Zahlung mit Status paid/extern_paid/invoice_paid">–</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<small>{{ $row['payment_txactions'] ?: '–' }}</small>
|
||||
@if (($row['payment_count'] ?? 0) > 1)
|
||||
<span class="badge badge-secondary"
|
||||
title="Anzahl Zahlungszeilen">{{ $row['payment_count'] }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right">
|
||||
@if ($row['diff'] === null)
|
||||
<span class="text-muted">–</span>
|
||||
@elseif($row['diff'] != 0)
|
||||
<strong class="text-danger">{{ number_format($row['diff'], 2, ',', '.') }}
|
||||
€</strong>
|
||||
@else
|
||||
<span class="text-success">0,00 €</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{!! $row['status_badge'] ?? '<span class="badge badge-pill badge-secondary">' . $row['status'] . '</span>' !!}</td>
|
||||
<td>
|
||||
@if ($row['paid'])
|
||||
<span class="badge badge-success">Ja</span>
|
||||
@else
|
||||
<span class="badge badge-danger">Nein</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $row['txaction'] }}</td>
|
||||
<td><small>{{ $row['created_at'] ? $row['created_at']->format('d.m.Y H:i') : '-' }}</small>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
268
resources/views/sys/tools/payone-callback-testbench.blade.php
Normal file
268
resources/views/sys/tools/payone-callback-testbench.blade.php
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<h4 class="font-weight-bold mb-3">
|
||||
Payone-Callback Testbench
|
||||
</h4>
|
||||
|
||||
<p class="text-muted mb-4">
|
||||
<strong>Erstbestellung Abo (realistisch):</strong> Zuerst legt der Checkout das Abo an
|
||||
(<code>CheckoutController</code> → <code>AboHelper::createNewAbo</code>), danach meldet Payone per
|
||||
<code>POST {{ route('api.payment_status', [], true) }}</code> den Zahlungsstatus – dann laufen u. a.
|
||||
<code>Payment::paymentStatusPaidAction</code>, Abo-Freischaltung (<code>setAboActive</code>) und
|
||||
<code>IncentiveTracker::trackAboActivated</code>. Die Testbench-Schritte sind in dieser Reihenfolge angeordnet.
|
||||
Nur außerhalb Production.
|
||||
</p>
|
||||
|
||||
@if (session('error'))
|
||||
<div class="alert alert-danger">{{ session('error') }}</div>
|
||||
@endif
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header font-weight-bold">1. Test-Bestellung anlegen</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="create_fixture">
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 col-form-label">Betrag (Brutto EUR)</label>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="amount_eur" class="form-control" step="0.01" min="0.01"
|
||||
value="{{ old('amount_eur', '119.00') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 col-form-label">Berater (users.id)</label>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="consultant_user_id" class="form-control" min="1"
|
||||
value="{{ old('consultant_user_id', '454') }}" required>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<small class="form-text text-muted">
|
||||
Bei <code>is_for = me</code> wird <code>auth_user_id</code> gesetzt; bei <code>ot</code> bleibt
|
||||
<code>auth_user_id</code> leer und <code>member_id</code> wird auf diese Berater-ID gesetzt.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 offset-md-3">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" name="is_abo" id="is_abo" class="form-check-input" value="1"
|
||||
{{ old('is_abo') ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="is_abo">Als Abo-Bestellung (<code>is_abo</code>)</label>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<input type="checkbox" name="is_for_ot" id="is_for_ot" class="form-check-input" value="1"
|
||||
{{ old('is_for_ot', true) ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="is_for_ot">Kundenkontext <code>is_for = ot</code> (für
|
||||
Incentive <code>trackAboActivated</code>)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 offset-md-3">
|
||||
<button type="submit" class="btn btn-primary">Bestellung + Zahlung anlegen</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!empty($fixture))
|
||||
<div class="card mb-4 border-success">
|
||||
<div class="card-header font-weight-bold text-success">Angelegte Testdaten</div>
|
||||
<div class="card-body">
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-sm-3">shopping_order_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $fixture['shopping_order_id'] }}</code></dd>
|
||||
<dt class="col-sm-3">shopping_payment_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $fixture['shopping_payment_id'] }}</code></dd>
|
||||
<dt class="col-sm-3">reference (16)</dt>
|
||||
<dd class="col-sm-9"><code>{{ $fixture['reference'] }}</code></dd>
|
||||
<dt class="col-sm-3">amount (Cent)</dt>
|
||||
<dd class="col-sm-9"><code>{{ $fixture['amount_cents'] }}</code> (=
|
||||
{{ number_format($fixture['amount_eur'], 2, ',', '.') }} €)</dd>
|
||||
<dt class="col-sm-3">Berater-ID</dt>
|
||||
<dd class="col-sm-9"><code>{{ $fixture['consultant_user_id'] ?? '–' }}</code></dd>
|
||||
<dt class="col-sm-3">Zuordnung</dt>
|
||||
<dd class="col-sm-9"><small>{{ $fixture['assignment_note'] ?? '' }}</small></dd>
|
||||
<dt class="col-sm-3">API-URL</dt>
|
||||
<dd class="col-sm-9"><small class="text-break">{{ $fixture['api_url'] }}</small></dd>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<p class="mb-2 font-weight-bold">2. Checkout-Erfolg (nur Abo)</p>
|
||||
<p class="small text-muted mb-2">
|
||||
Wie <code>handleSuccessfulTransaction</code> / <code>transactionApproved</code>:
|
||||
<code>AboHelper::createNewAbo($ShoppingPayment)</code> – legt UserAbo + UserAboOrder an.
|
||||
Ohne vorherige <code>payment_transactions</code> wird eine Minimal-Transaktion angelegt.
|
||||
</p>
|
||||
@if (!empty($fixture['is_abo']))
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="simulate_checkout_success">
|
||||
<input type="hidden" name="shopping_order_id" value="{{ $fixture['shopping_order_id'] }}">
|
||||
<button type="submit" class="btn btn-success">Abo anlegen (<code>createNewAbo</code>)</button>
|
||||
</form>
|
||||
@else
|
||||
<p class="small text-muted mb-0">Nicht-Abo – Schritt entfällt.</p>
|
||||
@endif
|
||||
|
||||
<hr>
|
||||
<p class="mb-2 font-weight-bold">3. Payone-API: Zahlung bestätigt (<code>paid</code>)</p>
|
||||
<p class="small text-muted mb-2">
|
||||
<code>Api\PayoneController::paymentStatus</code> → <code>Payment::paymentStatusPaidAction</code>
|
||||
(Abo freischalten, Incentive, …). Bei Abo-Erstbestellung nur nach Schritt 2 (sonst Fehlermeldung).
|
||||
</p>
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
|
||||
class="d-inline mr-2">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="simulate_paid">
|
||||
<input type="hidden" name="shopping_order_id" value="{{ $fixture['shopping_order_id'] }}">
|
||||
<button type="submit" class="btn btn-warning">Simulate <code>txaction=paid</code> (Erstbestellung)</button>
|
||||
</form>
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="clear_fixture">
|
||||
<button type="submit" class="btn btn-outline-secondary btn-sm">Session-Daten löschen</button>
|
||||
</form>
|
||||
|
||||
@php
|
||||
$benchUserAboId = $userAboId ?? ($checkoutSuccess['user_abo_id'] ?? null);
|
||||
@endphp
|
||||
@if (!empty($fixture['is_abo']) && $benchUserAboId)
|
||||
<hr>
|
||||
<p class="mb-2 font-weight-bold">4. Abo-Verlängerung (wie <code>user:make_abo_order</code> / Cron)</p>
|
||||
<p class="small text-muted mb-2">
|
||||
Setzt <code>next_date</code> auf heute, entfernt ggf. heutige <code>user_abo_orders</code> (Test-Wiederholung),
|
||||
führt dann <code>UserMakeAboOrder::makeOrder</code> aus (neue Bestellung + Payone). Anschließend Incentive-Zähler
|
||||
(z. B. qualifizierte Abos) und Umsatzpunkte prüfen – für Rechnung/SV wie in Produktion Schritt 5.
|
||||
</p>
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
|
||||
class="mb-3">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="simulate_cron_renewal">
|
||||
<div class="form-group row align-items-center">
|
||||
<label class="col-md-3 col-form-label"><code>user_abos.id</code></label>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="user_abo_id" class="form-control" min="1"
|
||||
value="{{ old('user_abo_id', $benchUserAboId) }}">
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<small class="form-text text-muted mb-0">Standard aus Session nach Schritt 2/3; anpassbar.</small>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-primary">Cron-Verlängerung ausführen</button>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
@if (!empty($cronRenewalOrderId))
|
||||
<hr>
|
||||
<p class="mb-2 font-weight-bold">5. Payone-API: Verlängerung bestätigt (<code>paid</code>)</p>
|
||||
<p class="small text-muted mb-2">
|
||||
Wie Server-zu-Server-Callback nach Cron-Zahlung: <code>Payment::paymentStatusPaidAction</code> (Rechnung,
|
||||
<code>createAndSalesVolume</code> → <code>IncentiveTracker::trackSalesVolume</code>, …).
|
||||
</p>
|
||||
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="simulate_paid">
|
||||
<input type="hidden" name="shopping_order_id" value="{{ $cronRenewalOrderId }}">
|
||||
<button type="submit" class="btn btn-warning">Simulate <code>txaction=paid</code> (Verlängerung)</button>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
<hr>
|
||||
<p class="mb-2 font-weight-bold">Manuell (z. B. Postman / curl)</p>
|
||||
<pre class="bg-light p-3 small text-break mb-0" style="white-space: pre-wrap;">{{ $fixture['curl'] }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!empty($simulateResult))
|
||||
<div class="card mb-4 border-info">
|
||||
<div class="card-header font-weight-bold">Ergebnis Schritt 3 (Payone-API)</div>
|
||||
<div class="card-body">
|
||||
@if (!empty($simulateResult['hint']))
|
||||
<p class="small text-muted mb-3">{{ $simulateResult['hint'] }}</p>
|
||||
@endif
|
||||
<dl class="row">
|
||||
<dt class="col-sm-3">HTTP (Kernel)</dt>
|
||||
<dd class="col-sm-9"><code>{{ $simulateResult['http_status'] }}</code></dd>
|
||||
<dt class="col-sm-3">Body</dt>
|
||||
<dd class="col-sm-9"><code>{{ $simulateResult['body'] }}</code> <span class="text-muted">(Payone
|
||||
erwartet TSOK)</span></dd>
|
||||
<dt class="col-sm-3">Order paid</dt>
|
||||
<dd class="col-sm-9">{{ $simulateResult['order_paid'] ? 'true' : 'false' }}</dd>
|
||||
<dt class="col-sm-3">Order txaction</dt>
|
||||
<dd class="col-sm-9"><code>{{ $simulateResult['order_txaction'] ?? 'null' }}</code></dd>
|
||||
</dl>
|
||||
<p class="mb-1 font-weight-bold">Gesendeter Payload</p>
|
||||
<pre class="bg-light p-3 small mb-0">{{ json_encode($simulateResult['payload'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!empty($checkoutSuccess))
|
||||
<div class="card mb-4 border-success">
|
||||
<div class="card-header font-weight-bold text-success">Ergebnis Schritt 2 (Checkout / createNewAbo)</div>
|
||||
<div class="card-body">
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-sm-3">user_abo_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $checkoutSuccess['user_abo_id'] ?? '–' }}</code></dd>
|
||||
<dt class="col-sm-3">user_abo_orders.id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $checkoutSuccess['user_abo_order_id'] ?? '–' }}</code></dd>
|
||||
<dt class="col-sm-3">shopping_order_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $checkoutSuccess['shopping_order_id'] ?? '–' }}</code></dd>
|
||||
<dt class="col-sm-3">Order paid (nachher)</dt>
|
||||
<dd class="col-sm-9">{{ !empty($checkoutSuccess['order_paid_after']) ? 'true' : 'false' }}</dd>
|
||||
</dl>
|
||||
@if (!empty($checkoutSuccess['hint']))
|
||||
<p class="small text-muted mb-0 mt-2">{{ $checkoutSuccess['hint'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!empty($cronRenewal))
|
||||
<div class="card mb-4 border-primary">
|
||||
<div class="card-header font-weight-bold text-primary">Ergebnis Schritt 4 (Cron-Verlängerung)</div>
|
||||
<div class="card-body">
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-sm-3">Erfolg</dt>
|
||||
<dd class="col-sm-9">{{ !empty($cronRenewal['success']) ? 'true' : 'false' }}</dd>
|
||||
@if (!empty($cronRenewal['shopping_order_id']))
|
||||
<dt class="col-sm-3">Neue shopping_order_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $cronRenewal['shopping_order_id'] }}</code></dd>
|
||||
@endif
|
||||
@if (!empty($cronRenewal['user_abo_id']))
|
||||
<dt class="col-sm-3">user_abo_id</dt>
|
||||
<dd class="col-sm-9"><code>{{ $cronRenewal['user_abo_id'] }}</code></dd>
|
||||
@endif
|
||||
@if (!empty($cronRenewal['message']))
|
||||
<dt class="col-sm-3">Hinweis</dt>
|
||||
<dd class="col-sm-9">{{ $cronRenewal['message'] }}</dd>
|
||||
@endif
|
||||
@if (!empty($cronRenewal['diagnosis']))
|
||||
<dt class="col-sm-3">Diagnose</dt>
|
||||
<dd class="col-sm-9">
|
||||
<pre class="bg-light p-2 small mb-0 text-break"
|
||||
style="white-space: pre-wrap;">{{ json_encode($cronRenewal['diagnosis'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}</pre>
|
||||
</dd>
|
||||
@endif
|
||||
</dl>
|
||||
@if (!empty($cronRenewal['hint']))
|
||||
<p class="small text-muted mb-0 mt-2">{{ $cronRenewal['hint'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
111
resources/views/user/abo/_abo_chart.blade.php
Normal file
111
resources/views/user/abo/_abo_chart.blade.php
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
@php
|
||||
$chartId = 'aboChart_' . str_replace('.', '', microtime(true));
|
||||
$chartDataJson = json_encode(array_values($chartData));
|
||||
$chartLabelsJson = json_encode(array_values($chartMonths));
|
||||
$nonNullValues = array_filter($chartData, fn($v) => $v !== null);
|
||||
$maxVal = count($nonNullValues) ? max($nonNullValues) : 0;
|
||||
|
||||
// Großzügige Schritte für die Y-Achse
|
||||
if ($maxVal <= 5) { $stepSize = 1; }
|
||||
elseif ($maxVal <= 10) { $stepSize = 2; }
|
||||
elseif ($maxVal <= 20) { $stepSize = 5; }
|
||||
elseif ($maxVal <= 50) { $stepSize = 10; }
|
||||
elseif ($maxVal <= 100) { $stepSize = 20; }
|
||||
elseif ($maxVal <= 200) { $stepSize = 50; }
|
||||
elseif ($maxVal <= 500) { $stepSize = 100; }
|
||||
elseif ($maxVal <= 1000) { $stepSize = 200; }
|
||||
else { $stepSize = 500; }
|
||||
|
||||
// Genug Platz nach oben, damit das Label nicht abgeschnitten wird
|
||||
$suggestedMax = $maxVal + $stepSize;
|
||||
@endphp
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body pb-2">
|
||||
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
||||
<h6 class="font-weight-bold mb-2">
|
||||
{{ __('abo.chart_monthly_abos') }}
|
||||
<span class="text-muted font-weight-normal ml-1">{{ $chartYear }}</span>
|
||||
</h6>
|
||||
<div class="mb-2">
|
||||
@foreach($chartYears as $y)
|
||||
<a href="{{ url()->current() }}?year={{ $y }}"
|
||||
class="btn btn-xs btn-sm {{ $chartYear == $y ? 'btn-secondary' : 'btn-outline-secondary' }} mr-1 mb-1">
|
||||
{{ $y }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-0">
|
||||
<div class="card-body pt-3 pb-2">
|
||||
<canvas id="{{ $chartId }}" height="80"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/vendor/libs/chartjs/chartjs.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
// Inline data-labels plugin für Chart.js v2
|
||||
var dataLabelsPlugin = {
|
||||
afterDatasetsDraw: function (chart) {
|
||||
var ctx = chart.ctx;
|
||||
chart.data.datasets.forEach(function (dataset, i) {
|
||||
var meta = chart.getDatasetMeta(i);
|
||||
if (meta.hidden) { return; }
|
||||
meta.data.forEach(function (bar, index) {
|
||||
var value = dataset.data[index];
|
||||
if (value === null || value === undefined || value === 0) { return; }
|
||||
ctx.save();
|
||||
ctx.fillStyle = '#495057';
|
||||
ctx.font = 'bold 11px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillText(value, bar._model.x, bar._model.y - 3);
|
||||
ctx.restore();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var ctx = document.getElementById('{{ $chartId }}').getContext('2d');
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
plugins: [dataLabelsPlugin],
|
||||
data: {
|
||||
labels: {!! $chartLabelsJson !!},
|
||||
datasets: [{
|
||||
label: '{{ __('abo.chart_active_abos') }}',
|
||||
data: {!! $chartDataJson !!},
|
||||
backgroundColor: 'rgba(102, 110, 232, 0.2)',
|
||||
borderColor: 'rgba(102, 110, 232, 0.8)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: { display: false },
|
||||
tooltips: { enabled: false },
|
||||
layout: {
|
||||
padding: { top: 20 }
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
stepSize: {{ $stepSize }},
|
||||
suggestedMax: {{ $suggestedMax }},
|
||||
callback: function (value) {
|
||||
return Number.isInteger(value) ? value : null;
|
||||
}
|
||||
},
|
||||
gridLines: { color: 'rgba(0,0,0,0.05)' }
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: { display: false }
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
</script>
|
||||
|
|
@ -1,27 +1,39 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
<a href="{{route('user_abos', [$view])}}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
<a href="{{ route('user_abos', [$view]) }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
|
||||
<div>
|
||||
@if($view === 'ot') {{ __('navigation.customerabo') }} @endif
|
||||
@if($view === 'me') {{ __('navigation.myabo') }} @endif
|
||||
<span class="text-muted">{{ '#'.$user_abo->payone_userid }}</span>
|
||||
@if ($view === 'ot')
|
||||
{{ __('navigation.customerabo') }}
|
||||
@endif
|
||||
@if ($view === 'me')
|
||||
{{ __('navigation.myabo') }}
|
||||
@endif
|
||||
<span class="text-muted">{{ '#' . $user_abo->payone_userid }}</span>
|
||||
</div>
|
||||
</h4>
|
||||
|
||||
|
||||
@if(Session::has('alert-error'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-error') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if (Session::has('alert-error'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-error') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if (Session::has('alert-warning'))
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-warning p-2 mt-2">
|
||||
<ul>
|
||||
<li>{{ Session::get('alert-warning') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card">
|
||||
@include('admin.abo._detail')
|
||||
</div>
|
||||
|
|
@ -34,13 +46,18 @@
|
|||
@php
|
||||
$addOnlyMode = App\Services\AboHelper::isAddOnlyMode($user_abo, $view);
|
||||
@endphp
|
||||
{!! Form::open(['action' => route('user_abos_update', [$view, $user_abo->id]), 'class' => 'form-horizontal', 'id'=>'cart-order-form', 'data-add-only-mode' => $addOnlyMode ? '1' : '0']) !!}
|
||||
<input type="hidden" name="is_for" value="{{ $user_abo->is_for }}">
|
||||
{!! Form::open([
|
||||
'action' => route('user_abos_update', [$view, $user_abo->id]),
|
||||
'class' => 'form-horizontal',
|
||||
'id' => 'cart-order-form',
|
||||
'data-add-only-mode' => $addOnlyMode ? '1' : '0',
|
||||
]) !!}
|
||||
<input type="hidden" name="is_for" value="{{ $user_abo->is_for }}">
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._order_abo', ['add_only_mode' => $addOnlyMode])
|
||||
</div>
|
||||
|
||||
@if($comp_products && Yard::instance('shopping')->getNumComp() > 0)
|
||||
@if ($comp_products && Yard::instance('shopping')->getNumComp() > 0)
|
||||
<div id="holder_html_view_comp_product">
|
||||
@include('user.order.comp_product')
|
||||
</div>
|
||||
|
|
@ -52,48 +69,49 @@
|
|||
</div>
|
||||
|
||||
|
||||
<a href="{{route('user_abos', [$view])}}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
<a href="{{ route('user_abos', [$view]) }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
|
||||
<div class="modal fade" id="modal-confirm-add" tabindex="-1" role="dialog" aria-labelledby="modal-confirm-add-label" aria-hidden="true"
|
||||
data-title-add-only="{{ __('abo.confirm_add_title') }}"
|
||||
data-title-normal="{{ __('abo.confirm_add_title_normal') }}"
|
||||
data-warning-add-only="{{ __('abo.confirm_add_warning') }}"
|
||||
data-warning-normal="{{ __('abo.confirm_add_warning_normal') }}">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modal-confirm-add-label"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning mb-3">
|
||||
<i class="fa fa-exclamation-triangle"></i> <span id="confirm-add-warning-text"></span>
|
||||
<div class="modal fade" id="modal-confirm-add" tabindex="-1" role="dialog" aria-labelledby="modal-confirm-add-label"
|
||||
aria-hidden="true" data-title-add-only="{{ __('abo.confirm_add_title') }}"
|
||||
data-title-normal="{{ __('abo.confirm_add_title_normal') }}"
|
||||
data-warning-add-only="{{ __('abo.confirm_add_warning') }}"
|
||||
data-warning-normal="{{ __('abo.confirm_add_warning_normal') }}">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modal-confirm-add-label"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning mb-3">
|
||||
<i class="fa fa-exclamation-triangle"></i> <span id="confirm-add-warning-text"></span>
|
||||
</div>
|
||||
<table class="table table-sm mb-0">
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('order.article') }}:</td>
|
||||
<td id="confirm-add-product-name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.price') }}:</td>
|
||||
<td id="confirm-add-product-price"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.quantity') }}:</td>
|
||||
<td id="confirm-add-qty-info"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default"
|
||||
data-dismiss="modal">{{ __('abo.confirm_add_cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary"
|
||||
id="confirm-add-btn">{{ __('abo.confirm_add_ok') }}</button>
|
||||
</div>
|
||||
<table class="table table-sm mb-0">
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('order.article') }}:</td>
|
||||
<td id="confirm-add-product-name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.price') }}:</td>
|
||||
<td id="confirm-add-product-price"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-weight-bold">{{ __('tables.quantity') }}:</td>
|
||||
<td id="confirm-add-qty-info"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('abo.confirm_add_cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary" id="confirm-add-btn">{{ __('abo.confirm_add_ok') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
|
|
@ -105,4 +123,4 @@
|
|||
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
</div>
|
||||
</h4>
|
||||
|
||||
@if(isset($chartData))
|
||||
@include('user.abo._abo_chart')
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
||||
|
|
@ -82,8 +86,13 @@
|
|||
{{ $user_abo->getCountOrders() }}
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="text-muted small">{{ __('tables.amount') }}</div>
|
||||
{{ $user_abo->getFormattedAmount() }} €
|
||||
@if($view === 'ot')
|
||||
<div class="text-muted small">{{ __('navigation.points') }}</div>
|
||||
<strong class="text-primary">{{ $user_abo->getFormattedTotalPoints() }} Pkt.</strong>
|
||||
@else
|
||||
<div class="text-muted small">{{ __('tables.amount') }}</div>
|
||||
{{ $user_abo->getFormattedAmount() }} €
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="text-muted small">{{ __('tables.payment') }}</div>
|
||||
|
|
|
|||
98
resources/views/user/incentive/details.blade.php
Normal file
98
resources/views/user/incentive/details.blade.php
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
{{ $incentive->name }} - {{ __('incentive.my_calculation') }}
|
||||
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-sm btn-outline-primary float-right">
|
||||
<span class="fa fa-arrow-left"></span> {{ __('incentive.back_to_ranking') }}
|
||||
</a>
|
||||
</h4>
|
||||
|
||||
{{-- Zusammenfassung --}}
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted">{{ __('incentive.total_points') }}</h5>
|
||||
<h2 class="font-weight-bold">{{ number_format($participant->total_points, 0, ',', '.') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted">{{ __('incentive.rank') }}</h5>
|
||||
<h2 class="font-weight-bold">{{ $participant->rank ?? '-' }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted">{{ __('incentive.partners') }}</h5>
|
||||
<h2 class="font-weight-bold {{ $participant->qualified_partners >= $incentive->min_direct_partners ? 'text-success' : '' }}">
|
||||
{{ $participant->qualified_partners }}/{{ $incentive->min_direct_partners }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted">{{ __('incentive.abos') }}</h5>
|
||||
<h2 class="font-weight-bold {{ $participant->qualified_abos >= $incentive->min_customer_abos ? 'text-success' : '' }}">
|
||||
{{ $participant->qualified_abos }}/{{ $incentive->min_customer_abos }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Sektion A: Neupartner-Punkte --}}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<strong>{{ __('incentive.section_partners') }}</strong>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@include('partials.incentive._source_table', [
|
||||
'sources' => $partner_sources,
|
||||
'type' => 'partner',
|
||||
'label_header' => __('incentive.new_partner'),
|
||||
'date_header' => __('incentive.entry_date'),
|
||||
'empty_message' => __('incentive.no_partners_yet'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Sektion B: Kundenabo-Punkte --}}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<strong>{{ __('incentive.section_abos') }}</strong>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@include('partials.incentive._source_table', [
|
||||
'sources' => $abo_sources,
|
||||
'type' => 'abo',
|
||||
'label_header' => __('incentive.customer_abo'),
|
||||
'date_header' => __('incentive.abo_date'),
|
||||
'empty_message' => __('incentive.no_abos_yet'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Gesamtpunkte --}}
|
||||
<div class="card border-primary">
|
||||
<div class="card-body text-center">
|
||||
<h4>{{ __('incentive.total_points') }}:
|
||||
<strong>{{ number_format($participant->total_points, 0, ',', '.') }}</strong></h4>
|
||||
@if ($participant->is_qualified)
|
||||
<span class="badge badge-success badge-lg p-2">{{ __('incentive.qualified') }}</span>
|
||||
@if ($participant->isWinner())
|
||||
<span class="badge badge-warning badge-lg p-2">{{ __('incentive.winner') }}</span>
|
||||
@endif
|
||||
@else
|
||||
<span class="badge badge-secondary badge-lg p-2">{{ __('incentive.not_yet_qualified') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
953
resources/views/user/incentive/show.blade.php
Normal file
953
resources/views/user/incentive/show.blade.php
Normal file
|
|
@ -0,0 +1,953 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
.inc-header {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
border-radius: .75rem;
|
||||
color: #fff;
|
||||
padding: 1.5rem 2rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -60%;
|
||||
right: -20%;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: rgba(215, 215, 0, 0.08);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.inc-header h5 {
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.inc-header .stat-box {
|
||||
text-align: center;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.inc-header .stat-label {
|
||||
font-size: .68rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .05em;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.inc-header .stat-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.inc-header .badge-qual {
|
||||
background: rgba(215, 215, 0, 0.85);
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
padding: .35rem .8rem;
|
||||
border-radius: 50px;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.inc-header .badge-open {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
padding: .35rem .8rem;
|
||||
border-radius: 50px;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.inc-header .btn-details {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50px;
|
||||
padding: .4rem 1.2rem;
|
||||
font-weight: 600;
|
||||
font-size: .85rem;
|
||||
transition: background .2s;
|
||||
}
|
||||
|
||||
.inc-header .btn-details:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.inc-toggle-bar {
|
||||
background: #f4f5f0;
|
||||
border-radius: 0 0 .75rem .75rem;
|
||||
margin-top: -0.75rem;
|
||||
padding-top: .75rem;
|
||||
}
|
||||
|
||||
.inc-toggle-bar .btn {
|
||||
border: none;
|
||||
color: #6b7758;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.inc-info-tile {
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
transition: transform .2s ease, box-shadow .2s ease;
|
||||
}
|
||||
|
||||
.inc-info-tile:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.inc-tile-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.3rem;
|
||||
color: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.inc-tile-icon-calendar {
|
||||
background: linear-gradient(135deg, #6b7758, #4a5340);
|
||||
}
|
||||
|
||||
.inc-tile-icon-plane {
|
||||
background: linear-gradient(135deg, #6b7758, #8a9a70);
|
||||
}
|
||||
|
||||
.inc-tile-icon-star {
|
||||
background: linear-gradient(135deg, #b8b800, #d7d700);
|
||||
}
|
||||
|
||||
.inc-hero-img {
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inc-hero-img img {
|
||||
width: 100%;
|
||||
max-height: 350px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inc-hero-img .hero-gradient {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.4) 100%);
|
||||
}
|
||||
|
||||
.inc-intro {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
color: #fff;
|
||||
border-radius: .75rem;
|
||||
padding: 1.5rem 2rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.65;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-intro::before {
|
||||
content: '\201C';
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 12px;
|
||||
font-size: 6rem;
|
||||
opacity: .1;
|
||||
font-family: Georgia, serif;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.inc-points-section {
|
||||
background: #f4f5f0;
|
||||
border-radius: .75rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.inc-point-card {
|
||||
background: #fff;
|
||||
border-radius: .75rem;
|
||||
padding: 1.2rem;
|
||||
height: 100%;
|
||||
border-left: 4px solid;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.inc-point-card-partner {
|
||||
border-left-color: #6b7758;
|
||||
}
|
||||
|
||||
.inc-point-card-abo {
|
||||
border-left-color: #d7d700;
|
||||
}
|
||||
|
||||
.inc-point-card .inc-point-val {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.inc-point-card-partner .inc-point-val {
|
||||
color: #6b7758;
|
||||
}
|
||||
|
||||
.inc-point-card-abo .inc-point-val {
|
||||
color: #9a9a00;
|
||||
}
|
||||
|
||||
.inc-point-card li {
|
||||
font-size: .88rem;
|
||||
color: #555;
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
.inc-participate {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
border-radius: .75rem;
|
||||
color: #fff;
|
||||
padding: 2rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-participate::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -40%;
|
||||
left: -20%;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
background: rgba(215, 215, 0, 0.08);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.inc-participate h5 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.inc-participate .btn-participate {
|
||||
background: #d7d700;
|
||||
color: #333;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
font-weight: 700;
|
||||
padding: .6rem 1.5rem;
|
||||
transition: transform .2s, box-shadow .2s;
|
||||
}
|
||||
|
||||
.inc-participate .btn-participate:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.inc-participate .custom-control-label {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.inc-participate a {
|
||||
color: #d7d700;
|
||||
}
|
||||
|
||||
.inc-terms-toggle {
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.inc-terms-toggle .card-header {
|
||||
background: #f4f5f0;
|
||||
border: none;
|
||||
padding: .8rem 1.2rem;
|
||||
}
|
||||
|
||||
.inc-terms-toggle .card-header a {
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.inc-ranking-card {
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.inc-ranking-card .card-header {
|
||||
background: #f4f5f0;
|
||||
border: none;
|
||||
padding: 1.2rem 1.5rem;
|
||||
}
|
||||
|
||||
.inc-ranking-card .ranking-title {
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.inc-ranking-card .badge-top {
|
||||
background: linear-gradient(135deg, #6b7758, #4a5340);
|
||||
color: #fff;
|
||||
border-radius: 50px;
|
||||
padding: .3rem .7rem;
|
||||
font-size: .75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.inc-ranking-card .hint-text {
|
||||
font-size: .8rem;
|
||||
color: #888;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.inc-ranking-table {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.inc-ranking-table thead th {
|
||||
background: #fafaf6;
|
||||
border-top: none;
|
||||
font-size: .78rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .04em;
|
||||
color: #6b7758;
|
||||
padding: .75rem 1rem;
|
||||
}
|
||||
|
||||
.inc-ranking-table tbody td {
|
||||
padding: .75rem 1rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.inc-ranking-table .row-winner {
|
||||
background: rgba(215, 215, 0, 0.08);
|
||||
}
|
||||
|
||||
.inc-ranking-table .row-me {
|
||||
background: rgba(107, 119, 88, 0.1);
|
||||
}
|
||||
|
||||
.inc-ranking-table .rank-trophy {
|
||||
color: #d7d700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.inc-ranking-table .badge-winner {
|
||||
background: linear-gradient(135deg, #b8b800, #d7d700);
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
border-radius: 50px;
|
||||
padding: .25rem .6rem;
|
||||
font-size: .72rem;
|
||||
}
|
||||
|
||||
.inc-ranking-table .badge-qualified {
|
||||
background: #6b7758;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
border-radius: 50px;
|
||||
padding: .25rem .6rem;
|
||||
font-size: .72rem;
|
||||
}
|
||||
|
||||
.inc-ranking-table .badge-open-status {
|
||||
background: #e8e8e8;
|
||||
color: #777;
|
||||
font-weight: 600;
|
||||
border-radius: 50px;
|
||||
padding: .25rem .6rem;
|
||||
font-size: .72rem;
|
||||
}
|
||||
|
||||
.inc-ranking-table .check-ok {
|
||||
color: #6b7758;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.inc-ranking-table .badge-me {
|
||||
background: #6b7758;
|
||||
color: #fff;
|
||||
border-radius: 50px;
|
||||
padding: .15rem .5rem;
|
||||
font-size: .7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pending-banner {
|
||||
background: rgba(215, 215, 0, 0.12);
|
||||
border: 1px solid rgba(215, 215, 0, 0.3);
|
||||
border-radius: .75rem;
|
||||
padding: 1rem 1.5rem;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.pending-banner i {
|
||||
color: #9a9a00;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.inc-header {
|
||||
padding: 1.2rem;
|
||||
}
|
||||
|
||||
.inc-header .stat-box {
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
|
||||
.inc-participate {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
{{-- Flash-Nachrichten --}}
|
||||
@if (Session::has('alert-success'))
|
||||
<div class="alert alert-success">{{ Session::get('alert-success') }}</div>
|
||||
@endif
|
||||
@if (Session::has('alert-error'))
|
||||
<div class="alert alert-danger">{{ Session::get('alert-error') }}</div>
|
||||
@endif
|
||||
@if (Session::has('alert-info'))
|
||||
<div class="alert alert-info">{{ Session::get('alert-info') }}</div>
|
||||
@endif
|
||||
|
||||
@if ($hasConfirmedParticipation)
|
||||
{{-- ============================================================
|
||||
ANSICHT: TEILNEHMER – kompakter Header, Info eingeklappt
|
||||
============================================================ --}}
|
||||
|
||||
<div class="inc-header mb-0">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap">
|
||||
|
||||
<div class="d-flex align-items-center mr-3 mb-2 mb-md-0">
|
||||
<i class="ion ion-md-trophy mr-2" style="font-size: 1.5rem; color: #d7d700;"></i>
|
||||
<h5>{{ $incentive->name }}</h5>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center flex-wrap">
|
||||
@if ($participant->rank)
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">{{ __('incentive.your_rank') }}</div>
|
||||
<div class="stat-value">{{ $participant->rank }}</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">{{ __('incentive.total_points') }}</div>
|
||||
<div class="stat-value">{{ number_format($participant->total_points, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
<div class="mr-3">
|
||||
@if ($participant->is_qualified)
|
||||
<span class="badge-qual">{{ __('incentive.qualified') }}</span>
|
||||
@else
|
||||
<span class="badge-open">{{ __('incentive.not_yet_qualified') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
<a href="{{ route('user_incentive_details', [$incentive->slug]) }}" class="btn-details">
|
||||
<i class="ion ion-md-stats mr-1"></i>{{ __('incentive.my_details') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inc-toggle-bar mb-3">
|
||||
<button type="button" id="incentive-info-toggle" class="btn btn-block py-2 text-center" data-toggle="collapse"
|
||||
data-target="#incentive-info" aria-expanded="false" aria-controls="incentive-info">
|
||||
<i class="ion ion-md-arrow-dropdown mr-1" id="incentive-info-icon"></i>
|
||||
<span id="incentive-info-label">{{ __('incentive.read_more') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- Eingeklappter Info-Bereich --}}
|
||||
<div id="incentive-info" class="collapse mb-3">
|
||||
|
||||
@if ($incentive->image)
|
||||
<div class="inc-hero-img mb-4">
|
||||
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}">
|
||||
<div class="hero-gradient"></div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($incentive->getLang('description'))
|
||||
<div class="inc-intro mb-4">
|
||||
{!! $incentive->getLang('description') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
|
||||
{{-- Qualifikationszeitraum --}}
|
||||
<div class="card inc-info-tile shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="inc-tile-icon inc-tile-icon-calendar mr-3">
|
||||
<i class="ion ion-md-calendar"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="font-weight-bold mb-2">{{ __('incentive.section_period') }}</h6>
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li class="mb-1">
|
||||
<strong>{{ __('incentive.qualification_period') }}:</strong>
|
||||
{{ $incentive->qualification_start->format('d.m.Y') }}
|
||||
– {{ $incentive->qualification_end->format('d.m.Y') }}
|
||||
</li>
|
||||
<li class="text-muted">
|
||||
<strong>{{ __('incentive.calculation_period') }}:</strong>
|
||||
{{ __('incentive.calculation_period_hint', ['date' => $incentive->calculation_end->format('d.m.Y')]) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Mindestqualifikation --}}
|
||||
<div class="card inc-info-tile shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="inc-tile-icon inc-tile-icon-plane mr-3">
|
||||
<i class="ion ion-md-airplane"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="font-weight-bold mb-2">{{ __('incentive.section_min_qual') }}</h6>
|
||||
<p class="text-muted small mb-2">{{ __('incentive.min_qual_intro') }}</p>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li class="mb-1">
|
||||
<strong style="color: #6b7758;">{{ $incentive->min_direct_partners }}</strong>
|
||||
{{ __('incentive.min_partners_label') }}
|
||||
</li>
|
||||
<li>
|
||||
<strong style="color: #6b7758;">{{ $incentive->min_customer_abos }}</strong>
|
||||
{{ __('incentive.min_abos_label') }}
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-muted small mb-0">
|
||||
<i class="ion ion-md-information-circle mr-1"></i>
|
||||
{{ __('incentive.min_qual_ranking_hint') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Punkte-System --}}
|
||||
<div class="inc-points-section mb-4">
|
||||
<h6 class="font-weight-bold mb-3">
|
||||
<i class="ion ion-md-star mr-1" style="color: #d7d700;"></i>
|
||||
{{ __('incentive.section_points') }}
|
||||
</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="inc-point-card inc-point-card-partner">
|
||||
<h6 class="font-weight-bold mb-1" style="font-size: .9rem;">
|
||||
<i class="ion ion-md-person-add mr-1"></i>
|
||||
{{ __('incentive.points_partners_title') }}
|
||||
</h6>
|
||||
<div class="inc-point-val mb-2">
|
||||
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul class="pl-3 mb-0">
|
||||
<li>{{ __('incentive.points_onetime_label') }}</li>
|
||||
<li>{{ __('incentive.points_starter_package_label') }}</li>
|
||||
<li>{{ __('incentive.points_partner_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="inc-point-card inc-point-card-abo">
|
||||
<h6 class="font-weight-bold mb-1" style="font-size: .9rem;">
|
||||
<i class="ion ion-md-ribbon mr-1"></i>
|
||||
{{ __('incentive.points_abos_title') }}
|
||||
</h6>
|
||||
<div class="inc-point-val mb-2">
|
||||
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul class="pl-3 mb-0">
|
||||
<li>{{ __('incentive.points_onetime_label') }}</li>
|
||||
<li>{{ __('incentive.points_abo_direct') }}</li>
|
||||
<li>{{ __('incentive.points_abo_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
@if ($incentive->getLang('terms'))
|
||||
<div class="card inc-terms-toggle mb-4">
|
||||
<div class="card-header">
|
||||
<a href="#terms" data-toggle="collapse" class="d-flex align-items-center">
|
||||
<i class="ion ion-md-document mr-2"></i>
|
||||
<strong>{{ __('incentive.terms') }}</strong>
|
||||
<i class="ion ion-md-chevron-down ml-auto"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="terms" class="collapse">
|
||||
<div class="card-body">
|
||||
<div class="small">{!! $incentive->getLang('terms') !!}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var collapse = document.getElementById('incentive-info');
|
||||
var icon = document.getElementById('incentive-info-icon');
|
||||
var label = document.getElementById('incentive-info-label');
|
||||
|
||||
if (collapse) {
|
||||
collapse.addEventListener('show.bs.collapse', function() {
|
||||
icon.className = 'ion ion-md-arrow-dropup mr-1';
|
||||
label.textContent = '{{ __('incentive.read_less') }}';
|
||||
});
|
||||
collapse.addEventListener('hide.bs.collapse', function() {
|
||||
icon.className = 'ion ion-md-arrow-dropdown mr-1';
|
||||
label.textContent = '{{ __('incentive.read_more') }}';
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@else
|
||||
{{-- ============================================================
|
||||
ANSICHT: NOCH KEINE ZUSTIMMUNG (Punkte laufen) ODER KEIN TEILNEHMER
|
||||
============================================================ --}}
|
||||
@if ($participant)
|
||||
<div class="inc-header mb-3">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap">
|
||||
<div class="d-flex align-items-center mr-3 mb-2 mb-md-0">
|
||||
<i class="ion ion-md-trophy mr-2" style="font-size: 1.5rem; color: #d7d700;"></i>
|
||||
<h5>{{ $incentive->name }}</h5>
|
||||
</div>
|
||||
<div class="d-flex align-items-center flex-wrap">
|
||||
@if ($participant->rank)
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">{{ __('incentive.your_rank') }}</div>
|
||||
<div class="stat-value">{{ $participant->rank }}</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">{{ __('incentive.total_points') }}</div>
|
||||
<div class="stat-value">{{ number_format($participant->total_points, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
<div>
|
||||
@if ($participant->is_qualified)
|
||||
<span class="badge-qual">{{ __('incentive.qualified') }}</span>
|
||||
@else
|
||||
<span class="badge-open">{{ __('incentive.not_yet_qualified') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pending-banner mb-4">
|
||||
<i class="ion ion-md-information-circle mr-1"></i>
|
||||
{{ __('incentive.pending_confirmation_banner') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($incentive->image)
|
||||
<div class="inc-hero-img mb-4">
|
||||
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}"
|
||||
style="max-height: 450px;">
|
||||
<div class="hero-gradient"></div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<h3 class="font-weight-bold mb-3">
|
||||
<i class="ion ion-md-trophy mr-2" style="color: #d7d700;"></i>{{ $incentive->name }}
|
||||
</h3>
|
||||
|
||||
@if ($incentive->getLang('description'))
|
||||
<div class="inc-intro mb-4">
|
||||
{!! $incentive->getLang('description') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
|
||||
{{-- Qualifikationszeitraum --}}
|
||||
<div class="card inc-info-tile shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="inc-tile-icon inc-tile-icon-calendar mr-3">
|
||||
<i class="ion ion-md-calendar"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="font-weight-bold mb-2">{{ __('incentive.section_period') }}</h6>
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li class="mb-1">
|
||||
<strong>{{ __('incentive.qualification_period') }}:</strong>
|
||||
{{ $incentive->qualification_start->format('d.m.Y') }}
|
||||
– {{ $incentive->qualification_end->format('d.m.Y') }}
|
||||
</li>
|
||||
<li class="text-muted">
|
||||
<strong>{{ __('incentive.calculation_period') }}:</strong>
|
||||
{{ __('incentive.calculation_period_hint', ['date' => $incentive->calculation_end->format('d.m.Y')]) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Mindestqualifikation --}}
|
||||
<div class="card inc-info-tile shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="inc-tile-icon inc-tile-icon-plane mr-3">
|
||||
<i class="ion ion-md-airplane"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="font-weight-bold mb-2">{{ __('incentive.section_min_qual') }}</h6>
|
||||
<p class="text-muted small mb-2">{{ __('incentive.min_qual_intro') }}</p>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li class="mb-1">
|
||||
<strong style="color: #6b7758;">{{ $incentive->min_direct_partners }}</strong>
|
||||
{{ __('incentive.min_partners_label') }}
|
||||
</li>
|
||||
<li>
|
||||
<strong style="color: #6b7758;">{{ $incentive->min_customer_abos }}</strong>
|
||||
{{ __('incentive.min_abos_label') }}
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-muted small mb-0">
|
||||
<i class="ion ion-md-information-circle mr-1"></i>
|
||||
{{ __('incentive.min_qual_ranking_hint') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Punkte-System --}}
|
||||
<div class="inc-points-section mb-4">
|
||||
<h6 class="font-weight-bold mb-3">
|
||||
<i class="ion ion-md-star mr-1" style="color: #d7d700;"></i>
|
||||
{{ __('incentive.section_points') }}
|
||||
</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="inc-point-card inc-point-card-partner">
|
||||
<h6 class="font-weight-bold mb-1" style="font-size: .9rem;">
|
||||
<i class="ion ion-md-person-add mr-1"></i>
|
||||
{{ __('incentive.points_partners_title') }}
|
||||
</h6>
|
||||
<div class="inc-point-val mb-2">
|
||||
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul class="pl-3 mb-0">
|
||||
<li>{{ __('incentive.points_onetime_label') }}</li>
|
||||
<li>{{ __('incentive.points_partner_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="inc-point-card inc-point-card-abo">
|
||||
<h6 class="font-weight-bold mb-1" style="font-size: .9rem;">
|
||||
<i class="ion ion-md-ribbon mr-1"></i>
|
||||
{{ __('incentive.points_abos_title') }}
|
||||
</h6>
|
||||
<div class="inc-point-val mb-2">
|
||||
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul class="pl-3 mb-0">
|
||||
<li>{{ __('incentive.points_onetime_label') }}</li>
|
||||
<li>{{ __('incentive.points_abo_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
|
||||
<div class="inc-participate mb-4">
|
||||
<h5>
|
||||
<i class="ion ion-md-log-in mr-1"></i>
|
||||
{{ __('incentive.participate_title') }}
|
||||
</h5>
|
||||
@if ($incentive->isActive())
|
||||
<p class="small mb-3" style="opacity: .85;">{{ __('incentive.participate_intro') }}</p>
|
||||
@if (!empty($participateHasTrackableAbos))
|
||||
<div class="mb-3 p-2 small" style="background: rgba(255,255,255,0.12); border-radius: .5rem;">
|
||||
<i class="ion ion-md-information-circle mr-1"></i>
|
||||
{{ __('incentive.participate_abo_hint') }}
|
||||
</div>
|
||||
@endif
|
||||
<form action="{{ route('user_incentive_participate', [$incentive->slug]) }}" method="POST">
|
||||
@csrf
|
||||
<div class="custom-control custom-checkbox mb-3">
|
||||
<input type="checkbox" class="custom-control-input" id="accept_terms"
|
||||
name="accept_terms" value="1" required>
|
||||
<label class="custom-control-label" for="accept_terms">
|
||||
{{ __('incentive.accept_terms') }}
|
||||
@if ($incentive->getLang('terms'))
|
||||
(<a href="#terms" data-toggle="collapse">{{ __('incentive.show_terms') }}</a>)
|
||||
@endif
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-participate btn-block">
|
||||
<i class="ion ion-md-checkmark mr-1"></i>
|
||||
{{ __('incentive.participate_now') }}
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<p class="mb-0" style="opacity: .8;">{{ __('incentive.not_active') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($incentive->getLang('terms'))
|
||||
<div class="card inc-terms-toggle mb-4">
|
||||
<div class="card-header">
|
||||
<a href="#terms" data-toggle="collapse" class="d-flex align-items-center">
|
||||
<i class="ion ion-md-document mr-2"></i>
|
||||
<strong>{{ __('incentive.terms') }}</strong>
|
||||
<i class="ion ion-md-chevron-down ml-auto"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="terms" class="collapse">
|
||||
<div class="card-body">
|
||||
<div class="small">{!! $incentive->getLang('terms') !!}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
{{-- ============================================================
|
||||
LIVE-RANKING – immer sichtbar
|
||||
============================================================ --}}
|
||||
<div class="inc-ranking-card mt-2 mb-4">
|
||||
<div class="card-header">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="ion ion-md-list mr-2" style="font-size: 1.2rem; color: #6b7758;"></i>
|
||||
<span class="ranking-title">{{ __('incentive.section_ranking') }}</span>
|
||||
<span class="badge-top ml-2">Top {{ $rankingDisplayLimit }}</span>
|
||||
</div>
|
||||
<span
|
||||
class="hint-text">{{ __('incentive.ranking_winners_hint', ['n' => $incentive->max_winners]) }}</span>
|
||||
</div>
|
||||
<div class="hint-text mt-2">
|
||||
{{ __('incentive.ranking_extended_hint', ['n' => $incentive->max_winners]) }}
|
||||
<br>{{ __('incentive.ranking_anonymous_hint') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if ($ranking->isEmpty())
|
||||
<div class="p-4 text-center text-muted">
|
||||
<i class="ion ion-md-people mb-2 d-block" style="font-size: 2.5rem; opacity: .4;"></i>
|
||||
{{ __('incentive.no_participants_with_points') }}
|
||||
</div>
|
||||
@else
|
||||
<div class="table-responsive">
|
||||
<table class="table inc-ranking-table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60px;">{{ __('incentive.rank') }}</th>
|
||||
<th>{{ __('incentive.consultant') }}</th>
|
||||
<th class="text-right">{{ __('incentive.total_points') }}</th>
|
||||
<th class="text-center">{{ __('incentive.partners') }}</th>
|
||||
<th class="text-center">{{ __('incentive.abos') }}</th>
|
||||
<th class="text-center">{{ __('incentive.status') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($ranking as $p)
|
||||
@php
|
||||
$isWinner = $p->is_qualified && $p->rank && $p->rank <= $incentive->max_winners;
|
||||
$isMe = $participant && $p->id === $participant->id;
|
||||
@endphp
|
||||
<tr
|
||||
class="{{ $isWinner ? 'row-winner' : '' }} {{ $p->is_qualified ? 'font-weight-bold' : '' }} {{ $isMe ? 'row-me' : '' }}">
|
||||
<td class="text-center">
|
||||
@if ($isWinner && $p->rank && $p->rank <= 3)
|
||||
<i class="ion ion-md-trophy rank-trophy"></i>
|
||||
@elseif ($p->rank)
|
||||
{{ $p->rank }}
|
||||
@else
|
||||
—
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($p->accepted_terms_at)
|
||||
@if ($p->user && $p->user->account)
|
||||
{{ $p->user->account->first_name }} {{ $p->user->account->last_name }}
|
||||
@else
|
||||
{{ $p->user->email ?? 'N/A' }}
|
||||
@endif
|
||||
@else
|
||||
<span class="text-muted">{{ __('incentive.anonymous_consultant') }}</span>
|
||||
@endif
|
||||
@if ($isMe)
|
||||
<span class="badge-me ml-1">{{ __('incentive.you') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<strong>{{ number_format($p->total_points, 0, ',', '.') }}</strong>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ $p->qualified_partners }}/{{ $incentive->min_direct_partners }}
|
||||
@if ($p->qualified_partners >= $incentive->min_direct_partners)
|
||||
<span class="check-ok">✓</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ $p->qualified_abos }}/{{ $incentive->min_customer_abos }}
|
||||
@if ($p->qualified_abos >= $incentive->min_customer_abos)
|
||||
<span class="check-ok">✓</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if ($isWinner)
|
||||
<span class="badge-winner">{{ __('incentive.winner') }}</span>
|
||||
@elseif ($p->is_qualified)
|
||||
<span class="badge-qualified">{{ __('incentive.qualified') }}</span>
|
||||
@else
|
||||
<span class="badge-open-status">{{ __('incentive.open') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
744
resources/views/user/incentive/teaser.blade.php
Normal file
744
resources/views/user/incentive/teaser.blade.php
Normal file
|
|
@ -0,0 +1,744 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
.incentive-hero {
|
||||
margin: -1.5rem -1.5rem 0 -1.5rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 520px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.incentive-hero img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.incentive-hero .hero-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(to bottom,
|
||||
rgba(0, 0, 0, 0.10) 0%,
|
||||
rgba(0, 0, 0, 0.25) 40%,
|
||||
rgba(0, 0, 0, 0.75) 100%);
|
||||
}
|
||||
|
||||
.incentive-hero .hero-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 2.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.incentive-hero .hero-badge {
|
||||
display: inline-block;
|
||||
background: rgba(215, 215, 0, 0.92);
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
padding: .35rem 1rem;
|
||||
border-radius: 50px;
|
||||
font-size: .85rem;
|
||||
letter-spacing: .5px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.incentive-hero h1 {
|
||||
font-size: 2.6rem;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
text-shadow: 0 3px 12px rgba(0, 0, 0, 0.5);
|
||||
margin-bottom: .5rem;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.incentive-hero .hero-subtitle {
|
||||
font-size: 1.25rem;
|
||||
color: rgba(255, 255, 255, 0.92);
|
||||
text-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.incentive-intro {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
color: #fff;
|
||||
border-radius: .75rem;
|
||||
padding: 2rem 2.5rem;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.7;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.incentive-intro::before {
|
||||
content: '\201C';
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 15px;
|
||||
font-size: 8rem;
|
||||
opacity: .12;
|
||||
font-family: Georgia, serif;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.incentive-intro strong {
|
||||
color: #d7d700;
|
||||
}
|
||||
|
||||
.incentive-intro .cta-line {
|
||||
color: #d7d700;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.info-tile {
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
transition: transform .25s ease, box-shadow .25s ease;
|
||||
}
|
||||
|
||||
.info-tile:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.info-tile .tile-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 1.2rem;
|
||||
font-size: 1.8rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tile-icon-calendar {
|
||||
background: linear-gradient(135deg, #6b7758, #4a5340);
|
||||
}
|
||||
|
||||
.tile-icon-plane {
|
||||
background: linear-gradient(135deg, #6b7758, #8a9a70);
|
||||
}
|
||||
|
||||
.tile-icon-star {
|
||||
background: linear-gradient(135deg, #b8b800, #d7d700);
|
||||
}
|
||||
|
||||
.info-tile .tile-value {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.info-tile .tile-label {
|
||||
font-size: .82rem;
|
||||
color: #888;
|
||||
margin-top: .25rem;
|
||||
}
|
||||
|
||||
.points-section {
|
||||
background: #f4f5f0;
|
||||
border-radius: .75rem;
|
||||
padding: 2.5rem;
|
||||
}
|
||||
|
||||
.points-section .points-heading {
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.point-card {
|
||||
background: #fff;
|
||||
border-radius: .75rem;
|
||||
padding: 1.5rem;
|
||||
height: 100%;
|
||||
border-left: 4px solid;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.point-card-partner {
|
||||
border-left-color: #6b7758;
|
||||
}
|
||||
|
||||
.point-card-abo {
|
||||
border-left-color: #d7d700;
|
||||
}
|
||||
|
||||
.point-card .point-value {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.point-card-partner .point-value {
|
||||
color: #6b7758;
|
||||
}
|
||||
|
||||
.point-card-abo .point-value {
|
||||
color: #9a9a00;
|
||||
}
|
||||
|
||||
.point-card ul {
|
||||
padding-left: 1.1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.point-card li {
|
||||
margin-bottom: .35rem;
|
||||
color: #555;
|
||||
font-size: .92rem;
|
||||
}
|
||||
|
||||
.gallery-section {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.gallery-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.gallery-thumb {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: .5rem;
|
||||
cursor: pointer;
|
||||
aspect-ratio: 4/3;
|
||||
}
|
||||
|
||||
.gallery-thumb img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform .35s ease;
|
||||
}
|
||||
|
||||
.gallery-thumb:hover img {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
.gallery-thumb::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
transition: background .25s ease;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
|
||||
.gallery-thumb:hover::after {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.gallery-lightbox {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
background: rgba(0, 0, 0, 0.92);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.gallery-lightbox.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.gallery-lightbox img {
|
||||
max-width: 90vw;
|
||||
max-height: 85vh;
|
||||
border-radius: .5rem;
|
||||
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-close {
|
||||
position: absolute;
|
||||
top: 1.5rem;
|
||||
right: 1.5rem;
|
||||
color: #fff;
|
||||
font-size: 2rem;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background .2s;
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-close:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-nav {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #fff;
|
||||
font-size: 2.5rem;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background .2s;
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-nav:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-prev {
|
||||
left: 1.5rem;
|
||||
}
|
||||
|
||||
.gallery-lightbox .lb-next {
|
||||
right: 1.5rem;
|
||||
}
|
||||
|
||||
.cta-banner {
|
||||
background: linear-gradient(135deg, #6b7758 0%, #4a5340 100%);
|
||||
border-radius: .75rem;
|
||||
color: #fff;
|
||||
padding: 3rem 2rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cta-banner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -30%;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.cta-banner h3 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.cta-banner p {
|
||||
opacity: .9;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.cta-banner .btn-light {
|
||||
font-weight: 700;
|
||||
padding: .65rem 2.5rem;
|
||||
font-size: 1.05rem;
|
||||
border-radius: 50px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
transition: transform .2s ease, box-shadow .2s ease;
|
||||
}
|
||||
|
||||
.cta-banner .btn-light:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.cta-banner .btn-outline-light {
|
||||
font-weight: 600;
|
||||
padding: .65rem 2rem;
|
||||
font-size: 1.05rem;
|
||||
border-radius: 50px;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.cta-status-icon {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 1.2rem;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.cta-status-icon-success {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #d7d700;
|
||||
}
|
||||
|
||||
.cta-status-icon-warning {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #d7d700;
|
||||
}
|
||||
|
||||
.cta-status-icon-muted {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.terms-toggle {
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.terms-toggle .card-header {
|
||||
background: #f4f5f0;
|
||||
border: none;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
.terms-toggle .card-header a {
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.incentive-hero {
|
||||
min-height: 360px;
|
||||
}
|
||||
|
||||
.incentive-hero h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.incentive-hero .hero-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.incentive-intro {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.points-section {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
{{-- ===== HERO ===== --}}
|
||||
@if ($incentive->image)
|
||||
<div class="incentive-hero mb-5">
|
||||
<img src="{{ asset('img/incentive/' . $incentive->image) }}" alt="{{ $incentive->name }}">
|
||||
<div class="hero-overlay"></div>
|
||||
<div class="hero-content">
|
||||
<span class="hero-badge">
|
||||
<i class="ion ion-md-trophy mr-1"></i> {{ __('incentive.section_period') }}:
|
||||
{{ $incentive->qualification_start->format('d.m.') }} –
|
||||
{{ $incentive->qualification_end->format('d.m.Y') }}
|
||||
</span>
|
||||
<h1>{{ $incentive->name }}</h1>
|
||||
@if ($incentive->getLang('subtitle'))
|
||||
<p class="hero-subtitle mb-0">{{ $incentive->getLang('subtitle') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="mb-5 pt-3">
|
||||
<h1 class="font-weight-bold">
|
||||
<i class="ion ion-md-trophy text-warning mr-2"></i>{{ $incentive->name }}
|
||||
</h1>
|
||||
@if ($incentive->getLang('subtitle'))
|
||||
<p class="lead text-muted">{{ $incentive->getLang('subtitle') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- ===== INTRO-TEXT ===== --}}
|
||||
@if ($incentive->getLang('description'))
|
||||
<div class="incentive-intro mb-5">
|
||||
{!! $incentive->getLang('description') !!}
|
||||
</div>
|
||||
@else
|
||||
<div class="incentive-intro mb-5">
|
||||
<p class="mb-1">
|
||||
<strong>{{ __('incentive.teaser_intro_bold') }}</strong>
|
||||
{{ __('incentive.teaser_intro_text') }}
|
||||
</p>
|
||||
<p class="mb-0 cta-line">
|
||||
{{ __('incentive.teaser_intro_cta', ['n' => $incentive->max_winners]) }}
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- ===== 3 INFO-KARTEN ===== --}}
|
||||
<div class="row mb-5">
|
||||
|
||||
{{-- Qualifikationszeitraum --}}
|
||||
<div class="col-md-4 mb-3 mb-md-0">
|
||||
<div class="card info-tile h-100 shadow-sm">
|
||||
<div class="card-body text-center py-4">
|
||||
<div class="tile-icon tile-icon-calendar">
|
||||
<i class="ion ion-md-calendar"></i>
|
||||
</div>
|
||||
<h5 class="font-weight-bold mb-3">{{ __('incentive.section_period') }}</h5>
|
||||
<div class="mb-2">
|
||||
<span class="tile-label d-block">{{ __('incentive.qualification_period') }}</span>
|
||||
<span class="tile-value">
|
||||
{{ $incentive->qualification_start->format('d.m.Y') }}
|
||||
–
|
||||
{{ $incentive->qualification_end->format('d.m.Y') }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="tile-label d-block">{{ __('incentive.calculation_period') }}</span>
|
||||
<strong>{{ __('incentive.teaser_until') }}
|
||||
{{ $incentive->calculation_end->format('d.m.Y') }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Mindestqualifikation --}}
|
||||
<div class="col-md-4 mb-3 mb-md-0">
|
||||
<div class="card info-tile h-100 shadow-sm">
|
||||
<div class="card-body text-center py-4">
|
||||
<div class="tile-icon tile-icon-plane">
|
||||
<i class="ion ion-md-airplane"></i>
|
||||
</div>
|
||||
<h5 class="font-weight-bold mb-3">{{ __('incentive.section_min_qual') }}</h5>
|
||||
<div class="mb-3">
|
||||
<div class="tile-value">{{ $incentive->min_direct_partners }}</div>
|
||||
<span class="tile-label">{{ __('incentive.min_partners_label') }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="tile-value">{{ $incentive->min_customer_abos }}</div>
|
||||
<span class="tile-label">{{ __('incentive.min_abos_label') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Punkte-System --}}
|
||||
<div class="col-md-4">
|
||||
<div class="card info-tile h-100 shadow-sm">
|
||||
<div class="card-body text-center py-4">
|
||||
<div class="tile-icon tile-icon-star">
|
||||
<i class="ion ion-md-star"></i>
|
||||
</div>
|
||||
<h5 class="font-weight-bold mb-3">{{ __('incentive.section_points') }}</h5>
|
||||
<div class="mb-3">
|
||||
<span class="tile-value" style="color: #6b7758;">
|
||||
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</span>
|
||||
<span class="tile-label d-block">{{ __('incentive.points_partners_title') }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="tile-value" style="color: #9a9a00;">
|
||||
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</span>
|
||||
<span class="tile-label d-block">{{ __('incentive.points_abos_title') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- ===== PUNKTE-DETAIL ===== --}}
|
||||
<div class="points-section mb-5">
|
||||
<h4 class="points-heading">
|
||||
<i class="ion ion-md-star text-warning mr-1"></i>
|
||||
{{ __('incentive.section_points') }}
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="point-card point-card-partner">
|
||||
<h6 class="font-weight-bold mb-2">
|
||||
<i class="ion ion-md-person-add mr-1"></i>
|
||||
{{ __('incentive.points_partners_title') }}
|
||||
</h6>
|
||||
<div class="point-value">
|
||||
{{ number_format($incentive->points_partner_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li>{{ __('incentive.teaser_partner_onetime_text') }}</li>
|
||||
<li>{{ __('incentive.points_starter_package_label') }}</li>
|
||||
<li>{{ __('incentive.points_partner_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="point-card point-card-abo">
|
||||
<h6 class="font-weight-bold mb-2">
|
||||
<i class="ion ion-md-ribbon mr-1"></i>
|
||||
{{ __('incentive.points_abos_title') }}
|
||||
</h6>
|
||||
<div class="point-value">
|
||||
{{ number_format($incentive->points_abo_onetime, 0, ',', '.') }}
|
||||
<span class="small font-weight-normal">{{ __('incentive.points_short') }}</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li>{{ __('incentive.teaser_abo_onetime_text') }}</li>
|
||||
<li>{{ __('incentive.points_abo_direct') }}</li>
|
||||
<li>{{ __('incentive.points_abo_boost') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ===== BILDERGALERIE ===== --}}
|
||||
@if (count($galleryImages) > 0)
|
||||
<div class="gallery-section mb-5">
|
||||
<h4 class="font-weight-bold mb-3 text-center">
|
||||
<i class="ion ion-md-images text-primary mr-1"></i>
|
||||
{{ __('incentive.gallery_title') }}
|
||||
</h4>
|
||||
<div class="gallery-grid">
|
||||
@foreach ($galleryImages as $idx => $img)
|
||||
<div class="gallery-thumb" data-gallery-index="{{ $idx }}">
|
||||
<img src="{{ asset($img) }}" alt="Impression {{ $idx + 1 }}" loading="lazy">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Lightbox --}}
|
||||
<div class="gallery-lightbox" id="galleryLightbox">
|
||||
<button class="lb-close" title="Schließen">×</button>
|
||||
<button class="lb-nav lb-prev" title="Zurück"><i class="ion ion-md-arrow-back"></i></button>
|
||||
<button class="lb-nav lb-next" title="Weiter"><i class="ion ion-md-arrow-forward"></i></button>
|
||||
<img src="" alt="Gallery" id="lightboxImage">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- ===== CTA-BEREICH ===== --}}
|
||||
<div class="cta-banner mb-5">
|
||||
@if ($participant && $participant->accepted_terms_at)
|
||||
<div class="cta-status-icon cta-status-icon-success">
|
||||
<i class="ion ion-md-checkmark-circle"></i>
|
||||
</div>
|
||||
<h3>{{ __('incentive.you_participate') }}</h3>
|
||||
<p class="mb-4">{{ __('incentive.teaser_cta_already_in') }}</p>
|
||||
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg mr-2">
|
||||
<i class="ion ion-md-list mr-1"></i>{{ __('incentive.teaser_cta_to_ranking') }}
|
||||
</a>
|
||||
<a href="{{ route('user_incentive_details', [$incentive->slug]) }}" class="btn btn-outline-secondary btn-lg">
|
||||
<i class="ion ion-md-stats mr-1"></i>{{ __('incentive.my_details') }}
|
||||
</a>
|
||||
@elseif ($participant)
|
||||
<div class="cta-status-icon cta-status-icon-warning">
|
||||
<i class="ion ion-md-trophy"></i>
|
||||
</div>
|
||||
<h3>{{ __('incentive.teaser_pending_title') }}</h3>
|
||||
<p class="mb-4">{{ __('incentive.teaser_pending_text') }}</p>
|
||||
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
|
||||
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_confirm') }}
|
||||
</a>
|
||||
@elseif($incentive->isActive())
|
||||
<div class="cta-status-icon cta-status-icon-warning">
|
||||
<i class="ion ion-md-trophy"></i>
|
||||
</div>
|
||||
<h3>{{ __('incentive.teaser_cta_ready') }}</h3>
|
||||
<p class="mb-4">{{ __('incentive.teaser_cta_text', ['n' => $incentive->max_winners]) }}</p>
|
||||
<a href="{{ route('user_incentive_show', [$incentive->slug]) }}" class="btn btn-secondary btn-lg">
|
||||
<i class="ion ion-md-checkmark mr-1"></i>{{ __('incentive.teaser_cta_button') }}
|
||||
</a>
|
||||
@else
|
||||
<div class="cta-status-icon cta-status-icon-muted">
|
||||
<i class="ion ion-md-time"></i>
|
||||
</div>
|
||||
<h3>{{ __('incentive.teaser_cta_coming_soon') }}</h3>
|
||||
<p class="mb-0">{{ __('incentive.not_active') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- ===== TEILNAHMEBEDINGUNGEN (Collapse) ===== --}}
|
||||
@if ($incentive->getLang('terms'))
|
||||
<div class="card terms-toggle mb-4">
|
||||
<div class="card-header">
|
||||
<a href="#terms-teaser" data-toggle="collapse" class="text-body d-flex align-items-center collapsed">
|
||||
<i class="ion ion-md-document mr-2"></i>
|
||||
<strong>{{ __('incentive.terms') }}</strong>
|
||||
<i class="ion ion-md-chevron-down ml-auto"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="terms-teaser" class="collapse show">
|
||||
<div class="card-body">
|
||||
{!! $incentive->getLang('terms') !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@if (count($galleryImages) > 0)
|
||||
<script>
|
||||
(function() {
|
||||
var images = @json(collect($galleryImages)->map(fn($i) => asset($i))->values());
|
||||
var current = 0;
|
||||
var lightbox = document.getElementById('galleryLightbox');
|
||||
var lbImg = document.getElementById('lightboxImage');
|
||||
|
||||
document.querySelectorAll('.gallery-thumb').forEach(function(el) {
|
||||
el.addEventListener('click', function() {
|
||||
current = parseInt(el.dataset.galleryIndex);
|
||||
lbImg.src = images[current];
|
||||
lightbox.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
lightbox.querySelector('.lb-close').addEventListener('click', function() {
|
||||
lightbox.classList.remove('active');
|
||||
});
|
||||
|
||||
lightbox.querySelector('.lb-prev').addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
current = (current - 1 + images.length) % images.length;
|
||||
lbImg.src = images[current];
|
||||
});
|
||||
|
||||
lightbox.querySelector('.lb-next').addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
current = (current + 1) % images.length;
|
||||
lbImg.src = images[current];
|
||||
});
|
||||
|
||||
lightbox.addEventListener('click', function(e) {
|
||||
if (e.target === lightbox) {
|
||||
lightbox.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (!lightbox.classList.contains('active')) return;
|
||||
if (e.key === 'Escape') lightbox.classList.remove('active');
|
||||
if (e.key === 'ArrowLeft') lightbox.querySelector('.lb-prev').click();
|
||||
if (e.key === 'ArrowRight') lightbox.querySelector('.lb-next').click();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endif
|
||||
@endsection
|
||||
|
|
@ -65,5 +65,11 @@
|
|||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@if ($is_abo)
|
||||
<script>
|
||||
window.aboIntervalWarningTemplate = @json(__('abo.warning_next_date_soon_select', ['placeholder_days' => '__DAYS__', 'placeholder_date' => '__DATE__']));
|
||||
window.aboIntervalInfoTemplate = @json(__('abo.info_next_execution_select', ['placeholder_days' => '__DAYS__', 'placeholder_date' => '__DATE__']));
|
||||
</script>
|
||||
@endif
|
||||
<script src="{{ asset('/js/iq-shopping-cart.js') }}?v=1{{ get_file_last_time('/js/iq-shopping-cart.js') }}"></script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,369 +1,428 @@
|
|||
@if (Yard::instance('shopping')->content()->count())
|
||||
@if (Yard::instance('shopping')->compCount() > 0)
|
||||
<style>
|
||||
.yard-items-head {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.yard-item {
|
||||
position: relative;
|
||||
padding-top: 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
@if(Yard::instance('shopping')->content()->count())
|
||||
@if(Yard::instance('shopping')->compCount() > 0)
|
||||
<style>
|
||||
.yard-items-head {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.yard-item a.shop-item-hl {
|
||||
color: #9aa983;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.yard-item {
|
||||
position: relative;
|
||||
padding-top: 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.yard-item .options {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.yard-item a.shop-item-hl {
|
||||
color: #9aa983;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.yard-item a.auto-delete-product {
|
||||
font-size: 0.7em;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.yard-item .options {
|
||||
margin-top: 4px;
|
||||
}
|
||||
.yard-item .quantity {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.yard-item a.auto-delete-product {
|
||||
font-size: 0.7em;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.quantity-select {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.yard-item .quantity {
|
||||
position: relative;
|
||||
}
|
||||
.quantity-select select.form-control:not([size]):not([multiple]) {
|
||||
width: auto;
|
||||
min-width: 5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.quantity-select {
|
||||
text-align: right;
|
||||
}
|
||||
.yard-item .price-total {
|
||||
margin-top: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.quantity-select select.form-control:not([size]):not([multiple]) {
|
||||
width: auto;
|
||||
min-width: 5em;
|
||||
display: inline-block;
|
||||
}
|
||||
.yard-item .font-semi-bold {
|
||||
color: #393939;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.yard-item .price-total {
|
||||
margin-top: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.yard-item .font-semi-bold .small {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.yard-item .font-semi-bold {
|
||||
color: #393939;
|
||||
font-weight: 500;
|
||||
}
|
||||
.yard-item .font-bold {
|
||||
color: #393939;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.yard-item .font-semi-bold .small {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.price-single {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.yard-item .font-bold {
|
||||
color: #393939;
|
||||
font-weight: bold;
|
||||
}
|
||||
.price-total {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.price-single {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.quantity-select {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.price-total {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.quantity-select {
|
||||
text-align: right;
|
||||
}
|
||||
.quantity-select input.form-control {
|
||||
width: auto;
|
||||
min-width: 4em;
|
||||
display: inline-block;
|
||||
}
|
||||
.xsmall {
|
||||
font-size: 85%;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
<div id="cartContent">
|
||||
.quantity-select input.form-control {
|
||||
width: auto;
|
||||
min-width: 4em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
<div class="yard-items-head d-none d-sm-block">
|
||||
<div class="row">
|
||||
<div class="col-3 col-sm-2">
|
||||
<div class="row"> </div>
|
||||
</div>
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7">
|
||||
{{ __('order.article') }}
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-2 text-left">
|
||||
{{ __('order.unit_price') }}
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-3 text-right">
|
||||
{{ __('order.quantity') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@foreach(Yard::instance('shopping')->getContentByOrder() as $row)
|
||||
@php($product = \App\Models\Product::find($row->id))
|
||||
<div class="row yard-item">
|
||||
.xsmall {
|
||||
font-size: 85%;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
<div id="cartContent">
|
||||
|
||||
<div class="col-3 col-sm-2">
|
||||
@if($row->options->has('image'))
|
||||
<img src="{{ route('product_image', [$row->options->image]) }}" class="d-block ui-w-80 ui-bordered mr-4" alt="">
|
||||
@else
|
||||
<img src="{{ asset('/assets/images/1x1.png') }}" class="d-block ui-w-80 ui-bordered mr-4" alt="">
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7 description">
|
||||
<div class="media-body">
|
||||
<div class="d-block text-body" style="font-size: 15px; font-weight: 500;">{{ $row->name }} @if(isset($is_abo) && $is_abo) {!! get_abo_type_badge_by_product($product) !!} @endif</div>
|
||||
<div class="text-body">
|
||||
<div>{{ __('order.content') }}: {{ $product->contents }}</div>
|
||||
<div>{{ __('order.art_no') }}: {{ $product->number }}</div>
|
||||
<div>{{ __('order.points') }}: @if($row->options->comp) 0 @else {{ $product->getFormattedPoints() }} @endif</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options">
|
||||
@if(!$row->options->comp)
|
||||
<a href="#" class="auto-delete-product remove_item_form_cart product-tooltip" data-row-id="{{$row->rowId}}" data-product-id="{{ $product->id }}"><i class="fa fa-times"></i> {{ __('order.article_remove') }}</a>
|
||||
@else
|
||||
@if(Yard::instance('shopping')->getNumComp() > 1)
|
||||
{{$row->options->comp}}. {{ __('order.compensation_product') }}
|
||||
@else
|
||||
{{ __('order.compensation_product') }}
|
||||
@endif
|
||||
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-3 col-md-2 text-left font-semi-bold price-single">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->rowPriceNet($row, 3) }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="xsmall">~{{ Yard::instance('shopping')->getCurrencyByKey('rowPriceNetCurrency', $row, 3) }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-3 col-md-3 quantity">
|
||||
<div class="quantity-select">
|
||||
@if($row->options->comp)
|
||||
<span class="text-right product-tooltip" data-toggle="tooltip" title="{{ __('order.compensation_product') }}">1 x</span>
|
||||
@else
|
||||
<input type="number" class="form-control text-center cart-input-event-onchange" data-row-id="{{$row->rowId}}" data-product-id="{{ $product->id }}" value="{{ $row->qty }}" name="quantity[{{$row->rowId}}]" maxlength="3" max="999" min="1">
|
||||
@endif
|
||||
</div>
|
||||
<div class="price-total text-right">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->rowSubtotalNet($row) }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('rowSubtotalCurrency', $row, 3) }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
<div class="clearfix"></div>
|
||||
<div class="yard-items-head d-none d-sm-block">
|
||||
<div class="row">
|
||||
<div class="col-3 col-sm-2">
|
||||
<div class="row"> </div>
|
||||
</div>
|
||||
|
||||
<!-- / Shopping cart table -->
|
||||
<div class="d-flex flex-wrap justify-content-between pb-4">
|
||||
<div class="mt-2">
|
||||
<p class="small mb-2"> {!! __('order.you_has_article_in_shopping_cart', ['num'=> Yard::instance('shopping')->compCount() ]) !!}</p>
|
||||
<p>{{ __('order.points_total') }}: {{ formatNumber(Yard::instance('shopping')->points()) }}</p>
|
||||
<button type="button" class="btn btn-default btn-sm" id="clear-products-basket"><i class="ion ion-ios-trash"></i> {{ __('order.shopping_cart_delete') }}</button>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="text-right mt-2">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-left" style="border-top:none;">{{ __('order.subtotal') }}:</td>
|
||||
<td style="border-top:none;">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->subtotal() }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('subtotal') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('Delivery country') }}:</td>
|
||||
<td>{{ Yard::instance('shopping')->getShippingCountryName() }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.shipping_costs') }}:</td>
|
||||
<td>
|
||||
|
||||
@php($shippingFree = Yard::instance('shopping')->getShippingFree())
|
||||
@php($missingValue = Yard::instance('shopping')->getShippingFreeMissingValue())
|
||||
@php($currentShipping = Yard::instance('shopping')->shippingNet())
|
||||
@if($shippingFree && intval($currentShipping) == 0)
|
||||
{{-- Versandkostenfrei erreicht --}}
|
||||
<div class="badge badge-success font-weight-bold" style="font-size: 0.80rem; padding: 0.3rem 0.4rem;">
|
||||
<i class="fa fa-check-circle"></i> {{ __('order.free_shipping') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<small class="text-success font-weight-bold">
|
||||
<i class="fa fa-gift"></i> {{ __('order.free_shipping_reached', ['amount' => number_format($shippingFree, 2, ',', '.')]) }}
|
||||
</small>
|
||||
</div>
|
||||
@else
|
||||
{{-- Normale Versandkosten --}}
|
||||
<div class="no-line-break">{{ $currentShipping }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('shippingNet') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
|
||||
@if($shippingFree && $missingValue > 0)
|
||||
{{-- Zeige wie viel noch fehlt --}}
|
||||
<div class="mt-1">
|
||||
<small class="text-info">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
{{ __('order.free_shipping_info', [
|
||||
'amount' => number_format($shippingFree, 2, ',', '.'),
|
||||
'missing' => number_format($missingValue, 2, ',', '.')
|
||||
]) }}
|
||||
</small>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.total_without_VAT') }}:</td>
|
||||
<td>
|
||||
<div class="no-line-break"> {{ Yard::instance('shopping')->subtotalWithShipping() }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('subtotalWithShipping') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.plus_VAT') }}:</td>
|
||||
<td>
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->taxWithShipping() }} €</div>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('taxWithShipping') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@if(Yard::instance('shopping')->getUserTaxFree())
|
||||
<tr>
|
||||
<td class="text-left"><strong>{{ __('order.total_net') }}:</strong></td>
|
||||
<td>
|
||||
<strong><div class="no-line-break">{{ Yard::instance('shopping')->totalWithShipping() }} €</div></strong>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('totalWithShipping') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
<td class="text-left"><strong>{{ __('order.total_gross') }}:</strong></td>
|
||||
<td>
|
||||
<strong><div class="no-line-break">{{ Yard::instance('shopping')->totalWithShipping() }} €</div></strong>
|
||||
@if(Yard::instance('shopping')->isPriceCurrency())
|
||||
<span class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('totalWithShipping') }} {{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7">
|
||||
{{ __('order.article') }}
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-2 text-left">
|
||||
{{ __('order.unit_price') }}
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 col-md-3 text-right">
|
||||
{{ __('order.quantity') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
@foreach (Yard::instance('shopping')->getContentByOrder() as $row)
|
||||
@php($product = \App\Models\Product::find($row->id))
|
||||
<div class="row yard-item">
|
||||
|
||||
<div class="col-3 col-sm-2">
|
||||
@if ($row->options->has('image'))
|
||||
<img src="{{ route('product_image', [$row->options->image]) }}"
|
||||
class="d-block ui-w-80 ui-bordered mr-4" alt="">
|
||||
@else
|
||||
<img src="{{ asset('/assets/images/1x1.png') }}" class="d-block ui-w-80 ui-bordered mr-4"
|
||||
alt="">
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-9 col-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-7 description">
|
||||
<div class="media-body">
|
||||
<div class="d-block text-body" style="font-size: 15px; font-weight: 500;">
|
||||
{{ $row->name }} @if (isset($is_abo) && $is_abo)
|
||||
{!! get_abo_type_badge_by_product($product) !!}
|
||||
@endif
|
||||
</div>
|
||||
<div class="text-body">
|
||||
<div>{{ __('order.content') }}: {{ $product->contents }}</div>
|
||||
<div>{{ __('order.art_no') }}: {{ $product->number }}</div>
|
||||
<div>{{ __('order.points') }}: @if ($row->options->comp)
|
||||
0
|
||||
@else
|
||||
{{ $product->getFormattedPoints() }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options">
|
||||
@if (!$row->options->comp)
|
||||
<a href="#"
|
||||
class="auto-delete-product remove_item_form_cart product-tooltip"
|
||||
data-row-id="{{ $row->rowId }}" data-product-id="{{ $product->id }}"><i
|
||||
class="fa fa-times"></i> {{ __('order.article_remove') }}</a>
|
||||
@else
|
||||
@if (Yard::instance('shopping')->getNumComp() > 1)
|
||||
{{ $row->options->comp }}. {{ __('order.compensation_product') }}
|
||||
@else
|
||||
{{ __('order.compensation_product') }}
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-3 col-md-2 text-left font-semi-bold price-single">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->rowPriceNet($row, 3) }}
|
||||
€</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="xsmall">~{{ Yard::instance('shopping')->getCurrencyByKey('rowPriceNetCurrency', $row, 3) }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-3 col-md-3 quantity">
|
||||
<div class="quantity-select">
|
||||
@if ($row->options->comp)
|
||||
<span class="text-right product-tooltip" data-toggle="tooltip"
|
||||
title="{{ __('order.compensation_product') }}">1 x</span>
|
||||
@else
|
||||
<input type="number" class="form-control text-center cart-input-event-onchange"
|
||||
data-row-id="{{ $row->rowId }}" data-product-id="{{ $product->id }}"
|
||||
value="{{ $row->qty }}" name="quantity[{{ $row->rowId }}]"
|
||||
maxlength="3" max="999" min="1">
|
||||
@endif
|
||||
</div>
|
||||
<div class="price-total text-right">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->rowSubtotalNet($row) }}
|
||||
€</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('rowSubtotalCurrency', $row, 3) }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<!-- / Shopping cart table -->
|
||||
<div class="d-flex flex-wrap justify-content-between pb-4">
|
||||
<div class="mt-2">
|
||||
<p class="small mb-2"> {!! __('order.you_has_article_in_shopping_cart', ['num' => Yard::instance('shopping')->compCount()]) !!}</p>
|
||||
<p>{{ __('order.points_total') }}: {{ formatNumber(Yard::instance('shopping')->points()) }}</p>
|
||||
<button type="button" class="btn btn-default btn-sm" id="clear-products-basket"><i
|
||||
class="ion ion-ios-trash"></i> {{ __('order.shopping_cart_delete') }}</button>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="text-right mt-2">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-left" style="border-top:none;">{{ __('order.subtotal') }}:</td>
|
||||
<td style="border-top:none;">
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->subtotal() }} €</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('subtotal') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('Delivery country') }}:</td>
|
||||
<td>{{ Yard::instance('shopping')->getShippingCountryName() }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.shipping_costs') }}:</td>
|
||||
<td>
|
||||
|
||||
@php($shippingFree = Yard::instance('shopping')->getShippingFree())
|
||||
@php($missingValue = Yard::instance('shopping')->getShippingFreeMissingValue())
|
||||
@php($currentShipping = Yard::instance('shopping')->shippingNet())
|
||||
@if ($shippingFree && intval($currentShipping) == 0)
|
||||
{{-- Versandkostenfrei erreicht --}}
|
||||
<div class="badge badge-success font-weight-bold"
|
||||
style="font-size: 0.80rem; padding: 0.3rem 0.4rem;">
|
||||
<i class="fa fa-check-circle"></i> {{ __('order.free_shipping') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<small class="text-success font-weight-bold">
|
||||
<i class="fa fa-gift"></i>
|
||||
{{ __('order.free_shipping_reached', ['amount' => number_format($shippingFree, 2, ',', '.')]) }}
|
||||
</small>
|
||||
</div>
|
||||
@else
|
||||
{{-- Normale Versandkosten --}}
|
||||
<div class="no-line-break">{{ $currentShipping }} €</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('shippingNet') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
|
||||
@if ($shippingFree && $missingValue > 0)
|
||||
{{-- Zeige wie viel noch fehlt --}}
|
||||
<div class="mt-1">
|
||||
<small class="text-info">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
{{ __('order.free_shipping_info', [
|
||||
'amount' => number_format($shippingFree, 2, ',', '.'),
|
||||
'missing' => number_format($missingValue, 2, ',', '.'),
|
||||
]) }}
|
||||
</small>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.total_without_VAT') }}:</td>
|
||||
<td>
|
||||
<div class="no-line-break">
|
||||
{{ Yard::instance('shopping')->subtotalWithShipping() }} €</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('subtotalWithShipping') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-left">{{ __('order.plus_VAT') }}:</td>
|
||||
<td>
|
||||
<div class="no-line-break">{{ Yard::instance('shopping')->taxWithShipping() }} €
|
||||
</div>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('taxWithShipping') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@if (Yard::instance('shopping')->getUserTaxFree())
|
||||
<tr>
|
||||
<td class="text-left"><strong>{{ __('order.total_net') }}:</strong></td>
|
||||
<td>
|
||||
<strong>
|
||||
<div class="no-line-break">
|
||||
{{ Yard::instance('shopping')->totalWithShipping() }} €</div>
|
||||
</strong>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('totalWithShipping') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
<td class="text-left"><strong>{{ __('order.total_gross') }}:</strong></td>
|
||||
<td>
|
||||
<strong>
|
||||
<div class="no-line-break">
|
||||
{{ Yard::instance('shopping')->totalWithShipping() }} €</div>
|
||||
</strong>
|
||||
@if (Yard::instance('shopping')->isPriceCurrency())
|
||||
<span
|
||||
class="small">~{{ Yard::instance('shopping')->getCurrencyByKey('totalWithShipping') }}
|
||||
{{ Yard::instance('shopping')->getPriceCurrencyUnit() }} </span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
@if (isset($is_abo) && $is_abo)
|
||||
<div class="text-right">
|
||||
<div class="alert alert-info">
|
||||
<h4>{{ __('abo.abo_settings') }}</h4>
|
||||
|
||||
@if(isset($is_abo) && $is_abo)
|
||||
<div class="text-right">
|
||||
<div class="alert alert-info">
|
||||
<h4>{{ __('abo.abo_settings') }}</h4>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-6 col-sm-8 col-md-9 col-lg-9 mb-1">
|
||||
</div>
|
||||
<div class="col-12 col-sm-4 col-md-3 col-lg-3 mb-1 text-right">
|
||||
<label class="form-label">{{ __('abo.delivery_day') }}*</label>
|
||||
<select class="custom-select" name="abo_interval">
|
||||
{!! HTMLHelper::getAboDeliveryOptions() !!}
|
||||
</select>
|
||||
</div>
|
||||
<select class="custom-select" name="abo_interval" id="abo_interval_select">
|
||||
{!! HTMLHelper::getAboDeliveryOptions() !!}
|
||||
</select>
|
||||
<div id="abo_interval_info" class="alert alert-info mt-2 small"></div>
|
||||
<div id="abo_interval_warning" class="alert alert-warning mt-2 small d-none"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-4 col-lg-6 mb-1">
|
||||
<div class="col-12 col-sm-12 col-md-4 col-lg-6 mb-1">
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 mb-1">
|
||||
<div class="text-right">
|
||||
<em class="small"> <i> {!! __('abo.abo_order_info_check') !!}</em>
|
||||
<hr style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
<em class="font-weight-bold"> <i> {!! __('abo.abo_order_info_check_2') !!}</em>
|
||||
<hr style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
<em class="small"> <i> {!! __('abo.abo_order_info_check_3', ['abo-min-duration' => \App\Models\Setting::getContentBySlug('abo-min-duration')]) !!}</em>
|
||||
<hr style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
<hr
|
||||
style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
<em class="font-weight-bold"> <i> {!! __('abo.abo_order_info_check_2') !!}</em>
|
||||
<hr
|
||||
style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
<em class="small"> <i> {!! __('abo.abo_order_info_check_3', [
|
||||
'abo-min-duration' => \App\Models\Setting::getContentBySlug('abo-min-duration'),
|
||||
]) !!}</em>
|
||||
<hr
|
||||
style="margin-top: 10px; margin-bottom: 10px; border-color: #b4b4b4; border-width: 1px;">
|
||||
|
||||
<label class="switcher switcher-success">
|
||||
<input type="checkbox" class="switcher-input" name="abo_order_info_checkbox"
|
||||
value="true" required>
|
||||
<span class="switcher-indicator">
|
||||
<span class="switcher-yes">
|
||||
<span class="ion ion-md-checkmark"></span>
|
||||
</span>
|
||||
<span class="switcher-no">
|
||||
<span class="ion ion-md-close"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="switcher-label"><strong>{{ __('abo.abo_order_info_checkbox') }}</strong></span>
|
||||
</label>
|
||||
|
||||
|
||||
<label class="switcher switcher-success">
|
||||
<input type="checkbox" class="switcher-input" name="abo_order_info_checkbox" value="true" required>
|
||||
<span class="switcher-indicator">
|
||||
<span class="switcher-yes">
|
||||
<span class="ion ion-md-checkmark"></span>
|
||||
</span>
|
||||
<span class="switcher-no">
|
||||
<span class="ion ion-md-close"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="switcher-label"><strong>{{ __('abo.abo_order_info_checkbox') }}</strong></span>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@php($is_disabled = false)
|
||||
@if(isset($is_abo) && $is_abo && !\App\Services\AboHelper::aboHasBaseProduct(Yard::instance('shopping')->getContentByOrder()))
|
||||
@php($is_disabled = true)
|
||||
<div class="float-right">
|
||||
<div class="alert alert-danger text-right">
|
||||
<strong>{!! __('abo.abo_type_info_base', ['base'=>get_abo_type_badge('base')]) !!}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<br clear="all">
|
||||
@endif
|
||||
@if((isset($data['for']) && $data['for'] === 'ot-customer') || (isset($for) && $for === 'abo-ot-customer'))
|
||||
<div class="float-right">
|
||||
<button type="submit" class="btn btn-secondary" @if($is_disabled) disabled @endif><i class="ion ion-ios-redo"></i> {{ __('order.confirm_and_send_order') }}</button>
|
||||
</div>
|
||||
<br><br>
|
||||
<div class="text-right">
|
||||
<em class="small"> <i class="fa fa-info-circle"></i> {!! __('order.confirm_send_order_info') !!}</em>
|
||||
</div>
|
||||
@else
|
||||
<div class="float-right">
|
||||
<button type="submit" class="btn btn-secondary" @if($is_disabled) disabled @endif><i class="ion ion-ios-redo"></i> {{ __('order.confirm_and_proceed_to_checkout') }}</button>
|
||||
</div>
|
||||
<br><br>
|
||||
<div class="text-right">
|
||||
<em class="small"> <i class="fa fa-lock"></i> {!! __('payment.checkout_ssl_server') !!}</em>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endif
|
||||
<hr>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@php($is_disabled = false)
|
||||
@if (isset($is_abo) &&
|
||||
$is_abo &&
|
||||
!\App\Services\AboHelper::aboHasBaseProduct(Yard::instance('shopping')->getContentByOrder()))
|
||||
@php($is_disabled = true)
|
||||
<div class="float-right">
|
||||
<div class="alert alert-danger text-right">
|
||||
<strong>{!! __('abo.abo_type_info_base', ['base' => get_abo_type_badge('base')]) !!}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<br clear="all">
|
||||
@endif
|
||||
@if ((isset($data['for']) && $data['for'] === 'ot-customer') || (isset($for) && $for === 'abo-ot-customer'))
|
||||
<div class="float-right">
|
||||
<button type="submit" class="btn btn-secondary" @if ($is_disabled) disabled @endif><i
|
||||
class="ion ion-ios-redo"></i> {{ __('order.confirm_and_send_order') }}</button>
|
||||
</div>
|
||||
<br><br>
|
||||
<div class="text-right">
|
||||
<em class="small"> <i class="fa fa-info-circle"></i> {!! __('order.confirm_send_order_info') !!}</em>
|
||||
</div>
|
||||
@else
|
||||
<div class="float-right">
|
||||
<button type="submit" class="btn btn-secondary" @if ($is_disabled) disabled @endif><i
|
||||
class="ion ion-ios-redo"></i> {{ __('order.confirm_and_proceed_to_checkout') }}</button>
|
||||
</div>
|
||||
<br><br>
|
||||
<div class="text-right">
|
||||
<em class="small"> <i class="fa fa-lock"></i> {!! __('payment.checkout_ssl_server') !!}</em>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endif
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
</div>
|
||||
</h4>
|
||||
|
||||
@if(isset($chartData))
|
||||
@include('user.abo._abo_chart')
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
||||
|
|
@ -74,8 +78,8 @@
|
|||
{{ $user_abo->getCountOrders() }}
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="text-muted small">{{ __('tables.amount') }}</div>
|
||||
{{ $user_abo->getFormattedAmount() }} €
|
||||
<div class="text-muted small">{{ __('navigation.points') }}</div>
|
||||
<strong class="text-primary">{{ $user_abo->getFormattedTotalPoints() }} Pkt.</strong>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="text-muted small">{{ __('tables.payment') }}</div>
|
||||
|
|
|
|||
132
resources/views/user/team/customer_abos.blade.php
Normal file
132
resources/views/user/team/customer_abos.blade.php
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2 d-flex justify-content-between align-items-center w-100">
|
||||
<div>
|
||||
{{ __('abo.team_customer_abos') }} / {{ __('navigation.overview') }}
|
||||
</div>
|
||||
</h4>
|
||||
|
||||
@if(isset($chartData))
|
||||
@include('user.abo._abo_chart')
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
||||
@if($groupedByMember->isEmpty())
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<p class="text-muted mb-0">{{ __('tables.no_data_available') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
@php $memberIndex = 0; @endphp
|
||||
@foreach($groupedByMember as $memberId => $memberAbos)
|
||||
@php
|
||||
$member = $memberAbos->first()->member;
|
||||
$memberName = $member && $member->account
|
||||
? $member->account->first_name . ' ' . $member->account->last_name
|
||||
: '#' . $memberId;
|
||||
$totalPoints = $memberAbos->sum(fn($abo) => $abo->getTotalPoints());
|
||||
$aboCount = $memberAbos->count();
|
||||
$collapseId = 'member-abos-' . $memberId;
|
||||
$memberIndex++;
|
||||
@endphp
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body pb-2">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-6">
|
||||
<h5 class="mb-0">
|
||||
<a href="#" class="text-black" data-toggle="modal"
|
||||
data-target="#modals-load-content"
|
||||
data-id="{{ $memberId }}"
|
||||
data-action="business-user-show"
|
||||
data-back=""
|
||||
data-modal="modal-md"
|
||||
data-init_from="member"
|
||||
data-route="{{ route('modal_load') }}">
|
||||
<span class="mr-1 ion ion-ios-contact"></span>
|
||||
{{ $memberName }}
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button"
|
||||
data-toggle="collapse" data-target="#{{ $collapseId }}"
|
||||
aria-expanded="{{ $memberIndex === 1 ? 'true' : 'false' }}">
|
||||
<span class="ion ion-ios-list mr-1"></span>
|
||||
{{ $aboCount }} {{ __('abo.abo') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-0">
|
||||
<div class="card-body py-2">
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-1">
|
||||
<span class="text-muted small">{{ __('abo.abo_count') }}:</span>
|
||||
<strong class="ml-1">{{ $aboCount }}</strong>
|
||||
</div>
|
||||
<div class="col-md-4 mb-1">
|
||||
<span class="text-muted small">{{ __('navigation.points') }}:</span>
|
||||
<strong class="ml-1 text-primary">{{ \App\Services\Util::formatNumber($totalPoints) }} Pkt.</strong>
|
||||
</div>
|
||||
<div class="col-md-4 mb-1">
|
||||
<span class="text-muted small">{{ __('tables.active') }}:</span>
|
||||
<strong class="ml-1">{{ $memberAbos->where('active', true)->count() }} / {{ $aboCount }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="collapse {{ $memberIndex === 1 ? 'show' : '' }}" id="{{ $collapseId }}">
|
||||
<hr class="m-0">
|
||||
<div class="card-body pt-2 pb-1">
|
||||
<p class="text-muted small mb-2">
|
||||
<span class="ion ion-ios-lock mr-1"></span>
|
||||
{{ __('abo.customer_privacy_info') }}
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>{{ __('tables.customer') }}</th>
|
||||
<th>{{ __('navigation.points') }}</th>
|
||||
<th>{{ __('tables.status') }}</th>
|
||||
<th>{{ __('tables.next_date') }}</th>
|
||||
<th>{{ __('tables.abo_delivery') }}</th>
|
||||
<th>{{ __('tables.active') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($memberAbos as $index => $abo)
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge badge-outline-secondary">
|
||||
{{ __('tables.customer') }} #{{ $index + 1 }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<strong class="text-primary">
|
||||
{{ $abo->getFormattedTotalPoints() }} Pkt.
|
||||
</strong>
|
||||
</td>
|
||||
<td>{!! $abo->getStatusFormated() !!}</td>
|
||||
<td>{{ $abo->next_date }}</td>
|
||||
<td>{{ $abo->getCountOrders() }}</td>
|
||||
<td>{!! get_active_badge($abo->active) !!}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Loading…
Add table
Add a link
Reference in a new issue