Files
kalendar/frontend/index.html
2026-10-07 21:14:56 +02:00

16 lines
3.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Kalender MVP</title><style>
:root{font:16px system-ui,sans-serif;color:#202423;background:#f3f4f1}*{box-sizing:border-box}body{margin:0;padding:32px 16px}.wrap{max-width:900px;margin:auto}.card{background:white;border:1px solid #dfe2dd;border-radius:14px;padding:22px;margin:16px 0;box-shadow:0 5px 20px #18251c0b}header,.row{display:flex;align-items:center;justify-content:space-between;gap:12px}h1{font-size:26px;margin:0}h2{font-size:18px;margin:0 0 16px}button,input,textarea{font:inherit}button{background:#315f47;color:#fff;border:0;border-radius:8px;padding:9px 14px;cursor:pointer}button.secondary{background:#e9ece8;color:#202423}form{display:grid;grid-template-columns:1fr 1fr;gap:12px}label{display:grid;gap:5px;font-size:14px}input,textarea{width:100%;padding:9px;border:1px solid #cbd1ca;border-radius:7px}textarea{grid-column:1/-1;min-height:70px}.wide{grid-column:1/-1}.event{padding:12px 0;border-top:1px solid #eceeeb}.muted{color:#68716a;font-size:14px}.empty{padding:18px 0;color:#68716a}@media(max-width:600px){form{grid-template-columns:1fr}.wide,textarea{grid-column:auto}body{padding:18px 10px}}
</style></head><body><main class="wrap">
<header><h1>Mein Kalender</h1><div class="row"><button class="secondary" id="prev">‹</button><strong id="month"></strong><button class="secondary" id="next">›</button></div></header>
<section class="card"><h2>Termin anlegen</h2><form id="form"><label>Titel<input name="title" required maxlength="120" placeholder="z. B. Teammeeting"></label><label>Datum<input name="date" type="date" required></label><label class="wide">Notiz<textarea name="notes" maxlength="1000" placeholder="Optional"></textarea></label><button class="wide">Termin speichern</button></form></section>
<section class="card"><h2>Termine im Monat</h2><div id="events" class="muted">Lade Termine …</div></section>
</main><script>
const base=location.pathname.replace(/\/$/,'');let cursor=new Date();const monthEl=document.querySelector('#month'),eventsEl=document.querySelector('#events');
const pad=n=>String(n).padStart(2,'0');const monthKey=d=>String(d.getFullYear())+'-'+pad(d.getMonth()+1);
function api(path,options){return fetch(base+'/api'+path,options||{headers:{'content-type':'application/json'}})}
async function refresh(){monthEl.textContent=new Intl.DateTimeFormat('de-DE',{month:'long',year:'numeric'}).format(cursor);const r=await api('/events?month='+monthKey(cursor));if(!r.ok){eventsEl.textContent='Termine konnten nicht geladen werden.';return}const data=await r.json();eventsEl.replaceChildren();if(!data.events.length){eventsEl.textContent='Noch keine Termine in diesem Monat.';eventsEl.className='empty';return}eventsEl.className='';for(const e of data.events){const item=document.createElement('article');item.className='event';const title=document.createElement('strong');title.textContent=e.title;const date=document.createElement('div');date.className='muted';date.textContent=new Intl.DateTimeFormat('de-DE',{dateStyle:'full'}).format(new Date(e.event_date+'T12:00:00'));item.append(title,date);if(e.notes){const note=document.createElement('p');note.textContent=e.notes;item.append(note)}eventsEl.append(item)}}
document.querySelector('#prev').onclick=()=>{cursor.setMonth(cursor.getMonth()-1);refresh()};document.querySelector('#next').onclick=()=>{cursor.setMonth(cursor.getMonth()+1);refresh()};document.querySelector('#form').onsubmit=async e=>{e.preventDefault();const f=new FormData(e.currentTarget);const saved=await api('/events',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({title:f.get('title'),event_date:f.get('date'),notes:f.get('notes')})});if(!saved.ok){alert('Speichern fehlgeschlagen.');return}e.currentTarget.reset();refresh()};refresh();
</script></body></html>