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();