Merge version_6 into main #17

Merged
bender merged 5 commits from version_6 into main 2026-03-11 20:24:21 +00:00
5 changed files with 761 additions and 15 deletions

View File

@@ -0,0 +1,88 @@
import { NextRequest, NextResponse } from 'next/server';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
const DB_FILE = path.join(process.cwd(), 'data', 'users.json');
interface User {
id: string;
name: string;
email: string;
passwordHash: string;
createdAt: string;
}
function ensureDbDirectory() {
const dir = path.dirname(DB_FILE);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
function hashPassword(password: string): string {
return crypto.createHash('sha256').update(password).digest('hex');
}
function getUsers(): User[] {
try {
if (fs.existsSync(DB_FILE)) {
const data = fs.readFileSync(DB_FILE, 'utf-8');
return JSON.parse(data);
}
} catch (error) {
console.error('Error reading users file:', error);
}
return [];
}
function saveUsers(users: User[]) {
ensureDbDirectory();
fs.writeFileSync(DB_FILE, JSON.stringify(users, null, 2));
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { name, email, password } = body;
if (!name || !email || !password) {
return NextResponse.json(
{ message: 'Missing required fields' },
{ status: 400 }
);
}
const users = getUsers();
const existingUser = users.find(u => u.email === email);
if (existingUser) {
return NextResponse.json(
{ message: 'Email already registered' },
{ status: 409 }
);
}
const newUser: User = {
id: crypto.randomUUID(),
name,
email,
passwordHash: hashPassword(password),
createdAt: new Date().toISOString(),
};
users.push(newUser);
saveUsers(users);
return NextResponse.json(
{ message: 'User registered successfully', userId: newUser.id },
{ status: 201 }
);
} catch (error) {
console.error('Registration error:', error);
return NextResponse.json(
{ message: 'Internal server error' },
{ status: 500 }
);
}
}

168
src/app/auth/login/page.tsx Normal file
View File

@@ -0,0 +1,168 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterBase from '@/components/sections/footer/FooterBase';
import Input from '@/components/form/Input';
import ButtonDirectionalHover from '@/components/button/ButtonDirectionalHover/ButtonDirectionalHover';
import { Mail, Lock, LogIn } from 'lucide-react';
export default function LoginPage() {
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
setIsLoading(true);
try {
const response = await fetch("/api/auth/login", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
const data = await response.json();
throw new Error(data.message || "Login failed");
}
router.push("/dashboard");
} catch (err: any) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
return (
<ThemeProvider
defaultButtonVariant="elastic-effect"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="smallMedium"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="gradient-bordered"
primaryButtonStyle="flat"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "/" },
{ name: "Treino", id: "training" },
{ name: "Nutrição", id: "nutrition" },
]}
button={{ text: "Registrar", href: "/auth/register" }}
brandName="FitFlow Pro"
/>
</div>
<div className="min-h-[calc(100vh-200px)] flex items-center justify-center py-20 px-4">
<div className="w-full max-w-md">
<div className="bg-card rounded-2xl p-8 shadow-lg border border-accent/20">
<div className="mb-8 text-center">
<div className="flex items-center justify-center mb-4 gap-2">
<LogIn className="w-8 h-8 text-primary-cta" />
<h1 className="text-3xl font-extrabold text-foreground">Login</h1>
</div>
<p className="text-foreground/70 text-sm">Acesse sua conta FitFlow Pro</p>
</div>
<form onSubmit={handleLogin} className="space-y-6">
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Email
</label>
<div className="relative">
<Mail className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={email}
onChange={setEmail}
type="email"
placeholder="seu.email@exemplo.com"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Senha
</label>
<div className="relative">
<Lock className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={password}
onChange={setPassword}
type="password"
placeholder="Sua senha segura"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
{error && (
<div className="p-4 bg-red-500/10 border border-red-500/30 rounded-lg">
<p className="text-red-600 text-sm font-medium">{error}</p>
</div>
)}
<div className="flex gap-3">
<ButtonDirectionalHover
text={isLoading ? "Entrando..." : "Entrar"}
onClick={handleLogin}
disabled={isLoading}
className="flex-1"
/>
</div>
</form>
<div className="mt-6 pt-6 border-t border-accent/20 text-center">
<p className="text-foreground/70 text-sm">
Não tem conta?{" "}
<a href="/auth/register" className="text-primary-cta hover:text-primary-cta/80 font-semibold">
Registre-se
</a>
</p>
</div>
</div>
</div>
</div>
<div id="footer" data-section="footer">
<FooterBase
columns={[
{
title: "Produto", items: [
{ label: "Dashboard", href: "dashboard" },
{ label: "Treino", href: "training" },
{ label: "Nutrição", href: "nutrition" },
]
},
{
title: "Empresa", items: [
{ label: "Sobre", href: "/" },
{ label: "Contato", href: "contact" },
{ label: "Privacidade", href: "privacy" },
]
}
]}
logoText="FitFlow Pro"
copyrightText="© 2025 FitFlow Pro. Todos os direitos reservados."
/>
</div>
</ThemeProvider>
);
}

