diff --git a/public/app.js b/public/app.js new file mode 100644 index 0000000..6c90a48 --- /dev/null +++ b/public/app.js @@ -0,0 +1,295 @@ +const C24 = u => u; // check24 proxy urls already absolute +const REG = { + kroatien:{flag:'đŸ‡­đŸ‡·',name:'Kroatien',color:'var(--kro)',mk:'#e8643c'}, + kanaren:{flag:'🇼🇹',name:'Kanaren',color:'var(--kan)',mk:'#f1a23b'}, + madeira:{flag:'đŸ‡”đŸ‡č',name:'Madeira',color:'var(--mad)',mk:'#19a37a'}, + kreuzfahrt:{flag:'🚱',name:'AIDA-Kreuzfahrt',color:'var(--cruise)',mk:'#2f7fd6'} +}; + +const OPTIONS = [ + {id:'amadria',name:'Amadria Park Hotel Jakov',region:'kroatien',loc:'Ć ibenik · Norddalmatien',stars:4, + rate:'8,4',rlabel:'Sehr gut',bew:12,price:'ab 3.125 €',fav:true,geo:[43.698492,15.889556], + url:'https://urlaub.check24.de/suche/angebot?countryId=60&hotelId=12950&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Direkte Strandlage','Familienresort','Flughafen Split 37 km'], + why:[['ok','Krka-Nationalpark ~30 Min'],['ok','Kornati-Inseln per Boot ab Resort'],['ok','Shopping Split ~1 h / Ć ibenik 6 km'],['ok','Sehr kinderfreundlich']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy8zNDAwMDAwMC8zMzYzMDAwMC8zMzYyNTkwMC8zMzYyNTg1OC9iM2EyNzQxY193LmpwZw==!07717e/picture.jpg', + 'https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9ob3RlbGltYWdlcy5zdW5ob3RlbHMubmV0L0hvdGVsSW5mby9ob3RlbEltYWdlLmFzcHg-aWQ9MTYxODE3MjUmZnVsbD0x!cc720d/picture.jpg']}, + + {id:'valamar',name:'Valamar Meteor Hotel',region:'kroatien',loc:'Makarska · Mitteldalmatien',stars:4, + rate:'8,4',rlabel:'Sehr gut',bew:128,price:'ab 3.531 €',fav:false,geo:[43.29907,17.014845], + url:'https://urlaub.check24.de/suche/angebot?countryId=60&hotelId=4619&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Top Hotel Award','Direkte Strandlage','Flughafen Split 64 km'], + why:[['ok','Top bewertet, Strand + Promenade'],['ok','InselfĂ€hren Brač/Hvar via Split'],['no','Krka ~1h45, Plitvice 3h+'],['ok','Familientauglich']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cDovL3Bob3Rvcy5ob3RlbGJlZHMuY29tL2dpYXRhL29yaWdpbmFsLzI1LzI1MzUxOS8yNTM1MTlhX2hiX3NfMDA1LmpwZw==!a9bbf6/picture.jpg', + 'https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy84MDAwMDAwLzc3MDAwMDAvNzY5NzYwMC83Njk3NTMxLzhkMDY0YTM3X3cuanBn!7c92d2/picture.jpg', + 'https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cDovL21lZGlhLmRldi5wYXhpbXVtLmNvbS9ob3RlbGltYWdlcy8yNzA0MTgvNDcuanBn!8c2535/picture.jpg']}, + + {id:'bluesun',name:'Bluesun Hotel Berulia',region:'kroatien',loc:'Brela · Mitteldalmatien',stars:4, + rate:'8,4',rlabel:'Sehr gut',bew:13,price:'ab 4.706 €',fav:false,geo:[43.362448,16.938868], + url:'https://urlaub.check24.de/suche/angebot?countryId=60&hotelId=1739068&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Direkte Strandlage','Traumstrand Brela','Flughafen Split 55 km'], + why:[['ok','Einer der schönsten StrĂ€nde Kroatiens'],['no','Krka ~1h30–2h, Plitvice zu weit'],['ok','Inseln via Split'],['no','Teuerste Hotel-Option']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy8zMDAwMDAwLzI4MjAwMDAvMjgxNDUwMC8yODE0NDA5LzZjYjI4NzAwX3cuanBn!774551/picture.jpg']}, + + {id:'morenia',name:'Morenia Beach Resort',region:'kroatien',loc:'Podaca · Mitteldalmatien',stars:4, + rate:'7,8',rlabel:'Gut',bew:48,price:'ab 3.527 €',fav:false,geo:[43.130196,17.286675], + url:'https://urlaub.check24.de/suche/angebot?hotelId=1859719&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Direkte Strandlage','Familie & Strand','Flughafen Split 92 km'], + why:[['ok','Ruhige Bucht, familienorientiert'],['no','Weit von Split & Nationalparks'],['no','LĂ€ngster Flughafentransfer'],['ok','Solide Preis-Leistung']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9hcGktaW1nLmhvdGVsc3Rvbi5jb20vcmVzb3VyY2UvaG90ZWwvaW1hZ2VzLzcvMy84LzMvNy8yLzYvMy8xMDMxMzQzNTY0LmpwZw==!9db0ac/picture.jpg']}, + + {id:'tui',name:'TUI KIDS CLUB Taurito Princess',region:'kanaren',loc:'Taurito · Gran Canaria',stars:4, + rate:'8,0',rlabel:'Sehr gut',bew:400,price:'Preis auf Check24',fav:true,geo:[27.815366,-15.754307], + url:'https://urlaub.check24.de/suche/angebot?hotelId=3265&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Echter Kinderclub','Sommer mild ~26°C','Flughafen LPA 38 km'], + why:[['ok','Top fĂŒr Felix (Betreuung & Animation)'],['ok','400 Bewertungen, sehr beliebt'],['no','Keine Kroatien-WĂŒnsche (Insel/NP)'],['ok','DĂŒnen & Berge fĂŒr AusflĂŒge']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy85MDAwMDAwLzgxNjAwMDAvODE1ODAwMC84MTU3OTc5LzRjNjE3OTlkX3cuanBn!55230f/picture.jpg', + 'https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cDovL21lZGlhLmRldi5wYXhpbXVtLmNvbS9ob3RlbGltYWdlcy8yMjY0NTYvZDFhYzA3MGQ0OTg1Zjg3ZmI4YjM5OTA2MzAxNTMzZGQuanBn!c32a55/picture.jpg']}, + + {id:'iberostar',name:'Iberostar Waves Bouganville Playa',region:'kanaren',loc:'Playa de las AmĂ©ricas · Teneriffa',stars:4, + rate:'8,4',rlabel:'Sehr gut',bew:103,price:'Preis auf Check24',fav:false,geo:[28.074417,-16.732332], + url:'https://urlaub.check24.de/suche/angebot?hotelId=2134&extendedSearch=1&airport=HAM,HAJ&transportType=flight&days=1w&departureDate=2026-07-11&returnDate=2026-07-21&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Am Meer','Sehr kurzer Transfer','Flughafen TFS 16 km'], + why:[['ok','Nur 16 km vom Flughafen'],['ok','Teide-Nationalpark als Ausflug'],['no','Keine Boots-/Inselkultur wie HR'],['ok','Gut bewertet']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cDovL3Bob3Rvcy5ob3RlbGJlZHMuY29tL2dpYXRhL29yaWdpbmFsLzAwLzAwMTEzNi8wMDExMzZhX2hiX3RfMDExLmpwZw==!e1aee2/picture.jpg']}, + + {id:'riu',name:'Hotel Riu Madeira',region:'madeira',loc:'Caniço de Baixo · Madeira',stars:4, + rate:'8,4',rlabel:'Sehr gut',bew:752,price:'Preis auf Check24',fav:false,geo:[32.645679,-16.826868], + url:'https://urlaub.check24.de/suche/angebot?countryId=88&hotelId=8761&extendedSearch=1&airport=HAM,HAJ,BRE,RLG,LBC,GWT&transportType=flight&days=1w&departureDate=2026-07-12&returnDate=2026-07-22&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Strand ~400 m','752 Bewertungen','Wander-Insel'], + why:[['ok','Sehr viele gute Bewertungen'],['no','Madeira = Wandern, kaum Sandstrand'],['no','Kein klassischer Badeurlaub fĂŒr Felix'],['ok','Mild, grĂŒn, schöne Natur']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy81MDAwMDAwLzQ4MjAwMDAvNDgxMzQwMC80ODEzMzUxL2Y4ZjNkYTE3X3cuanBn!cb047b/picture.jpg', + 'https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cDovL3Bob3Rvcy5ob3RlbGJlZHMuY29tL2dpYXRhL29yaWdpbmFsLzAwLzAwNTUyOS8wMDU1MjlhX2hiX2FfMDIzLmpwZw==!406b07/picture.jpg']}, + + {id:'dreams',name:'Dreams Madeira Resort, Spa & Marina',region:'madeira',loc:'Caniçal · Madeira',stars:5, + rate:'8,4',rlabel:'Sehr gut',bew:111,price:'Preis auf Check24',fav:false,geo:[32.742452,-16.709186], + url:'https://urlaub.check24.de/suche/angebot?countryId=88&hotelId=30324&extendedSearch=1&airport=HAM,HAJ,BRE,RLG,LBC,GWT&transportType=flight&days=1w&departureDate=2026-07-12&returnDate=2026-07-22&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['5 Sterne','Direkte Strandlage','Marina & Spa'], + why:[['ok','Hochwertiges 5★-Resort'],['no','Ruhiger Osten – eher Ruhe/Paar'],['no','Madeira kein Bade-Klassiker'],['ok','Schön fĂŒr Astrid']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy83MDAwMDAwLzYxNTAwMDAvNjE0MTgwMC82MTQxNzIzLzI5YmZiMjE0X3cuanBn!da02c7/picture.jpg']}, + + {id:'sentido',name:'Sentido Galosol',region:'madeira',loc:'Caniço de Baixo · Madeira',stars:4, + rate:null,rlabel:null,bew:216,price:'Preis auf Check24',fav:false,geo:[32.642268,-16.831963], + url:'https://urlaub.check24.de/suche/angebot?countryId=88&hotelId=2205&extendedSearch=1&airport=HAM,HAJ,BRE,RLG,LBC,GWT&transportType=flight&days=1w&departureDate=2026-07-12&returnDate=2026-07-22&roomAllocation=A-A-5&directFlight=1&hotelCategoryList=4,5&noRedirect=1', + chips:['Top Lage','216 Bewertungen','Meerblick'], + why:[['ok','Beliebte Lage, Klippenbad'],['no','Kein Sandstrand'],['no','Eher ruhig, nicht kinderfokussiert'],['ok','Gutes Preisniveau']], + imgs:['https://cdn1.urlaub.check24.de/size=625c440/di=3/nfc=200/source=aHR0cHM6Ly9pLnRyYXZlbGFwaS5jb20vbG9kZ2luZy8xMDAwMDAwLzkzMDAwMC85MjI0MDAvOTIyMzE5Lzg3YjE3ODc3X3ouanBn!d36a31/picture.jpg']}, + + {id:'aida',name:'AIDA Cosma · Mediterrane SchĂ€tze mit Korsika',region:'kreuzfahrt',loc:'ab/bis Mallorca · 7 NĂ€chte · 11.–18.07.',stars:0, + rate:'4,8',rlabel:'Ahoi',bew:null,price:'ab 6.477 €',fav:true,geo:[39.5696,2.6502], + url:'https://www.ahoi-schiff.de/aida/routen/mediterrane-schaetze-mit-korsika-ab-mallorca/aidacosma-2026-07-11?paxe=2', + url2:'https://aida.de/buchen/CO07260711/CLASSIC/meine-reise/anreise', + chips:['4 Pers., 2 Balkonkabinen','inkl. Flug & Vollpension','La Spezia · Rom · Korsika · Barcelona'], + why:[['ok','Null Selbstfahren – ideal fĂŒr Astrid'],['ok','Fixer Komplettpreis, Vollpension'],['ok','Jeden Tag ein neues Ziel'],['no','Mit Felix (3) straffer Rhythmus']], + imgs:['https://files.ahoi-schiff.de/aida-cruises/s/aidacosma.webp']} +]; + +// AIDA route ports (for map polyline) +const ROUTE = [ + {n:'Palma de Mallorca',c:[39.5696,2.6502]}, + {n:'La Spezia / Florenz',c:[44.1025,9.8200]}, + {n:'Rom / Civitavecchia',c:[42.0930,11.7896]}, + {n:'Ajaccio (Korsika)',c:[41.9192,8.7386]}, + {n:'Barcelona',c:[41.3568,2.1597]}, + {n:'Palma de Mallorca',c:[39.5696,2.6502]} +]; + +const RECOS = [ + {rank:'Empfehlung 1 · Rundum-Kroatien',opt:'amadria', + text:'ErfĂŒllt alle WĂŒnsche auf einmal: Krka-Nationalpark in ~30 Min, Kornati-Inseln per Boot, Shopping in Split – und ein großes, kinderfreundliches Strand-Resort. KĂŒrzeste Wege, grĂ¶ĂŸtes „fĂŒr alle was dabei".', + price:'ab ~5.400 €', + lines:[['Pauschal (Flug HAM/HAJ + Hotel)','~4.700 €*'],['Mietwagen Kombi/SUV (10 T)','~650 €'],['Nationalparks/Inseln','Krka, Kornati, Plitvice']], + foot:'*fĂŒr 4 Pers. hochgerechnet – auf Check24 mit eurer Belegung prĂŒfen.'}, + {rank:'Empfehlung 2 · Entspannt ohne Fahren',opt:'aida', + text:'AIDA Cosma ab Mallorca: Florenz, Rom, Korsika und Barcelona – ohne Koffer-Schleppen und ohne Mietwagen. Fixer All-in-Preis mit Vollpension, perfekt wenn Astrid mitkommt. Mit Felix etwas straffer Tagesrhythmus.', + price:'~6.480 €', + lines:[['4 Pers., 2 Balkonkabinen','inkl. Flug'],['Vollpension an Bord','inkl.'],['Mietwagen','nicht nötig (0 €)']], + foot:'LIGHT/CLASSIC ab Hannover 6.477 € / ab HH 6.487–6.677 €. LandausflĂŒge optional extra.'}, + {rank:'Empfehlung 3 · Stressfrei mit Kind',opt:'tui', + text:'TUI KIDS CLUB auf Gran Canaria: der entspannteste Familienurlaub – echter Kinderclub fĂŒr Felix, mildes Sommerklima, kurzer Transfer. Ohne die Kroatien-WĂŒnsche (Nationalpark/Insel), dafĂŒr maximal unkompliziert.', + price:'~4.500–5.500 €', + lines:[['Pauschal (Flug + Hotel)','auf Check24 prĂŒfen'],['Kinderclub fĂŒr Felix','inkl.'],['Mietwagen optional','~500 € / 10 T']], + foot:'Preis grob fĂŒr 4 Pers. – Gran Canaria & Teneriffa beide in der Auswahl unten.'} +]; + +const byId = id => OPTIONS.find(o=>o.id===id); +const VOTER_LABEL = {till:'Till',lea:'Lea',astrid:'Astrid'}; +let me_ = localStorage.getItem('voter') || null; +let STATE = {votes:{}}; + +/* ---------- hero ---------- */ +document.getElementById('herobg').style.backgroundImage = + "url('"+byId('bluesun').imgs[0]+"')"; + +/* ---------- voter selector ---------- */ +const whoEl = document.getElementById('who'); +function renderWho(){ + whoEl.innerHTML=''; + ['till','lea','astrid'].forEach(v=>{ + const b=document.createElement('button'); + b.className=(me_===v?'on '+v:''); + b.innerHTML=`${VOTER_LABEL[v]}`; + b.onclick=()=>{me_=v;localStorage.setItem('voter',v);renderWho();renderAll();}; + whoEl.appendChild(b); + }); +} + +/* ---------- recommendations ---------- */ +function renderRecos(){ + const el=document.getElementById('recos');el.innerHTML=''; + RECOS.forEach(r=>{ + const o=byId(r.opt); + const links=`${o.region==='kreuzfahrt'?'Ahoi-Schiff →':'Check24 →'}` + + (o.url2?`AIDA.de →`:'') + + `Details ↓`; + const d=document.createElement('div');d.className='reco'; + d.innerHTML=`
${r.rank}

