"use client"
import { AnimatePresence, motion } from "motion/react"
import { useState } from "react"
import { ArrowUpRightIcon, CheckIcon, MoveHorizontalIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import type { TemplateProps } from "../../lib/types"
import { DemoForm } from "../shared/demo-form"
import { TField, TSelect } from "../shared/fields"
import { splitList } from "../shared/hooks"
import { TImage } from "../shared/media"
import { Counter, Marquee, Reveal, RevealWords, ease, useScrollNav, wordmarkSize } from "../shared/motion"
import { TemplateShell } from "../shared/shell"
import { fitness, type FitnessData } from "./definition"
import { fonts } from "./fonts"
const em = "text-t-accent"
const container = "mx-auto w-full max-w-[1440px] px-5 md:px-10"
const display = "font-t-display uppercase tracking-[-0.02em]"
const DAYS = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
function Eyebrow({ children }: { children: string }) {
return
— {children}
}
function SkewButton({ href, children, ghost }: { href: string; children: string; ghost?: boolean }) {
return (
{children}
)
}
export function FitnessTemplate({ content }: TemplateProps) {
const { brand, hero, stats, marquee, programs, classes, transformation, pricing, coaches, trial } = content.data
const show = (key: string) => !content.hidden.includes(key)
const links = [
{ href: "#training", label: "Training", visible: show("programs") },
{ href: "#kurse", label: "Kursplan", visible: show("classes") },
{ href: "#preise", label: "Preise", visible: show("pricing") },
{ href: "#team", label: "Coaches", visible: show("coaches") },
].filter((link) => link.visible)
return (
{hero.eyebrow}
{hero.text}
{hero.cta}
{show("classes") && {hero.ctaSecondary}}
{show("stats") && (
{stats.items.map((stat, i) => (
0 && "md:border-l md:border-t-fg/15 md:pl-8")}>
-
{stat.suffix}
- {stat.label}
))}
)}
{show("marquee") && (
)}
{show("programs") && }
{show("classes") && }
{show("transformation") && }
{show("pricing") && (
{pricing.eyebrow}
{pricing.plans.map((plan, i) => {
const featured = Boolean(plan.highlight.trim())
return (
{featured && Beliebt}
{plan.name}
{plan.price}€
{plan.period}
{splitList(plan.features, "\n").map((feature) => (
-
{feature}
))}
Jetzt starten
)
})}
)}
{show("coaches") && (
{coaches.eyebrow}
{coaches.members.map((member, i) => (
{member.name}
{member.role}
))}
)}
{trial.text}
{brand.address} · {brand.phone}
Let's go!
Wir melden uns heute noch mit deinem Termin fürs Probetraining.
}
>
item.name))]} />
)
}
function Nav({ name, cta, links }: { name: string; cta: string; links: { href: string; label: string }[] }) {
const { scrolled, hidden } = useScrollNav()
return (
)
}
function Programs({ programs }: { programs: FitnessData["programs"] }) {
const [active, setActive] = useState(0)
return (
{programs.eyebrow}
{programs.items.map((item, i) => {
const open = active === i
return (
)
})}
)
}
function Schedule({ classes }: { classes: FitnessData["classes"] }) {
const days = DAYS.filter((day) => classes.items.some((item) => item.day === day))
const [day, setDay] = useState(days[0] ?? "Mo")
const [booked, setBooked] = useState([])
const current = days.includes(day) ? day : days[0]
return (
{classes.eyebrow}
{days.map((d) => (
))}
{classes.items.filter((item) => item.day === current).map((item) => {
const id = `${item.day}-${item.time}-${item.name}`
const isBooked = booked.includes(id)
const level = Math.min(3, Math.max(1, Number(item.level) || 1))
return (
{item.time}
{item.name}
mit {item.trainer}
mit {item.trainer}
{[1, 2, 3].map((bar) => (
))}
)
})}
)
}
function Transformation({ data }: { data: FitnessData["transformation"] }) {
const [position, setPosition] = useState(50)
return (
{data.eyebrow}
{data.text}
„{data.quote}“
{data.before}
{data.after}
setPosition(Number(event.target.value))}
aria-label="Vorher/Nachher vergleichen"
className="absolute inset-0 h-full w-full cursor-ew-resize opacity-0"
/>
)
}