Seed: fitness template (17 files)
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||
import { CheckCircle, Plus, ArrowRight } from "lucide-react";
|
||||
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||
import { toast } from "sonner";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const tiers = [
|
||||
{
|
||||
name: "Basic",
|
||||
price: "$29",
|
||||
desc: "Perfect for getting started",
|
||||
features: ["Gym floor & free weights", "Locker room access", "2 group classes per week", "Fitness assessment", "Mobile app access"],
|
||||
popular: false,
|
||||
},
|
||||
{
|
||||
name: "Pro",
|
||||
price: "$59",
|
||||
desc: "For dedicated fitness enthusiasts",
|
||||
features: ["Everything in Basic", "Unlimited group classes", "Sauna & pool access", "1 personal training session/mo", "Custom nutrition plan", "2 guest passes/mo"],
|
||||
popular: true,
|
||||
},
|
||||
{
|
||||
name: "Elite",
|
||||
price: "$99",
|
||||
desc: "The ultimate training experience",
|
||||
features: ["Everything in Pro", "Unlimited PT sessions", "Recovery suite & cryo", "Priority class booking", "20% merch discount", "24/7 facility access", "VIP lounge"],
|
||||
popular: false,
|
||||
},
|
||||
];
|
||||
|
||||
const addons = [
|
||||
{ name: "Meal Prep Box", price: "+$15/week" },
|
||||
{ name: "Towel Service", price: "+$10/mo" },
|
||||
{ name: "Parking Pass", price: "+$20/mo" },
|
||||
];
|
||||
|
||||
const faqs = [
|
||||
{ q: "Is there a sign-up fee?", a: "Nope! We believe in transparent pricing. The monthly rate is all you pay." },
|
||||
{ q: "Can I freeze my membership?", a: "Yes, you can freeze for up to 3 months per year at no extra charge." },
|
||||
{ q: "What is the cancellation policy?", a: "Cancel anytime with 30 days notice. No penalties, no hassle." },
|
||||
{ q: "Do you offer student or military discounts?", a: "Absolutely! Show a valid ID and get 20% off any plan." },
|
||||
];
|
||||
|
||||
export default function Pricing() {
|
||||
const { mutate: subscribe, loading: subscribing } = useSaasMutation("billing", "/checkout");
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-950 text-white">
|
||||
<Header />
|
||||
|
||||
{/* ── Hero ── */}
|
||||
<section className="pt-32 pb-16 bg-gradient-to-b from-slate-900 to-slate-950">
|
||||
<div className="mx-auto max-w-7xl px-6 text-center">
|
||||
<Badge className="mb-4 bg-orange-500/10 text-orange-400 border-orange-500/30 uppercase text-xs tracking-wider">Pricing</Badge>
|
||||
<h1 className="text-4xl md:text-5xl font-black uppercase text-white animate-fade-up">INVEST IN YOURSELF</h1>
|
||||
<p className="mt-4 text-slate-400 max-w-xl mx-auto">No long-term contracts. Cancel anytime. Start with a free 7-day trial on any plan.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Tiers ── */}
|
||||
<section className="py-16">
|
||||
<div className="mx-auto max-w-6xl px-6">
|
||||
<div className="grid md:grid-cols-3 gap-8 stagger">
|
||||
{tiers.map((tier, i) => (
|
||||
<Card key={i} className={`relative bg-slate-900/80 backdrop-blur border transition-all duration-300 hover:-translate-y-1 \${tier.popular ? "border-orange-500/50 shadow-2xl shadow-orange-500/10 scale-105" : "border-slate-800 hover:border-slate-700"}`}>
|
||||
{tier.popular && <div className="absolute -top-3 left-1/2 -translate-x-1/2"><Badge className="bg-gradient-to-r from-orange-500 to-red-500 text-white border-0 uppercase text-xs tracking-wider px-4">Most Popular</Badge></div>}
|
||||
<CardContent className="p-8">
|
||||
<h3 className="text-lg font-bold uppercase text-slate-300">{tier.name}</h3>
|
||||
<p className="text-sm text-slate-500 mt-1">{tier.desc}</p>
|
||||
<div className="mt-6 mb-8">
|
||||
<span className="text-5xl font-black text-white">{tier.price}</span>
|
||||
<span className="text-slate-500">/mo</span>
|
||||
</div>
|
||||
<div className="space-y-3 mb-8">
|
||||
{tier.features.map((f, j) => (
|
||||
<div key={j} className="flex items-center gap-3 text-sm text-slate-300">
|
||||
<CheckCircle className="h-4 w-4 text-orange-400 shrink-0" />
|
||||
<span>{f}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button disabled={subscribing} className={`w-full font-bold uppercase tracking-wide rounded-full active:scale-[0.97] transition-all \${tier.popular ? "bg-gradient-to-r from-orange-500 to-red-500 hover:from-orange-600 hover:to-red-600 text-white shadow-lg shadow-orange-500/25" : "bg-slate-800 hover:bg-slate-700 text-white"}`} onClick={async () => { const amount = Math.round((parseFloat(String(tier.price).replace(/[^0-9.]/g, "")) || 0) * 100); try { const res = await subscribe({ plan: tier.name, amount }); if (res?.url && String(res.url).indexOf("#") !== 0) { window.location.href = res.url; return; } toast.success(`\${tier.name} membership selected`); } catch { toast.error("Checkout unavailable. Please try again."); } }}>
|
||||
Get {tier.name}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Add-ons ── */}
|
||||
<section className="py-16 bg-slate-900/50">
|
||||
<div className="mx-auto max-w-4xl px-6">
|
||||
<h2 className="text-2xl font-black uppercase text-white text-center mb-10 animate-fade-up">Add-ons</h2>
|
||||
<div className="grid sm:grid-cols-3 gap-6">
|
||||
{addons.map((a, i) => (
|
||||
<Card key={i} className="bg-slate-900/80 backdrop-blur border border-slate-800 hover:border-orange-500/30 hover:-translate-y-1 hover:shadow-lg transition-all duration-300">
|
||||
<CardContent className="p-6 text-center">
|
||||
<Plus className="h-8 w-8 text-orange-400 mx-auto mb-3" />
|
||||
<h3 className="font-bold text-white">{a.name}</h3>
|
||||
<p className="text-orange-400 font-bold mt-2">{a.price}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FAQ ── */}
|
||||
<section className="py-16">
|
||||
<div className="mx-auto max-w-3xl px-6">
|
||||
<h2 className="text-2xl font-black uppercase text-white text-center mb-10 animate-fade-up">Frequently Asked Questions</h2>
|
||||
<Accordion type="single" collapsible className="space-y-3">
|
||||
{faqs.map((faq, i) => (
|
||||
<AccordionItem key={i} value={`faq-\${i}`} className="bg-slate-900/80 backdrop-blur border border-slate-800 rounded-xl px-6">
|
||||
<AccordionTrigger className="text-white font-semibold text-left hover:no-underline hover:text-orange-400 transition-colors">{faq.q}</AccordionTrigger>
|
||||
<AccordionContent className="text-slate-400">{faq.a}</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user