SHA256
Добавить promo-регистрацию и оффлайн генератор промокодов
This commit is contained in:
@@ -71,6 +71,7 @@ export function render({ navigate }) {
|
||||
|
||||
let passwordMode = String(state.registrationDraft.passwordMode || 'single') === 'words' ? 'words' : 'single';
|
||||
let passwordWords = normalizePasswordWords(state.registrationDraft.passwordWords);
|
||||
let usePromoCode = Boolean(state.registrationDraft.usePromoCode);
|
||||
|
||||
const loginInput = document.createElement('input');
|
||||
loginInput.className = 'input';
|
||||
@@ -117,6 +118,40 @@ export function render({ navigate }) {
|
||||
|
||||
passwordModeToggle.append(passwordModeCheckbox, passwordModeLabel);
|
||||
|
||||
const promoToggle = document.createElement('label');
|
||||
promoToggle.className = 'registration-toggle';
|
||||
|
||||
const promoCheckbox = document.createElement('input');
|
||||
promoCheckbox.type = 'checkbox';
|
||||
promoCheckbox.checked = usePromoCode;
|
||||
|
||||
const promoToggleLabel = document.createElement('span');
|
||||
promoToggleLabel.textContent = 'У меня есть промокод';
|
||||
|
||||
promoToggle.append(promoCheckbox, promoToggleLabel);
|
||||
|
||||
const promoField = document.createElement('label');
|
||||
promoField.className = 'stack';
|
||||
|
||||
const promoFieldLabel = document.createElement('span');
|
||||
promoFieldLabel.className = 'field-label';
|
||||
promoFieldLabel.textContent = 'Промокод';
|
||||
|
||||
const promoInput = document.createElement('input');
|
||||
promoInput.className = 'input';
|
||||
promoInput.type = 'text';
|
||||
promoInput.autocomplete = 'off';
|
||||
promoInput.autocapitalize = 'off';
|
||||
promoInput.spellcheck = false;
|
||||
promoInput.value = String(state.registrationDraft.promoCode || '');
|
||||
promoInput.placeholder = 'Вставьте промокод';
|
||||
|
||||
const promoHint = document.createElement('p');
|
||||
promoHint.className = 'meta-muted';
|
||||
promoHint.textContent = 'Если промокод включён, обычная проверка premium/trademark логина пропускается.';
|
||||
|
||||
promoField.append(promoFieldLabel, promoInput, promoHint);
|
||||
|
||||
const statusText = document.createElement('p');
|
||||
statusText.className = 'meta-muted';
|
||||
statusText.textContent = 'Проверка логина: не выполнена';
|
||||
@@ -202,6 +237,12 @@ export function render({ navigate }) {
|
||||
state.registrationDraft.passwordMode = passwordMode;
|
||||
state.registrationDraft.passwordWords = normalizePasswordWords(passwordWords);
|
||||
state.registrationDraft.password = getCurrentPassword();
|
||||
state.registrationDraft.usePromoCode = usePromoCode;
|
||||
state.registrationDraft.promoCode = String(promoInput.value || '').trim();
|
||||
}
|
||||
|
||||
function updatePromoVisibility() {
|
||||
promoField.style.display = usePromoCode ? 'grid' : 'none';
|
||||
}
|
||||
|
||||
async function runAvailabilityCheck() {
|
||||
@@ -212,6 +253,16 @@ export function render({ navigate }) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usePromoCode) {
|
||||
lastCheckedLogin = login;
|
||||
lastCheckedFree = true;
|
||||
lastCheckedClassName = 'promo';
|
||||
statusText.textContent = 'Промокод включён: обычная проверка premium/trademark логина пропущена';
|
||||
statusText.className = 'status-line is-available';
|
||||
formError.style.display = 'none';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (login === lastCheckedLogin) {
|
||||
if (!lastCheckedFree) {
|
||||
statusText.textContent = 'Логин уже занят ❌';
|
||||
@@ -320,8 +371,34 @@ export function render({ navigate }) {
|
||||
syncDraftState();
|
||||
});
|
||||
|
||||
promoCheckbox.addEventListener('change', () => {
|
||||
usePromoCode = promoCheckbox.checked;
|
||||
lastCheckedLogin = '';
|
||||
lastCheckedFree = false;
|
||||
lastCheckedClassName = '';
|
||||
updatePromoVisibility();
|
||||
syncDraftState();
|
||||
if (usePromoCode) {
|
||||
statusText.textContent = 'Промокод включён: проверка логина будет пропущена';
|
||||
statusText.className = 'status-line is-available';
|
||||
} else {
|
||||
statusText.textContent = 'Проверка логина: не выполнена';
|
||||
statusText.className = 'meta-muted';
|
||||
}
|
||||
});
|
||||
|
||||
promoInput.addEventListener('input', () => {
|
||||
syncDraftState();
|
||||
});
|
||||
|
||||
nextButton.addEventListener('click', async () => {
|
||||
formError.style.display = 'none';
|
||||
const promoCode = String(promoInput.value || '').trim();
|
||||
if (usePromoCode && !promoCode) {
|
||||
formError.textContent = 'Если включён промокод, поле промокода должно быть заполнено.';
|
||||
formError.style.display = '';
|
||||
return;
|
||||
}
|
||||
const isFree = await runAvailabilityCheck();
|
||||
if (!isFree) return;
|
||||
|
||||
@@ -345,6 +422,8 @@ export function render({ navigate }) {
|
||||
state.registrationDraft.password = nextPassword;
|
||||
state.registrationDraft.passwordMode = passwordMode;
|
||||
state.registrationDraft.passwordWords = normalizePasswordWords(passwordWords);
|
||||
state.registrationDraft.usePromoCode = usePromoCode;
|
||||
state.registrationDraft.promoCode = promoCode;
|
||||
if (credsChanged) {
|
||||
state.registrationDraft.preGeneratedKeyBundle = null;
|
||||
}
|
||||
@@ -363,10 +442,11 @@ export function render({ navigate }) {
|
||||
passwordField = form.children[1];
|
||||
loginField.append(loginInput);
|
||||
passwordField.append(passwordInput);
|
||||
form.append(passwordModeToggle, passwordLengthText, wordsSection, statusText, checkButton, formError);
|
||||
form.append(passwordModeToggle, promoToggle, promoField, passwordLengthText, wordsSection, statusText, checkButton, formError);
|
||||
actions.innerHTML = '';
|
||||
actions.append(backButton, nextButton);
|
||||
updatePasswordModeVisibility();
|
||||
updatePromoVisibility();
|
||||
syncDraftState();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user