${o.name.replace(' · Mediterrane SchÀtze mit Korsika','')}

📍 ${o.loc}
+
+

${r.text}

+
${r.price}
+ ${r.lines.map(l=>`
${l[0]}${l[1]}
`).join('')} +
+
${r.foot}
+ +
`; + el.appendChild(d); + }); +} + +/* ---------- regions + cards ---------- */ +function avgFor(id){ + let sum=0,n=0,per={}; + for(const v of ['till','lea','astrid']){ + const s=STATE.votes[v]&&STATE.votes[v][id]; + if(s){sum+=s;n++;per[v]=s;} + } + return {avg:n?sum/n:0,n,per}; +} +function cardHTML(o){ + const imgs=o.imgs.map((s,i)=>`${o.name}`).join(''); + const dots=o.imgs.length>1?`
${o.imgs.map((_,i)=>``).join('')}
`:''; + const nav=o.imgs.length>1?'':''; + const rate=o.rate?`${o.rate} ${o.rlabel}${o.bew?(' · '+o.bew+' Bew.'):''}`:(o.bew?`${o.bew} Bewertungen`:''); + const linkLabel=o.region==='kreuzfahrt'?'Ahoi-Schiff →':'Auf Check24 →'; + const link2=o.url2?`AIDA.de`:''; + return `
+
${imgs}${REG[o.region].name}${o.fav?'★ Empfehlung':''}${nav}${dots}
+
+

