From b0e7b684170677130c9546dc8723f4f34ddffba8 Mon Sep 17 00:00:00 2001 From: Ysabelle Moser Date: Sun, 22 Mar 2026 23:48:59 +0100 Subject: [PATCH] =?UTF-8?q?Erstellung=20CSS=20und=20JS=20File=20f=C3=BCr?= =?UTF-8?q?=20event-create=20inkl.=20=20Anpassung=20HTML=20von=20Event-cre?= =?UTF-8?q?ate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event-create.css | 450 ++++++++++++++++++++++++++++++++++++++++++++++ event-create.html | 327 ++++++++++++++++++++++++++++++++- event-create.js | 202 +++++++++++++++++++++ 3 files changed, 974 insertions(+), 5 deletions(-) create mode 100644 event-create.css create mode 100644 event-create.js diff --git a/event-create.css b/event-create.css new file mode 100644 index 0000000..a138e29 --- /dev/null +++ b/event-create.css @@ -0,0 +1,450 @@ +:root { + --color-bg: #f7f7f2; + --color-surface: #ffffff; + --color-text: #1f1f1f; + --color-muted: #6b6b6b; + --color-border: #d8d8d2; + --color-border-strong: #202020; + --color-primary: #222222; + --color-primary-hover: #111111; + --color-focus: #2f6fed; + --color-error: #b42318; + --shadow-soft: 0 10px 30px rgba(0, 0, 0, 0.06); + --radius-sm: 0.875rem; + --radius-md: 1.25rem; + --radius-lg: 999px; + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.5rem; + --space-6: 2rem; + --space-7: 3rem; + --space-8: 4rem; + --max-width: 1120px; + --header-height: 4.5rem; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-size: 100%; +} + +body { + margin: 0; + font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + background: var(--color-bg); + color: var(--color-text); + line-height: 1.5; +} + +a, +button, +input, +textarea { + font: inherit; +} + +a { + color: inherit; + text-decoration: none; +} + +.site-header { + background: var(--color-bg); + border-top: 2px solid #232323; + border-bottom: 1px solid var(--color-border); +} + +.site-nav { + width: min(100% - 2rem, var(--max-width)); + margin: 0 auto; + min-height: var(--header-height); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-4); +} + +.site-logo { + font-size: 2rem; + font-weight: 800; + letter-spacing: 0.02em; +} + +.site-nav-links { + display: flex; + align-items: center; + gap: var(--space-5); + margin: 0; + padding: 0; + list-style: none; +} + +.site-nav-links a { + font-weight: 500; +} + +.site-nav-links li:last-child a { + width: 2.25rem; + height: 2.25rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: #231f20; + color: #ffffff; + font-weight: 700; +} + +.event-create-page { + width: min(100% - 2rem, var(--max-width)); + margin: 0 auto; + padding: var(--space-5) 0 0; +} + +.event-flow-header { + display: flex; + justify-content: flex-end; + margin-bottom: var(--space-4); +} + +.event-form { + min-height: calc(100vh - var(--header-height) - 9rem); + display: flex; + flex-direction: column; +} + +.step { + display: none; + padding: var(--space-4) 0 var(--space-7); +} + +.step--active { + display: block; +} + +.step-layout { + width: min(100%, 760px); + margin: 0 auto; + display: grid; + gap: var(--space-6); +} + +.step-layout--intro { + min-height: 60vh; + align-content: center; + grid-template-columns: 1fr; +} + +.step-copy { + display: grid; + gap: var(--space-4); +} + +.step-kicker { + margin: 0; + font-weight: 700; + color: var(--color-muted); + letter-spacing: 0.02em; +} + +h1, +h2 { + margin: 0; + font-size: clamp(2rem, 4vw, 4rem); + line-height: 1.03; + letter-spacing: -0.03em; +} + +.step-text { + margin: 0; + max-width: 42rem; + color: #303030; + font-size: clamp(1rem, 1.4vw, 1.2rem); +} + +.intro-card { + max-width: 24rem; + padding: var(--space-6); + border: 1px solid var(--color-border); + border-radius: 1.75rem; + background: linear-gradient(135deg, #ffffff, #f0eee7); + box-shadow: var(--shadow-soft); +} + +.intro-card-emoji { + font-size: 2rem; + margin-bottom: var(--space-3); +} + +.step-fields { + display: grid; + gap: var(--space-5); +} + +.form-field, +fieldset { + margin: 0; + padding: 0; + border: 0; + display: grid; + gap: var(--space-3); +} + +label, +legend { + font-weight: 700; +} + +.field-hint { + margin: -0.25rem 0 0; + color: var(--color-muted); + font-size: 0.95rem; +} + +input[type="text"], +input[type="date"], +input[type="time"], +input[type="number"], +textarea { + width: 100%; + min-height: 3.5rem; + padding: 0.95rem 1rem; + border: 1px solid var(--color-border); + border-radius: 1rem; + background: var(--color-surface); + color: var(--color-text); +} + +textarea { + min-height: 9rem; + resize: vertical; +} + +.field-row { + display: grid; + gap: var(--space-4); +} + +.option-grid { + display: grid; + gap: var(--space-3); +} + +.option-card { + position: relative; + display: grid; + gap: 0.15rem; + min-height: 6rem; + padding: 1rem 1rem 1rem 1.05rem; + border: 1px solid var(--color-border); + border-radius: 1rem; + background: var(--color-surface); + transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; +} + +.option-card small { + color: var(--color-muted); +} + +.option-card:hover { + transform: translateY(-1px); + box-shadow: var(--shadow-soft); +} + +.option-card input { + position: absolute; + inset: 0; + opacity: 0; + cursor: pointer; +} + +.option-card:has(input:checked) { + border: 2px solid var(--color-border-strong); +} + +.counter { + display: inline-flex; + align-items: center; + gap: var(--space-3); +} + +.counter input { + width: 6rem; + text-align: center; +} + +.counter-button { + width: 3rem; + height: 3rem; + border: 1px solid var(--color-border); + border-radius: 50%; + background: var(--color-surface); + font-size: 1.5rem; +} + +.review-card { + padding: var(--space-5); + border: 1px solid var(--color-border); + border-radius: 1.5rem; + background: var(--color-surface); + box-shadow: var(--shadow-soft); +} + +.review-list { + display: grid; + gap: var(--space-4); + margin: 0; +} + +.review-item { + display: grid; + gap: var(--space-1); + padding-bottom: var(--space-4); + border-bottom: 1px solid #ecece7; +} + +.review-item:last-child { + border-bottom: 0; + padding-bottom: 0; +} + +.review-item dt { + font-weight: 700; +} + +.review-item dd { + margin: 0; + white-space: pre-wrap; + color: #303030; +} + +.flow-footer { + position: sticky; + bottom: 0; + z-index: 5; + margin-top: auto; + background: rgba(247, 247, 242, 0.96); + backdrop-filter: blur(8px); + padding-bottom: env(safe-area-inset-bottom); +} + +.progress { + width: 100%; + height: 0.375rem; + background: #ddddda; +} + +.progress-bar { + display: block; + width: 0; + height: 100%; + background: var(--color-primary); + transition: width 0.25s ease; +} + +.flow-actions { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-4); + padding: var(--space-4) 0; +} + +.flow-actions-right { + display: flex; + align-items: center; + gap: var(--space-4); +} + +.error-message { + min-height: 1.5rem; + margin: 0; + color: var(--color-error); + font-size: 0.95rem; +} + +.button { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 3rem; + padding: 0.9rem 1.35rem; + border-radius: var(--radius-lg); + border: 1px solid var(--color-border); + background: transparent; + color: var(--color-text); + cursor: pointer; +} + +.button--ghost:hover { + background: rgba(0, 0, 0, 0.03); +} + +.button--text { + border: 0; + padding-left: 0; +} + +.button--primary { + min-width: 10rem; + border-color: var(--color-primary); + background: var(--color-primary); + color: #ffffff; + font-weight: 700; +} + +.button--primary:hover { + background: var(--color-primary-hover); +} + +.button--primary:disabled { + opacity: 0.45; + cursor: not-allowed; +} + +.button--intro { + justify-self: start; + margin-top: var(--space-2); +} + +.site-footer { + width: min(100% - 2rem, var(--max-width)); + margin: 0 auto; + padding: var(--space-5) 0 var(--space-6); + color: var(--color-muted); + text-align: center; +} + +a:focus-visible, +button:focus-visible, +input:focus-visible, +textarea:focus-visible { + outline: 3px solid var(--color-focus); + outline-offset: 3px; +} + +@media (min-width: 768px) { + .step-layout--intro { + grid-template-columns: 1.25fr 0.8fr; + align-items: center; + } + + .field-row { + grid-template-columns: 1fr 1fr; + } + + .option-grid--3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .option-grid--4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} \ No newline at end of file diff --git a/event-create.html b/event-create.html index f6473ef..5190f9f 100644 --- a/event-create.html +++ b/event-create.html @@ -1,12 +1,329 @@ - - - Document - + + + Event erstellen | Invité + + - + + +
+
+ Abbrechen +
+ +
+
+
+
+

Event erstellen

+

Hey {{username}}, was hast du vor?

+

+ Erzähl uns von deiner Idee – vom Essen bis zur Stimmung. Ob Dinner, Brunch + oder etwas ganz Eigenes – wir helfen dir dabei, dein Event Schritt für Schritt aufzubauen. +

+ +
+ + +
+
+ +
+
+
+

Schritt 1

+

Was hast du vor?

+

+ Erzähl uns, was für ein Event du planst. Ist es ein gemütlicher Brunch, + ein Dinner mit Wow-Effekt oder einfach ein entspannter Abend mit gutem Essen? +

+
+ +
+
+ + +
+ +
+ Art des Essens + +
+ + + + + + + +
+
+
+
+
+ +
+
+
+

Schritt 2

+

Was kommt auf den Tisch?

+

+ Mach uns neugierig. Was kochst du – und wie fühlt sich dein Abend an? + Hier entsteht die Geschichte, auf die sich deine Gäste freuen. +

+
+ +
+
+ + +
+ +
+ + +
+
+
+
+ +
+
+
+

Schritt 3

+

Wen lädst du ein?

+

+ Wie viele Gäste passen zu deinem Event? Und gibt es etwas, das du bei + Ernährung oder Unverträglichkeiten beachten möchtest? +

+
+ +
+
+ Maximale Personenanzahl + +
+ + + +
+
+ +
+ Ernährungsform + +
+ + + + + +
+
+ +
+ Allergene / Unverträglichkeiten +

Optional – nur auswählen, wenn es für dein Event relevant ist.

+ +
+ + + + + +
+
+
+
+
+ +
+
+
+

Schritt 4

+

Wann findet dein Event statt?

+

+ Wähle Datum und Uhrzeit – und sag uns, wo dein Event stattfindet. + Keine Sorge: Die genaue Adresse sehen Gäste erst nach der Buchung. +

+
+ +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+
+
+
+ +
+
+
+

Schritt 5

+

Alles bereit für deine Gäste?

+

+ Schau dir dein Event nochmal in Ruhe an. Passt alles? + Dann kannst du es jetzt veröffentlichen und Gäste einladen. +

+
+ +
+
+
+
Eventtitel
+
+
+ +
+
Eventtyp
+
+
+ +
+
Menü
+
+
+ +
+
Event-Abend
+
+
+ +
+
Maximale Personenanzahl
+
+
+ +
+
Ernährungsform
+
+
+ +
+
Allergene / Unverträglichkeiten
+
Keine Angabe
+
+ +
+
Datum
+
+
+ +
+
Uhrzeit
+
+
+ +
+
Adresse
+
+
+ +
+
Ort
+
+
+
+
+
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/event-create.js b/event-create.js new file mode 100644 index 0000000..34d0847 --- /dev/null +++ b/event-create.js @@ -0,0 +1,202 @@ +const form = document.getElementById("eventForm"); +const steps = Array.from(document.querySelectorAll(".step")); +const backButton = document.getElementById("backButton"); +const nextButton = document.getElementById("nextButton"); +const progressBar = document.getElementById("progressBar"); +const errorMessage = document.getElementById("errorMessage"); +const usernameElement = document.getElementById("username"); + +let currentStep = 0; +const lastStep = steps.length - 1; + +const nextLabels = { + 0: "Weiter", + 1: "Weiter", + 2: "Weiter", + 3: "Weiter", + 4: "Weiter", + 5: "Event veröffentlichen" +}; + +// Demo-Platzhalter; später aus Nutzerprofil setzen +usernameElement.textContent = "Mia"; + +const flowFooter = document.getElementById("flowFooter"); + +function showStep(index) { + currentStep = index; + + steps.forEach((step, stepIndex) => { + step.classList.toggle("step--active", stepIndex === index); + }); + + const isIntroStep = index === 0; + + flowFooter.hidden = isIntroStep; + backButton.hidden = isIntroStep; + nextButton.textContent = nextLabels[index]; + errorMessage.textContent = ""; + + if (index === lastStep) { + updateReview(); + } + + function updateProgress(index) { + if (index === 0) { + progressBar.style.width = "0%"; + return; + } + + const totalSteps = lastStep; + const progress = ((index - 1) / (totalSteps - 1)) * 100; + + progressBar.style.width = `${progress}%`; +} + + window.scrollTo({ top: 0, behavior: "smooth" }); + + updateProgress(index); +} + +function stepFields(stepIndex) { + return Array.from(steps[stepIndex].querySelectorAll("input, textarea, select")); +} + +function validateCurrentStep() { + if (currentStep === 0 || currentStep === lastStep) { + return true; + } + + const fields = stepFields(currentStep); + + for (const field of fields) { + if (field.type === "radio") { + const group = Array.from(form.querySelectorAll(`input[name="${field.name}"]`)); + const isRequiredGroup = group.some((item) => item.required); + const hasSelection = group.some((item) => item.checked); + + if (isRequiredGroup && !hasSelection) { + errorMessage.textContent = "Bitte wähle eine Option aus, bevor du weitergehst."; + group[0].focus(); + return false; + } + + continue; + } + + if (field.type === "checkbox") { + continue; + } + + if (!field.checkValidity()) { + errorMessage.textContent = "Bitte fülle alle Pflichtfelder dieses Schritts aus."; + field.reportValidity(); + return false; + } + } + + errorMessage.textContent = ""; + return true; +} + +function getFieldValue(name) { + const field = form.elements[name]; + + if (!field) return "–"; + + if (field instanceof RadioNodeList) { + return field.value || "–"; + } + + return field.value.trim() || "–"; +} + +function getCheckboxValues(name) { + const checked = Array.from(form.querySelectorAll(`input[name="${name}"]:checked`)); + return checked.length ? checked.map((item) => item.value).join(", ") : "Keine Angabe"; +} + +function formatDate(value) { + if (!value || value === "–") return "–"; + + const date = new Date(value); + if (Number.isNaN(date.getTime())) return value; + + return new Intl.DateTimeFormat("de-CH", { + day: "2-digit", + month: "2-digit", + year: "numeric" + }).format(date); +} + +function updateReview() { + const values = { + eventTitle: getFieldValue("eventTitle"), + eventType: getFieldValue("eventType"), + menuDescription: getFieldValue("menuDescription"), + eventDescription: getFieldValue("eventDescription"), + maxGuests: getFieldValue("maxGuests"), + dietType: getFieldValue("dietType"), + allergies: getCheckboxValues("allergies"), + eventDate: formatDate(getFieldValue("eventDate")), + eventTime: getFieldValue("eventTime"), + eventAddress: getFieldValue("eventAddress"), + eventCity: getFieldValue("eventCity") + }; + + Object.entries(values).forEach(([key, value]) => { + const target = document.querySelector(`[data-review="${key}"]`); + if (target) { + target.textContent = value; + } + }); +} + +document.querySelectorAll("[data-start-flow]").forEach((button) => { + button.addEventListener("click", () => showStep(1)); +}); + +backButton.addEventListener("click", () => { + if (currentStep > 1) { + showStep(currentStep - 1); + } else { + showStep(0); + } +}); + +nextButton.addEventListener("click", () => { + if (!validateCurrentStep()) return; + + if (currentStep < lastStep) { + showStep(currentStep + 1); + return; + } + + form.requestSubmit(); +}); + +form.addEventListener("submit", (event) => { + event.preventDefault(); + alert("Dein Event wurde vorbereitet und würde jetzt veröffentlicht werden."); +}); + +document.querySelectorAll("[data-counter]").forEach((counter) => { + const input = counter.querySelector("input[type='number']"); + const decreaseButton = counter.querySelector("[data-counter-action='decrease']"); + const increaseButton = counter.querySelector("[data-counter-action='increase']"); + + decreaseButton.addEventListener("click", () => { + const min = Number(input.min || 1); + const currentValue = Number(input.value || min); + input.value = Math.max(min, currentValue - 1); + }); + + increaseButton.addEventListener("click", () => { + const currentValue = Number(input.value || 0); + input.value = currentValue + 1; + }); +}); + +showStep(0); + +