diff --git a/backend/services/clickTtPlayerRegistrationService.js b/backend/services/clickTtPlayerRegistrationService.js index f2b24273..486345ac 100644 --- a/backend/services/clickTtPlayerRegistrationService.js +++ b/backend/services/clickTtPlayerRegistrationService.js @@ -107,9 +107,10 @@ class ClickTtPlayerRegistrationService { await page.waitForLoadState('domcontentloaded'); await this._openApplicationAfterSearch(page, trace); - await this._fillApplicationForm(page, memberJson, primaryEmail); + await this._fillApplicationForm(page, memberJson, primaryEmail, trace); await this._clickByText(page, 'Weiter >>', trace); await page.waitForLoadState('domcontentloaded'); + await this._dismissConsentOverlays(page, trace); await this._clickByText(page, 'Speichern', trace); await page.waitForLoadState('domcontentloaded'); await this._clickByText(page, 'Einreichen', trace); @@ -390,27 +391,55 @@ class ClickTtPlayerRegistrationService { await searchForm.locator('input[name$=".5"]').first().fill(formatGermanDate(member.birthDate)); } - async _fillApplicationForm(page, member, email) { + async _fillApplicationForm(page, member, email, trace) { + const form = page.locator('form.edit-object[enctype="multipart/form-data"]').first(); + if (!(await form.count())) { + throw new HttpError('Click-TT-Antragsformular nicht gefunden', 500); + } + + this._trace(trace, 'step', { name: 'fill-application-form' }); + const birthDate = formatGermanDate(member.birthDate); - const textInputs = page.locator('input[type="text"]'); - const inputCount = await textInputs.count(); + await this._fillIfEmpty(form.locator('input[name$=".15"]').first(), member.lastName); + await this._fillIfEmpty(form.locator('input[name$=".17"]').first(), member.firstName); + await this._fillIfEmpty(form.locator('input[name$=".25"]').first(), birthDate); + await this._fillIfEmpty(form.locator('input[name$=".9"]').first(), member.street || ''); + await this._fillIfEmpty(form.locator('input[name$=".15"]').nth(1), member.postalCode || ''); + await this._fillIfEmpty(form.locator('input[name$=".17"]').nth(1), member.city || ''); + await this._fillIfEmpty(form.locator('input[name$=".5"]').last(), email || ''); - const fillIfEmpty = async (index, value) => { - if (!value || index >= inputCount) return; - const locator = textInputs.nth(index); - const currentValue = (await locator.inputValue().catch(() => '')).trim(); - if (!currentValue) { - await locator.fill(value); + const nationalitySelect = form.locator('select[name$=".27"]').first(); + if (await nationalitySelect.count()) { + const currentValue = await nationalitySelect.inputValue().catch(() => 'WONoSelectionString'); + if (!currentValue || currentValue === 'WONoSelectionString') { + await nationalitySelect.selectOption({ label: /Deutschland/ }); } - }; + } - await fillIfEmpty(0, member.lastName); - await fillIfEmpty(1, member.firstName); - await fillIfEmpty(3, birthDate); - await fillIfEmpty(5, member.street || ''); - await fillIfEmpty(6, member.postalCode || ''); - await fillIfEmpty(7, member.city || ''); - await fillIfEmpty(13, email); + const countrySelect = form.locator('select[name$=".21.3"]').first(); + if (await countrySelect.count()) { + const currentValue = await countrySelect.inputValue().catch(() => 'WONoSelectionString'); + if (!currentValue || currentValue === 'WONoSelectionString') { + await countrySelect.selectOption({ label: /Deutschland/ }); + } + } + + const genderMap = { + female: 'input[id^="radioGenderFemale_"]', + male: 'input[id^="radioGenderMale_"]', + diverse: 'input[id^="radioGenderNonBinary_"]', + unknown: 'input[id^="radioGenderNotSpecified_"]' + }; + const genderSelector = genderMap[member.gender] || genderMap.unknown; + const genderRadio = form.locator(genderSelector).first(); + if (await genderRadio.count()) { + await genderRadio.check(); + } + + const dataPrivacyCheckbox = form.locator('input[type="checkbox"][name$=".45.3.2"]').first(); + if (await dataPrivacyCheckbox.count()) { + await dataPrivacyCheckbox.check(); + } } async _openApplicationAfterSearch(page, trace) { @@ -472,6 +501,17 @@ class ClickTtPlayerRegistrationService { return false; } + async _fillIfEmpty(locator, value) { + if (!value || !(await locator.count())) { + return false; + } + const currentValue = (await locator.inputValue().catch(() => '')).trim(); + if (!currentValue) { + await locator.fill(value); + } + return true; + } + async _hasTextTarget(page, text) { const escaped = escapeRegExp(text); const selectors = [