Erste Aenderungen
This commit is contained in:
parent
a517191176
commit
79aa26d48a
13
index.html
13
index.html
@ -3,18 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>froggy-volleyball-haven</title>
|
<title>TG Laudenbach - Volleyball</title>
|
||||||
<meta name="description" content="Lovable Generated Project" />
|
|
||||||
<meta name="author" content="Lovable" />
|
|
||||||
|
|
||||||
<meta property="og:title" content="Lovable Generated Project" />
|
|
||||||
<meta property="og:description" content="Lovable Generated Project" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
|
||||||
<meta name="twitter:site" content="@lovable_dev" />
|
|
||||||
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
33
package-lock.json
generated
33
package-lock.json
generated
@ -43,6 +43,7 @@
|
|||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
|
"keen-slider": "^6.8.6",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@ -50,7 +51,7 @@
|
|||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-resizable-panels": "^2.1.3",
|
"react-resizable-panels": "^2.1.3",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.30.0",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"sonner": "^1.5.0",
|
"sonner": "^1.5.0",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.5.2",
|
||||||
@ -2310,9 +2311,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.20.0",
|
"version": "1.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
|
||||||
"integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==",
|
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@ -4942,6 +4943,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/keen-slider": {
|
||||||
|
"version": "6.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/keen-slider/-/keen-slider-6.8.6.tgz",
|
||||||
|
"integrity": "sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
@ -6117,12 +6124,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.27.0",
|
"version": "6.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz",
|
||||||
"integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==",
|
"integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.20.0"
|
"@remix-run/router": "1.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@ -6132,13 +6139,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.27.0",
|
"version": "6.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz",
|
||||||
"integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==",
|
"integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.20.0",
|
"@remix-run/router": "1.23.0",
|
||||||
"react-router": "6.27.0"
|
"react-router": "6.30.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
|
"keen-slider": "^6.8.6",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@ -53,7 +54,7 @@
|
|||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-resizable-panels": "^2.1.3",
|
"react-resizable-panels": "^2.1.3",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.30.0",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"sonner": "^1.5.0",
|
"sonner": "^1.5.0",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.5.2",
|
||||||
|
|||||||
BIN
public/images/abteilung-bg.jpg
Normal file
BIN
public/images/abteilung-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
@ -15,7 +15,7 @@ const Footer = () => {
|
|||||||
<span className="font-bold text-xl">TG Laudenbach</span>
|
<span className="font-bold text-xl">TG Laudenbach</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-gray-400">
|
<p className="text-gray-400">
|
||||||
Volleyball mit Leidenschaft und Teamgeist seit 1975.
|
Volleyball seit 1974.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<Button variant="ghost" size="icon" className="text-gray-400 hover:text-white">
|
<Button variant="ghost" size="icon" className="text-gray-400 hover:text-white">
|
||||||
|
|||||||
@ -1,24 +1,28 @@
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Volleyball } from "lucide-react";
|
import { Volleyball } from "lucide-react";
|
||||||
|
|
||||||
const Hero = () => {
|
const Hero = () => {
|
||||||
return (
|
return (
|
||||||
<div className="hero-pattern pt-28 pb-16">
|
<div
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
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="flex flex-col md:flex-row items-center">
|
||||||
<div className="md:w-1/2 text-white">
|
<div className="md:w-1/2 text-white">
|
||||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold">
|
<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>
|
</h1>
|
||||||
<p className="mt-4 text-lg md:text-xl">
|
<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>
|
</p>
|
||||||
<div className="mt-8 flex flex-wrap gap-4">
|
<div className="mt-8 flex flex-wrap gap-4">
|
||||||
<Button className="bg-white text-frog-700 hover:bg-gray-100">
|
<Button className="bg-white text-frog-700 hover:bg-gray-100">
|
||||||
Training besuchen
|
Training besuchen
|
||||||
</Button>
|
</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
|
Teams kennenlernen
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Menu, X, Volleyball } from "lucide-react";
|
import { Menu, X, Volleyball } from "lucide-react";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
const Navbar = () => {
|
const Navbar = () => {
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
@ -11,7 +12,7 @@ const Navbar = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
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="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 justify-between h-16 items-center">
|
||||||
<div className="flex 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="#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="#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>
|
<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>
|
</div>
|
||||||
|
|
||||||
{/* Mobile menu button */}
|
{/* Mobile menu button */}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ArrowRight } from "lucide-react";
|
import { ArrowRight } from "lucide-react";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
const NewsSection = () => {
|
const NewsSection = () => {
|
||||||
const news = [
|
const news = [
|
||||||
@ -59,9 +60,11 @@ const NewsSection = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center mt-12">
|
<div className="text-center mt-12">
|
||||||
|
<Link to="/alle-neuigkeiten">
|
||||||
<Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50">
|
<Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||||
Alle Neuigkeiten
|
Alle Neuigkeiten
|
||||||
</Button>
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</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 { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Users } from "lucide-react";
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
const TeamSection = () => {
|
const TeamSection = () => {
|
||||||
const teams = [
|
const teams = [
|
||||||
@ -32,20 +34,68 @@ const TeamSection = () => {
|
|||||||
league: "Hobby",
|
league: "Hobby",
|
||||||
description: "Für alle, die Volleyball zum Spaß spielen möchten. Anfänger und Fortgeschrittene sind willkommen!",
|
description: "Für alle, die Volleyball zum Spaß spielen möchten. Anfänger und Fortgeschrittene sind willkommen!",
|
||||||
trainingTimes: "Mo 18:00 - 20:00 Uhr"
|
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 (
|
return (
|
||||||
<section id="team" className="py-16">
|
<section id="team" className="py-16">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<h2 className="text-3xl font-bold text-gray-900">Unsere Teams</h2>
|
<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>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<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) => (
|
{teams.map((team) => (
|
||||||
<Card key={team.id} className="hover:shadow-lg transition-shadow border-t-4 border-t-frog-500">
|
<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>
|
<CardHeader>
|
||||||
<CardTitle className="flex items-center">
|
<CardTitle className="flex items-center">
|
||||||
<Users className="h-5 w-5 mr-2 text-frog-500" />
|
<Users className="h-5 w-5 mr-2 text-frog-500" />
|
||||||
@ -60,14 +110,18 @@ const TeamSection = () => {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter>
|
<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">
|
<Button variant="outline" size="sm" className="w-full border-frog-500 text-frog-600 hover:bg-frog-50">
|
||||||
Team Details
|
Team Details
|
||||||
</Button>
|
</Button>
|
||||||
|
</Link>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</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 React from "react";
|
||||||
import App from './App.tsx'
|
import ReactDOM from "react-dom/client";
|
||||||
import './index.css'
|
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 = () => {
|
const Index = () => {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-white">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
|
||||||
<Hero />
|
<Hero />
|
||||||
<NewsSection />
|
<NewsSection />
|
||||||
<TeamSection />
|
<TeamSection />
|
||||||
<GallerySection />
|
<GallerySection />
|
||||||
<AboutSection />
|
<AboutSection />
|
||||||
<ContactSection />
|
<ContactSection />
|
||||||
<Footer />
|
|
||||||
</div>
|
</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
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import type { Config } from "tailwindcss";
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -13,108 +12,104 @@ export default {
|
|||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
padding: '2rem',
|
padding: "2rem",
|
||||||
screens: {
|
screens: {
|
||||||
'2xl': '1400px'
|
"2xl": "1400px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
backgroundImage: {
|
||||||
|
"hero-pattern": "url('/images/abteilung-bg.jpg')",
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: 'hsl(var(--border))',
|
border: "hsl(var(--border))",
|
||||||
input: 'hsl(var(--input))',
|
input: "hsl(var(--input))",
|
||||||
ring: 'hsl(var(--ring))',
|
ring: "hsl(var(--ring))",
|
||||||
background: 'hsl(var(--background))',
|
background: "hsl(var(--background))",
|
||||||
foreground: 'hsl(var(--foreground))',
|
foreground: "hsl(var(--foreground))",
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: 'hsl(var(--primary))',
|
DEFAULT: "hsl(var(--primary))",
|
||||||
foreground: 'hsl(var(--primary-foreground))'
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
DEFAULT: 'hsl(var(--secondary))',
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
foreground: 'hsl(var(--secondary-foreground))'
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
},
|
},
|
||||||
destructive: {
|
destructive: {
|
||||||
DEFAULT: 'hsl(var(--destructive))',
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
foreground: 'hsl(var(--destructive-foreground))'
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
},
|
},
|
||||||
muted: {
|
muted: {
|
||||||
DEFAULT: 'hsl(var(--muted))',
|
DEFAULT: "hsl(var(--muted))",
|
||||||
foreground: 'hsl(var(--muted-foreground))'
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
DEFAULT: 'hsl(var(--accent))',
|
DEFAULT: "hsl(var(--accent))",
|
||||||
foreground: 'hsl(var(--accent-foreground))'
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
},
|
},
|
||||||
popover: {
|
popover: {
|
||||||
DEFAULT: 'hsl(var(--popover))',
|
DEFAULT: "hsl(var(--popover))",
|
||||||
foreground: 'hsl(var(--popover-foreground))'
|
foreground: "hsl(var(--popover-foreground))",
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
DEFAULT: 'hsl(var(--card))',
|
DEFAULT: "hsl(var(--card))",
|
||||||
foreground: 'hsl(var(--card-foreground))'
|
foreground: "hsl(var(--card-foreground))",
|
||||||
},
|
},
|
||||||
sidebar: {
|
sidebar: {
|
||||||
DEFAULT: 'hsl(var(--sidebar-background))',
|
DEFAULT: "hsl(var(--sidebar-background))",
|
||||||
foreground: 'hsl(var(--sidebar-foreground))',
|
foreground: "hsl(var(--sidebar-foreground))",
|
||||||
primary: 'hsl(var(--sidebar-primary))',
|
primary: "hsl(var(--sidebar-primary))",
|
||||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
|
||||||
accent: 'hsl(var(--sidebar-accent))',
|
accent: "hsl(var(--sidebar-accent))",
|
||||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
|
||||||
border: 'hsl(var(--sidebar-border))',
|
border: "hsl(var(--sidebar-border))",
|
||||||
ring: 'hsl(var(--sidebar-ring))'
|
ring: "hsl(var(--sidebar-ring))",
|
||||||
},
|
},
|
||||||
frog: {
|
frog: {
|
||||||
50: '#f0fdf4',
|
50: "#f0fdf4",
|
||||||
100: '#dcfce7',
|
100: "#dcfce7",
|
||||||
200: '#bbf7d0',
|
200: "#bbf7d0",
|
||||||
300: '#86efac',
|
300: "#86efac",
|
||||||
400: '#4ade80',
|
400: "#4ade80",
|
||||||
500: '#4CAF50', // Hauptfarbe Froschgrün
|
500: "#4CAF50", // Hauptfarbe Froschgrün
|
||||||
600: '#16a34a',
|
600: "#16a34a",
|
||||||
700: '#15803d',
|
700: "#15803d",
|
||||||
800: '#166534',
|
800: "#166534",
|
||||||
900: '#14532d',
|
900: "#14532d",
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
lg: 'var(--radius)',
|
lg: "var(--radius)",
|
||||||
md: 'calc(var(--radius) - 2px)',
|
md: "calc(var(--radius) - 2px)",
|
||||||
sm: 'calc(var(--radius) - 4px)'
|
sm: "calc(var(--radius) - 4px)",
|
||||||
},
|
},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
'accordion-down': {
|
"accordion-down": {
|
||||||
from: {
|
from: { height: "0" },
|
||||||
height: '0'
|
to: { height: "var(--radix-accordion-content-height)" },
|
||||||
},
|
},
|
||||||
to: {
|
"accordion-up": {
|
||||||
height: 'var(--radix-accordion-content-height)'
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
}
|
to: { height: "0" },
|
||||||
},
|
},
|
||||||
'accordion-up': {
|
"bounce-slow": {
|
||||||
from: {
|
"0%, 100%": {
|
||||||
height: 'var(--radix-accordion-content-height)'
|
transform: "translateY(-5%)",
|
||||||
|
animationTimingFunction: "cubic-bezier(0.8, 0, 1, 1)",
|
||||||
},
|
},
|
||||||
to: {
|
"50%": {
|
||||||
height: '0'
|
transform: "translateY(0)",
|
||||||
}
|
animationTimingFunction: "cubic-bezier(0, 0, 0.2, 1)",
|
||||||
},
|
},
|
||||||
'bounce-slow': {
|
|
||||||
'0%, 100%': {
|
|
||||||
transform: 'translateY(-5%)',
|
|
||||||
animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)'
|
|
||||||
},
|
},
|
||||||
'50%': {
|
|
||||||
transform: 'translateY(0)',
|
|
||||||
animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
'bounce-slow': 'bounce-slow 3s infinite'
|
"bounce-slow": "bounce-slow 3s infinite",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [require("tailwindcss-animate")],
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user