From b38f86ceb21883fe62001ccdeb1e7e70091de596 Mon Sep 17 00:00:00 2001 From: RedCat310 Date: Wed, 21 May 2025 18:58:04 +0200 Subject: [PATCH] final version --- src/App.css | 315 +++++++++++++++++++++++++++++++++++++++--------- src/App.js | 147 ---------------------- src/App.jsx | 214 ++++++++++++++++++++++++++++++++ src/firebase.js | 16 +++ src/logo.svg | 1 - 5 files changed, 486 insertions(+), 207 deletions(-) delete mode 100644 src/App.js create mode 100644 src/App.jsx create mode 100644 src/firebase.js delete mode 100644 src/logo.svg diff --git a/src/App.css b/src/App.css index bd44812..d44f106 100644 --- a/src/App.css +++ b/src/App.css @@ -71,19 +71,19 @@ body { } form { - background: rgba(0, 0, 0, 0.6); /* Halbtransparenter schwarzer Hintergrund */ - backdrop-filter: blur(10px); /* Blur-Effekt */ - padding: 25px; - border-radius: 12px; - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); - width: 70%; /* Noch breitere Box */ - margin: 25px auto; - margin-top: 200px; /* Abstand von der Oberseite */ + background: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(10px); + padding: 12px; /* Weniger Padding */ + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + width: 55%; /* Schmalere Box */ + margin: 15px auto; + margin-top: 120px; /* Weniger Abstand von oben */ transition: transform 0.2s ease-in-out; display: flex; flex-direction: column; - align-items: center; /* Zentriere die Inhalte in der Box */ - gap: 15px; /* Gleichmäßiger Abstand zwischen den Elementen */ + align-items: center; + gap: 8px; /* Weniger Abstand zwischen Elementen */ } form:hover { @@ -92,27 +92,25 @@ form:hover { form label { display: block; - margin-bottom: 12px; - font-size: 1.3em; - color: #ffffff; /* Weiß */ - width: 100%; /* Eingabefelder und Labels nehmen die gesamte Breite ein */ - text-align: center; /* Zentriere den Text der Labels */ + margin-bottom: 6px; + font-size: 1em; /* Kleinere Schriftgröße */ + color: #ffffff; + width: 100%; + text-align: center; } form input { - width: 95%; /* Noch breitere Textfelder */ - padding: 12px; - margin: 0 auto; /* Zentriere die Textfelder innerhalb der Box */ - margin-top: 6px; - margin-bottom: 18px; + width: 85%; /* Schmalere Felder */ + padding: 7px; + margin: 0 auto 10px auto; border: 1px solid #555; - border-radius: 6px; - font-size: 1.2em; /* Größere Schriftgröße */ - height: auto; /* Automatische Höhe */ - line-height: 1.5; /* Angemessene Zeilenhöhe */ - background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */ - color: #000000; /* Schwarz */ - text-align: center; /* Text zentriert in den Eingabefeldern */ + border-radius: 5px; + font-size: 1em; /* Kleinere Schriftgröße */ + height: auto; + line-height: 1.3; + background-color: rgba(255, 255, 255, 0.8); + color: #000000; + text-align: center; } form input:focus { @@ -122,14 +120,14 @@ form input:focus { } form select { - width: 95%; /* Gleiche Breite wie die Textfelder */ - padding: 12px; - margin: 0 auto 18px auto; /* Zentriere das Dropdown-Menü */ + width: 85%; + padding: 7px; + margin: 0 auto 10px auto; border: 1px solid #555; - border-radius: 6px; - font-size: 1.2em; /* Gleiche Schriftgröße wie die Textfelder */ - background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */ - color: #000000; /* Schwarz */ + border-radius: 5px; + font-size: 1em; + background-color: rgba(255, 255, 255, 0.8); + color: #000000; text-align: center; } @@ -140,14 +138,15 @@ form select:focus { } form button { - background-color: #28a745; /* Grün */ - color: #ffffff; /* Weiß */ + background-color: #28a745; + color: #ffffff; border: none; - padding: 12px 24px; - border-radius: 6px; - font-size: 1.1em; + padding: 8px 16px; /* Weniger Padding */ + border-radius: 5px; + font-size: 1em; /* Kleinere Schriftgröße */ cursor: pointer; transition: background-color 0.3s ease; + margin-top: 4px; } form button:hover { @@ -162,20 +161,20 @@ form button:active { .radio-group { display: flex; flex-wrap: wrap; /* Optionen umbrechen, falls nötig */ - gap: 15px; /* Abstand zwischen den Optionen */ + gap: 8px; /* Weniger Abstand */ justify-content: center; /* Zentriere die Optionen */ - margin: 15px 0; /* Abstand zur Umgebung */ + margin: 8px 0; /* Abstand zur Umgebung */ } .radio-group label { - font-size: 1.2em; /* Gleiche Schriftgröße wie die Textfelder */ + font-size: 1em; /* Gleiche Schriftgröße wie die Textfelder */ color: #ffffff; /* Weiß */ background: rgba(0, 0, 0, 0.5); /* Halbtransparenter Hintergrund */ - padding: 10px 15px; /* Polsterung für bessere Lesbarkeit */ - border-radius: 8px; /* Abgerundete Ecken */ + padding: 6px 10px; /* Polsterung für bessere Lesbarkeit */ + border-radius: 6px; /* Abgerundete Ecken */ display: flex; align-items: center; - gap: 10px; /* Abstand zwischen Radio-Button und Text */ + gap: 6px; /* Abstand zwischen Radio-Button und Text */ cursor: pointer; /* Zeige den Cursor als Hand */ transition: background-color 0.3s ease; border: 2px solid transparent; /* Standardrahmen transparent */ @@ -195,14 +194,14 @@ form button:active { } form input[type="number"] { - width: 95%; /* Gleiche Breite wie die anderen Eingabefelder */ - padding: 12px; - margin: 10px auto; /* Abstand zur Umgebung */ + width: 85%; + padding: 7px; + margin: 6px auto; border: 1px solid #555; - border-radius: 6px; - font-size: 1.2em; /* Gleiche Schriftgröße wie die Textfelder */ - background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */ - color: #000000; /* Schwarz */ + border-radius: 5px; + font-size: 1em; + background-color: rgba(255, 255, 255, 0.8); + color: #000000; text-align: center; } @@ -214,13 +213,9 @@ form input[type="number"]:focus { @media (max-width: 768px) { form { - width: 80%; /* Schmalere Box im mobilen Layout */ - padding: 20px; /* Weniger Padding für kleinere Bildschirme */ - display: flex; /* Flexbox aktivieren */ - justify-content: center; /* Inhalte horizontal zentrieren */ - flex-direction: column; - align-items: center; /* Zentriere die Inhalte in der Box */ - margin: 0 auto; /* Zusätzliche Sicherheit für horizontale Zentrierung */ + width: 95%; + padding: 8px; + margin-top: 40px; } form input { @@ -228,6 +223,17 @@ form input[type="number"]:focus { margin: 0; /* Entferne zusätzliche Margins */ } + form input, form select, form input[type="number"] { + width: 98%; + font-size: 0.95em; + padding: 6px; + } + + .radio-group label { + font-size: 0.95em; + padding: 5px 8px; + } + .App-header h1 { font-size: 2em; /* Kleinere Schriftgröße für Titel */ padding: 10px 15px; /* Weniger Padding für kleinere Bildschirme */ @@ -318,6 +324,126 @@ form input[type="number"]:focus { } } +#management-section { + min-height: 30%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 40px 20px 60px 20px; + border-radius: 16px; + margin: 40px auto 0 auto; + width: 80%; + box-shadow: 0 8px 32px rgba(0,0,0,0.4); + animation: fadeIn 0.7s; +} + +#management-section h2 { + font-size: 2.2em; + margin-bottom: 24px; + letter-spacing: 1px; + color: #61dafb; +} + +#management-section p { + font-size: 1.2em; + margin: 20px 0 0 0; + background: rgba(255,255,255,0.08); + padding: 18px 24px; + border-radius: 10px; + color: #e0e0e0; + max-width: 500px; +} + +#management-section button { + background-color: #28a745; + color: #fff; + border: none; + padding: 12px 28px; + border-radius: 8px; + font-size: 1.1em; + margin-bottom: 18px; + margin-top: 10px; + cursor: pointer; + transition: background 0.2s, transform 0.15s; + box-shadow: 0 2px 8px rgba(40,167,69,0.15); +} + +#management-section button:hover { + background-color: #218838; + transform: scale(1.04); +} + +.management-table { + width: 100%; + max-width: 420px; + margin: 18px auto 0 auto; + border-collapse: collapse; + background: rgba(255,255,255,0.07); + border-radius: 8px; + overflow: hidden; + font-size: 1.08em; + font-family: 'Segoe UI', Arial, sans-serif; + letter-spacing: 0.02em; + box-shadow: 0 2px 8px rgba(0,0,0,0.12); +} + +.management-table th, .management-table td { + padding: 10px 14px; + text-align: left; +} + +.management-table th { + background: rgba(40,167,69,0.92); + color: #fff; + font-weight: 700; + font-size: 1.13em; + letter-spacing: 0.04em; + text-shadow: 0 1px 2px #222; +} + +.management-table tr:nth-child(even) { + background: rgba(255,255,255,0.13); +} + +.management-table tr:nth-child(odd) { + background: rgba(0,0,0,0.13); +} + +.management-table td { + color: #fff; + font-weight: 600; + text-shadow: 0 1px 2px #222; +} + +@media (max-width: 768px) { + #management-section { + width: 95%; + padding: 20px 5px 40px 5px; + margin: 20px auto 0 auto; + } + #management-section h2 { + font-size: 1.5em; + } + #management-section p { + font-size: 1em; + padding: 12px 8px; + } + #management-section button { + font-size: 1em; + padding: 10px 18px; + } + .management-table { + font-size: 0.95em; + max-width: 98vw; + } + .management-table th, .management-table td { + padding: 6px 4px; + } +} + footer { background: rgba(0, 0, 0, 0.6); /* Halbtransparenter Hintergrund */ color: white; @@ -362,3 +488,74 @@ footer a:hover { .fact-value { text-align: right; } + +.login-form { + display: flex; + flex-direction: column; + align-items: center; + background: rgba(30,30,30,0.85); + padding: 32px 24px 24px 24px; + border-radius: 14px; + box-shadow: 0 4px 24px rgba(0,0,0,0.25); + min-width: 260px; + max-width: 340px; + margin: 0 auto; + animation: fadeIn 0.7s; +} + +.login-form h2 { + color: #61dafb; + margin-bottom: 18px; + font-size: 1.5em; +} + +.login-form input[type="password"] { + width: 90%; + padding: 12px; + margin-bottom: 18px; + border: 1px solid #555; + border-radius: 6px; + font-size: 1.1em; + background: rgba(255,255,255,0.9); + color: #222; + text-align: center; +} + +.login-form button { + background-color: #28a745; + color: #fff; + border: none; + padding: 10px 22px; + border-radius: 6px; + font-size: 1em; + margin-bottom: 6px; + cursor: pointer; + transition: background 0.2s, transform 0.15s; +} + +.login-form button[type="button"] { + background: #888; +} + +.login-form button:hover { + background-color: #218838; +} + +.login-form button[type="button"]:hover { + background: #555; +} + +.gesamtanzahl { + display: inline-block; + font-size: 1.13em; + font-weight: 700; + color: #fff; + background: #2196f3; /* Blau als Chip-Farbe */ + border-radius: 20px; + padding: 7px 22px; + margin: 10px 0 8px 0; + box-shadow: 0 2px 8px rgba(0,0,0,0.18); + letter-spacing: 0.04em; + text-shadow: 0 1px 2px #0d47a1; + border: 1px solid #bbdefb; /* Dünnerer Rand */ +} \ No newline at end of file diff --git a/src/App.js b/src/App.js deleted file mode 100644 index db08d14..0000000 --- a/src/App.js +++ /dev/null @@ -1,147 +0,0 @@ -import { useRef, useState } from 'react'; -import './App.css'; - -function App() { - const formSectionRef = useRef(null); - const [customNumber, setCustomNumber] = useState(false); - const [email, setEmail] = useState(""); - - - const scrollToForm = () => { - const formSection = formSectionRef.current; - formSection.classList.add('visible', 'bounce'); // Füge Bounce-Klasse hinzu - setTimeout(() => { - formSection.scrollIntoView({ behavior: 'smooth' }); - formSection.classList.remove('bounce'); // Entferne Bounce-Klasse nach der Animation - }, 190); // Wartezeit für die Bounce-Animation - }; - - const handleCustomInputChange = (e) => { - setCustomNumber(e.target.value); - }; - - const handleRadioChange = (e) => { - setCustomNumber(e.target.value === 'custom' ? '' : e.target.value); - }; - - const emailIsValid = (email1) => { - return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email1) - } - - const submit = (e) => { - e.preventDefault(); // Verhindert das Standardverhalten des Formulars - if (!emailIsValid(email)){ - alert("Bitte eine gültige E-Mailadresse eintrgen"); - return; - } - if(!customNumber){ - alert("Bitte angeben wie viele Personen mitkommen"); - return; - } - // send data - alert("Anmeldung gesendet.") - setEmail("") - setCustomNumber(false) - } - - return ( -
-
-

Willkommen zum Skatabend des Skat-Profils

-
-
- Zeit: - 18:00 -
-
- Ort: - Samuel-von-Pufendorf-Gymnasium in Flöha -
-
- Datum: - 25.06.2025 -
-
- -
-
-
- - setEmail(e.target.value))} value={email}/> -
- -
- - - - - -
- {customNumber === '' && ( - - )} -
- -
-
- -
- ); -} - -export default App; \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..216d645 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,214 @@ +import { useEffect, useRef, useState } from 'react'; +import './App.css'; +import { addDoc, collection, doc, getDoc, onSnapshot } from 'firebase/firestore'; +import { db } from './firebase'; + +function App() { + const radioGroupEntries = [1, 2, 3, 4] + const formSectionRef = useRef(null); + const [customNumber, setCustomNumber] = useState(false); + const [number, setNumber] = useState(null) + const [email, setEmail] = useState(""); + const [showManagement, setShowManagement] = useState(false); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [loginPassword, setLoginPassword] = useState(""); + const [data, setData] = useState([]); + + useEffect(() => { + let unsub = onSnapshot(collection(db, "forms"), (snapshot) => { + let data = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); + for(let i = 0; i < data.length; i++){ + let element = data[i] + if(element.id === "3GQrSzfPaZHZWleu6sq7") data.splice(i, 1) + } + setData(data) + }) + return () => { + unsub(); + }; + }, []); + + const getNumberOfUsers = () => { + let number = 0 + for(let user of data){ + number += user.number + } + return number; + } + + const scrollToForm = () => { + const formSection = formSectionRef.current; + formSection.classList.add('visible', 'bounce'); // Füge Bounce-Klasse hinzu + setTimeout(() => { + formSection.scrollIntoView({ behavior: 'smooth' }); + formSection.classList.remove('bounce'); // Entferne Bounce-Klasse nach der Animation + }, 190); // Wartezeit für die Bounce-Animation + }; + + const emailIsValid = (email1) => { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email1) + } + + const submit = async (e) => { + e.preventDefault(); // Verhindert das Standardverhalten des Formulars + if (!emailIsValid(email)){ + alert("Bitte eine gültige E-Mailadresse eintrgen"); + return; + } + if(!number){ + alert("Bitte angeben wie viele Personen mitkommen"); + return; + } + // send data + try { + addDoc(collection(db, "forms"), { + email: email, + number: number + }) + } catch (error) { + alert("Fehler beim Senden der Anmeldung. Bitte versuche es später erneut."); + console.error(error); + } + alert("Anmeldung gesendet.") + setEmail("") + setCustomNumber(false) + setNumber(null) + } + + const displayManagement = () => { + setShowManagement(true); + } + const hideManagement = () => { + setShowManagement(false); + setIsLoggedIn(false); + setLoginPassword(""); + } + + const handleLogin = async (e) => { + e.preventDefault(); + let pw = await getDoc(doc(db, "forms", "3GQrSzfPaZHZWleu6sq7")) + let pw2 = pw.data() + if (loginPassword === pw2.pw) { + setIsLoggedIn(true); + setLoginPassword(""); + } else { + alert("Falsches Passwort!"); + } + } + + return ( +
+ {showManagement ? ( +
+ {!isLoggedIn ? ( +
+

Verwaltung Login

+ setLoginPassword(e.target.value)} + autoFocus + /> + + +
+ ) : ( + <> +

Verwaltung

+ + {/* Gesamtanzahl Personen */} +
+ Gesamtanzahl Personen: { getNumberOfUsers() } +
+ {/* Tabelle mit Dummy-Daten */} + + + + + + + + + { data.map(user => ( + + + + + )) } + +
E-MailAnzahl Personen
{ user.email }{ user.number }
+ + )} +
+ ) : ( + <> +
+

Willkommen zum Skatabend des Skat-Profils

+
+
+ Zeit: + 18:00 +
+
+ Ort: + Samuel-von-Pufendorf-Gymnasium in Flöha +
+
+ Datum: + 25.06.2025 +
+
+ +
+
+
+ + setEmail(e.target.value))} value={email}/> +
+ +
+ { radioGroupEntries.map((entry) => ) } + +
+ {customNumber ? ( + setNumber(parseInt(e.target.value))} + value={number} + /> + ) : null} +
+ +
+
+ + )} + +
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/firebase.js b/src/firebase.js new file mode 100644 index 0000000..bddd94b --- /dev/null +++ b/src/firebase.js @@ -0,0 +1,16 @@ +import { initializeApp } from "firebase/app"; +import { getFirestore } from "firebase/firestore"; + +const firebaseConfig = { + apiKey: "AIzaSyAMimOrp73SW_pffgJ_MXeIjrXr7a-IIPE", + authDomain: "skatabend0.firebaseapp.com", + projectId: "skatabend0", + storageBucket: "skatabend0.firebasestorage.app", + messagingSenderId: "362332041327", + appId: "1:362332041327:web:87779c1bcb2a70f8c8dd9a" +} + +const app = initializeApp(firebaseConfig) +const db = getFirestore(app) + +export { db } \ No newline at end of file diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file