${o.name}

+
📍 ${o.loc} · ${'★'.repeat(o.stars)||'🚱'}
+
${rate}
+
${o.chips.map(c=>`${c}`).join('')}
+
${o.why.map(w=>`
${w[0]==='ok'?'✓':'✕'} ${w[1]}
`).join('')}
+
${o.price.startsWith('ab')||o.price.startsWith('~')?o.price:(''+o.price+'')} + ${link2}${linkLabel}
+
+
+
`; +} +function renderRegions(){ + const host=document.getElementById('regions');host.innerHTML=''; + ['kroatien','kanaren','madeira','kreuzfahrt'].forEach(rk=>{ + const items=OPTIONS.filter(o=>o.region===rk); + if(!items.length)return; + const sec=document.createElement('section'); + sec.innerHTML=`
${REG[rk].flag}

${REG[rk].name}

${items.length} ${items.length>1?'Optionen':'Option'}
+
${items.map(cardHTML).join('')}
`; + host.appendChild(sec); + }); + // carousels + document.querySelectorAll('.ph').forEach(ph=>{ + const ims=ph.querySelectorAll('img');if(ims.length<2)return; + const dts=ph.querySelectorAll('.dot');let i=0; + const go=d=>{ims[i].classList.remove('on');dts[i]&&dts[i].classList.remove('on'); + i=(i+d+ims.length)%ims.length;ims[i].classList.add('on');dts[i]&&dts[i].classList.add('on');}; + const l=ph.querySelector('.nav.l'),r=ph.querySelector('.nav.r'); + if(l)l.onclick=()=>go(-1);if(r)r.onclick=()=>go(1); + }); + renderVotes(); +} + +/* ---------- voting widgets ---------- */ +function renderVotes(){ + document.querySelectorAll('.vote').forEach(box=>{ + const id=box.dataset.opt;const {avg,n,per}=avgFor(id); + const mine=me_&&STATE.votes[me_]&&STATE.votes[me_][id]||0; + let stars=''; + for(let s=1;s<=5;s++) stars+=`★`; + const minis=['till','lea','astrid'].map(v=>{ + const sv=per[v]; + return `${VOTER_LABEL[v][0]}${sv?`${sv}`:''}`; + }).join(''); + box.innerHTML=`
${me_?('Deine Bewertung als '+VOTER_LABEL[me_]+':'):'WĂ€hle oben, wer du bist, dann bewerten:'}
+
${stars}
+
Schnitt: ${avg?avg.toFixed(1):'–'}${n?` (${n}/3)`:''}${minis}
`; + box.querySelectorAll('.starpick .s').forEach(st=>{ + st.onclick=()=>{const val=+st.dataset.s;const cur=mine;sendVote(id, val===cur?0:val);}; + }); + }); + renderRanking(); +} + +/* ---------- ranking ---------- */ +function renderRanking(){ + const arr=OPTIONS.map(o=>({o,...avgFor(o.id)})).filter(x=>x.n>0).sort((a,b)=>b.avg-a.avg||b.n-a.n); + const el=document.getElementById('ranklist'); + if(!arr.length){el.innerHTML='
Noch keine Bewertungen – sobald Till, Lea oder Astrid Sterne vergeben, erscheint hier das Ranking.
';return;} + el.innerHTML=arr.map((x,idx)=>`
+
${idx===0?'đŸ„‡':idx===1?'đŸ„ˆ':idx===2?'đŸ„‰':(idx+1)}
+
${x.o.name.replace(' · Mediterrane SchÀtze mit Korsika','')}${x.o.loc}
+
+
${x.avg.toFixed(1)} ★ · ${x.n}/3
+
`).join(''); +} + +/* ---------- server sync ---------- */ +async function loadState(){ + try{const r=await fetch('/api/state');STATE=await r.json();}catch(e){STATE={votes:{}};} + renderVotes(); +} +async function sendVote(option,stars){ + if(!me_)return; + // optimistic + STATE.votes[me_]=STATE.votes[me_]||{}; + if(stars===0)delete STATE.votes[me_][option];else STATE.votes[me_][option]=stars; + renderVotes();flashSaved(); + try{const r=await fetch('/api/vote',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({voter:me_,option,stars})});STATE=await r.json();renderVotes();}catch(e){} +} +function flashSaved(){const s=document.getElementById('saved');s.classList.add('on');setTimeout(()=>s.classList.remove('on'),1400);} +document.getElementById('resetBtn').onclick=async()=>{ + if(!confirm('Wirklich ALLE Bewertungen von Till, Lea und Astrid zurĂŒcksetzen?'))return; + try{const r=await fetch('/api/reset',{method:'POST'});STATE=await r.json();renderVotes();flashSaved();}catch(e){} +}; + +function renderAll(){renderWho();renderRecos();renderRegions();} + +/* ---------- map ---------- */ +function initMap(){ + const map=L.map('map',{scrollWheelZoom:false}).setView([41,6],5); + L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', + {attribution:'© OpenStreetMap, © CARTO',maxZoom:19}).addTo(map); + const pts=[]; + // cruise route line + L.polyline(ROUTE.map(r=>r.c),{color:'#2f7fd6',weight:3,opacity:.75,dashArray:'6 6'}).addTo(map); + ROUTE.slice(0,5).forEach(r=>{ + L.circleMarker(r.c,{radius:4,color:'#2f7fd6',fillColor:'#2f7fd6',fillOpacity:.9,weight:1}) + .addTo(map).bindTooltip(r.n,{direction:'top'}); + pts.push(r.c); + }); + OPTIONS.forEach(o=>{ + const col=REG[o.region].mk; + const icon=L.divIcon({className:'',html:`
`,iconSize:[20,20],iconAnchor:[10,10]}); + const m=L.marker(o.geo,{icon}).addTo(map); + const lbl=o.region==='kreuzfahrt'?'Zur Route →':'Zum Angebot →'; + m.bindPopup(`
${o.name}
${o.loc}
${o.rate?('⭐ '+o.rate+' '+o.rlabel+'
'):''}${lbl}
`); + pts.push(o.geo); + }); + map.fitBounds(pts,{padding:[35,35],maxZoom:6}); + setTimeout(()=>map.invalidateSize(),300); +} + +renderAll(); +initMap(); +loadState(); +setInterval(loadState, 12000); // live-ish sync between the three voters diff --git a/public/index.html b/public/index.html index 258fa23..658661a 100644 --- a/public/index.html +++ b/public/index.html @@ -237,301 +237,7 @@ Preise & VerfĂŒgbarkeit Ă€ndern sich laufend – bitte vor Buchung prĂŒfen. Erstellt fĂŒr Familie Heidrich. - - + +