View File

@@ -0,0 +1,212 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterBase from '@/components/sections/footer/FooterBase';
import Input from '@/components/form/Input';
import ButtonDirectionalHover from '@/components/button/ButtonDirectionalHover/ButtonDirectionalHover';
import { Mail, Lock, User, UserPlus } from 'lucide-react';
export default function RegisterPage() {
const router = useRouter();
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleRegister = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (password !== confirmPassword) {
setError("Senhas não correspondem");
return;
}
setIsLoading(true);
try {
const response = await fetch("/api/auth/register", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, email, password }),
});
if (!response.ok) {
const data = await response.json();
throw new Error(data.message || "Registration failed");
}
router.push("/auth/login?registered=true");
} catch (err: any) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
return (
<ThemeProvider
defaultButtonVariant="elastic-effect"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="smallMedium"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="gradient-bordered"
primaryButtonStyle="flat"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "/" },
{ name: "Treino", id: "training" },
{ name: "Nutrição", id: "nutrition" },
]}
button={{ text: "Login", href: "/auth/login" }}
brandName="FitFlow Pro"
/>
</div>
<div className="min-h-[calc(100vh-200px)] flex items-center justify-center py-20 px-4">
<div className="w-full max-w-md">
<div className="bg-card rounded-2xl p-8 shadow-lg border border-accent/20">
<div className="mb-8 text-center">
<div className="flex items-center justify-center mb-4 gap-2">
<UserPlus className="w-8 h-8 text-primary-cta" />
<h1 className="text-3xl font-extrabold text-foreground">Registrar</h1>
</div>
<p className="text-foreground/70 text-sm">Crie sua conta FitFlow Pro</p>
</div>
<form onSubmit={handleRegister} className="space-y-5">
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Nome Completo
</label>
<div className="relative">
<User className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={name}
onChange={setName}
type="text"
placeholder="Seu nome completo"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Email
</label>
<div className="relative">
<Mail className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={email}
onChange={setEmail}
type="email"
placeholder="seu.email@exemplo.com"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Senha
</label>
<div className="relative">
<Lock className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={password}
onChange={setPassword}
type="password"
placeholder="Sua senha segura"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Confirmar Senha
</label>
<div className="relative">
<Lock className="absolute left-3 top-3 w-5 h-5 text-accent/50" />
<Input
value={confirmPassword}
onChange={setConfirmPassword}
type="password"
placeholder="Confirme sua senha"
required
disabled={isLoading}
className="pl-10"
/>
</div>
</div>
{error && (
<div className="p-4 bg-red-500/10 border border-red-500/30 rounded-lg">
<p className="text-red-600 text-sm font-medium">{error}</p>
</div>
)}
<div className="flex gap-3">
<ButtonDirectionalHover
text={isLoading ? "Registrando..." : "Criar Conta"}
onClick={handleRegister}
disabled={isLoading}
className="flex-1"
/>
</div>
</form>
<div className="mt-6 pt-6 border-t border-accent/20 text-center">
<p className="text-foreground/70 text-sm">
tem conta?{" "}
<a href="/auth/login" className="text-primary-cta hover:text-primary-cta/80 font-semibold">
Faça login
</a>
</p>
</div>
</div>
</div>
</div>
<div id="footer" data-section="footer">
<FooterBase
columns={[
{
title: "Produto", items: [
{ label: "Dashboard", href: "dashboard" },
{ label: "Treino", href: "training" },
{ label: "Nutrição", href: "nutrition" },
]
},
{
title: "Empresa", items: [
{ label: "Sobre", href: "/" },
{ label: "Contato", href: "contact" },
{ label: "Privacidade", href: "privacy" },
]
}
]}
logoText="FitFlow Pro"
copyrightText="© 2025 FitFlow Pro. Todos os direitos reservados."
/>
</div>
</ThemeProvider>
);
}

