final version
This commit is contained in:
315
src/App.css
315
src/App.css
@@ -71,19 +71,19 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter schwarzer Hintergrund */
|
background: rgba(0, 0, 0, 0.6);
|
||||||
backdrop-filter: blur(10px); /* Blur-Effekt */
|
backdrop-filter: blur(10px);
|
||||||
padding: 25px;
|
padding: 12px; /* Weniger Padding */
|
||||||
border-radius: 12px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
width: 70%; /* Noch breitere Box */
|
width: 55%; /* Schmalere Box */
|
||||||
margin: 25px auto;
|
margin: 15px auto;
|
||||||
margin-top: 200px; /* Abstand von der Oberseite */
|
margin-top: 120px; /* Weniger Abstand von oben */
|
||||||
transition: transform 0.2s ease-in-out;
|
transition: transform 0.2s ease-in-out;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center; /* Zentriere die Inhalte in der Box */
|
align-items: center;
|
||||||
gap: 15px; /* Gleichmäßiger Abstand zwischen den Elementen */
|
gap: 8px; /* Weniger Abstand zwischen Elementen */
|
||||||
}
|
}
|
||||||
|
|
||||||
form:hover {
|
form:hover {
|
||||||
@@ -92,27 +92,25 @@ form:hover {
|
|||||||
|
|
||||||
form label {
|
form label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 6px;
|
||||||
font-size: 1.3em;
|
font-size: 1em; /* Kleinere Schriftgröße */
|
||||||
color: #ffffff; /* Weiß */
|
color: #ffffff;
|
||||||
width: 100%; /* Eingabefelder und Labels nehmen die gesamte Breite ein */
|
width: 100%;
|
||||||
text-align: center; /* Zentriere den Text der Labels */
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input {
|
form input {
|
||||||
width: 95%; /* Noch breitere Textfelder */
|
width: 85%; /* Schmalere Felder */
|
||||||
padding: 12px;
|
padding: 7px;
|
||||||
margin: 0 auto; /* Zentriere die Textfelder innerhalb der Box */
|
margin: 0 auto 10px auto;
|
||||||
margin-top: 6px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 6px;
|
border-radius: 5px;
|
||||||
font-size: 1.2em; /* Größere Schriftgröße */
|
font-size: 1em; /* Kleinere Schriftgröße */
|
||||||
height: auto; /* Automatische Höhe */
|
height: auto;
|
||||||
line-height: 1.5; /* Angemessene Zeilenhöhe */
|
line-height: 1.3;
|
||||||
background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
color: #000000; /* Schwarz */
|
color: #000000;
|
||||||
text-align: center; /* Text zentriert in den Eingabefeldern */
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input:focus {
|
form input:focus {
|
||||||
@@ -122,14 +120,14 @@ form input:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form select {
|
form select {
|
||||||
width: 95%; /* Gleiche Breite wie die Textfelder */
|
width: 85%;
|
||||||
padding: 12px;
|
padding: 7px;
|
||||||
margin: 0 auto 18px auto; /* Zentriere das Dropdown-Menü */
|
margin: 0 auto 10px auto;
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 6px;
|
border-radius: 5px;
|
||||||
font-size: 1.2em; /* Gleiche Schriftgröße wie die Textfelder */
|
font-size: 1em;
|
||||||
background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
color: #000000; /* Schwarz */
|
color: #000000;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,14 +138,15 @@ form select:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form button {
|
form button {
|
||||||
background-color: #28a745; /* Grün */
|
background-color: #28a745;
|
||||||
color: #ffffff; /* Weiß */
|
color: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 12px 24px;
|
padding: 8px 16px; /* Weniger Padding */
|
||||||
border-radius: 6px;
|
border-radius: 5px;
|
||||||
font-size: 1.1em;
|
font-size: 1em; /* Kleinere Schriftgröße */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form button:hover {
|
form button:hover {
|
||||||
@@ -162,20 +161,20 @@ form button:active {
|
|||||||
.radio-group {
|
.radio-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap; /* Optionen umbrechen, falls nötig */
|
flex-wrap: wrap; /* Optionen umbrechen, falls nötig */
|
||||||
gap: 15px; /* Abstand zwischen den Optionen */
|
gap: 8px; /* Weniger Abstand */
|
||||||
justify-content: center; /* Zentriere die Optionen */
|
justify-content: center; /* Zentriere die Optionen */
|
||||||
margin: 15px 0; /* Abstand zur Umgebung */
|
margin: 8px 0; /* Abstand zur Umgebung */
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-group label {
|
.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ß */
|
color: #ffffff; /* Weiß */
|
||||||
background: rgba(0, 0, 0, 0.5); /* Halbtransparenter Hintergrund */
|
background: rgba(0, 0, 0, 0.5); /* Halbtransparenter Hintergrund */
|
||||||
padding: 10px 15px; /* Polsterung für bessere Lesbarkeit */
|
padding: 6px 10px; /* Polsterung für bessere Lesbarkeit */
|
||||||
border-radius: 8px; /* Abgerundete Ecken */
|
border-radius: 6px; /* Abgerundete Ecken */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
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 */
|
cursor: pointer; /* Zeige den Cursor als Hand */
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
border: 2px solid transparent; /* Standardrahmen transparent */
|
border: 2px solid transparent; /* Standardrahmen transparent */
|
||||||
@@ -195,14 +194,14 @@ form button:active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form input[type="number"] {
|
form input[type="number"] {
|
||||||
width: 95%; /* Gleiche Breite wie die anderen Eingabefelder */
|
width: 85%;
|
||||||
padding: 12px;
|
padding: 7px;
|
||||||
margin: 10px auto; /* Abstand zur Umgebung */
|
margin: 6px auto;
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 6px;
|
border-radius: 5px;
|
||||||
font-size: 1.2em; /* Gleiche Schriftgröße wie die Textfelder */
|
font-size: 1em;
|
||||||
background-color: rgba(255, 255, 255, 0.8); /* Halbtransparenter weißer Hintergrund */
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
color: #000000; /* Schwarz */
|
color: #000000;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,13 +213,9 @@ form input[type="number"]:focus {
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
form {
|
form {
|
||||||
width: 80%; /* Schmalere Box im mobilen Layout */
|
width: 95%;
|
||||||
padding: 20px; /* Weniger Padding für kleinere Bildschirme */
|
padding: 8px;
|
||||||
display: flex; /* Flexbox aktivieren */
|
margin-top: 40px;
|
||||||
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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form input {
|
form input {
|
||||||
@@ -228,6 +223,17 @@ form input[type="number"]:focus {
|
|||||||
margin: 0; /* Entferne zusätzliche Margins */
|
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 {
|
.App-header h1 {
|
||||||
font-size: 2em; /* Kleinere Schriftgröße für Titel */
|
font-size: 2em; /* Kleinere Schriftgröße für Titel */
|
||||||
padding: 10px 15px; /* Weniger Padding für kleinere Bildschirme */
|
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 {
|
footer {
|
||||||
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter Hintergrund */
|
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter Hintergrund */
|
||||||
color: white;
|
color: white;
|
||||||
@@ -362,3 +488,74 @@ footer a:hover {
|
|||||||
.fact-value {
|
.fact-value {
|
||||||
text-align: right;
|
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 */
|
||||||
|
}
|
||||||
147
src/App.js
147
src/App.js
@@ -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 (
|
|
||||||
<div className="App">
|
|
||||||
<div id="intro">
|
|
||||||
<h1>Willkommen zum Skatabend des Skat-Profils</h1>
|
|
||||||
<div className="facts">
|
|
||||||
<div className="fact-row">
|
|
||||||
<span className="fact-label">Zeit:</span>
|
|
||||||
<span className="fact-value">18:00</span>
|
|
||||||
</div>
|
|
||||||
<div className="fact-row">
|
|
||||||
<span className="fact-label">Ort:</span>
|
|
||||||
<span className="fact-value">Samuel-von-Pufendorf-Gymnasium in Flöha</span>
|
|
||||||
</div>
|
|
||||||
<div className="fact-row">
|
|
||||||
<span className="fact-label">Datum:</span>
|
|
||||||
<span className="fact-value">25.06.2025</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button onClick={scrollToForm}>Jetzt Anmelden</button>
|
|
||||||
</div>
|
|
||||||
<div id="form-section" ref={formSectionRef}>
|
|
||||||
<form>
|
|
||||||
<label>E-Mail:</label>
|
|
||||||
<input type="email" name="email" placeholder="Deine E-Mail-Adresse" onChange={(e => setEmail(e.target.value))} value={email}/>
|
|
||||||
<br />
|
|
||||||
<label>Anzahl der Personen</label>
|
|
||||||
<div className="radio-group">
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="number"
|
|
||||||
value="1"
|
|
||||||
onChange={handleRadioChange}
|
|
||||||
checked={customNumber === '1'}
|
|
||||||
/>
|
|
||||||
1 Person
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="number"
|
|
||||||
value="2"
|
|
||||||
onChange={handleRadioChange}
|
|
||||||
checked={customNumber === '2'}
|
|
||||||
/>
|
|
||||||
2 Personen
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="number"
|
|
||||||
value="3"
|
|
||||||
onChange={handleRadioChange}
|
|
||||||
checked={customNumber === '3'}
|
|
||||||
/>
|
|
||||||
3 Personen
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="number"
|
|
||||||
value="4"
|
|
||||||
onChange={handleRadioChange}
|
|
||||||
checked={customNumber === '4'}
|
|
||||||
/>
|
|
||||||
4 Personen
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="number"
|
|
||||||
value="custom"
|
|
||||||
onChange={handleRadioChange}
|
|
||||||
checked={customNumber === ''}
|
|
||||||
/>
|
|
||||||
Andere
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{customNumber === '' && (
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="customNumber"
|
|
||||||
placeholder="Anzahl der Personen"
|
|
||||||
onChange={handleCustomInputChange}
|
|
||||||
value={customNumber}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<br />
|
|
||||||
<button type="submit" onClick={submit}>Anmelden</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<footer>
|
|
||||||
<p>
|
|
||||||
Bildquelle Hintergrund: <a href="https://store-images.s-microsoft.com/image/apps.42739.13510798887965433.cf25521d-d390-432c-8007-cbc0aa3ebe97.53ed75d0-4a6a-4c11-a3ae-fd528ef6444a?h=1280" target="_blank" rel="noopener noreferrer">hier klicken</a>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
214
src/App.jsx
Normal file
214
src/App.jsx
Normal file
@@ -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 (
|
||||||
|
<div className="App">
|
||||||
|
{showManagement ? (
|
||||||
|
<div id="management-section">
|
||||||
|
{!isLoggedIn ? (
|
||||||
|
<form onSubmit={handleLogin} className="login-form">
|
||||||
|
<h2>Verwaltung Login</h2>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="Passwort"
|
||||||
|
value={loginPassword}
|
||||||
|
onChange={e => setLoginPassword(e.target.value)}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
<button type="button" onClick={hideManagement} style={{background:'#888',marginTop:'10px'}}>Abbrechen</button>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h2>Verwaltung</h2>
|
||||||
|
<button onClick={hideManagement}>Abmelden & Zurück</button>
|
||||||
|
{/* Gesamtanzahl Personen */}
|
||||||
|
<div className="gesamtanzahl">
|
||||||
|
Gesamtanzahl Personen: <b>{ getNumberOfUsers() }</b>
|
||||||
|
</div>
|
||||||
|
{/* Tabelle mit Dummy-Daten */}
|
||||||
|
<table className="management-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>E-Mail</th>
|
||||||
|
<th>Anzahl Personen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{ data.map(user => (
|
||||||
|
<tr key={user.id}>
|
||||||
|
<td>{ user.email }</td>
|
||||||
|
<td>{ user.number }</td>
|
||||||
|
</tr>
|
||||||
|
)) }
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div id="intro">
|
||||||
|
<h1>Willkommen zum Skatabend des Skat-Profils</h1>
|
||||||
|
<div className="facts">
|
||||||
|
<div className="fact-row">
|
||||||
|
<span className="fact-label">Zeit:</span>
|
||||||
|
<span className="fact-value">18:00</span>
|
||||||
|
</div>
|
||||||
|
<div className="fact-row">
|
||||||
|
<span className="fact-label">Ort:</span>
|
||||||
|
<span className="fact-value">Samuel-von-Pufendorf-Gymnasium in Flöha</span>
|
||||||
|
</div>
|
||||||
|
<div className="fact-row">
|
||||||
|
<span className="fact-label">Datum:</span>
|
||||||
|
<span className="fact-value">25.06.2025</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={scrollToForm}>Jetzt Anmelden</button>
|
||||||
|
</div>
|
||||||
|
<div id="form-section" ref={formSectionRef}>
|
||||||
|
<form>
|
||||||
|
<label>E-Mail:</label>
|
||||||
|
<input type="email" name="email" placeholder="Deine E-Mail-Adresse" onChange={(e => setEmail(e.target.value))} value={email}/>
|
||||||
|
<br />
|
||||||
|
<label>Anzahl der Personen</label>
|
||||||
|
<div className="radio-group">
|
||||||
|
{ radioGroupEntries.map((entry) => <label key={entry} style={ number === entry && !customNumber ? { backgroundColor: "rgba(0, 128, 0, 0.7)" } : null }>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="number"
|
||||||
|
onChange={() => { setNumber(entry); setCustomNumber(false) }}
|
||||||
|
/>
|
||||||
|
{ entry } Person{ entry > 1 ? "en" : null }
|
||||||
|
</label> ) }
|
||||||
|
<label style={ customNumber ? { backgroundColor: "rgba(0, 128, 0, 0.7)" } : null }>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="number"
|
||||||
|
onChange={() => setCustomNumber(true)}
|
||||||
|
/>
|
||||||
|
Andere Nummer
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{customNumber ? (
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="customNumber"
|
||||||
|
placeholder="Anzahl der Personen"
|
||||||
|
min={1}
|
||||||
|
onChange={(e) => setNumber(parseInt(e.target.value))}
|
||||||
|
value={number}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<br />
|
||||||
|
<button type="submit" onClick={submit}>Anmelden</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<footer>
|
||||||
|
<p>
|
||||||
|
<a onClick={displayManagement} style={{ marginRight: '20px', cursor: 'pointer' }}>Verwaltung öffnen</a>
|
||||||
|
Bildquelle Hintergrund: <a href="https://store-images.s-microsoft.com/image/apps.42739.13510798887965433.cf25521d-d390-432c-8007-cbc0aa3ebe97.53ed75d0-4a6a-4c11-a3ae-fd528ef6444a?h=1280" target="_blank" rel="noopener noreferrer">hier klicken</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
16
src/firebase.js
Normal file
16
src/firebase.js
Normal file
@@ -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 }
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB |
Reference in New Issue
Block a user