Erste Aenderungen
This commit is contained in:
@@ -15,7 +15,7 @@ const Footer = () => {
|
||||
<span className="font-bold text-xl">TG Laudenbach</span>
|
||||
</div>
|
||||
<p className="text-gray-400">
|
||||
Volleyball mit Leidenschaft und Teamgeist seit 1975.
|
||||
Volleyball seit 1974.
|
||||
</p>
|
||||
<div className="flex space-x-4">
|
||||
<Button variant="ghost" size="icon" className="text-gray-400 hover:text-white">
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Volleyball } from "lucide-react";
|
||||
|
||||
const Hero = () => {
|
||||
return (
|
||||
<div className="hero-pattern pt-28 pb-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div
|
||||
className="relative min-h-[600px] md:min-h-[700px] lg:min-h-[800px] bg-cover bg-center bg-no-repeat pt-28 pb-16"
|
||||
style={{ backgroundImage: "url('/images/abteilung-bg.jpg')" }}
|
||||
>
|
||||
<div className="absolute inset-0 bg-black/15 z-0" />
|
||||
|
||||
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col md:flex-row items-center">
|
||||
<div className="md:w-1/2 text-white">
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold">
|
||||
Willkommen beim <span className="text-white">TG Laudenbach</span>
|
||||
Willkommen bei der <span className="text-white">TG Laudenbach - Abteilung Volleyball</span>
|
||||
</h1>
|
||||
<p className="mt-4 text-lg md:text-xl">
|
||||
Volleyball mit Leidenschaft und Teamgeist - werde Teil unserer Gemeinschaft!
|
||||
Volleyball mit Leidenschaft und Teamgeist – werde Teil unserer Gemeinschaft!
|
||||
</p>
|
||||
<div className="mt-8 flex flex-wrap gap-4">
|
||||
<Button className="bg-white text-frog-700 hover:bg-gray-100">
|
||||
Training besuchen
|
||||
</Button>
|
||||
<Button variant="outline" className="text-white border-white hover:bg-white/10">
|
||||
<Button className="bg-white text-frog-700 hover:bg-gray-100">
|
||||
Teams kennenlernen
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Menu, X, Volleyball } from "lucide-react";
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
const Navbar = () => {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
@@ -11,7 +12,7 @@ const Navbar = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="bg-white shadow-md fixed w-full z-50">
|
||||
<nav className="fixed top-0 left-0 w-full z-50 bg-white/30 backdrop-blur-md border-b border-white/20">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16 items-center">
|
||||
<div className="flex items-center">
|
||||
@@ -27,7 +28,11 @@ const Navbar = () => {
|
||||
<a href="#gallery" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Galerie</a>
|
||||
<a href="#about" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Über uns</a>
|
||||
<a href="#contact" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Kontakt</a>
|
||||
<Button className="bg-frog-500 hover:bg-frog-600 text-white">Mitglied werden</Button>
|
||||
<Link to="/mitglied-werden" className="w-full">
|
||||
<Button className="w-full bg-frog-500 hover:bg-frog-600 text-white">
|
||||
Mitglied werden
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
const NewsSection = () => {
|
||||
const news = [
|
||||
@@ -59,9 +60,11 @@ const NewsSection = () => {
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12">
|
||||
<Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||
Alle Neuigkeiten
|
||||
</Button>
|
||||
<Link to="/alle-neuigkeiten">
|
||||
<Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||
Alle Neuigkeiten
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
import { useKeenSlider } from "keen-slider/react";
|
||||
import { useRef } from "react";
|
||||
import { ChevronLeft, ChevronRight, Users } from "lucide-react";
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Users } from "lucide-react";
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
const TeamSection = () => {
|
||||
const teams = [
|
||||
@@ -32,40 +34,92 @@ const TeamSection = () => {
|
||||
league: "Hobby",
|
||||
description: "Für alle, die Volleyball zum Spaß spielen möchten. Anfänger und Fortgeschrittene sind willkommen!",
|
||||
trainingTimes: "Mo 18:00 - 20:00 Uhr"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "U12",
|
||||
league: "Jugendliga",
|
||||
description: "Unsere kleinsten Stars sammeln erste Spielerfahrung in der U12-Jugendliga.",
|
||||
trainingTimes: "Mi 16:00 - 17:30 Uhr"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "Mixed-Team",
|
||||
league: "Hobbyliga",
|
||||
description: "Spaß, Gemeinschaft und gemischte Teams – unser Mixed-Team steht für Vielfalt!",
|
||||
trainingTimes: "Fr 19:00 - 21:00 Uhr"
|
||||
}
|
||||
];
|
||||
|
||||
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
|
||||
slides: {
|
||||
perView: 1,
|
||||
spacing: 16,
|
||||
},
|
||||
breakpoints: {
|
||||
"(min-width: 640px)": {
|
||||
slides: { perView: 2, spacing: 16 },
|
||||
},
|
||||
"(min-width: 1024px)": {
|
||||
slides: { perView: 3, spacing: 20 },
|
||||
},
|
||||
"(min-width: 1280px)": {
|
||||
slides: { perView: 4, spacing: 24 },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<section id="team" className="py-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-gray-900">Unsere Teams</h2>
|
||||
<p className="mt-4 text-xl text-gray-600">Von Anfängern bis Leistungssport - für jeden ist etwas dabei</p>
|
||||
<p className="mt-4 text-xl text-gray-600">Von Anfängern bis Leistungssport – für jeden ist etwas dabei</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{teams.map((team) => (
|
||||
<Card key={team.id} className="hover:shadow-lg transition-shadow border-t-4 border-t-frog-500">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center">
|
||||
<Users className="h-5 w-5 mr-2 text-frog-500" />
|
||||
{team.name}
|
||||
</CardTitle>
|
||||
<CardDescription>{team.league}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-gray-600 mb-4">{team.description}</p>
|
||||
<div className="text-sm font-medium">
|
||||
<span className="text-frog-600">Training:</span> {team.trainingTimes}
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button variant="outline" size="sm" className="w-full border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||
Team Details
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
<div className="relative">
|
||||
{/* Navigation Buttons */}
|
||||
<button
|
||||
onClick={() => slider.current?.prev()}
|
||||
className="absolute left-0 top-1/2 -translate-y-1/2 z-10 bg-white rounded-full p-2 shadow-md hover:bg-frog-100"
|
||||
>
|
||||
<ChevronLeft className="text-frog-600" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => slider.current?.next()}
|
||||
className="absolute right-0 top-1/2 -translate-y-1/2 z-10 bg-white rounded-full p-2 shadow-md hover:bg-frog-100"
|
||||
>
|
||||
<ChevronRight className="text-frog-600" />
|
||||
</button>
|
||||
|
||||
<div ref={sliderRef} className="keen-slider">
|
||||
{teams.map((team) => (
|
||||
<div key={team.id} className="keen-slider__slide">
|
||||
<Card className="h-full hover:shadow-lg transition-shadow border-t-4 border-t-frog-500">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center">
|
||||
<Users className="h-5 w-5 mr-2 text-frog-500" />
|
||||
{team.name}
|
||||
</CardTitle>
|
||||
<CardDescription>{team.league}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-gray-600 mb-4">{team.description}</p>
|
||||
<div className="text-sm font-medium">
|
||||
<span className="text-frog-600">Training:</span> {team.trainingTimes}
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Link to={`/teams/${team.id}`} className="w-full">
|
||||
<Button variant="outline" size="sm" className="w-full border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||
Team Details
|
||||
</Button>
|
||||
</Link>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
19
src/layout/Layout.tsx
Normal file
19
src/layout/Layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import Navbar from "@/components/Navbar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
type LayoutProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const Layout = ({ children }: LayoutProps) => {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex flex-col">
|
||||
<Navbar />
|
||||
<main className="flex-1 pt-16">{children}</main>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
52
src/main.tsx
52
src/main.tsx
@@ -1,5 +1,49 @@
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||
import "keen-slider/keen-slider.min.css";
|
||||
|
||||
createRoot(document.getElementById("root")!).render(<App />);
|
||||
import Index from "./pages/Index";
|
||||
import MitgliedWerdenPage from "./pages/MitgliedWerden";
|
||||
import AlleNeuigkeitenPage from "./pages/AlleNeuigkeiten";
|
||||
import Layout from "./layout/Layout";
|
||||
import TeamDetailPage from "./pages/TeamDetailPage";
|
||||
|
||||
|
||||
import "./index.css"
|
||||
|
||||
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<Layout>
|
||||
<Index />
|
||||
</Layout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/mitglied-werden"
|
||||
element={
|
||||
<Layout>
|
||||
<MitgliedWerdenPage />
|
||||
</Layout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/alle-neuigkeiten"
|
||||
element={
|
||||
<Layout>
|
||||
<AlleNeuigkeitenPage />
|
||||
</Layout>
|
||||
}
|
||||
/>
|
||||
<Route path="/teams/:id" element={<Layout><TeamDetailPage /></Layout>} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
52
src/pages/AlleNeuigkeiten.tsx
Normal file
52
src/pages/AlleNeuigkeiten.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
const news = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Saisonstart 2023/24",
|
||||
date: "15. September 2023",
|
||||
description: "Die neue Saison beginnt mit einem Heimspiel gegen VfB Mosbach. Kommt vorbei und unterstützt unser Team!",
|
||||
image: "https://images.unsplash.com/photo-1612872087720-bb876e2e67d1?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Beachvolleyball-Turnier",
|
||||
date: "3. Juli 2023",
|
||||
description: "Unser jährliches Beachvolleyball-Turnier war ein voller Erfolg! 24 Teams kämpften um den Sieg.",
|
||||
image: "https://images.unsplash.com/photo-1583514555852-6f77e7c9e081?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Neuer Trainer für die Jugendmannschaft",
|
||||
date: "21. Mai 2023",
|
||||
description: "Wir freuen uns, Marc Schneider als neuen Trainer für unsere U16-Mannschaft begrüßen zu dürfen.",
|
||||
image: "https://images.unsplash.com/photo-1547347298-4074fc3086f0?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
|
||||
},
|
||||
// 🔜 später kannst du hier easy mehr News reinladen oder aus ner API holen
|
||||
];
|
||||
|
||||
const AlleNeuigkeitenPage = () => {
|
||||
return (
|
||||
<div className="max-w-5xl mx-auto px-4 py-12">
|
||||
<h1 className="text-3xl font-bold text-center mb-8 text-frog-600">Alle Neuigkeiten</h1>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{news.map((item) => (
|
||||
<Card key={item.id} className="overflow-hidden">
|
||||
<div className="h-48 overflow-hidden">
|
||||
<img src={item.image} alt={item.title} className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<CardHeader>
|
||||
<CardTitle>{item.title}</CardTitle>
|
||||
<CardDescription>{item.date}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>{item.description}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AlleNeuigkeitenPage;
|
||||
@@ -11,14 +11,12 @@ import Footer from "@/components/Footer";
|
||||
const Index = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<Navbar />
|
||||
<Hero />
|
||||
<NewsSection />
|
||||
<TeamSection />
|
||||
<GallerySection />
|
||||
<AboutSection />
|
||||
<ContactSection />
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
26
src/pages/MitgliedWerden.tsx
Normal file
26
src/pages/MitgliedWerden.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
|
||||
const MitgliedWerdenPage = () => {
|
||||
return (
|
||||
<div className="flex justify-center mt-10">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardContent className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4 text-center">Mitglied werden</h1>
|
||||
<form className="space-y-4">
|
||||
<Input placeholder="Vorname" />
|
||||
<Input placeholder="Nachname" />
|
||||
<Input placeholder="E-Mail" type="email" />
|
||||
<Input placeholder="Geburtsdatum" type="date" />
|
||||
<Button type="submit" className="w-full bg-frog-500 hover:bg-frog-600 text-white">
|
||||
Absenden
|
||||
</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MitgliedWerdenPage;
|
||||
37
src/pages/TeamDetailPage.tsx
Normal file
37
src/pages/TeamDetailPage.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
const teamData = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Damen I",
|
||||
league: "Landesliga Nord",
|
||||
description: "Unsere erste Damenmannschaft ...",
|
||||
trainingTimes: "Di & Do 19:00 - 21:00 Uhr",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Herren I",
|
||||
league: "Bezirksliga",
|
||||
description: "Das Herrenteam kämpft ...",
|
||||
trainingTimes: "Mo & Mi 20:00 - 22:00 Uhr",
|
||||
},
|
||||
// usw...
|
||||
];
|
||||
|
||||
const TeamDetailPage = () => {
|
||||
const { id } = useParams();
|
||||
const team = teamData.find((t) => t.id === id);
|
||||
|
||||
if (!team) return <p>Team nicht gefunden 🐸</p>;
|
||||
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto py-12 px-4">
|
||||
<h1 className="text-4xl font-bold text-frog-600 mb-2">{team.name}</h1>
|
||||
<p className="text-gray-700 mb-2">{team.league}</p>
|
||||
<p className="text-gray-600 mb-4">{team.description}</p>
|
||||
<p className="text-sm text-frog-700 font-medium">Training: {team.trainingTimes}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamDetailPage;
|
||||
0
src/routes.tsx
Normal file
0
src/routes.tsx
Normal file
Reference in New Issue
Block a user