View File

@@ -34,8 +34,9 @@ export default function LandingPage() {
{ name: "Dashboard", id: "dashboard" },
{ name: "Treino", id: "training" },
{ name: "Nutrição", id: "nutrition" },
{ name: "Receitas", id: "/recipes" },
{ name: "Comunidade", id: "community" },
{ name: "Perfil", id: "onboarding" }
{ name: "Perfil", id: "profile" }
]}
button={{ text: "Começar Agora", href: "contact" }}
brandName="FitFlow Pro"
@@ -212,12 +213,14 @@ export default function LandingPage() {
tagIcon={Apple}
plans={[
{
id: "deficit", badge: "Perda de Peso", price: "Déficit Calórico", subtitle: "Receitas otimizadas para queima de calorias", features: [
id: "deficit", badge: "Perda de Peso", badgeIcon: TrendingDown,
price: "Déficit Calórico", subtitle: "Receitas otimizadas para queima de calorias", features: [
"Macros calculados automaticamente", "Prep time entre 15-30 min", "Proteína alta, carboidrato estratégico", "Rastreamento integrado", "Sugestões diárias personalizadas"
]
},
{
id: "surplus", badge: "Ganho de Massa", price: "Superávit Estratégico", subtitle: "Nutrição para crescimento muscular", features: [
id: "surplus", badge: "Ganho de Massa", badgeIcon: TrendingUp,
price: "Superávit Estratégico", subtitle: "Nutrição para crescimento muscular", features: [
"Calorias calculadas para ganho", "Proteína máxima (2g por kg)", "Carbos pré e pós-treino", "Tempo de preparo eficiente", "Sincronizado com treino de força"
]
}
@@ -260,16 +263,16 @@ export default function LandingPage() {
tagIcon={Users}
members={[
{
id: "1", name: "Marcus A.", role: "Elite Runner", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/professional-athlete-portrait-male-fitne-1773256979726-5009f852.png?_wi=1"
id: "1", name: "Marcus A.", role: "Elite Runner", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/professional-athlete-portrait-male-fitne-1773256979726-5009f852.png?_wi=1", imageAlt: "Marcus A."
},
{
id: "2", name: "Ana L.", role: "Strength Coach", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/fit-female-athlete-portrait-determined-e-1773256980310-c05dce2f.png?_wi=1"
id: "2", name: "Ana L.", role: "Strength Coach", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/fit-female-athlete-portrait-determined-e-1773256980310-c05dce2f.png?_wi=1", imageAlt: "Ana L."
},
{
id: "3", name: "Rafael S.", role: "Nutrition Expert", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/athletic-male-trainer-portrait-confident-1773256979906-c5e05a88.png?_wi=1"
id: "3", name: "Rafael S.", role: "Nutrition Expert", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/athletic-male-trainer-portrait-confident-1773256979906-c5e05a88.png?_wi=1", imageAlt: "Rafael S."
},
{
id: "4", name: "Sofia M.", role: "Fitness Trainer", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-fitness-coach-portrait-profession-1773256979710-97e8b5fe.png?_wi=1"
id: "4", name: "Sofia M.", role: "Fitness Trainer", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-fitness-coach-portrait-profession-1773256979710-97e8b5fe.png?_wi=1", imageAlt: "Sofia M."
}
]}
animationType="blur-reveal"
@@ -283,22 +286,22 @@ export default function LandingPage() {
<TestimonialCardTwelve
testimonials={[
{
id: "1", name: "Carlos M.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/professional-athlete-portrait-male-fitne-1773256979726-5009f852.png?_wi=2"
id: "1", name: "Carlos M.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/professional-athlete-portrait-male-fitne-1773256979726-5009f852.png?_wi=2", imageAlt: "Carlos M."
},
{
id: "2", name: "Beatriz R.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/fit-female-athlete-portrait-determined-e-1773256980310-c05dce2f.png?_wi=2"
id: "2", name: "Beatriz R.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/fit-female-athlete-portrait-determined-e-1773256980310-c05dce2f.png?_wi=2", imageAlt: "Beatriz R."
},
{
id: "3", name: "Diego P.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/athletic-male-trainer-portrait-confident-1773256979906-c5e05a88.png?_wi=2"
id: "3", name: "Diego P.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/athletic-male-trainer-portrait-confident-1773256979906-c5e05a88.png?_wi=2", imageAlt: "Diego P."
},
{
id: "4", name: "Juliana T.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-fitness-coach-portrait-profession-1773256979710-97e8b5fe.png?_wi=2"
id: "4", name: "Juliana T.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-fitness-coach-portrait-profession-1773256979710-97e8b5fe.png?_wi=2", imageAlt: "Juliana T."
},
{
id: "5", name: "Lucas F.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/young-athlete-male-portrait-energetic-ex-1773256982698-63e4e494.png"
id: "5", name: "Lucas F.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/young-athlete-male-portrait-energetic-ex-1773256982698-63e4e494.png", imageAlt: "Lucas F."
},
{
id: "6", name: "Marina S.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-athlete-portrait-fit-build-profes-1773256980134-0faaa8fa.png"
id: "6", name: "Marina S.", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-athlete-portrait-fit-build-profes-1773256980134-0faaa8fa.png", imageAlt: "Marina S."
}
]}
cardTitle="Mais de 150 mil atletas já transformaram seu corpo com FitFlow Pro"
@@ -354,13 +357,13 @@ export default function LandingPage() {
{ label: "Dashboard", href: "dashboard" },
{ label: "Treino", href: "training" },
{ label: "Nutrição", href: "nutrition" },
{ label: "Cardio Hub", href: "cardio" }
{ label: "Receitas", href: "/recipes" }
]
},
{
title: "Comunidade", items: [
{ label: "Comunidade", href: "community" },
{ label: "Perfil", href: "onboarding" },
{ label: "Perfil", href: "profile" },
{ label: "Rankings", href: "rankings" },
{ label: "Blog", href: "blog" }
]

275
src/app/recipes/page.tsx Normal file
View File

@@ -0,0 +1,275 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import HeroSplitKpi from '@/components/sections/hero/HeroSplitKpi';
import ProductCardTwo from '@/components/sections/product/ProductCardTwo';
import ContactSplit from '@/components/sections/contact/ContactSplit';
import FooterBase from '@/components/sections/footer/FooterBase';
import { useState } from 'react';
import { Flame, Target, TrendingDown, TrendingUp, Mail } from 'lucide-react';
interface Recipe {
id: string;
brand: string;
name: string;
price: string;
rating: number;
reviewCount: string;
imageSrc: string;
imageAlt: string;
goal: 'weight-loss' | 'muscle-gain';
}
const recipes: Recipe[] = [
{
id: '1',
brand: 'Deficit Smart',
name: 'Grilled Chicken Salad Bowl',
price: '380 cal',
rating: 5,
reviewCount: '2.3k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/ultra-modern-fitness-app-dashboard-with--1773256981295-f56c580b.png',
imageAlt: 'Grilled Chicken Salad',
goal: 'weight-loss'
},
{
id: '2',
brand: 'Lean Protein',
name: 'Egg White Omelette',
price: '250 cal',
rating: 4,
reviewCount: '1.8k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/nutrition-dashboard-showing-meal-plans-d-1773256981349-9348b6d9.png',
imageAlt: 'Egg White Omelette',
goal: 'weight-loss'
},
{
id: '3',
brand: 'Surplus Gains',
name: 'Protein Pasta with Salmon',
price: '650 cal',
rating: 5,
reviewCount: '3.1k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/premium-onboarding-screen-for-fitness-ap-1773256981180-774b293c.png',
imageAlt: 'Protein Pasta with Salmon',
goal: 'muscle-gain'
},
{
id: '4',
brand: 'Bulk Smart',
name: 'Rice & Chicken Combo',
price: '720 cal',
rating: 5,
reviewCount: '2.9k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/performance-metrics-showcase-displaying--1773256982260-f9a5cff0.png',
imageAlt: 'Rice & Chicken Combo',
goal: 'muscle-gain'
},
{
id: '5',
brand: 'Low Cal',
name: 'Zucchini Noodles',
price: '150 cal',
rating: 4,
reviewCount: '1.2k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/gps-running-tracker-interface-with-real--1773256980694-2abe167e.png',
imageAlt: 'Zucchini Noodles',
goal: 'weight-loss'
},
{
id: '6',
brand: 'Muscle Builder',
name: 'Sweet Potato & Steak',
price: '800 cal',
rating: 5,
reviewCount: '2.7k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/interactive-anatomical-body-model-showin-1773256980448-3cccd7b3.png',
imageAlt: 'Sweet Potato & Steak',
goal: 'muscle-gain'
},
{
id: '7',
brand: 'Keto Smart',
name: 'Avocado & Salmon Bowl',
price: '420 cal',
rating: 4,
reviewCount: '1.9k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/workout-execution-interface-showing-set--1773256980664-da11c464.png',
imageAlt: 'Avocado & Salmon Bowl',
goal: 'weight-loss'
},
{
id: '8',
brand: 'Protein Max',
name: 'Greek Yogurt Parfait',
price: '580 cal',
rating: 5,
reviewCount: '2.5k',
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/female-athlete-portrait-fit-build-profes-1773256980134-0faaa8fa.png',
imageAlt: 'Greek Yogurt Parfait',
goal: 'muscle-gain'
}
];
export default function RecipesPage() {
const [activeGoal, setActiveGoal] = useState<'weight-loss' | 'muscle-gain' | 'all'>('all');
const filteredRecipes = activeGoal === 'all'
? recipes
: recipes.filter(recipe => recipe.goal === activeGoal);
return (
<ThemeProvider
defaultButtonVariant="elastic-effect"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="smallMedium"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="gradient-bordered"
primaryButtonStyle="flat"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Dashboard", id: "dashboard" },
{ name: "Treino", id: "training" },
{ name: "Nutrição", id: "nutrition" },
{ name: "Receitas", id: "/recipes" },
{ name: "Comunidade", id: "community" },
{ name: "Perfil", id: "profile" }
]}
button={{ text: "Começar Agora", href: "contact" }}
brandName="FitFlow Pro"
/>
</div>
<div id="hero" data-section="hero">
<HeroSplitKpi
title="Receitas Inteligentes para Seu Objetivo"
description="Explore receitas selecionadas especificamente para suas metas de fitness. Filtro por objetivo de perda de peso ou ganho de massa muscular. Cada receita inclui macros calculados, tempo de preparo e recomendações nutricionais."
tag="Receituário Inteligente"
tagIcon={Flame}
background={{ variant: "glowing-orb" }}
kpis={[
{ value: "500+", label: "Receitas" },
{ value: "30min", label: "Prep Time Médio" },
{ value: "4.8★", label: "Avaliação" }
]}
enableKpiAnimation={true}
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/nutrition-dashboard-showing-meal-plans-d-1773256981349-9348b6d9.png"
imageAlt="Receitas inteligentes"
imagePosition="right"
mediaAnimation="slide-up"
buttons={[
{ text: "Explorar Receitas", href: "#recipes" }
]}
/>
</div>
<div id="recipes" data-section="recipes" className="py-16 md:py-24">
<div className="container mx-auto px-4">
<div className="mb-12 text-center">
<h2 className="text-2xl md:text-4xl font-bold mb-6">Filtrar por Objetivo</h2>
<div className="flex flex-wrap gap-4 justify-center">
<button
onClick={() => setActiveGoal('all')}
className={`px-6 py-3 rounded-full font-semibold transition-all duration-300 ${
activeGoal === 'all'
? 'bg-primary-cta text-white shadow-lg'
: 'bg-secondary-cta bg-opacity-50 hover:bg-opacity-100'
}`}
>
Todas as Receitas
</button>
<button
onClick={() => setActiveGoal('weight-loss')}
className={`px-6 py-3 rounded-full font-semibold transition-all duration-300 flex items-center gap-2 ${
activeGoal === 'weight-loss'
? 'bg-primary-cta text-white shadow-lg'
: 'bg-secondary-cta bg-opacity-50 hover:bg-opacity-100'
}`}
>
<TrendingDown className="w-4 h-4" />
Perda de Peso
</button>
<button
onClick={() => setActiveGoal('muscle-gain')}
className={`px-6 py-3 rounded-full font-semibold transition-all duration-300 flex items-center gap-2 ${
activeGoal === 'muscle-gain'
? 'bg-primary-cta text-white shadow-lg'
: 'bg-secondary-cta bg-opacity-50 hover:bg-opacity-100'
}`}
>
<TrendingUp className="w-4 h-4" />
Ganho de Massa
</button>
</div>
</div>
<ProductCardTwo
products={filteredRecipes}
animationType="slide-up"
textboxLayout="default"
useInvertedBackground={false}
gridVariant="three-columns-all-equal-width"
/>
</div>
</div>
<div id="contact" data-section="contact">
<ContactSplit
tag="Dica Nutricional"
tagIcon={Mail}
title="Receba Receitas Personalizadas"
description="Inscreva-se para receber receitas semanais personalizadas baseadas em suas metas e preferências alimentares. Nossos nutricionistas selecionam as melhores opções para você."
background={{ variant: "sparkles-gradient" }}
useInvertedBackground={false}
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/nutrition-dashboard-showing-meal-plans-d-1773256981349-9348b6d9.png"
imageAlt="Receitas personalizadas"
mediaAnimation="slide-up"
mediaPosition="right"
inputPlaceholder="seu.email@exemplo.com"
buttonText="Inscrever-se"
termsText="Você receberá sugestões de receitas toda segunda-feira. Sem spam, promessa."
/>
</div>
<div id="footer" data-section="footer">
<FooterBase
columns={[
{
title: "Produto", items: [
{ label: "Dashboard", href: "dashboard" },
{ label: "Treino", href: "training" },
{ label: "Nutrição", href: "nutrition" },
{ label: "Receitas", href: "/recipes" }
]
},
{
title: "Comunidade", items: [
{ label: "Comunidade", href: "community" },
{ label: "Perfil", href: "profile" },
{ label: "Rankings", href: "rankings" },
{ label: "Blog", href: "blog" }
]
},
{
title: "Empresa", items: [
{ label: "Sobre", href: "about" },
{ label: "Contato", href: "contact" },
{ label: "Privacidade", href: "privacy" },
{ label: "Termos", href: "terms" }
]
}
]}
logoText="FitFlow Pro"
copyrightText="© 2025 FitFlow Pro. Todos os direitos reservados."
/>
</div>
</ThemeProvider>
);
}