Einfügen Icons + Anpassung Styling Radio-Buttons und Foto-Buttons bei Eventerstellung
This commit is contained in:
parent
ee1c78f5de
commit
4bd4f8046d
@ -229,6 +229,24 @@ textarea:focus {
|
||||
transition: box-shadow 0.2s ease, transform 0.2s ease, background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.option-card--with-icon {
|
||||
justify-items: center;
|
||||
align-content: center;
|
||||
gap: var(--space-2);
|
||||
color: var(--brown);
|
||||
}
|
||||
|
||||
.option-card__icon {
|
||||
color: var(--brown);
|
||||
font-size: 1.35rem;
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.option-card--with-icon span {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
.option-card:hover {
|
||||
background: var(--olive-light);
|
||||
@ -236,6 +254,41 @@ textarea:focus {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.option-grid--tomato-choices .option-card:hover,
|
||||
.option-grid--tomato-choices .option-card:has(input:focus-visible) {
|
||||
border-color: var(--tomato);
|
||||
background: var(--tomato);
|
||||
color: var(--butter-light);
|
||||
}
|
||||
|
||||
.option-grid--tomato-choices .option-card:has(input:checked) {
|
||||
border-color: var(--tomato);
|
||||
background: var(--tomato);
|
||||
color: var(--butter-light);
|
||||
}
|
||||
|
||||
.option-grid--icon-choices .option-card--with-icon:hover .option-card__icon,
|
||||
.option-grid--icon-choices .option-card--with-icon:has(input:focus-visible) .option-card__icon,
|
||||
.option-grid--icon-choices .option-card--with-icon:has(input:checked) .option-card__icon {
|
||||
color: var(--butter-light);
|
||||
}
|
||||
|
||||
.option-grid--icon-choices .option-card--with-icon:has(input:disabled) {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.option-grid--icon-choices .option-card--with-icon:has(input:disabled):hover {
|
||||
border-color: var(--olive-light);
|
||||
background: var(--butter-light);
|
||||
color: var(--brown);
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.option-grid--icon-choices .option-card--with-icon:has(input:disabled):hover .option-card__icon {
|
||||
color: var(--brown);
|
||||
}
|
||||
|
||||
.option-card input {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
@ -253,14 +306,37 @@ textarea:focus {
|
||||
box-shadow: 0 0 0 2px rgba(212, 75, 36, 0.14);
|
||||
}
|
||||
|
||||
.guest-count-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
color: var(--brown);
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.guest-count-icon::before {
|
||||
display: block;
|
||||
transform: translateX(1.1rem);
|
||||
}
|
||||
|
||||
.counter {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-16);
|
||||
}
|
||||
|
||||
.counter input {
|
||||
.counter-value-group {
|
||||
display: grid;
|
||||
justify-items: stretch;
|
||||
row-gap: var(--space-1);
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.counter input {
|
||||
width: 100%;
|
||||
height: 3rem;
|
||||
padding-block: 0.75rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -327,6 +403,20 @@ textarea:focus {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.review-gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.review-gallery__thumb {
|
||||
width: 4.5rem;
|
||||
height: 4.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
object-fit: cover;
|
||||
box-shadow: var(--shadow-interaction);
|
||||
}
|
||||
|
||||
.submission-success-actions {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
@ -417,22 +507,58 @@ textarea:focus {
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
|
||||
/* Gallery Upload */
|
||||
.gallery-upload {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
gap: var(--space-16);
|
||||
}
|
||||
|
||||
.gallery-preview {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.gallery-add-button {
|
||||
width: 7rem;
|
||||
height: 7rem;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
align-content: center;
|
||||
gap: var(--space-1);
|
||||
padding: var(--space-1);
|
||||
border: 1.5px solid var(--olive-light);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--butter-light);
|
||||
color: var(--olive);
|
||||
font-family: var(--font-main);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.gallery-add-button__icon {
|
||||
color: var(--brown);
|
||||
font-size: 2rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.gallery-add-button__text {
|
||||
color: var(--black);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.15;
|
||||
text-align: center;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gallery-add-button:hover {
|
||||
background: var(--olive-light);
|
||||
box-shadow: var(--shadow-interaction);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.gallery-thumb {
|
||||
position: relative;
|
||||
width: 5.5rem;
|
||||
height: 5.5rem;
|
||||
width: 7rem;
|
||||
height: 7rem;
|
||||
border-radius: var(--radius-sm, 0.5rem);
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
|
||||
@ -80,24 +80,28 @@
|
||||
<fieldset class="form-field">
|
||||
<label>Art des Essens / Eventtyp</label>
|
||||
|
||||
<div class="option-grid option-grid--4">
|
||||
<label class="option-card option">
|
||||
<div class="option-grid option-grid--4 option-grid--event-type option-grid--icon-choices option-grid--tomato-choices">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="radio" name="eventType" value="Brunch" required />
|
||||
<i class="fa-solid fa-bread-slice option-card__icon" aria-hidden="true"></i>
|
||||
<span>Brunch</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="radio" name="eventType" value="Lunch" />
|
||||
<i class="fa-solid fa-pizza-slice option-card__icon" aria-hidden="true"></i>
|
||||
<span>Lunch</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="radio" name="eventType" value="Kaffee + Kuchen" />
|
||||
<i class="fa-solid fa-mug-hot option-card__icon" aria-hidden="true"></i>
|
||||
<span>Kaffee + Kuchen</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="radio" name="eventType" value="Dinner" />
|
||||
<i class="fa-solid fa-martini-glass option-card__icon" aria-hidden="true"></i>
|
||||
<span>Dinner</span>
|
||||
</label>
|
||||
</div>
|
||||
@ -115,15 +119,18 @@
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<div class="counter-value-group">
|
||||
<i class="fa-solid fa-user-group guest-count-icon" aria-hidden="true"></i>
|
||||
<input
|
||||
type="number"
|
||||
id="maxGuests"
|
||||
name="maxGuests"
|
||||
min="1"
|
||||
step="1"
|
||||
value="4"
|
||||
value="0"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="counter-button"
|
||||
@ -152,24 +159,28 @@
|
||||
<fieldset class="form-field">
|
||||
<label>Ernährungsform</label>
|
||||
|
||||
<div class="option-grid option-grid--4">
|
||||
<label class="option-card option">
|
||||
<div class="option-grid option-grid--4 option-grid--icon-choices option-grid--tomato-choices">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="checkbox" name="dietType" value="Fleisch" />
|
||||
<i class="fa-solid fa-drumstick-bite option-card__icon" aria-hidden="true"></i>
|
||||
<span>Fleisch</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="checkbox" name="dietType" value="Fisch" />
|
||||
<i class="fa-solid fa-fish option-card__icon" aria-hidden="true"></i>
|
||||
<span>Fisch</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="checkbox" name="dietType" value="Vegetarisch" />
|
||||
<i class="fa-solid fa-seedling option-card__icon" aria-hidden="true"></i>
|
||||
<span>Vegetarisch</span>
|
||||
</label>
|
||||
|
||||
<label class="option-card option">
|
||||
<label class="option-card option option-card--with-icon">
|
||||
<input type="checkbox" name="dietType" value="Vegan" />
|
||||
<i class="fa-solid fa-leaf option-card__icon" aria-hidden="true"></i>
|
||||
<span>Vegan</span>
|
||||
</label>
|
||||
</div>
|
||||
@ -198,7 +209,7 @@
|
||||
<label>Allergene / Unverträglichkeiten</label>
|
||||
<p class="field-hint">Optional – nur auswählen, wenn es für dein Event relevant ist.</p>
|
||||
|
||||
<div class="option-grid option-grid--3">
|
||||
<div class="option-grid option-grid--3 option-grid--tomato-choices">
|
||||
<label class="option-card option">
|
||||
<input type="checkbox" name="allergies" value="glutenfrei" />
|
||||
<span>Glutenfrei</span>
|
||||
@ -243,7 +254,7 @@
|
||||
|
||||
<div class="form-field">
|
||||
<label for="eventTime">Uhrzeit</label>
|
||||
<input type="time" id="eventTime" name="eventTime" value="00:00" required />
|
||||
<input type="time" id="eventTime" name="eventTime" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -297,10 +308,13 @@
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>Fotos hinzufügen <span class="field-hint-inline">(optional)</span></label>
|
||||
<label>Wie wird dein Event aussehen? <span class="field-hint-inline">(optional)</span></label>
|
||||
<div class="gallery-upload">
|
||||
<div class="gallery-preview" id="galleryPreview"></div>
|
||||
<button type="button" class="button-primary" id="galleryAddBtn" aria-label="Foto hinzufügen">Foto hinzufügen</button>
|
||||
<button type="button" class="gallery-add-button" id="galleryAddBtn" aria-label="Foto hinzufügen">
|
||||
<i class="fa-solid fa-plus gallery-add-button__icon" aria-hidden="true"></i>
|
||||
<span class="gallery-add-button__text">Foto<br>hinzufügen</span>
|
||||
</button>
|
||||
<input type="file" id="galleryFileInput" accept="image/*" multiple hidden />
|
||||
</div>
|
||||
</div>
|
||||
@ -375,6 +389,15 @@
|
||||
<dt>Event-Abend</dt>
|
||||
<dd data-review="eventDescription">–</dd>
|
||||
</div>
|
||||
|
||||
<div class="review-item" data-edit-step="6" data-edit-field="galleryAddBtn" role="button" tabindex="0" aria-label="Fotos bearbeiten">
|
||||
<dt>Fotos</dt>
|
||||
<dd>
|
||||
<div class="review-gallery" data-review-gallery>
|
||||
<span>Keine Fotos hinzugefügt</span>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -270,6 +270,29 @@ function updateReviewField(fieldName, value) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt hochgeladene Fotos als kleine Vorschaubilder in der Review.
|
||||
*/
|
||||
function updateReviewGallery() {
|
||||
const target = document.querySelector("[data-review-gallery]");
|
||||
if (!target) return;
|
||||
|
||||
target.innerHTML = "";
|
||||
|
||||
if (galleryImages.length === 0) {
|
||||
target.textContent = "Keine Fotos hinzugefügt";
|
||||
return;
|
||||
}
|
||||
|
||||
galleryImages.forEach((src, index) => {
|
||||
const image = document.createElement("img");
|
||||
image.className = "review-gallery__thumb";
|
||||
image.src = src;
|
||||
image.alt = `Foto ${index + 1}`;
|
||||
target.appendChild(image);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Baut den Text für Allergien / Hinweise zusammen.
|
||||
* Dabei werden Checkboxen und zusätzliches Freitextfeld kombiniert.
|
||||
@ -297,6 +320,8 @@ function updateReview() {
|
||||
Object.entries(reviewValues).forEach(([key, value]) => {
|
||||
updateReviewField(key, value);
|
||||
});
|
||||
|
||||
updateReviewGallery();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -539,6 +564,52 @@ function validateDietType() {
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Verhindert widersprüchliche Ernährungsformen:
|
||||
* Fleisch/Fisch dürfen zusammen, schliessen aber vegetarisch/vegan aus.
|
||||
*/
|
||||
function registerDietConflictHandlers() {
|
||||
const dietOptions = Array.from(form.querySelectorAll('input[name="dietType"]'));
|
||||
const meatFishOptions = dietOptions.filter(input => ["Fleisch", "Fisch"].includes(input.value));
|
||||
const plantOptions = dietOptions.filter(input => ["Vegetarisch", "Vegan"].includes(input.value));
|
||||
|
||||
const updateDietAvailability = changedInput => {
|
||||
if (changedInput?.checked && changedInput.value === "Vegetarisch") {
|
||||
dietOptions.forEach(input => {
|
||||
if (input.value === "Vegan") input.checked = false;
|
||||
});
|
||||
}
|
||||
|
||||
if (changedInput?.checked && changedInput.value === "Vegan") {
|
||||
dietOptions.forEach(input => {
|
||||
if (input.value === "Vegetarisch") input.checked = false;
|
||||
});
|
||||
}
|
||||
|
||||
const hasMeatOrFish = meatFishOptions.some(input => input.checked);
|
||||
const selectedPlantDiet = plantOptions.find(input => input.checked);
|
||||
|
||||
meatFishOptions.forEach(input => {
|
||||
input.disabled = Boolean(selectedPlantDiet);
|
||||
});
|
||||
|
||||
plantOptions.forEach(input => {
|
||||
input.disabled = hasMeatOrFish || Boolean(selectedPlantDiet && input !== selectedPlantDiet);
|
||||
});
|
||||
};
|
||||
|
||||
dietOptions.forEach(input => {
|
||||
input.addEventListener("change", () => {
|
||||
dietOptions.forEach(option => {
|
||||
option.closest(".option-card")?.classList.remove("option-card--invalid");
|
||||
});
|
||||
updateDietAvailability(input);
|
||||
});
|
||||
});
|
||||
|
||||
updateDietAvailability();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft alle Pflichtfelder ausser Radios und Checkboxen.
|
||||
* Rückgabe:
|
||||
@ -648,11 +719,17 @@ function registerCounterHandlers() {
|
||||
|
||||
/**
|
||||
* Erhöht oder verringert den Wert eines Zahlenfelds.
|
||||
* Der Wert darf dabei nie kleiner als das definierte Minimum werden.
|
||||
* 0 bleibt als bewusster Startwert erlaubt; gültig ist erst eine Auswahl ab min.
|
||||
*/
|
||||
function updateCounterValue(input, change) {
|
||||
const min = Number(input.min || 1);
|
||||
const currentValue = Number(input.value || min);
|
||||
const currentValue = Number(input.value || 0);
|
||||
|
||||
if (currentValue < min && change < 0) {
|
||||
input.value = currentValue;
|
||||
return;
|
||||
}
|
||||
|
||||
input.value = Math.max(min, currentValue + change);
|
||||
}
|
||||
|
||||
@ -765,7 +842,7 @@ function registerValidationFeedbackHandlers() {
|
||||
* Setzt den Fokus auf ein bestimmtes Feld oder die erste Option einer Radio-Gruppe.
|
||||
*/
|
||||
function focusFieldByName(fieldName) {
|
||||
const field = form.elements[fieldName];
|
||||
const field = form.elements[fieldName] || document.getElementById(fieldName);
|
||||
|
||||
if (!field) return;
|
||||
|
||||
@ -862,6 +939,7 @@ function initEventCreationFlow() {
|
||||
|
||||
// Counter aktivieren
|
||||
registerCounterHandlers();
|
||||
registerDietConflictHandlers();
|
||||
registerMenuBulletHandler();
|
||||
registerValidationFeedbackHandlers();
|
||||
registerReviewEditHandlers();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user