Eigener Abschnitt auf der Abo-Seite (CRM me/ot und Kundenportal) mit Fortschritt zur Mindestlaufzeit, Pause und Kuendigung. Die Kuendigung laeuft ueber ein Modal, das die Folgen nennt (Abo endet, Konditionen entfallen, ein neues Abo hat wieder 6 Pflichtlieferungen), die Pause als Alternative anbietet und erst nach Bestaetigungs-Checkbox freigibt. Innerhalb der Sperrfrist vor der Ausfuehrung erscheint statt der Buttons ein Hinweis (AboHelper::isPauseCancelLocked). Das Einstellungs-Modal verweist nur noch auf den Abschnitt. Die Kuendigung im Repository ist jetzt wie die Pause eine eigenstaendige Aktion: Erfolgsmeldung statt Liefertermin-Hinweis, next_date bleibt unangetastet. Sprachdateien de/en/es/fr, Tests in AboPauseCancelSectionTest, Plan-Status. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
169 lines
9.8 KiB
PHP
169 lines
9.8 KiB
PHP
{{--
|
|
Abschnitt "Abo pausieren oder kündigen" (Ticket A4, Entwicklungsplan September 2026).
|
|
Wird auf der Abo-Detailseite im CRM (view me/ot) und im Kundenportal (view portal)
|
|
eingebunden. Erwartet $user_abo und $view. Beide Aktionen posten wie das
|
|
Einstellungs-Modal auf `user_abos_update` (action abo_update_settings); der
|
|
aktuelle Liefertag wird unverändert mitgesendet, damit die Liefertag-Validierung
|
|
nicht greift.
|
|
--}}
|
|
@php
|
|
$pcStatus = (int) $user_abo->status;
|
|
$pcEnded = in_array($pcStatus, App\Services\AboHelper::ENDED_STATUSES, true);
|
|
$pcMinDuration = (int) App\Services\AboHelper::getAboMinDuration();
|
|
$pcPaidOrders = (int) $user_abo->getCountPaidOrders();
|
|
$pcCanCancel = App\Services\AboHelper::canCancelAbo($user_abo, $view);
|
|
$pcCanPause = App\Services\AboHelper::canPauseAbo($user_abo, $view);
|
|
$pcNextPossiblePause = App\Services\AboHelper::nextPossiblePauseDate($user_abo);
|
|
$pcLocked = App\Services\AboHelper::isPauseCancelLocked($user_abo, $view);
|
|
$pcProgress = $pcMinDuration > 0 ? min(100, (int) round($pcPaidOrders / $pcMinDuration * 100)) : 100;
|
|
$pcUpdateRoute = route('user_abos_update', [$view, $user_abo->id]);
|
|
$pcNextDate = $user_abo->next_date ? \Carbon\Carbon::parse($user_abo->next_date) : null;
|
|
@endphp
|
|
|
|
@if ($pcStatus >= 2 && ! $pcEnded)
|
|
<div class="card mt-3 mb-3" id="abo-pause-cancel">
|
|
<div class="card-body">
|
|
<h6 class="font-weight-bold">
|
|
<i class="ion ion-md-pause text-muted mr-1"></i>{{ __('abo.pause_cancel_title') }}
|
|
</h6>
|
|
<p class="text-muted mb-3">{{ __('abo.pause_cancel_intro', ['min' => $pcMinDuration]) }}</p>
|
|
|
|
<div class="mb-1 small">
|
|
{{ __('abo.pause_cancel_progress', ['count' => $pcPaidOrders, 'min' => $pcMinDuration]) }}
|
|
</div>
|
|
<div class="progress mb-3" style="height: 8px;">
|
|
<div class="progress-bar {{ $pcCanCancel ? 'bg-success' : 'bg-primary' }}" role="progressbar"
|
|
style="width: {{ $pcProgress }}%;" aria-valuenow="{{ $pcPaidOrders }}" aria-valuemin="0"
|
|
aria-valuemax="{{ $pcMinDuration }}"></div>
|
|
</div>
|
|
|
|
@if (! $pcCanCancel)
|
|
<div class="alert alert-info mb-0">
|
|
{{ __('abo.info_min_duration_orders_left', ['count' => max(0, $pcMinDuration - $pcPaidOrders)]) }}
|
|
</div>
|
|
@elseif ($pcLocked && $pcNextDate)
|
|
<div class="alert alert-warning mb-0">
|
|
{{ __('abo.pause_cancel_locked_hint', [
|
|
'date' => $pcNextDate->format(Util::formatDateDB()),
|
|
'lock' => App\Repositories\AboRepository::getLockDaysPauseCancel(),
|
|
]) }}
|
|
</div>
|
|
@else
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<div class="font-weight-semibold mb-1">{{ __('abo.pause_abo') }}</div>
|
|
<p class="text-muted small mb-2">
|
|
{{ __('abo.abo_copy_pause', ['months' => App\Services\AboHelper::getPauseIntervalMonths()]) }}
|
|
</p>
|
|
@if ($pcCanPause)
|
|
<form method="POST" action="{{ $pcUpdateRoute }}" class="d-inline" id="abo-pause-form">
|
|
@csrf
|
|
<input type="hidden" name="action" value="abo_update_settings">
|
|
<input type="hidden" name="id" value="{{ $user_abo->id }}">
|
|
<input type="hidden" name="view" value="{{ $view }}">
|
|
<input type="hidden" name="abo_interval" value="{{ $user_abo->abo_interval }}">
|
|
<input type="hidden" name="abo_is_active" value="{{ $user_abo->active }}">
|
|
<input type="hidden" name="abo_pause" value="true">
|
|
<button type="submit" class="btn btn-outline-primary btn-sm"
|
|
onclick="return confirm('{{ __('abo.confirm_pause') }}')">
|
|
<i class="ion ion-md-pause"></i> {{ __('abo.pause_abo') }}
|
|
</button>
|
|
</form>
|
|
@elseif ($pcNextPossiblePause)
|
|
<div class="text-muted small">
|
|
{{ __('abo.info_pause_available_from', ['date' => $pcNextPossiblePause->format(Util::formatDateDB()), 'months' => App\Services\AboHelper::getPauseIntervalMonths()]) }}
|
|
</div>
|
|
@else
|
|
<div class="text-muted small">{{ __('abo.error_pause_not_active') }}</div>
|
|
@endif
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<div class="font-weight-semibold mb-1">{{ __('abo.cancel_abo') }}</div>
|
|
<p class="text-muted small mb-2">{{ __('abo.cancel_short_copy', ['min' => $pcMinDuration]) }}</p>
|
|
<button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
|
|
data-target="#modal-abo-cancel">
|
|
<i class="ion ion-ios-trash"></i> {{ __('abo.cancel_abo') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@if ($pcCanCancel && ! $pcLocked)
|
|
<div class="modal fade" id="modal-abo-cancel" tabindex="-1" role="dialog" aria-labelledby="modal-abo-cancel-label"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<form method="POST" action="{{ $pcUpdateRoute }}" id="abo-cancel-form">
|
|
@csrf
|
|
<input type="hidden" name="action" value="abo_update_settings">
|
|
<input type="hidden" name="id" value="{{ $user_abo->id }}">
|
|
<input type="hidden" name="view" value="{{ $view }}">
|
|
<input type="hidden" name="abo_interval" value="{{ $user_abo->abo_interval }}">
|
|
<input type="hidden" name="abo_is_active" value="{{ $user_abo->active }}">
|
|
<input type="hidden" name="abo_cancel" value="true">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="modal-abo-cancel-label">{{ __('abo.cancel_modal_title') }}</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-danger">
|
|
<strong>{{ __('abo.cancel_consequences_intro') }}</strong>
|
|
<ul class="mb-0 mt-1 pl-3">
|
|
<li>{{ __('abo.cancel_consequence_end') }}</li>
|
|
<li>{{ __('abo.cancel_consequence_points') }}</li>
|
|
<li>{{ __('abo.cancel_consequence_restart', ['min' => $pcMinDuration]) }}</li>
|
|
</ul>
|
|
</div>
|
|
@if ($pcCanPause)
|
|
<div class="alert alert-info">
|
|
{{ __('abo.cancel_alternative_pause') }}
|
|
</div>
|
|
@endif
|
|
<div class="custom-control custom-checkbox">
|
|
<input type="checkbox" class="custom-control-input" id="abo-cancel-confirm" name="abo_cancel_confirm" value="1">
|
|
<label class="custom-control-label" for="abo-cancel-confirm">
|
|
{{ __('abo.cancel_confirm_checkbox', ['min' => $pcMinDuration]) }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
|
|
@if ($pcCanPause)
|
|
<button type="button" class="btn btn-primary" id="abo-cancel-prefer-pause">
|
|
<i class="ion ion-md-pause"></i> {{ __('abo.cancel_prefer_pause_button') }}
|
|
</button>
|
|
@endif
|
|
<button type="submit" class="btn btn-outline-danger" id="abo-cancel-submit" disabled>
|
|
{{ __('abo.cancel_anyway_button') }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
$(document).ready(function () {
|
|
var confirmBox = $('#abo-cancel-confirm');
|
|
var submitButton = $('#abo-cancel-submit');
|
|
confirmBox.on('change', function () {
|
|
submitButton.prop('disabled', !confirmBox.is(':checked'));
|
|
});
|
|
$('#modal-abo-cancel').on('hidden.bs.modal', function () {
|
|
confirmBox.prop('checked', false);
|
|
submitButton.prop('disabled', true);
|
|
});
|
|
$('#abo-cancel-prefer-pause').on('click', function () {
|
|
$('#modal-abo-cancel').modal('hide');
|
|
if (confirm('{{ __('abo.confirm_pause') }}')) {
|
|
$('#abo-pause-form').trigger('submit');
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
@endif
|
|
@endif
|