UI improvements
This commit is contained in:
@@ -12,6 +12,7 @@ use App\Providers\DoubleCheckEventRegistrationProvider;
|
|||||||
use App\Providers\InertiaProvider;
|
use App\Providers\InertiaProvider;
|
||||||
use App\Resources\UserResource;
|
use App\Resources\UserResource;
|
||||||
use App\Scopes\CommonController;
|
use App\Scopes\CommonController;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -194,7 +195,7 @@ class SignupController extends CommonController {
|
|||||||
$arrival = \DateTime::createFromFormat('Y-m-d', $request->input('arrival'));
|
$arrival = \DateTime::createFromFormat('Y-m-d', $request->input('arrival'));
|
||||||
$departure = \DateTime::createFromFormat('Y-m-d', $request->input('departure'));
|
$departure = \DateTime::createFromFormat('Y-m-d', $request->input('departure'));
|
||||||
|
|
||||||
$amount = $event->calculateAmount(
|
$baseFee = $event->calculateAmount(
|
||||||
$request->input('participationType'),
|
$request->input('participationType'),
|
||||||
$request->input('beitrag'),
|
$request->input('beitrag'),
|
||||||
$arrival,
|
$arrival,
|
||||||
@@ -205,12 +206,27 @@ class SignupController extends CommonController {
|
|||||||
// Gewählte Zusätze immer einrechnen -- so enthält der finale Anzeigebetrag (und der Bestätigungstext)
|
// Gewählte Zusätze immer einrechnen -- so enthält der finale Anzeigebetrag (und der Bestätigungstext)
|
||||||
// stets die Addons und der Zahlungsschritt wird nur bei Gesamt 0 € übersprungen.
|
// stets die Addons und der Zahlungsschritt wird nur bei Gesamt 0 € übersprungen.
|
||||||
$selectedAddonKeys = array_keys(array_filter((array)$request->input('addons', []), fn($v) => (bool)$v));
|
$selectedAddonKeys = array_keys(array_filter((array)$request->input('addons', []), fn($v) => (bool)$v));
|
||||||
$amount->addAmount($event->resolveAddons($selectedAddonKeys, $arrival, $departure)['total']);
|
$resolution = $event->resolveAddons($selectedAddonKeys, $arrival, $departure);
|
||||||
|
|
||||||
|
// Gesamt = Teilnahmebeitrag + Zusätze; Basisbetrag separat für die Kostenübersicht in der Zusammenfassung.
|
||||||
|
$total = new Amount($baseFee->getAmount(), 'Euro');
|
||||||
|
$total->addAmount($resolution['total']);
|
||||||
|
|
||||||
|
$addonLines = array_map(fn($item) => [
|
||||||
|
'key' => $item['key'],
|
||||||
|
'title' => $item['title'],
|
||||||
|
'amountValue' => $item['amount'],
|
||||||
|
'amount' => new Amount($item['amount'], 'Euro')->toString(),
|
||||||
|
'free' => $item['amount'] <= 0,
|
||||||
|
], $resolution['items']);
|
||||||
|
|
||||||
// amountValue (numerisch) steuert im Frontend das Überspringen des Zahlungsart-Schritts bei 0 €.
|
// amountValue (numerisch) steuert im Frontend das Überspringen des Zahlungsart-Schritts bei 0 €.
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'amount' => $amount->toString(),
|
'amount' => $total->toString(),
|
||||||
'amountValue' => $amount->getAmount(),
|
'amountValue' => $total->getAmount(),
|
||||||
|
'baseAmount' => $baseFee->toString(),
|
||||||
|
'baseAmountValue' => $baseFee->getAmount(),
|
||||||
|
'addons' => $addonLines,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ const emit = defineEmits(['registrationDone'])
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
currentStep, goToStep, formData, selectedAddons,
|
currentStep, goToStep, formData, selectedAddons,
|
||||||
submit, submitting, submitResult, summaryLoading, summaryAmount, summaryAmountValue
|
submit, submitting, submitResult, summaryLoading, summaryAmount, summaryAmountValue,
|
||||||
|
summaryBaseAmount, summaryAddonLines
|
||||||
} = useSignupForm(props.event, props.participantData)
|
} = useSignupForm(props.event, props.participantData)
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
@@ -107,7 +108,8 @@ const steps = [
|
|||||||
v-if="currentStep === 11"
|
v-if="currentStep === 11"
|
||||||
:formData="formData"
|
:formData="formData"
|
||||||
:event="event"
|
:event="event"
|
||||||
:selectedAddons="selectedAddons"
|
:summaryBaseAmount="summaryBaseAmount"
|
||||||
|
:summaryAddonLines="summaryAddonLines"
|
||||||
:summaryAmount="summaryAmount"
|
:summaryAmount="summaryAmount"
|
||||||
:summaryAmountValue="summaryAmountValue"
|
:summaryAmountValue="summaryAmountValue"
|
||||||
:summaryLoading="summaryLoading"
|
:summaryLoading="summaryLoading"
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ export function useSignupForm(event, participantData) {
|
|||||||
|
|
||||||
const summaryAmount = ref('')
|
const summaryAmount = ref('')
|
||||||
const summaryAmountValue = ref(0)
|
const summaryAmountValue = ref(0)
|
||||||
|
const summaryBaseAmount = ref('')
|
||||||
|
const summaryAddonLines = ref([])
|
||||||
|
|
||||||
const fetchAmount = async () => {
|
const fetchAmount = async () => {
|
||||||
summaryLoading.value = true
|
summaryLoading.value = true
|
||||||
@@ -77,6 +79,8 @@ export function useSignupForm(event, participantData) {
|
|||||||
})
|
})
|
||||||
summaryAmount.value = res.data.amount
|
summaryAmount.value = res.data.amount
|
||||||
summaryAmountValue.value = Number(res.data.amountValue ?? 0)
|
summaryAmountValue.value = Number(res.data.amountValue ?? 0)
|
||||||
|
summaryBaseAmount.value = res.data.baseAmount ?? ''
|
||||||
|
summaryAddonLines.value = res.data.addons ?? []
|
||||||
} finally {
|
} finally {
|
||||||
summaryLoading.value = false
|
summaryLoading.value = false
|
||||||
}
|
}
|
||||||
@@ -128,6 +132,8 @@ export function useSignupForm(event, participantData) {
|
|||||||
submitResult,
|
submitResult,
|
||||||
summaryLoading,
|
summaryLoading,
|
||||||
summaryAmount,
|
summaryAmount,
|
||||||
summaryAmountValue
|
summaryAmountValue,
|
||||||
|
summaryBaseAmount,
|
||||||
|
summaryAddonLines
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ const PAYMENT_ACCOUNT_TRANSACTION = 'PAYMENT_ACCOUNT_TRANSACTION'
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
formData: Object,
|
formData: Object,
|
||||||
event: Object,
|
event: Object,
|
||||||
selectedAddons: {type: Object, default: () => ({})},
|
summaryBaseAmount: {type: String, default: ''},
|
||||||
|
summaryAddonLines: {type: Array, default: () => []},
|
||||||
summaryAmount: String,
|
summaryAmount: String,
|
||||||
summaryAmountValue: {type: Number, default: 0},
|
summaryAmountValue: {type: Number, default: 0},
|
||||||
summaryLoading: Boolean,
|
summaryLoading: Boolean,
|
||||||
@@ -36,16 +37,6 @@ const paymentConfirmationText = computed(() => {
|
|||||||
// Zurück führt zur Zahlungsart (10), sofern dieser Schritt gezeigt wurde; bei 0 € direkt zu Allergien (9).
|
// Zurück führt zur Zahlungsart (10), sofern dieser Schritt gezeigt wurde; bei 0 € direkt zu Allergien (9).
|
||||||
const backTarget = computed(() => props.summaryAmountValue > 0 ? 10 : 9)
|
const backTarget = computed(() => props.summaryAmountValue > 0 ? 10 : 9)
|
||||||
|
|
||||||
// Gewählte Zusätze (Event-Addons) für die Zusammenfassung mit Preisanzeige.
|
|
||||||
const selectedAddonList = computed(() =>
|
|
||||||
(props.event.addons ?? [])
|
|
||||||
.filter(addon => props.selectedAddons[addon.key])
|
|
||||||
.map(addon => ({
|
|
||||||
title: addon.title,
|
|
||||||
price: addon.free ? 'Kostenfrei' : (addon.priceReadable + (addon.flat ? '' : ' / Tag')),
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Gewählte Teilnahmeoptionen für die Zusammenfassung (label statt value anzeigen).
|
// Gewählte Teilnahmeoptionen für die Zusammenfassung (label statt value anzeigen).
|
||||||
const selectedParticipationOptions = computed(() =>
|
const selectedParticipationOptions = computed(() =>
|
||||||
(props.event.participationOptions ?? []).map(question => {
|
(props.event.participationOptions ?? []).map(question => {
|
||||||
@@ -140,11 +131,6 @@ function eatingHabit() {
|
|||||||
<td>{{ option.value }}</td>
|
<td>{{ option.value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr v-for="addon in selectedAddonList" :key="addon.title">
|
|
||||||
<td>{{ addon.title }}:</td>
|
|
||||||
<td>{{ addon.price }}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Foto-Erlaubnis:</td>
|
<td>Foto-Erlaubnis:</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -179,6 +165,22 @@ function eatingHabit() {
|
|||||||
<tr><td>Abreise:</td><td>{{ formatDate(formData.departure) }}</td></tr>
|
<tr><td>Abreise:</td><td>{{ formatDate(formData.departure) }}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<h4 style="margin: 0 0 8px 0;">Kostenübersicht</h4>
|
||||||
|
<table class="form-table cost-table" style="margin-bottom: 20px;">
|
||||||
|
<tr>
|
||||||
|
<td>Teilnahmebeitrag:</td>
|
||||||
|
<td>{{ summaryBaseAmount }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="addon in summaryAddonLines" :key="addon.key">
|
||||||
|
<td>{{ addon.title }}:</td>
|
||||||
|
<td>{{ addon.free ? 'Kostenfrei' : addon.amount }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="cost-total">
|
||||||
|
<td><strong>Gesamtbetrag:</strong></td>
|
||||||
|
<td><strong>{{ summaryAmount }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px;">
|
<div style="display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px;">
|
||||||
<label style="display: flex; gap: 10px; cursor: pointer;">
|
<label style="display: flex; gap: 10px; cursor: pointer;">
|
||||||
<input type="checkbox" v-model="formData.summary_information_correct" />
|
<input type="checkbox" v-model="formData.summary_information_correct" />
|
||||||
@@ -212,3 +214,10 @@ function eatingHabit() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.cost-table .cost-total td {
|
||||||
|
border-top: 1px solid #d1d5db;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user