Support oft parent groups

This commit is contained in:
2026-09-29 14:35:33 +02:00
parent c4ca101594
commit a5e4e55df5
86 changed files with 1936 additions and 80 deletions
@@ -62,6 +62,7 @@ class CreateEventCommand {
'vat_pricing_mode' => $tenant->vat_pricing_mode,
'tax_exemption_reason' => $tenant->tax_exemption_reason,
'tax_exemption_note' => $tenant->tax_exemption_note,
'participant_group_type' => $this->request->participantGroupType->value,
// Den Event-Teil der Rechnungsnummer einfrieren: Tenant-Präfix und Startdatum sind später
// änderbar, eine herausgegebene Rechnung würde sonst zu einer anderen Nummer gehören.
//
@@ -2,6 +2,7 @@
namespace App\Domains\Event\Actions\CreateEvent;
use App\Enumerations\ParticipantGroupType;
use App\Enumerations\ParticipationFeeType;
use DateTime;
@@ -21,8 +22,11 @@ class CreateEventRequest {
public bool $payPerDay;
public ?string $street;
public ?string $houseNumber;
/** Wonach bei der Anmeldung gefragt wird: Local Group oder Parent Group. */
public ParticipantGroupType $participantGroupType;
public function __construct(string $name, string $location, string $postalCode, string $email, DateTime $begin, DateTime $end, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $earlyBirdEndAmountIncrease, ParticipationFeeType $participationFeeType, string $accountOwner, string $accountIban, bool $payPerDay, ?string $street = null, ?string $houseNumber = null) {
public function __construct(string $name, string $location, string $postalCode, string $email, DateTime $begin, DateTime $end, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $earlyBirdEndAmountIncrease, ParticipationFeeType $participationFeeType, string $accountOwner, string $accountIban, bool $payPerDay, ?string $street = null, ?string $houseNumber = null, ParticipantGroupType $participantGroupType = ParticipantGroupType::LocalGroup) {
$this->participantGroupType = $participantGroupType;
$this->name = $name;
$this->location = $location;
$this->postalCode = $postalCode;
@@ -4,6 +4,8 @@ namespace App\Domains\Event\Actions\ShortSignUp;
use App\Domains\Event\Actions\SignUp\SignUpCommand;
use App\Domains\Event\Actions\SignUp\SignUpRequest;
use App\Models\ParentGroup;
use App\Models\Tenant;
use App\ValueObjects\Age;
/**
@@ -53,18 +55,21 @@ class ShortSignUpCommand {
return $response;
}
// Stamm: bei genau einem teilnehmenden Stamm wird dieser gesetzt, bei mehreren muss gewählt werden,
// ohne teilnehmende Stämme bleibt die Zuordnung leer.
$localGroups = $this->request->event->localGroups;
$localGroup = null;
// Gruppe (Local oder Parent Group, je nach Veranstaltung): bei genau einer Option wird diese gesetzt, bei
// mehreren muss gewählt werden, ohne Optionen bleibt die Zuordnung leer.
$groupOptions = $this->request->event->participantGroupOptions();
$participantGroup = null;
if ($localGroups->count() === 1) {
$localGroup = $localGroups->first();
} elseif ($localGroups->count() > 1) {
$localGroup = $localGroups->firstWhere('id', $this->request->localGroupId);
if ($groupOptions->count() === 1) {
$participantGroup = $groupOptions->first();
} elseif ($groupOptions->count() > 1) {
$participantGroup = $groupOptions->firstWhere('id', $this->request->localGroupId);
if ($localGroup === null) {
$response->message = 'Bitte einen Stamm auswählen.';
if ($participantGroup === null) {
$response->message = sprintf(
'Bitte bei „%s" eine Auswahl treffen.',
$this->request->event->participantGroupType()->label(),
);
return $response;
}
}
@@ -87,7 +92,7 @@ class ShortSignUpCommand {
lastname: $this->request->lastname,
nickname: $this->request->nickname,
participationType: $participationType,
localGroup: $localGroup,
localGroup: $participantGroup instanceof Tenant ? $participantGroup : null,
birthday: $this->request->birthday,
address_1: self::PLACEHOLDER,
address_2: null,
@@ -123,6 +128,7 @@ class ShortSignUpCommand {
addonItems: [],
feeType: $this->request->feeType,
siblingReduction: false,
parentGroup: $participantGroup instanceof ParentGroup ? $participantGroup : null,
);
$signUpResponse = new SignUpCommand($signUpRequest)->execute();
@@ -61,6 +61,7 @@ class SignUpCommand {
'fee_type' => $this->request->feeType,
'sibling_reduction' => $this->request->siblingReduction,
'local_group' => $this->request->localGroup?->slug,
'parent_group_id' => $this->request->parentGroup?->id,
'birthday' => $this->request->birthday,
'address_1' => $this->request->address_1,
'address_2' => $this->request->address_2,
@@ -3,6 +3,7 @@
namespace App\Domains\Event\Actions\SignUp;
use App\Models\Event;
use App\Models\ParentGroup;
use App\Models\Tenant;
use App\ValueObjects\Amount;
use DateTime;
@@ -55,6 +56,8 @@ class SignUpRequest {
public ?string $feeType = null,
/** Ob die 50-%-Geschwisterermäßigung in `amount` eingerechnet ist. */
public bool $siblingReduction = false,
/** Parent Group -- nur bei Veranstaltungen, die danach statt nach der Local Group fragen. */
public ?ParentGroup $parentGroup = null,
) {
}
}
@@ -2,6 +2,8 @@
namespace App\Domains\Event\Actions\UpdateEvent;
use App\Repositories\EventParticipantRepository;
class UpdateEventCommand {
public UpdateEventRequest $request;
public function __construct(UpdateEventRequest $request) {
@@ -26,6 +28,14 @@ class UpdateEventCommand {
$this->request->event->registration_allowed = $this->request->registrationAllowed;
$this->request->event->short_registration = $this->request->shortRegistration;
$this->request->event->swimming_permission_required = $this->request->swimmingPermissionRequired;
// Umstellen zwischen Local und Parent Group nur ohne Anmeldungen -- sonst stünden in einer Veranstaltung
// beide Arten von Antworten nebeneinander.
if ($this->request->participantGroupType !== null
&& !new EventParticipantRepository()->existsForEvent($this->request->event)) {
$this->request->event->participant_group_type = $this->request->participantGroupType->value;
}
$this->request->event->save();
$this->request->event->resetAllowedEatingHabits();
@@ -2,6 +2,7 @@
namespace App\Domains\Event\Actions\UpdateEvent;
use App\Enumerations\ParticipantGroupType;
use App\Models\Event;
use App\ValueObjects\Amount;
use DateTime;
@@ -25,9 +26,12 @@ class UpdateEventRequest {
public Amount $supportPerPerson;
public array $contributingLocalGroups;
public array $eatingHabits;
/** Wonach bei der Anmeldung gefragt wird; null = unverändert. Greift nur, solange es keine Anmeldungen gibt. */
public ?ParticipantGroupType $participantGroupType;
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true, ?string $street = null, ?string $houseNumber = null)
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true, ?string $street = null, ?string $houseNumber = null, ?ParticipantGroupType $participantGroupType = null)
{
$this->participantGroupType = $participantGroupType;
$this->event = $event;
$this->eventName = $eventName;
$this->eventLocation = $eventLocation;
@@ -31,9 +31,8 @@ class UpdateParticipantCommand {
$p->address_2 = $this->request->address_2;
$p->postcode = $this->request->postcode;
$p->city = $this->request->city;
// Leerer String würde als Fremdschlüssel scheitern -- kein Stamm heißt null.
$p->local_group = $this->request->localgroup ?: null;
$p->birthday = DateTime::createFromFormat('Y-m-d', $this->request->birthday);
$this->applyParticipantGroup($p);
$p->birthday = DateTime::createFromFormat('Y-m-d', $this->request->birthday);
$p->email_1 = $this->request->email_1;
$p->phone_1 = $this->request->phone_1;
$p->contact_person = $this->request->contact_person;
@@ -87,6 +86,29 @@ class UpdateParticipantCommand {
return $this->response;
}
/**
* Übernimmt die gewählte Gruppe -- je nach Veranstaltung die Local Group (Slug) oder die Parent Group (ID).
* Angenommen wird nur, was die Veranstaltung zur Auswahl stellt; leer heißt keine Angabe (null, ein leerer
* String würde als Fremdschlüssel scheitern).
*/
private function applyParticipantGroup(EventParticipant $participant): void
{
$event = $participant->event;
$value = trim((string) $this->request->participantGroup);
if ($event->asksForParentGroup()) {
$participant->parent_group_id = $value === ''
? null
: $event->participantGroupOptions()->firstWhere('id', (int) $value)?->id;
return;
}
$participant->local_group = $value === ''
? null
: $event->participantGroupOptions()->firstWhere('slug', $value)?->slug;
}
/**
* Ersetzt die zugeordneten Zusätze (Event-Addons) anhand der Auswahl. Bewusst **ohne Preis/Betrag**
* (amount 0): der Teilnahmebeitrag wird in den Details ohnehin manuell gesetzt. Es wird nur der Titel als
@@ -14,8 +14,11 @@ class UpdateParticipantRequest {
public ?string $address_2,
public string $postcode,
public string $city,
/** Stamm-Slug; leer/null bei Anmeldungen, die keinen Stamm erfasst haben (Kurzanmeldung). */
public ?string $localgroup,
/**
* Gewählte Gruppe: Slug der Local Group bzw. ID der Parent Group, je nachdem, wonach die Veranstaltung
* fragt. Leer/null = keine Angabe.
*/
public ?string $participantGroup,
public string $birthday,
public string $email_1,
public string $phone_1,
@@ -9,6 +9,7 @@ use App\Domains\Event\Actions\CreateEvent\CreateEventRequest;
use App\Domains\Event\Actions\SetCostUnit\SetCostUnitCommand;
use App\Domains\Event\Actions\SetCostUnit\SetCostUnitRequest;
use App\Enumerations\CostUnitType;
use App\Enumerations\ParticipantGroupType;
use App\Enumerations\ParticipationFeeType;
use App\Providers\InertiaProvider;
use App\Resources\EventResource;
@@ -28,6 +29,7 @@ class CreateController extends CommonController {
'participationFeeType' => $this->tenant->slug === 'lv' ?
ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED :
ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY,
'participantGroupTypes' => ParticipantGroupType::options(),
])->render();
}
@@ -58,7 +60,8 @@ class CreateController extends CommonController {
$request->input('eventIban'),
$payPerDay,
$request->input('eventStreet'),
$request->input('eventHouseNumber')
$request->input('eventHouseNumber'),
ParticipantGroupType::fromStored($request->input('eventParticipantGroupType')),
);
$wasSuccessful = false;
@@ -14,6 +14,7 @@ use App\Domains\Event\Actions\UpdateEvent\UpdateEventCommand;
use App\Domains\Event\Actions\UpdateEvent\UpdateEventRequest;
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersCommand;
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersRequest;
use App\Enumerations\ParticipantGroupType;
use App\Enumerations\ParticipationFeeType;
use App\Enumerations\ParticipationType;
use App\Providers\InertiaProvider;
@@ -27,7 +28,10 @@ use Illuminate\Http\Response;
class DetailsController extends CommonController {
public function __invoke(string $eventId) {
$event = $this->events->getByIdentifier($eventId);
return new InertiaProvider('Event/Details', ['event' => $event])->render();
return new InertiaProvider('Event/Details', [
'event' => $event,
'participantGroupLabel' => $event->participantGroupType()->label(),
])->render();
}
public function summary(int $eventId, Request $request) : JsonResponse {
@@ -65,6 +69,7 @@ class DetailsController extends CommonController {
(bool)$request->input('swimmingPermissionRequired', true),
$request->input('street'),
$request->input('houseNumber'),
ParticipantGroupType::tryFrom((string) $request->input('participantGroupType')),
);
$eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
@@ -185,6 +190,7 @@ class DetailsController extends CommonController {
'rows' => $participants,
'kitchenRequirements' => $kitchenOverview,
'participantsForKitchenList' => $this->eventParticipants->getParticipantsWithIntolerances($event, $request),
'participantGroupLabel' => $event->participantGroupType()->label(),
])->render();
$pdf = PdfGenerateAndDownloadProvider::fromHtml(
@@ -208,6 +214,9 @@ class DetailsController extends CommonController {
$csv = view('csvs.' . $listType, [
'event' => $event->name,
'rows' => $participants,
// Die Anschriftsspalten beschreiben immer die Local Group, die Gruppenspalte die gewählte Gruppe.
'localGroupLabel' => ParticipantGroupType::LocalGroup->label(),
'participantGroupLabel' => $event->participantGroupType()->label(),
])->render();
return response($csv, 200, [
@@ -220,7 +229,7 @@ class DetailsController extends CommonController {
$event = $this->events->getByIdentifier($eventId);
switch ($listType) {
case 'by-local-group':
$participants = $this->eventParticipants->groupByLocalGroup($event, $request);
$participants = $this->eventParticipants->groupByParticipantGroup($event, $request);
break;
case 'by-participation-group':
$participants = $this->eventParticipants->groupByParticipationType($event, $request);
@@ -12,7 +12,7 @@ class ByGroupController extends CommonController
$recipients = [];
switch ($groupType) {
case 'by-local-group':
$participants = $this->eventParticipants->groupByLocalGroup($event, $request, $request->input('groupName'));
$participants = $this->eventParticipants->groupByParticipantGroup($event, $request, $request->input('groupName'));
$recipients = $this->eventParticipants->getMailAddresses($participants[$request->input('groupName')]);
break;
case 'by-participation-group':
@@ -22,7 +22,7 @@ class ParticipantUpdateController extends CommonController {
address_2: $request->input('address_2'),
postcode: $request->input('postcode'),
city: $request->input('city'),
localgroup: $request->input('localgroup'),
participantGroup: $request->input('participantGroup'),
birthday: $request->input('birthday'),
email_1: $request->input('email_1'),
phone_1: $request->input('phone_1'),
@@ -7,6 +7,7 @@ use App\Domains\Event\Actions\CertificateOfConductionCheck\CertificateOfConducti
use App\Domains\Event\Actions\SignUp\SignUpCommand;
use App\Domains\Event\Actions\SignUp\SignUpRequest;
use App\Mail\ParticipantParticipationMails\EventSignUpSuccessfullMail;
use App\Models\ParentGroup;
use App\Models\Tenant;
use App\Providers\DoubleCheckEventRegistrationProvider;
use App\Providers\InertiaProvider;
@@ -65,7 +66,7 @@ class SignupController extends CommonController {
$inertiaProvider = new InertiaProvider('Event/Signup', [
'event' => $event,
'availableEvents' => $availableEvents,
'localGroups' => $event['contributingLocalGroups'],
'localGroups' => $event['participantGroupOptions'] ?? [],
'participantData' => $participantData,
]);
return $inertiaProvider->render();
@@ -111,6 +112,15 @@ class SignupController extends CommonController {
$addonResolution = $eventResource->resolveAddons($selectedAddonKeys, $arrival, $departure);
$amount->addAmount($addonResolution['total']);
// Gewählt wird eine der Optionen der Veranstaltung (Local oder Parent Group); anderes wird abgelehnt.
$participantGroup = $event->participantGroupOptions()->firstWhere('id', (int)($registrationData['localGroup'] ?? 0));
if ($participantGroup === null) {
return response()->json([
'status' => 'error',
'message' => sprintf('Bitte bei „%s" eine Auswahl treffen.', $event->participantGroupType()->label()),
], 422);
}
$signupRequest = new SignUpRequest(
$event,
$registrationData['userId'] ?? null,
@@ -118,7 +128,7 @@ class SignupController extends CommonController {
$registrationData['nachname'],
$registrationData['pfadiname'],
$registrationData['participationType'],
Tenant::findOrFail($registrationData['localGroup']),
$participantGroup instanceof Tenant ? $participantGroup : null,
\DateTime::createFromFormat('Y-m-d', $registrationData['geburtsdatum']),
$registrationData['address1'],
$registrationData['address2'],
@@ -153,6 +163,7 @@ class SignupController extends CommonController {
$addonResolution['items'],
$registrationData['beitrag'],
$siblingReduction,
$participantGroup instanceof ParentGroup ? $participantGroup : null,
);
$signupCommand = new SignUpCommand($signupRequest);
+12
View File
@@ -15,6 +15,7 @@
'eventIban': String,
"eventPayPerDay": Boolean,
"participationFeeType": String,
"participantGroupTypes": {type: Array, default: () => []},
})
const errors = reactive({})
@@ -35,6 +36,7 @@
eventIban: props.eventIban ? props.eventIban : '',
eventPayPerDay: props.eventPayPerDay ? props.eventPayPerDay : false,
eventParticipationFeeType: props.participationFeeType ? props.participationFeeType : 'fixed',
eventParticipantGroupType: 'local_group',
});
watch(
@@ -159,6 +161,7 @@
eventIban: formData.eventIban,
eventPayPerDay: formData.eventPayPerDay,
eventParticipationFeeType: formData.eventParticipationFeeType,
eventParticipantGroupType: formData.eventParticipantGroupType,
}
});
@@ -256,6 +259,15 @@
</td>
</tr>
<tr style="vertical-align: top;">
<th class="width-medium pr-20 height-50">Bei der Anmeldung abfragen</th>
<td class="height-50">
<select v-model="formData.eventParticipantGroupType" class="width-half-full">
<option v-for="type in props.participantGroupTypes" :key="type.value" :value="type.value">{{ type.label }}</option>
</select>
</td>
</tr>
<tr style="vertical-align: top;">
<th class="width-medium pr-20 height-50">Preiserhöhung nach Early-Bird-Phase</th>
+2 -1
View File
@@ -10,6 +10,7 @@ import Overview from "./Partials/Overview.vue";
const props = defineProps({
event: Object,
participantGroupLabel: {type: String, default: 'Stamm'},
})
const tabs = [
@@ -24,7 +25,7 @@ const tabs = [
endpoint: "/api/v1/event/details/" + props.event.identifier + '/participants/all',
},
{
title: 'Teilis nach Stamm',
title: 'Teilis nach ' + props.participantGroupLabel,
component: ParticipantsList,
endpoint: "/api/v1/event/details/" + props.event.identifier + '/participants/by-local-group',
},
@@ -16,8 +16,13 @@ const emit = defineEmits(['close'])
const dynmicProps = reactive({
localGroups: [],
eatingHabits:[],
participantGroupTypes: [],
localGroupLabelPlural: 'Stämme',
});
// Umstellen zwischen Local und Parent Group nur, solange es keine Anmeldungen gibt.
const participantGroupTypeLocked = (props.event.totalParticipantCount ?? 0) > 0
const contributingLocalGroups = ref([])
const eatingHabits = ref([]);
@@ -41,6 +46,7 @@ const emit = defineEmits(['close'])
swimmingPermissionRequired: props.event.swimmingPermissionRequired,
flatSupport: props.event.flatSupportEdit,
supportPerson: props.event.supportPersonIndex,
participantGroupType: props.event.participantGroupType ?? 'local_group',
})
onMounted(async () => {
@@ -76,6 +82,7 @@ const emit = defineEmits(['close'])
supportPerson: formData.supportPerson,
contributingLocalGroups: contributingLocalGroups.value,
eatingHabits: eatingHabits.value,
participantGroupType: formData.participantGroupType,
}
})
@@ -173,6 +180,18 @@ const emit = defineEmits(['close'])
</td>
</tr>
<tr>
<th>Bei der Anmeldung abfragen</th>
<td>
<select v-model="formData.participantGroupType" class="width-full" :disabled="participantGroupTypeLocked">
<option v-for="type in dynmicProps.participantGroupTypes" :key="type.value" :value="type.value">{{ type.label }}</option>
</select>
<span v-if="participantGroupTypeLocked" style="font-size: 0.8rem; color: #6b7280;">
Nicht mehr änderbar, da bereits Anmeldungen vorliegen.
</span>
</td>
</tr>
<tr>
<th>Mindestalter für Alkoholkonsum</th>
<td>
@@ -223,7 +242,7 @@ const emit = defineEmits(['close'])
<div class="right">
<table>
<tr>
<th>Teilnehmende Stämme</th>
<th>Teilnehmende {{ dynmicProps.localGroupLabelPlural }}</th>
</tr>
<tr v-for="localGroup in dynmicProps.localGroups">
<td>
@@ -42,7 +42,7 @@ const form = reactive({
address_2: '',
postcode: '',
city: '',
localgroup: '',
participantGroup: '',
birthday: '',
email_1: '',
phone_1: '',
@@ -71,6 +71,9 @@ const form = reactive({
// Teilnahmeoptionen des Events (Definition mit Titel/Frage/Optionen).
const participationQuestions = computed(() => staticProps.event?.participationOptions ?? []);
// Bezeichnung der gewählten Gruppe (z. B. „Stamm" oder „Bund"), je nach Einstellung der Veranstaltung.
const localGroupLabel = computed(() => staticProps.event?.participantGroupLabel ?? 'Stamm');
// Zusatzoptionen (Event-Addons) des Events.
const eventAddons = computed(() => staticProps.event?.addons ?? []);
@@ -95,7 +98,7 @@ watch(
form.address_2 = participant?.address_2 ?? '';
form.postcode = participant?.postcode ?? '';
form.city = participant?.city ?? '';
form.localgroup = participant?.local_group ?? '';
form.participantGroup = participant?.participantGroupValue ?? '';
form.birthday = participant?.birthdayDate ?? '';
form.email_1 = participant?.email_1 ?? '';
form.phone_1 = participant?.phone_1 ?? '';
@@ -229,12 +232,12 @@ function saveParticipant() {
</tr>
<tr>
<th>Stamm</th>
<th>{{ localGroupLabel }}</th>
<td>
<span v-if="!staticProps.editMode">{{ props.participant.localgroup }}</span>
<select v-else v-model="form.localgroup">
<option value="">Kein Stamm</option>
<option v-for="group in staticProps.event.contributingLocalGroups" :key="group.id" :value="group.slug">{{ group.name }}</option>
<span v-if="!staticProps.editMode">{{ props.participant.participantGroup }}</span>
<select v-else v-model="form.participantGroup">
<option value="">Keine Angabe</option>
<option v-for="group in staticProps.event.participantGroupOptions" :key="group.id" :value="group.value">{{ group.name }}</option>
</select>
</td>
</tr>
@@ -162,7 +162,7 @@ async function saveParticipant(formData) {
document.getElementById('participant-' + data.participant.identifier + '-fullname').innerHTML = data.participant.fullname;
document.getElementById('participant-' + data.participant.identifier + '-birthday').innerText = data.participant.birthday;
document.getElementById('participant-' + data.participant.identifier + '-age').innerText = data.participant.age;
document.getElementById('participant-' + data.participant.identifier + '-localgroup').innerText = data.participant.localgroup;
document.getElementById('participant-' + data.participant.identifier + '-localgroup').innerText = data.participant.participantGroup;
document.getElementById('participant-' + data.participant.identifier + '-arrival').innerText = data.participant.arrival;
document.getElementById('participant-' + data.participant.identifier + '-departure').innerText = data.participant.departure;
document.getElementById('participant-' + data.participant.identifier + '-email_1').innerText = data.participant.email_1;
@@ -641,7 +641,7 @@ function mailToGroup(groupKey) {
<tr class="participant-meta-row" :id="'participant-' + participant.identifier + '-meta'">
<td colspan="5" class="pl-meta">
<label :id="'participant-' + participant.identifier +'-localgroup'">
{{ participant?.localgroup ?? "-" }}
{{ participant?.participantGroup ?? "-" }}
</label> |
<strong> Anreise: </strong>
<label :id="'participant-' + participant.identifier +'-arrival'">
@@ -13,10 +13,12 @@ export function useShortSignupForm(event, participantData) {
// Gibt es nur eine Zahlungsart, wird sie vorausgewählt und der Zahlungsschritt entfällt.
const activeMethods = (event.paymentMethods ?? []).filter(m => m.active)
// Bei genau einem teilnehmenden Stamm wird dieser gesetzt, ohne danach zu fragen; erst ab zwei
// Stämmen erscheint das Auswahlfeld.
const localGroups = event.contributingLocalGroups ?? []
// Auswahl je nach Veranstaltung: teilnehmende Stämme oder deren Bünde. Bei genau einer Option wird diese
// gesetzt, ohne danach zu fragen; erst ab zwei Optionen erscheint das Auswahlfeld.
const localGroups = event.participantGroupOptions ?? []
const needsLocalGroup = localGroups.length > 1
// Vorbelegung mit dem Stamm des eingeloggten Nutzers nur, wenn er zur Auswahl gehört (bei Bund-Abfrage nie).
const preselectedGroup = localGroups.some(g => g.id === participantData.localGroup) ? participantData.localGroup : '-1'
const formData = reactive({
userId: participantData.id,
@@ -26,7 +28,7 @@ export function useShortSignupForm(event, participantData) {
geburtsdatum: participantData.birthday ?? '',
email_1: participantData.email ?? '',
telefon_1: participantData.phone ?? '',
localGroup: localGroups.length === 1 ? localGroups[0].id : (participantData.localGroup ?? '-1'),
localGroup: localGroups.length === 1 ? localGroups[0].id : preselectedGroup,
ansprechpartner: '',
email_2: '',
allergien: participantData.allergies ?? '',
@@ -11,6 +11,9 @@ const props = defineProps({
})
const emit = defineEmits(['next'])
// Bezeichnung der Auswahl (z. B. „Stamm" oder „Bund"), je nach Einstellung der Veranstaltung.
const localGroupLabel = props.event?.participantGroupLabel ?? 'Stamm'
const errors = reactive({
vorname: '',
nachname: '',
@@ -46,7 +49,7 @@ const next = () => {
}
if (props.needsLocalGroup && (!props.formData.localGroup || props.formData.localGroup === '-1')) {
errors.localGroup = 'Bitte einen Stamm auswählen.'
errors.localGroup = 'Bitte bei „' + localGroupLabel + '" eine Auswahl treffen.'
hasError = true
}
@@ -122,7 +125,7 @@ const next = () => {
</td>
</tr>
<tr v-if="needsLocalGroup">
<td>Stamm:</td>
<td>{{ localGroupLabel }}:</td>
<td>
<select v-model="formData.localGroup">
<option value="-1">Bitte wählen</option>
@@ -43,9 +43,9 @@ const selectedParticipationOptions = computed(() =>
}).filter(entry => entry.value !== '')
)
// Der Stamm steht entweder fest (genau ein teilnehmender Stamm) oder wurde auf Seite 1 gewählt.
// Die Gruppe (Stamm oder Bund) steht entweder fest (genau eine Option) oder wurde auf Seite 1 gewählt.
const localGroupName = computed(() =>
(props.event.contributingLocalGroups ?? []).find(g => g.id === props.formData.localGroup)?.name ?? null
(props.event.participantGroupOptions ?? []).find(g => g.id === props.formData.localGroup)?.name ?? null
)
const permissionName = (list, slug) =>
@@ -84,7 +84,7 @@ const canSubmit = computed(() =>
<td>{{ formData.telefon_1 }}</td>
</tr>
<tr v-if="localGroupName">
<td>Stamm:</td>
<td>{{ event.participantGroupLabel ?? 'Stamm' }}:</td>
<td>{{ localGroupName }}</td>
</tr>
@@ -92,7 +92,7 @@ const steps = [
<form @submit.prevent="submit">
<StepAge v-if="currentStep === 1" :event="event" @next="goToStep" />
<StepContactPerson v-if="currentStep === 2" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
<StepPersonalData v-if="currentStep === 3" :formData="formData" :localGroups="localGroups" @next="goToStep" @back="goToStep" />
<StepPersonalData v-if="currentStep === 3" :formData="formData" :event="event" :localGroups="localGroups" @next="goToStep" @back="goToStep" />
<StepArrival v-if="currentStep === 4" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
<StepRegistrationMode v-if="currentStep === 5" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
<StepAddons v-if="currentStep === 6" :formData="formData" :event="event" :selectedAddons="selectedAddons" @next="goToStep" @back="goToStep" />
@@ -24,7 +24,10 @@ export function useSignupForm(event, participantData) {
vorname: participantData.firstname ?? '',
nachname: participantData.lastname ?? '',
pfadiname: participantData.nickname ?? '',
localGroup: participantData.localGroup ?? '-1',
// Vorbelegung mit dem Stamm des eingeloggten Nutzers nur, wenn er zur Auswahl gehört (bei Bund-Abfrage nie).
localGroup: (event.participantGroupOptions ?? []).some(g => g.id === participantData.localGroup)
? participantData.localGroup
: '-1',
geburtsdatum: participantData.birthday ?? '',
address1: participantData.address_1 ?? '',
address2: participantData.address_2 ?? '',
@@ -2,9 +2,12 @@
import {reactive} from "vue";
import ErrorText from "../../../../../../Views/Components/ErrorText.vue";
const props = defineProps({ formData: Object, localGroups: Array })
const props = defineProps({ formData: Object, event: Object, localGroups: Array })
const emit = defineEmits(['next', 'back'])
// Bezeichnung der Auswahl (z. B. „Stamm" oder „Bund"), je nach Einstellung der Veranstaltung.
const localGroupLabel = props.event?.participantGroupLabel ?? 'Stamm'
const errors = reactive({
vorname: '',
nachname: '',
@@ -46,7 +49,7 @@ const next = () => {
}
if (props.formData.localGroup === '-1') {
errors.localGroup = 'Bitte den Stamm auswählen.'
errors.localGroup = 'Bitte bei „' + localGroupLabel + '" eine Auswahl treffen.'
hasError = true
}
@@ -90,7 +93,7 @@ const next = () => {
<tr><td>Nachname:</td><td><input type="text" v-model="props.formData.nachname" /><ErrorText :message="errors.nachname"/></td></tr>
<tr><td>Pfadiname:</td><td><input type="text" v-model="props.formData.pfadiname" /></td></tr>
<tr>
<td>Stamm:</td>
<td>{{ localGroupLabel }}:</td>
<td>
<select v-model="props.formData.localGroup">
<option value="-1">Bitte wählen</option>