(function () { const TEXT = { prizeTypesSelected: function ( n ) { return n + ' typer premie valgt'; }, errFillName: 'Fyll inn navn.', errFillPurpose: 'Fyll inn formål.', errFillEmail: 'Fyll inn e-postadresse.', errInvalidEmail: 'Ugyldig e-postadresse.', errFillPhone: 'Fyll inn mobilnummer.', errInvalidPhone: 'Mobilnummer må være 8 siffer.', errFillAccount: 'Fyll inn bankkontonummer.', errInvalidAccount: 'Ugyldig kontonummer (11 siffer med riktig kontrollsiffer).', errTicketsRange: 'Antall må være mellom 100 og 10000.', errMin5Prizes: 'Legg til minst 5 premier.', errPrizeTitle: 'Fyll inn tittel.', errLowWinChance: 'For lav vinnersjanse — legg til flere premier eller øk antallet per premie.', labelStk: ' stk', labelEstimatedValue: 'Verdi: ', labelSelectedFile: 'Valgt fil: ', labelNoLogo: 'Ingen' }; const STORAGE_KEY = 'klubblodd_campaign_state_v1'; const ENDPOINT_URL = '/api/2026-05/register-campaign'; function byId ( id ) { return document.getElementById( id ); } function qs ( sel , root ) { return ( root || document ).querySelector( sel ); } function qsa ( sel , root ) { return Array.prototype.slice.call( ( root || document ).querySelectorAll( sel ) ); } function onlyDigits ( s ) { return String( s || '' ).replace( /[^0-9]/g , '' ); } // Norsk kontonummer: 11 siffer med MOD11-kontrollsiffer. function validAccount ( acc ) { acc = onlyDigits( acc ); if ( acc.length !== 11 ) return false; const w = [ 5, 4, 3, 2, 7, 6, 5, 4, 3, 2 ]; let sum = 0; for ( let i = 0; i < 10; i++ ) sum += parseInt( acc.charAt( i ) , 10 ) * w[ i ]; const rest = sum % 11; const ctrl = rest === 0 ? 0 : 11 - rest; if ( ctrl === 10 ) return false; return ctrl === parseInt( acc.charAt( 10 ) , 10 ); } function escapeHtml ( s ) { return String( s || '' ) .replace( /&/g , '&' ) .replace( //g , '>' ) .replace( /"/g , '"' ) .replace( /'/g , ''' ); /* " */ } function setError ( id , msg ) { const out = qs( '.error[data-for="' + id + '"]' ); if ( out ) out.textContent = msg || ''; const el = byId( id ); if ( el ) { if ( msg ) el.classList.add( 'invalid' ); else el.classList.remove( 'invalid' ); } } function safeParseJson ( s , fallback ) { try { return JSON.parse( s ); } catch ( err ) { return fallback; } } function getPrizes () { const el = byId( 'prizes_json' ); if ( !el ) return []; return safeParseJson( el.value || '[]' , [] ); } function setPrizes ( prizes ) { const el = byId( 'prizes_json' ); if ( el ) el.value = JSON.stringify( prizes || [] ); renderPrizes(); saveStateToStorage(); } function renderPrizes () { const prizes = getPrizes(); const list = byId( 'prize_list' ); const count = byId( 'prize_count' ); if ( list ) list.innerHTML = ''; prizes.forEach( function ( p , idx ) { const row = document.createElement( 'div' ); row.className = 'prize_row'; const left = document.createElement( 'div' ); left.className = 'prize_left'; const title = ( p.title || '' ).trim(); const qty = parseInt( p.qty || 0 , 10 ) || 0; const value = ( p.value || '' ).trim(); let meta = ''; if ( qty ) meta += qty + TEXT.labelStk.trim(); if ( value ) meta += ( meta ? ' - ca kr ' : 'ca kr ' ) + value + ',-'; left.innerHTML = '
' + escapeHtml( title ) + '
' + '
' + escapeHtml( meta ) + '
'; const right = document.createElement( 'div' ); right.className = 'prize_right'; const del = document.createElement( 'button' ); del.type = 'button'; del.className = 'mini'; del.textContent = 'Fjern'; del.addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); e.stopPropagation(); prizes.splice( idx , 1 ); setPrizes( prizes ); } , { passive: false } ); right.appendChild( del ); row.appendChild( left ); row.appendChild( right ); if ( list ) list.appendChild( row ); } ); if ( count ) count.textContent = TEXT.prizeTypesSelected( prizes.length ); updateWinChance(); } // ── Premieforslag ──────────────────────────────────────────────── function renderSuggestions () { const wrap = byId( 'prize_suggestions' ); if ( !wrap ) return; const templates = Array.isArray( window.__PRIZE_TEMPLATES ) ? window.__PRIZE_TEMPLATES : []; wrap.innerHTML = ''; templates.forEach( function ( t ) { const chip = document.createElement( 'button' ); chip.type = 'button'; chip.className = 'suggest_chip'; chip.textContent = t.name; if ( t.text ) chip.title = t.text; chip.addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); addPrizeQuick( t.name ); } , { passive: false } ); wrap.appendChild( chip ); } ); } function addPrizeQuick ( name ) { name = String( name || '' ).trim(); if ( !name ) return; const prizes = getPrizes(); // Finnes premien alt? Øk antallet i stedet for duplikat. const existing = prizes.filter( function ( p ) { return ( p.title || '' ).toLowerCase() === name.toLowerCase(); } )[ 0 ]; if ( existing ) { existing.qty = ( parseInt( existing.qty , 10 ) || 0 ) + 1; } else { prizes.push( { title: name , qty: 1 , value: '' } ); } setPrizes( prizes ); } // ── Vinnersjanse ───────────────────────────────────────────────── function winRate () { const tickets = parseInt( onlyDigits( ( byId( 'lottery_tickets' ) || {} ).value || '0' ) , 10 ) || 0; if ( tickets <= 0 ) return { rate: 0, winners: 0, tickets: 0 }; let winners = getPrizes().reduce( function ( sum , p ) { return sum + ( parseInt( p.qty , 10 ) || 0 ); } , 0 ); // Hovedpremien teller som én ekstra vinner når tittel er satt const mainTitle = ( ( byId( 'main_title' ) || {} ).value || '' ).trim(); if ( mainTitle.length >= 2 ) winners += 1; return { rate: winners / tickets, winners: winners, tickets: tickets }; } function updateWinChance () { const fill = byId( 'winchance_fill' ); const text = byId( 'winchance_text' ); if ( !fill || !text ) return; const cfg = window.__WINCHANCE || { min: 0.10, good: 0.25 }; const w = winRate(); const pct = Math.round( w.rate * 1000 ) / 10; // én desimal const oneIn = w.winners > 0 ? Math.round( w.tickets / w.winners ) : 0; // Bredde på måleren (skala 0–good*2, kappet 100%) const fillPct = Math.max( 0, Math.min( 100, ( w.rate / ( cfg.good * 2 ) ) * 100 ) ); fill.style.width = fillPct + '%'; let cls = 'wc_bad', msg; if ( w.winners === 0 || w.tickets === 0 ) { cls = 'wc_bad'; msg = 'Legg til premier for å se vinnersjansen.'; } else if ( w.rate >= cfg.good ) { cls = 'wc_good'; msg = 'Gode vinnersjanser! ' + pct + ' % vinner (omtrent 1 av ' + oneIn + ' lodd).'; } else if ( w.rate >= cfg.min ) { cls = 'wc_ok'; msg = 'Ok vinnersjanse: ' + pct + ' % (1 av ' + oneIn + '). Vi anbefaler minst ' + Math.round( cfg.good * 100 ) + ' % — legg gjerne til flere premier.'; } else { cls = 'wc_bad'; msg = 'For lav vinnersjanse: ' + pct + ' %' + ( oneIn ? ' (1 av ' + oneIn + ')' : '' ) + '. Minst ' + Math.round( cfg.min * 100 ) + ' % kreves — øk antall premier.'; } const box = byId( 'winchance' ); if ( box ) box.className = 'winchance ' + cls; text.textContent = msg; } function validateStep1 () { let ok = true; const name = ( byId( 'org_name' ).value || '' ).trim(); const purpose = ( byId( 'org_purpose' ).value || '' ).trim(); const email = ( byId( 'org_email' ).value || '' ).trim(); const phone = onlyDigits( byId( 'org_phone' ).value || '' ); setError( 'org_name' , '' ); setError( 'org_purpose' , '' ); setError( 'org_email' , '' ); setError( 'org_phone' , '' ); if ( name.length < 2 ) { setError( 'org_name' , TEXT.errFillName ); ok = false; } if ( purpose.length < 2 ) { setError( 'org_purpose' , TEXT.errFillPurpose ); ok = false; } if ( email.length === 0 ) { setError( 'org_email' , TEXT.errFillEmail ); ok = false; } else if ( !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test( email ) ) { setError( 'org_email' , TEXT.errInvalidEmail ); ok = false; } if ( phone.length === 0 ) { setError( 'org_phone' , TEXT.errFillPhone ); ok = false; } else if ( phone.length !== 8 ) { setError( 'org_phone' , TEXT.errInvalidPhone ); ok = false; } else { byId( 'org_phone' ).value = phone; } const account = onlyDigits( ( byId( 'org_account' ) || {} ).value || '' ); setError( 'org_account' , '' ); if ( account.length === 0 ) { setError( 'org_account' , TEXT.errFillAccount ); ok = false; } else if ( !validAccount( account ) ) { setError( 'org_account' , TEXT.errInvalidAccount ); ok = false; } else if ( byId( 'org_account' ) ) { byId( 'org_account' ).value = account; } return ok; } function validateStep2 () { let ok = true; setError( 'lottery_tickets' , '' ); if ( byId( 'prize_error' ) ) byId( 'prize_error' ).textContent = ''; const tickets = parseInt( onlyDigits( byId( 'lottery_tickets' ).value || '0' ) , 10 ) || 0; if ( tickets < 100 || tickets > 10000 ) { setError( 'lottery_tickets' , TEXT.errTicketsRange ); ok = false; } else { byId( 'lottery_tickets' ).value = String( tickets ); } const prizes = getPrizes(); if ( prizes.length < 5 ) { if ( byId( 'prize_error' ) ) byId( 'prize_error' ).textContent = TEXT.errMin5Prizes; ok = false; } // Vinnersjanse-sperre — blokker under minimumsterskel updateWinChance(); const w = winRate(); const cfg = window.__WINCHANCE || { min: 0.10, good: 0.25 }; if ( w.tickets > 0 && w.rate < cfg.min ) { if ( byId( 'prize_error' ) ) byId( 'prize_error' ).textContent = TEXT.errLowWinChance; ok = false; } return ok; } function validateStep3 () { return true; } function readState () { const prizes = getPrizes(); return { name: ( byId( 'org_name' ).value || '' ).trim(), purpose: ( byId( 'org_purpose' ).value || '' ).trim(), email: ( byId( 'org_email' ).value || '' ).trim(), phone: onlyDigits( byId( 'org_phone' ).value || '' ), account: onlyDigits( ( byId( 'org_account' ) || {} ).value || '' ), tickets: parseInt( onlyDigits( byId( 'lottery_tickets' ).value || '0' ) , 10 ) || 0, price: parseInt( byId( 'lottery_price' ).value || '0' , 10 ) || 0, prizes: prizes, days: parseInt( byId( 'lottery_days' ).value || '0' , 10 ) || 0, color: byId( 'partner_color' ).value || '', main_title: ( ( byId( 'main_title' ) || {} ).value || '' ).trim(), main_value: ( ( byId( 'main_value' ) || {} ).value || '' ).trim(), logoName: ( byId( 'lottery_logo' ).files && byId( 'lottery_logo' ).files[ 0 ] ) ? byId( 'lottery_logo' ).files[ 0 ].name : '' }; } function saveStateToStorage () { try { localStorage.setItem( STORAGE_KEY , JSON.stringify( readState() ) ); } catch ( err ) {} } function loadStateFromStorage () { const raw = ( function () { try { return localStorage.getItem( STORAGE_KEY ); } catch ( err ) { return null; } } )(); if ( !raw ) return null; const s = safeParseJson( raw , null ); if ( !s || typeof s !== 'object' ) return null; return s; } function applyStateToForm ( s ) { if ( !s ) return; if ( byId( 'org_name' ) && typeof s.name === 'string' ) byId( 'org_name' ).value = s.name; if ( byId( 'org_purpose' ) && typeof s.purpose === 'string' ) byId( 'org_purpose' ).value = s.purpose; if ( byId( 'org_email' ) && typeof s.email === 'string' ) byId( 'org_email' ).value = s.email; if ( byId( 'org_phone' ) && typeof s.phone === 'string' ) byId( 'org_phone' ).value = onlyDigits( s.phone ); if ( byId( 'org_account' ) && typeof s.account === 'string' ) byId( 'org_account' ).value = onlyDigits( s.account ); if ( byId( 'lottery_tickets' ) ) byId( 'lottery_tickets' ).value = s.tickets ? String( parseInt( s.tickets , 10 ) || 0 ) : ''; if ( byId( 'lottery_price' ) ) byId( 'lottery_price' ).value = s.price ? String( parseInt( s.price , 10 ) || 0 ) : ''; if ( byId( 'lottery_days' ) ) byId( 'lottery_days' ).value = s.days ? String( parseInt( s.days , 10 ) || 0 ) : ''; if ( byId( 'partner_color' ) && typeof s.color === 'string' ) byId( 'partner_color' ).value = s.color; if ( byId( 'main_title' ) && typeof s.main_title === 'string' ) byId( 'main_title' ).value = s.main_title; if ( byId( 'main_value' ) && typeof s.main_value === 'string' ) byId( 'main_value' ).value = s.main_value; if ( Array.isArray( s.prizes ) ) { const cleaned = s.prizes.map( function ( p ) { return { title: ( p && p.title ) ? String( p.title ) : '', qty: ( p && p.qty != null ) ? parseInt( p.qty , 10 ) || 0 : 0, value: ( p && p.value ) ? String( p.value ) : '' }; } ); const el = byId( 'prizes_json' ); if ( el ) el.value = JSON.stringify( cleaned ); renderPrizes(); } if ( byId( 'logo_note' ) && s.logoName ) { byId( 'logo_note' ).textContent = TEXT.labelSelectedFile + s.logoName; } } function renderPreview () { const s = readState(); const el = byId( 'preview' ); if ( !el ) return; const prizeRows = s.prizes.map( function ( p ) { const t = escapeHtml( p.title || '' ); const q = parseInt( p.qty || 0 , 10 ) || 0; const v = escapeHtml( p.value || '' ); let meta = ''; if ( q ) meta += q + TEXT.labelStk.trim(); meta += ( meta ? ' ' : '' ) +'( '+ TEXT.labelEstimatedValue + ( v ? 'Kr '+ v +',-' : '-' ) + ' )'; return '
' + t + '
' + escapeHtml( meta ) + '
'; } ).join( '' ); el.innerHTML = '
' + '
Arrangør
' + '
Navn
' + escapeHtml( s.name ) + '
' + '
Formål
' + escapeHtml( s.purpose ) + '
' + '
E-post
' + escapeHtml( s.email ) + '
' + '
Mobil
' + escapeHtml( s.phone ) + '
' + '
Konto
' + escapeHtml( s.account || '' ) + '
' + '
' + '
' + '
Lodd
' + '
Antall
' + escapeHtml( String( s.tickets ) ) + '
' + '
Pris
' + escapeHtml( String( s.price ) ) + ' kr
' + '
' + '
' + '
Premier
' + ( s.main_title ? '
🏆 ' + escapeHtml( s.main_title ) + '
Hovedpremie' + ( s.main_value ? ' · ' + escapeHtml( s.main_value ) : '' ) + '
' : '' ) + ( prizeRows || ( s.main_title ? '' : '
Ingen premier lagt til.
' ) ) + '
' + '
' + '
Innstillinger
' + '
Lengde
' + escapeHtml( String( s.days ) ) + ' dager
' + '
Farge
' + escapeHtml( s.color ) + '
' + ( function () { var lp = byId( 'logo_preview' ); var lsrc = ( lp && lp.src && lp.src.indexOf( 'data:' ) === 0 ) ? lp.src : ''; return '
Logo
' + ( lsrc ? '' : ( s.logoName ? escapeHtml( s.logoName ) : TEXT.labelNoLogo ) ) + '
'; } )() + '
'; if ( byId( 'payload_json' ) ) byId( 'payload_json' ).value = JSON.stringify( s ); saveStateToStorage(); } function setStep ( step ) { const stepNum = parseInt( step || '1' , 10 ) || 1; qsa( '.step_panel' ).forEach( function ( p ) { p.classList.remove( 'is_active' ); if ( parseInt( p.getAttribute( 'data-step' ) || '0' , 10 ) === stepNum ) { p.classList.add( 'is_active' ); } } ); qsa( '.step_btn' ).forEach( function ( b ) { b.classList.remove( 'is_active' ); if ( parseInt( b.getAttribute( 'data-step' ) || '0' , 10 ) === stepNum ) { b.classList.add( 'is_active' ); } } ); const bar = byId( 'progress_bar' ); if ( bar ) { const pct = Math.round( ( stepNum - 1 ) / 3 * 100 ); bar.style.width = pct + '%'; } if ( stepNum === 4 ) renderPreview(); saveStateToStorage(); window.scrollTo( 0 , 0 ); } function openModal () { byId( 'prize_modal' ).classList.remove( 'is_hidden' ); byId( 'prize_title' ).value = ''; byId( 'prize_qty' ).value = '1'; byId( 'prize_value' ).value = ''; setError( 'prize_title' , '' ); byId( 'prize_title' ).focus(); } function closeModal () { byId( 'prize_modal' ).classList.add( 'is_hidden' ); } function addPrizeFromModal () { const title = ( byId( 'prize_title' ).value || '' ).trim(); setError( 'prize_title' , '' ); if ( title.length < 2 ) { setError( 'prize_title' , TEXT.errPrizeTitle ); byId( 'prize_title' ).focus(); return; } const qty = Math.max( 1, parseInt( onlyDigits( byId( 'prize_qty' ).value || '1' ) , 10 ) || 1 ); const value = ( byId( 'prize_value' ).value || '' ).trim(); const prizes = getPrizes(); prizes.push( { title: title , qty: qty , value: value } ); setPrizes( prizes ); closeModal(); } function sendFinalStateToEndpoint () { const s = readState(); const payload = JSON.stringify( s ); try { localStorage.setItem( STORAGE_KEY , payload ); } catch ( err ) {} const form = byId( 'campaign_form' ); const fd = new FormData( form || undefined ); fd.set( 'payload_json' , payload ); function setDialogStatus ( ok , msg , onClose , details ) { const dlg = document.querySelector( 'dialog[data-sent-flag]' ); if ( !dlg || typeof dlg.showModal !== 'function' ) return; const statusEl = dlg.querySelector( '[data-status]' ); const msgEl = dlg.querySelector( '[data-message]' ); if ( statusEl ) statusEl.textContent = ok ? 'Lagret!' : 'Noe gikk galt'; if ( msgEl ){ msgEl.innerHTML = ''; if ( msg ){ const p = document.createElement( 'p' ); p.textContent = msg; msgEl.appendChild( p ); } else if ( !ok ){ const p = document.createElement( 'p' ); p.textContent = 'Kunne ikke lagre.'; msgEl.appendChild( p ); } if ( !ok && Array.isArray( details ) && details.length ){ const ul = document.createElement( 'ul' ); ul.style.marginTop = '8px'; ul.style.paddingLeft = '20px'; details.forEach( function ( d ){ const li = document.createElement( 'li' ); li.textContent = d; ul.appendChild( li ); } ); msgEl.appendChild( ul ); } } dlg.setAttribute( 'data-ok' , ok ? '1' : '0' ); if ( typeof onClose === 'function' ) { dlg.addEventListener( 'close', function () { onClose(); }, { once: true } ); } if ( !dlg.open ) dlg.showModal(); } try { fetch( ENDPOINT_URL , { method: 'POST', body: fd, credentials: 'same-origin', keepalive: true, headers: { 'X-Requested-With': 'XMLHttpRequest' } } ) .then( function ( res ) { return res.json().then( function ( j ) { if ( j && j.status && j.status.code === 200 ) { // Success — server returns next URL for confirmation step try { localStorage.removeItem( STORAGE_KEY ); } catch ( err ) {} const next = ( j.data && j.data.next ) || '/'; setDialogStatus( true , 'Vi har sendt en bekreftelseskode til e-posten din.' , function () { window.location.href = next; } ); } else { const m = ( j && j.status && j.status.message ) ? String( j.status.message ) : 'Kunne ikke lagre.'; const det = ( j && j.data && Array.isArray( j.data.details ) ) ? j.data.details : null; setDialogStatus( false , m , null , det ); } return null; } ).catch( function () { setDialogStatus( false , 'Ugyldig svar fra server.' ); return null; } ); } ) .catch( function () { setDialogStatus( false , 'Nettverksfeil.' ); } ); } catch ( err ) { setDialogStatus( false , 'Teknisk feil.' ); } } function bindAutoSave () { const ids = [ 'org_name', 'org_purpose', 'org_email', 'org_phone', 'org_account', 'lottery_tickets', 'lottery_price', 'lottery_days', 'partner_color', 'main_title', 'main_value' ]; ids.forEach( function ( id ) { const el = byId( id ); if ( !el ) return; el.addEventListener( 'input' , function () { saveStateToStorage(); } ); el.addEventListener( 'change' , function () { saveStateToStorage(); } ); } ); } // ── Bilde-opplasting (generisk dropzone + forhåndsvisning) ─────── function setupDropzone ( opts ) { const inp = byId( opts.input ); const dz = byId( opts.drop ); const img = byId( opts.preview ); const ph = byId( opts.placeholder ); const clr = byId( opts.clear ); const note = opts.note ? byId( opts.note ) : null; if ( !inp || !dz ) return; function showPreview ( file ) { if ( !img || !file ) return; if ( !/^image\//.test( file.type || '' ) ) { clearIt(); return; } const reader = new FileReader(); reader.onload = function ( e ) { img.src = e.target.result; img.hidden = false; if ( ph ) ph.hidden = true; if ( clr ) clr.hidden = false; dz.classList.add( 'has_file' ); }; reader.readAsDataURL( file ); if ( note ) note.textContent = TEXT.labelSelectedFile + file.name; } function clearIt () { inp.value = ''; if ( img ) { img.src = ''; img.hidden = true; } if ( ph ) ph.hidden = false; if ( clr ) clr.hidden = true; dz.classList.remove( 'has_file' ); if ( note ) note.textContent = ''; saveStateToStorage(); } inp.addEventListener( 'change' , function () { const f = ( inp.files && inp.files[ 0 ] ) ? inp.files[ 0 ] : null; if ( f ) showPreview( f ); else clearIt(); saveStateToStorage(); } ); [ 'dragenter' , 'dragover' ].forEach( function ( ev ) { dz.addEventListener( ev , function ( e ) { e.preventDefault(); dz.classList.add( 'is_drag' ); } ); } ); [ 'dragleave' , 'dragend' ].forEach( function ( ev ) { dz.addEventListener( ev , function () { dz.classList.remove( 'is_drag' ); } ); } ); dz.addEventListener( 'drop' , function ( e ) { e.preventDefault(); dz.classList.remove( 'is_drag' ); const files = e.dataTransfer && e.dataTransfer.files; if ( files && files.length ) { try { inp.files = files; } catch ( err ) {} showPreview( files[ 0 ] ); saveStateToStorage(); } } ); if ( clr ) { clr.addEventListener( 'click' , function ( e ) { e.preventDefault(); e.stopPropagation(); clearIt(); } ); } } // ⚠️ TEST ONLY — REMOVE BEFORE PROD — START function fillWithTestData () { var orgs = [ { name: 'Berglia Idrettslag', purpose: 'Ny drakter til juniorlaget', email: 'test1@example.com', phone: '40000001', account: '12345678903' }, { name: 'Frogner Fotballklubb', purpose: 'Reise til sommerturneringen', email: 'test2@example.com', phone: '92345678', account: '98765432103' }, { name: 'Åsly Musikkorps', purpose: 'Nytt instrument til korpset', email: 'test3@example.com', phone: '41234567', account: '15065431006' }, { name: 'Skansen Barnehage', purpose: 'Dugnadsmidler til lekeplassen', email: 'test4@example.com', phone: '99887766', account: '80005000002' }, { name: 'Nordvik Svømmeklubb', purpose: 'Utstyr til høstsesongen', email: 'test5@example.com', phone: '47000001', account: '12001200125' } ]; var prizeSets = [ [ { title: 'Gavekort', qty: 5, value: '250' }, { title: 'Termos', qty: 10, value: '180' }, { title: 'Sjokolade', qty: 20, value: '45' }, { title: 'Caps', qty: 8, value: '130' }, { title: 'Kaffekopp', qty: 15, value: '75' }, { title: 'Nøkkelring', qty: 25, value: '30' } ], [ { title: 'Treningsvest', qty: 3, value: '280' }, { title: 'Vannflaske', qty: 12, value: '140' }, { title: 'T-skjorte', qty: 6, value: '190' }, { title: 'Lue', qty: 10, value: '110' }, { title: 'Badesvamp', qty: 20, value: '35' }, { title: 'Munnbind', qty: 30, value: '20' } ] ]; var org = orgs[ Math.floor( Math.random() * orgs.length ) ]; var prizes = prizeSets[ Math.floor( Math.random() * prizeSets.length ) ]; applyStateToForm( { name: org.name, purpose: org.purpose, email: org.email, phone: org.phone, account: org.account, tickets: 500, price: 25, prizes: prizes, days: 30, color: 'RED', main_title: 'Signert klubbdrakt', main_value: '290' } ); updateWinChance(); saveStateToStorage(); } // ⚠️ TEST ONLY — REMOVE BEFORE PROD — END function bind () { const stored = loadStateFromStorage(); if ( stored ) { applyStateToForm( stored ); } else { setPrizes( [] ); } setStep( 1 ); // ⚠️ TEST ONLY — REMOVE BEFORE PROD — START var titleEl = qs( '.title' ); if ( titleEl ) titleEl.addEventListener( 'dblclick' , fillWithTestData ); // ⚠️ TEST ONLY — REMOVE BEFORE PROD — END bindAutoSave(); renderSuggestions(); updateWinChance(); qsa( '[data-next]' ).forEach( function ( btn ) { btn.addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); const next = parseInt( btn.getAttribute( 'data-next' ) || '1' , 10 ) || 1; if ( next === 2 && !validateStep1() ) return; if ( next === 3 && !validateStep2() ) return; if ( next === 4 && !validateStep3() ) return; setStep( next ); } , { passive: false } ); } ); qsa( '[data-prev]' ).forEach( function ( btn ) { btn.addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); const prev = parseInt( btn.getAttribute( 'data-prev' ) || '1' , 10 ) || 1; setStep( prev ); } , { passive: false } ); } ); qsa( '.step_btn' ).forEach( function ( btn ) { btn.addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); const target = parseInt( btn.getAttribute( 'data-step' ) || '1' , 10 ) || 1; if ( target === 2 && !validateStep1() ) return; if ( target === 3 && ( !validateStep1() || !validateStep2() ) ) return; if ( target === 4 && ( !validateStep1() || !validateStep2() || !validateStep3() ) ) return; setStep( target ); } , { passive: false } ); } ); byId( 'btn_add_prize' ).addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); openModal(); } , { passive: false } ); byId( 'btn_modal_cancel' ).addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); closeModal(); } , { passive: false } ); byId( 'btn_modal_add' ).addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); addPrizeFromModal(); } , { passive: false } ); byId( 'modal_backdrop' ).addEventListener( 'pointerdown' , function ( e ) { e.preventDefault(); closeModal(); } , { passive: false } ); byId( 'org_phone' ).addEventListener( 'input' , function () { byId( 'org_phone' ).value = onlyDigits( byId( 'org_phone' ).value ); saveStateToStorage(); } ); if ( byId( 'org_account' ) ) { byId( 'org_account' ).addEventListener( 'input' , function () { byId( 'org_account' ).value = onlyDigits( byId( 'org_account' ).value ); saveStateToStorage(); } ); } byId( 'lottery_tickets' ).addEventListener( 'input' , function () { byId( 'lottery_tickets' ).value = onlyDigits( byId( 'lottery_tickets' ).value ); updateWinChance(); saveStateToStorage(); } ); setupDropzone( { input:'lottery_logo', drop:'logo_drop', preview:'logo_preview', placeholder:'logo_placeholder', clear:'logo_clear', note:'logo_note' } ); setupDropzone( { input:'main_prize_image', drop:'mainimg_drop', preview:'mainimg_preview', placeholder:'mainimg_placeholder', clear:'mainimg_clear' } ); if ( byId( 'main_title' ) ) { byId( 'main_title' ).addEventListener( 'input' , updateWinChance ); } byId( 'campaign_form' ).addEventListener( 'submit' , function ( e ) { e.preventDefault(); renderPreview(); if ( byId( 'payload_json' ) ) byId( 'payload_json' ).value = JSON.stringify( readState() ); saveStateToStorage(); sendFinalStateToEndpoint(); } ); } if ( document.readyState === 'loading' ) { document.addEventListener( 'DOMContentLoaded' , bind ); } else { bind(); } })();