mivita/resources/views/admin/abo/_pause_cancel.blade.php
Kevin e8057f9f7b Abo (A4): Abschnitt "Abo pausieren oder kuendigen" mit Kuendigungs-Hinweis
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>
2026-09-16 10:14:51 +00:00

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