292 lines
10 KiB
JavaScript
292 lines
10 KiB
JavaScript
import './bootstrap';
|
|
|
|
import Alpine from 'alpinejs';
|
|
|
|
document.addEventListener('alpine:init', () => {
|
|
Alpine.data('publicPreregisterPage', (config) => ({
|
|
phase: config.phase,
|
|
startAtMs: config.startAtMs,
|
|
phoneEnabled: config.phoneEnabled,
|
|
subscribeUrl: config.subscribeUrl,
|
|
csrfToken: config.csrfToken,
|
|
genericError: config.genericError,
|
|
days: 0,
|
|
hours: 0,
|
|
minutes: 0,
|
|
seconds: 0,
|
|
countdownTimer: null,
|
|
first_name: '',
|
|
last_name: '',
|
|
email: '',
|
|
phone: '',
|
|
submitting: false,
|
|
formError: '',
|
|
fieldErrors: {},
|
|
thankYouMessage: '',
|
|
|
|
init() {
|
|
if (this.phase === 'before') {
|
|
this.tickCountdown();
|
|
this.countdownTimer = setInterval(() => this.tickCountdown(), 1000);
|
|
}
|
|
},
|
|
|
|
tickCountdown() {
|
|
const start = this.startAtMs;
|
|
const now = Date.now();
|
|
const diff = start - now;
|
|
if (diff <= 0) {
|
|
if (this.countdownTimer !== null) {
|
|
clearInterval(this.countdownTimer);
|
|
this.countdownTimer = null;
|
|
}
|
|
this.phase = 'active';
|
|
return;
|
|
}
|
|
const totalSeconds = Math.floor(diff / 1000);
|
|
this.days = Math.floor(totalSeconds / 86400);
|
|
this.hours = Math.floor((totalSeconds % 86400) / 3600);
|
|
this.minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
this.seconds = totalSeconds % 60;
|
|
},
|
|
|
|
pad(n) {
|
|
return String(n).padStart(2, '0');
|
|
},
|
|
|
|
async submitForm() {
|
|
const form = this.$refs.form;
|
|
if (form !== undefined && form !== null && !form.checkValidity()) {
|
|
form.reportValidity();
|
|
return;
|
|
}
|
|
|
|
this.formError = '';
|
|
this.fieldErrors = {};
|
|
this.submitting = true;
|
|
try {
|
|
const body = {
|
|
first_name: this.first_name,
|
|
last_name: this.last_name,
|
|
email: this.email,
|
|
};
|
|
if (this.phoneEnabled) {
|
|
body.phone = this.phone;
|
|
}
|
|
const res = await fetch(this.subscribeUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json',
|
|
'X-CSRF-TOKEN': this.csrfToken,
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
},
|
|
body: JSON.stringify(body),
|
|
});
|
|
const data = await res.json().catch(() => ({}));
|
|
if (res.ok && data.success) {
|
|
this.phase = 'thanks';
|
|
this.thankYouMessage = data.message ?? '';
|
|
return;
|
|
}
|
|
if (typeof data.message === 'string' && data.message !== '') {
|
|
this.formError = data.message;
|
|
}
|
|
if (data.errors !== undefined && data.errors !== null && typeof data.errors === 'object') {
|
|
this.fieldErrors = data.errors;
|
|
}
|
|
} catch {
|
|
this.formError = this.genericError;
|
|
} finally {
|
|
this.submitting = false;
|
|
}
|
|
},
|
|
}));
|
|
|
|
Alpine.data('mailwizzWizard', (cfg) => ({
|
|
listsUrl: cfg.listsUrl,
|
|
fieldsUrl: cfg.fieldsUrl,
|
|
phoneEnabled: cfg.phoneEnabled,
|
|
hasExistingConfig: cfg.hasExistingConfig,
|
|
existing: cfg.existing,
|
|
csrf: cfg.csrf,
|
|
step: 1,
|
|
apiKey: '',
|
|
lists: [],
|
|
selectedListUid: '',
|
|
selectedListName: '',
|
|
allFields: [],
|
|
fieldEmail: '',
|
|
fieldFirstName: '',
|
|
fieldLastName: '',
|
|
fieldPhone: '',
|
|
tagField: '',
|
|
tagValue: '',
|
|
loading: false,
|
|
errorMessage: '',
|
|
|
|
init() {
|
|
if (this.existing) {
|
|
this.fieldEmail = this.existing.field_email ?? '';
|
|
this.fieldFirstName = this.existing.field_first_name ?? '';
|
|
this.fieldLastName = this.existing.field_last_name ?? '';
|
|
this.fieldPhone = this.existing.field_phone ?? '';
|
|
this.tagField = this.existing.tag_field ?? '';
|
|
this.tagValue = this.existing.tag_value ?? '';
|
|
this.selectedListUid = this.existing.list_uid ?? '';
|
|
this.selectedListName = this.existing.list_name ?? '';
|
|
}
|
|
},
|
|
|
|
textFields() {
|
|
return this.allFields.filter((f) => f.type_identifier === 'text');
|
|
},
|
|
|
|
emailFieldChoices() {
|
|
const texts = this.textFields();
|
|
const tagged = texts.filter(
|
|
(f) =>
|
|
(f.tag && f.tag.toUpperCase().includes('EMAIL')) ||
|
|
(f.label && f.label.toLowerCase().includes('email')),
|
|
);
|
|
return tagged.length > 0 ? tagged : texts;
|
|
},
|
|
|
|
phoneFields() {
|
|
return this.allFields.filter((f) => f.type_identifier === 'phonenumber');
|
|
},
|
|
|
|
checkboxFields() {
|
|
return this.allFields.filter((f) => f.type_identifier === 'checkboxlist');
|
|
},
|
|
|
|
tagOptionsList() {
|
|
const f = this.allFields.find((x) => x.tag === this.tagField);
|
|
if (!f || !f.options) {
|
|
return [];
|
|
}
|
|
return Object.entries(f.options).map(([key, label]) => ({
|
|
key,
|
|
label: String(label),
|
|
}));
|
|
},
|
|
|
|
async postJson(url, body) {
|
|
const res = await fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json',
|
|
'X-CSRF-TOKEN': this.csrf,
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
},
|
|
body: JSON.stringify(body),
|
|
});
|
|
const data = await res.json().catch(() => ({}));
|
|
return { res, data };
|
|
},
|
|
|
|
async connectLists() {
|
|
this.errorMessage = '';
|
|
if (!this.apiKey.trim()) {
|
|
this.errorMessage = cfg.strings.apiKeyRequired;
|
|
return;
|
|
}
|
|
this.loading = true;
|
|
try {
|
|
const { res, data } = await this.postJson(this.listsUrl, { api_key: this.apiKey });
|
|
if (!res.ok) {
|
|
this.errorMessage = data.message || data.error || cfg.strings.genericError;
|
|
return;
|
|
}
|
|
this.lists = Array.isArray(data.lists) ? data.lists : [];
|
|
if (this.lists.length === 0) {
|
|
this.errorMessage = cfg.strings.noListsError;
|
|
return;
|
|
}
|
|
if (this.existing?.list_uid) {
|
|
const match = this.lists.find((l) => l.list_uid === this.existing.list_uid);
|
|
if (match) {
|
|
this.selectedListUid = match.list_uid;
|
|
this.selectedListName = match.name;
|
|
}
|
|
}
|
|
this.step = 2;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async loadFieldsAndGoStep3() {
|
|
this.errorMessage = '';
|
|
if (!this.selectedListUid) {
|
|
this.errorMessage = cfg.strings.selectListError;
|
|
return;
|
|
}
|
|
this.syncListNameFromSelection();
|
|
this.loading = true;
|
|
try {
|
|
const { res, data } = await this.postJson(this.fieldsUrl, {
|
|
api_key: this.apiKey,
|
|
list_uid: this.selectedListUid,
|
|
});
|
|
if (!res.ok) {
|
|
this.errorMessage = data.message || data.error || cfg.strings.genericError;
|
|
return;
|
|
}
|
|
this.allFields = Array.isArray(data.fields) ? data.fields : [];
|
|
if (this.existing) {
|
|
this.fieldEmail = this.existing.field_email || this.fieldEmail;
|
|
this.fieldFirstName = this.existing.field_first_name || this.fieldFirstName;
|
|
this.fieldLastName = this.existing.field_last_name || this.fieldLastName;
|
|
this.fieldPhone = this.existing.field_phone || this.fieldPhone;
|
|
this.tagField = this.existing.tag_field || this.tagField;
|
|
this.tagValue = this.existing.tag_value || this.tagValue;
|
|
}
|
|
this.step = 3;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
syncListNameFromSelection() {
|
|
const l = this.lists.find((x) => x.list_uid === this.selectedListUid);
|
|
this.selectedListName = l ? l.name : '';
|
|
},
|
|
|
|
goStep4() {
|
|
this.errorMessage = '';
|
|
if (!this.fieldEmail || !this.fieldFirstName || !this.fieldLastName) {
|
|
this.errorMessage = cfg.strings.mapFieldsError;
|
|
return;
|
|
}
|
|
if (this.phoneEnabled && !this.fieldPhone) {
|
|
this.errorMessage = cfg.strings.mapPhoneError;
|
|
return;
|
|
}
|
|
if (!this.tagField) {
|
|
this.errorMessage = cfg.strings.tagFieldError;
|
|
return;
|
|
}
|
|
this.step = 4;
|
|
},
|
|
|
|
submitSave() {
|
|
this.errorMessage = '';
|
|
if (!this.tagValue) {
|
|
this.errorMessage = cfg.strings.tagValueError;
|
|
return;
|
|
}
|
|
if (!this.hasExistingConfig && !this.apiKey.trim()) {
|
|
this.errorMessage = cfg.strings.apiKeyRequired;
|
|
return;
|
|
}
|
|
this.$refs.saveForm.requestSubmit();
|
|
},
|
|
}));
|
|
});
|
|
|
|
window.Alpine = Alpine;
|
|
|
|
Alpine.start();
|