Refactor code structure for improved readability and maintainability
This commit is contained in:
328
src/App.css
328
src/App.css
@@ -13,8 +13,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: url('./assets/image.png') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter schwarzer Hintergrund */
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -22,6 +30,31 @@
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-header h1, .App-header p {
|
||||
background: rgba(0, 0, 0, 0.5); /* Halbtransparenter schwarzer Hintergrund */
|
||||
padding: 10px 15px;
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.App-header h1 {
|
||||
background: rgba(0, 0, 0, 0.7); /* Dunklerer halbtransparenter Hintergrund */
|
||||
font-size: 2.5em; /* Größere Schriftgröße */
|
||||
padding: 15px 20px; /* Mehr Padding für bessere Lesbarkeit */
|
||||
border-radius: 10px;
|
||||
color: #ffffff; /* Weiß für besseren Kontrast */
|
||||
}
|
||||
|
||||
.App-header p {
|
||||
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter Hintergrund */
|
||||
font-size: 1.2em; /* Etwas größere Schriftgröße */
|
||||
padding: 10px 15px;
|
||||
border-radius: 8px;
|
||||
color: #f0f0f0; /* Helles Grau für besseren Kontrast */
|
||||
}
|
||||
|
||||
.App-link {
|
||||
@@ -36,3 +69,296 @@
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
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 */
|
||||
}
|
||||
|
||||
form:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
form input {
|
||||
width: 95%; /* Noch breitere Textfelder */
|
||||
padding: 12px;
|
||||
margin: 0 auto; /* Zentriere die Textfelder innerhalb der Box */
|
||||
margin-top: 6px;
|
||||
margin-bottom: 18px;
|
||||
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 */
|
||||
}
|
||||
|
||||
form input:focus {
|
||||
outline: none;
|
||||
border-color: #61dafb;
|
||||
box-shadow: 0 0 5px #61dafb;
|
||||
}
|
||||
|
||||
form select {
|
||||
width: 95%; /* Gleiche Breite wie die Textfelder */
|
||||
padding: 12px;
|
||||
margin: 0 auto 18px auto; /* Zentriere das Dropdown-Menü */
|
||||
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 */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form select:focus {
|
||||
outline: none;
|
||||
border-color: #61dafb;
|
||||
box-shadow: 0 0 5px #61dafb;
|
||||
}
|
||||
|
||||
form button {
|
||||
background-color: #28a745; /* Grün */
|
||||
color: #ffffff; /* Weiß */
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 6px;
|
||||
font-size: 1.1em;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
form button:hover {
|
||||
background-color: #218838; /* Dunkleres Grün beim Hover */
|
||||
}
|
||||
|
||||
form button:active {
|
||||
background-color: #1b8cd8;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap; /* Optionen umbrechen, falls nötig */
|
||||
gap: 15px; /* Abstand zwischen den Optionen */
|
||||
justify-content: center; /* Zentriere die Optionen */
|
||||
margin: 15px 0; /* Abstand zur Umgebung */
|
||||
}
|
||||
|
||||
.radio-group label {
|
||||
font-size: 1.2em; /* 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 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px; /* 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 */
|
||||
}
|
||||
|
||||
.radio-group label:hover {
|
||||
background-color: rgba(0, 128, 0, 0.7); /* Dunklerer grüner Hintergrund beim Hover */
|
||||
}
|
||||
|
||||
.radio-group input[type="radio"] {
|
||||
display: none; /* Verstecke die Radio-Buttons */
|
||||
}
|
||||
|
||||
.radio-group input[type="radio"]:checked + label {
|
||||
border-color: #28a745; /* Grüner Rahmen bei Auswahl */
|
||||
background-color: rgba(0, 128, 0, 0.7); /* Grüner Hintergrund nur bei Auswahl */
|
||||
}
|
||||
|
||||
form input[type="number"] {
|
||||
width: 95%; /* Gleiche Breite wie die anderen Eingabefelder */
|
||||
padding: 12px;
|
||||
margin: 10px auto; /* Abstand zur Umgebung */
|
||||
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 */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form input[type="number"]:focus {
|
||||
outline: none;
|
||||
border-color: #61dafb;
|
||||
box-shadow: 0 0 5px #61dafb;
|
||||
}
|
||||
|
||||
@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 */
|
||||
}
|
||||
|
||||
form input {
|
||||
width: 90%; /* Textfelder nehmen die gesamte Breite der Box ein */
|
||||
margin: 0; /* Entferne zusätzliche Margins */
|
||||
}
|
||||
|
||||
.App-header h1 {
|
||||
font-size: 2em; /* Kleinere Schriftgröße für Titel */
|
||||
padding: 10px 15px; /* Weniger Padding für kleinere Bildschirme */
|
||||
}
|
||||
|
||||
.App-header p {
|
||||
font-size: 1em; /* Kleinere Schriftgröße für Untertitel */
|
||||
padding: 8px 12px; /* Weniger Padding für kleinere Bildschirme */
|
||||
}
|
||||
}
|
||||
|
||||
#intro {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background: rgba(0, 0, 0, 0.5); /* Halbtransparenter Hintergrund */
|
||||
color: white;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#intro h1 {
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#intro p {
|
||||
font-size: 1.2em;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#intro button {
|
||||
background-color: #28a745; /* Grün */
|
||||
color: #282c34;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 6px;
|
||||
font-size: 1.1em;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
#intro button:hover {
|
||||
background-color: #218838; /* Dunkleres Grün beim Hover */
|
||||
}
|
||||
|
||||
#form-section {
|
||||
display: none; /* Formularbereich zunächst ausblenden */
|
||||
padding-top: 50px;
|
||||
min-height: 100vh; /* Füllt den gesamten Bildschirm aus */
|
||||
background: transparent; /* Vollständig transparenter Hintergrund */
|
||||
transition: opacity 1.5s ease-in-out, transform 0.5s ease-in-out; /* Längere Übergangszeit für Transparenz */
|
||||
opacity: 0;
|
||||
transform: translateY(20px) scale(0.9); /* Leicht nach unten verschoben und Start mit kleinerer Skalierung */
|
||||
}
|
||||
|
||||
#form-section.visible {
|
||||
display: block; /* Formularbereich sichtbar machen */
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1); /* Zurück in die ursprüngliche Position und zur vollen Größe skalieren */
|
||||
animation: bounceIn 0.8s ease-in-out; /* Bounce-Effekt hinzufügen */
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounceIn {
|
||||
0% {
|
||||
transform: translateY(-50px) scale(0.8); /* Start kleiner und weiter oben */
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(10px) scale(1.1); /* Überschwingung nach unten */
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0) scale(1); /* Endposition */
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
background: rgba(0, 0, 0, 0.6); /* Halbtransparenter Hintergrund */
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 5px 0; /* Weniger Padding */
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
font-size: 0.8em; /* Kleinere Schriftgröße */
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #61dafb;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.facts {
|
||||
margin: 20px 0;
|
||||
text-align: left;
|
||||
display: inline-block;
|
||||
background: rgba(0, 0, 0, 0.5); /* Halbtransparenter Hintergrund */
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.fact-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.fact-label {
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.fact-value {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
137
src/App.js
137
src/App.js
@@ -1,25 +1,134 @@
|
||||
import logo from './logo.svg';
|
||||
import { useRef, useState } from 'react';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const formSectionRef = useRef(null);
|
||||
const [customNumber, setCustomNumber] = useState();
|
||||
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 submit = (e) => {
|
||||
e.preventDefault(); // Verhindert das Standardverhalten des Formulars
|
||||
if (email === ""){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<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))} />
|
||||
<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>
|
||||
Edit <code>src/App.js</code> and save to reload.
|
||||
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>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
@@ -1,8 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
BIN
src/assets/image.png
Normal file
BIN
src/assets/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 MiB |
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
@@ -10,8 +9,3 @@ root.render(
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
@@ -1,5 +0,0 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
Reference in New Issue
Block a user