Merge version_4 into main #6
418
src/app/app/page.tsx
Normal file
418
src/app/app/page.tsx
Normal file
@@ -0,0 +1,418 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import FooterMedia from '@/components/sections/footer/FooterMedia';
|
||||
import { useState, useEffect } from "react";
|
||||
import { ChefHat, LogOut, User, Heart, Settings, Plus, X, Sparkles, Clock, Users2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function AppPage() {
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const [user, setUser] = useState<any>(null);
|
||||
const [ingredients, setIngredients] = useState<string[]>([]);
|
||||
const [currentInput, setCurrentInput] = useState("");
|
||||
const [recipes, setRecipes] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [savedRecipes, setSavedRecipes] = useState<any[]>([]);
|
||||
const [showSavedOnly, setShowSavedOnly] = useState(false);
|
||||
const [showProfile, setShowProfile] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if user is logged in
|
||||
const checkAuth = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/auth/me');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setUser(data.user);
|
||||
setIsLoggedIn(true);
|
||||
setSavedRecipes(data.user.savedRecipes || []);
|
||||
} else {
|
||||
window.location.href = '/auth';
|
||||
}
|
||||
} catch (error) {
|
||||
window.location.href = '/auth';
|
||||
}
|
||||
};
|
||||
checkAuth();
|
||||
}, []);
|
||||
|
||||
const addIngredient = () => {
|
||||
if (currentInput.trim()) {
|
||||
setIngredients([...ingredients, currentInput.trim()]);
|
||||
setCurrentInput("");
|
||||
}
|
||||
};
|
||||
|
||||
const removeIngredient = (index: number) => {
|
||||
setIngredients(ingredients.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
const handleKeyPress = (e: React.KeyboardEvent) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
addIngredient();
|
||||
}
|
||||
};
|
||||
|
||||
const generateRecipes = async () => {
|
||||
if (ingredients.length === 0) {
|
||||
alert("Please add at least one ingredient");
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch("/api/recipes/generate", {
|
||||
method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ ingredients })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setRecipes(data.recipes || []);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Recipe generation failed:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const saveRecipe = async (recipe: any) => {
|
||||
try {
|
||||
const response = await fetch("/api/recipes/save", {
|
||||
method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ recipe })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setSavedRecipes([...savedRecipes, recipe]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to save recipe:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await fetch("/api/auth/logout", { method: "POST" });
|
||||
window.location.href = "/";
|
||||
} catch (error) {
|
||||
console.error("Logout failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!isLoggedIn || !user) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="expand-hover"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="none"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="inline-block animate-spin mb-4">
|
||||
<Sparkles size={40} className="text-purple-600" />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300">Loading your kitchen...</p>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const displayRecipes = showSavedOnly ? savedRecipes : recipes;
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="expand-hover"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="none"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleFullscreen
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/#features" },
|
||||
{ name: "Auth", id: "/auth" },
|
||||
{ name: "App", id: "/app" },
|
||||
{ name: "Contact", id: "/#contact" }
|
||||
]}
|
||||
bottomLeftText={`Welcome, ${user?.fullName}`}
|
||||
bottomRightText={user?.email}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="app" data-section="app" className="min-h-screen py-20 px-4 bg-gradient-to-br from-purple-50 via-white to-blue-50 dark:from-gray-950 dark:via-gray-900 dark:to-gray-950">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Header with Profile */}
|
||||
<div className="flex items-center justify-between mb-12">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-16 h-16 bg-gradient-to-r from-purple-600 to-blue-600 rounded-full flex items-center justify-center">
|
||||
<ChefHat size={32} className="text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">Welcome back!</h1>
|
||||
<p className="text-gray-600 dark:text-gray-400">{user?.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => setShowProfile(!showProfile)}
|
||||
className="p-3 bg-white dark:bg-gray-800 rounded-full shadow-lg hover:shadow-xl transition-shadow"
|
||||
>
|
||||
<User size={20} className="text-gray-600 dark:text-gray-300" />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="p-3 bg-red-500/10 hover:bg-red-500/20 rounded-full transition-colors"
|
||||
>
|
||||
<LogOut size={20} className="text-red-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Profile Card */}
|
||||
{showProfile && (
|
||||
<div className="mb-8 backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-3xl p-8 shadow-xl">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">Your Profile</h2>
|
||||
<button onClick={() => setShowProfile(false)}>
|
||||
<X size={24} className="text-gray-600 dark:text-gray-300" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-gradient-to-br from-purple-500/20 to-blue-500/20 rounded-2xl p-6">
|
||||
<p className="text-gray-600 dark:text-gray-400 text-sm">Full Name</p>
|
||||
<p className="text-xl font-bold text-gray-900 dark:text-white">{user?.fullName}</p>
|
||||
</div>
|
||||
<div className="bg-gradient-to-br from-purple-500/20 to-blue-500/20 rounded-2xl p-6">
|
||||
<p className="text-gray-600 dark:text-gray-400 text-sm">Email</p>
|
||||
<p className="text-xl font-bold text-gray-900 dark:text-white break-all">{user?.email}</p>
|
||||
</div>
|
||||
<div className="bg-gradient-to-br from-purple-500/20 to-blue-500/20 rounded-2xl p-6">
|
||||
<p className="text-gray-600 dark:text-gray-400 text-sm">Saved Recipes</p>
|
||||
<p className="text-xl font-bold text-gray-900 dark:text-white">{savedRecipes.length}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button className="mt-6 w-full py-3 bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white rounded-xl font-semibold flex items-center justify-center gap-2 transition-all">
|
||||
<Settings size={20} />
|
||||
Account Settings
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Main Generator Section */}
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
{/* Left - Ingredient Input */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-3xl p-8 shadow-xl sticky top-24">
|
||||
<h3 className="text-xl font-bold mb-6 text-gray-900 dark:text-white flex items-center gap-2">
|
||||
<Plus size={24} />
|
||||
Your Ingredients
|
||||
</h3>
|
||||
|
||||
{/* Input */}
|
||||
<div className="flex gap-2 mb-6">
|
||||
<input
|
||||
type="text"
|
||||
value={currentInput}
|
||||
onChange={(e) => setCurrentInput(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
placeholder="e.g., chicken"
|
||||
className="flex-1 px-4 py-2.5 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:border-purple-500 dark:bg-white/5 dark:border-white/10 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
||||
/>
|
||||
<button
|
||||
onClick={addIngredient}
|
||||
className="px-4 py-2.5 bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white rounded-xl font-semibold transition-all"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Ingredients List */}
|
||||
{ingredients.length > 0 && (
|
||||
<div className="mb-8">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-3">Added ({ingredients.length}):</h4>
|
||||
<div className="space-y-2">
|
||||
{ingredients.map((ingredient, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center justify-between bg-gradient-to-r from-purple-500/20 to-blue-500/20 px-4 py-2 rounded-xl"
|
||||
>
|
||||
<span className="text-gray-900 dark:text-white font-medium">{ingredient}</span>
|
||||
<button
|
||||
onClick={() => removeIngredient(index)}
|
||||
className="text-red-500 hover:text-red-600 transition-colors"
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Generate Button */}
|
||||
<button
|
||||
onClick={generateRecipes}
|
||||
disabled={loading || ingredients.length === 0}
|
||||
className="w-full py-3 bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 disabled:opacity-50 disabled:cursor-not-allowed text-white rounded-xl font-semibold flex items-center justify-center gap-2 transition-all group"
|
||||
>
|
||||
<Sparkles size={20} className="group-hover:rotate-12 transition-transform" />
|
||||
{loading ? 'Generating...' : 'Generate Recipes'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Recipes Display */}
|
||||
<div className="lg:col-span-2">
|
||||
{/* Toggle Buttons */}
|
||||
<div className="flex gap-2 mb-6">
|
||||
<button
|
||||
onClick={() => setShowSavedOnly(false)}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition-all ${
|
||||
!showSavedOnly
|
||||
? 'bg-gradient-to-r from-purple-600 to-blue-600 text-white'
|
||||
: 'bg-white/10 dark:bg-white/5 border border-white/20 text-gray-900 dark:text-white'
|
||||
}`}
|
||||
>
|
||||
Generated ({recipes.length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowSavedOnly(true)}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition-all flex items-center gap-2 ${
|
||||
showSavedOnly
|
||||
? 'bg-gradient-to-r from-purple-600 to-blue-600 text-white'
|
||||
: 'bg-white/10 dark:bg-white/5 border border-white/20 text-gray-900 dark:text-white'
|
||||
}`}
|
||||
>
|
||||
<Heart size={18} />
|
||||
Saved ({savedRecipes.length})
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Recipes Grid */}
|
||||
{displayRecipes.length > 0 ? (
|
||||
<div className="space-y-4">
|
||||
{displayRecipes.map((recipe, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-2xl p-6 shadow-lg hover:shadow-xl transition-all group"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex-1">
|
||||
<h4 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-purple-600 transition-colors">
|
||||
{recipe.name}
|
||||
</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 text-sm mb-3">
|
||||
{recipe.description}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => saveRecipe(recipe)}
|
||||
className="p-2 hover:bg-red-500/20 rounded-full transition-colors"
|
||||
>
|
||||
<Heart size={20} className={savedRecipes.some(r => r.name === recipe.name) ? 'fill-red-500 text-red-500' : 'text-gray-400'} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4 mb-4">
|
||||
<div>
|
||||
<h5 className="font-semibold text-gray-900 dark:text-white text-sm mb-2">Ingredients:</h5>
|
||||
<ul className="space-y-1">
|
||||
{recipe.ingredients?.slice(0, 4).map((ing: string, i: number) => (
|
||||
<li key={i} className="text-sm text-gray-600 dark:text-gray-300 flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-purple-500 rounded-full"></span>
|
||||
{ing}
|
||||
</li>
|
||||
))}
|
||||
{recipe.ingredients?.length > 4 && (
|
||||
<li className="text-sm text-gray-500 dark:text-gray-400">+{recipe.ingredients.length - 4} more</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm bg-gradient-to-br from-purple-500/20 to-blue-500/20 rounded-xl p-3">
|
||||
<div className="flex items-center gap-1 text-gray-600 dark:text-gray-300">
|
||||
<Clock size={16} />
|
||||
<span>{recipe.cookTime || 30} mins</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-gray-600 dark:text-gray-300">
|
||||
<Users2 size={16} />
|
||||
<span>Serves {recipe.servings || 2}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300 line-clamp-2">
|
||||
{recipe.instructions}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-3xl p-12 text-center">
|
||||
<Sparkles size={48} className="mx-auto mb-4 text-purple-400 opacity-50" />
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{showSavedOnly
|
||||
? "No saved recipes yet. Generate some and save your favorites!"
|
||||
: "Add ingredients and generate recipes to get started"}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterMedia
|
||||
imageSrc="https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=1920&q=80"
|
||||
imageAlt="Footer background"
|
||||
columns={[
|
||||
{
|
||||
title: "App", items: [
|
||||
{ label: "Recipe Generator", href: "/app" },
|
||||
{ label: "My Recipes", href: "/app" },
|
||||
{ label: "Settings", href: "/app" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Account", items: [
|
||||
{ label: "Profile", href: "/app" },
|
||||
{ label: "Preferences", href: "/app" },
|
||||
{ label: "Security", href: "/app" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Help Center", href: "/" },
|
||||
{ label: "Privacy Policy", href: "/" },
|
||||
{ label: "Terms of Service", href: "/" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
logoText="EasyRecipes"
|
||||
copyrightText="© 2025 EasyRecipes. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
298
src/app/auth/page.tsx
Normal file
298
src/app/auth/page.tsx
Normal file
@@ -0,0 +1,298 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { Mail, Lock, User, Eye, EyeOff, ArrowRight, CheckCircle, AlertCircle } from "lucide-react";
|
||||
|
||||
export default function AuthPage() {
|
||||
const [isLogin, setIsLogin] = useState(true);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState<{ type: 'success' | 'error' | ''; text: string }>({ type: '', text: '' });
|
||||
const [formData, setFormData] = useState({
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
fullName: ''
|
||||
});
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setMessage({ type: '', text: '' });
|
||||
|
||||
try {
|
||||
const endpoint = isLogin ? '/api/auth/login' : '/api/auth/signup';
|
||||
const body = isLogin
|
||||
? { email: formData.email, password: formData.password }
|
||||
: { email: formData.email, password: formData.password, fullName: formData.fullName };
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
setMessage({ type: 'success', text: isLogin ? 'Login successful!' : 'Account created successfully!' });
|
||||
setTimeout(() => {
|
||||
window.location.href = '/app';
|
||||
}, 1500);
|
||||
} else {
|
||||
setMessage({ type: 'error', text: data.error || 'Something went wrong' });
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage({ type: 'error', text: 'Connection error. Please try again.' });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleForgotPassword = async () => {
|
||||
if (!formData.email) {
|
||||
setMessage({ type: 'error', text: 'Please enter your email address' });
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch('/api/auth/forgot-password', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email: formData.email })
|
||||
});
|
||||
if (response.ok) {
|
||||
setMessage({ type: 'success', text: 'Recovery email sent! Check your inbox.' });
|
||||
} else {
|
||||
setMessage({ type: 'error', text: 'Email not found' });
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage({ type: 'error', text: 'Failed to send recovery email' });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="expand-hover"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="none"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleFullscreen
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/#features" },
|
||||
{ name: "Auth", id: "/auth" },
|
||||
{ name: "App", id: "/app" },
|
||||
{ name: "Contact", id: "/#contact" }
|
||||
]}
|
||||
bottomLeftText="Secure Login"
|
||||
bottomRightText="hello@easyrecipes.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="auth" data-section="auth" className="min-h-screen flex items-center justify-center py-12 px-4">
|
||||
<div className="w-full max-w-md">
|
||||
{/* Liquid Glass Card */}
|
||||
<div className="backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-3xl p-8 shadow-2xl">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-3xl font-bold mb-2 text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-blue-600">
|
||||
{isLogin ? 'Welcome Back' : 'Join EasyRecipes'}
|
||||
</h1>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{isLogin ? 'Sign in to your account' : 'Create your account to get started'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Message Display */}
|
||||
{message.text && (
|
||||
<div className={`mb-6 p-4 rounded-xl flex items-center gap-3 ${
|
||||
message.type === 'success'
|
||||
? 'bg-green-500/20 border border-green-500/50 text-green-700 dark:text-green-300'
|
||||
: 'bg-red-500/20 border border-red-500/50 text-red-700 dark:text-red-300'
|
||||
}`}>
|
||||
{message.type === 'success' ? (
|
||||
<CheckCircle size={20} />
|
||||
) : (
|
||||
<AlertCircle size={20} />
|
||||
)}
|
||||
<span>{message.text}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{!isLogin && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Full Name
|
||||
</label>
|
||||
<div className="relative">
|
||||
<User className="absolute left-4 top-3.5 text-gray-400" size={20} />
|
||||
<input
|
||||
type="text"
|
||||
name="fullName"
|
||||
value={formData.fullName}
|
||||
onChange={handleInputChange}
|
||||
placeholder="John Doe"
|
||||
className="w-full pl-12 pr-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:border-purple-500 dark:bg-white/5 dark:border-white/10 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Email Address
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail className="absolute left-4 top-3.5 text-gray-400" size={20} />
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
placeholder="you@example.com"
|
||||
className="w-full pl-12 pr-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:border-purple-500 dark:bg-white/5 dark:border-white/10 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Lock className="absolute left-4 top-3.5 text-gray-400" size={20} />
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter your password"
|
||||
className="w-full pl-12 pr-12 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:border-purple-500 dark:bg-white/5 dark:border-white/10 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-4 top-3.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
||||
>
|
||||
{showPassword ? <EyeOff size={20} /> : <Eye size={20} />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!isLogin && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Confirm Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Lock className="absolute left-4 top-3.5 text-gray-400" size={20} />
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
name="confirmPassword"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Confirm your password"
|
||||
className="w-full pl-12 pr-12 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:border-purple-500 dark:bg-white/5 dark:border-white/10 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Forgot Password */}
|
||||
{isLogin && (
|
||||
<div className="text-right">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleForgotPassword}
|
||||
className="text-sm text-purple-600 dark:text-purple-400 hover:text-purple-700 dark:hover:text-purple-300 transition-colors"
|
||||
>
|
||||
Forgot password?
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Submit Button */}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-3 bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 disabled:opacity-50 text-white font-semibold rounded-xl flex items-center justify-center gap-2 transition-all duration-300 group"
|
||||
>
|
||||
{loading ? 'Processing...' : isLogin ? 'Sign In' : 'Create Account'}
|
||||
{!loading && <ArrowRight size={20} className="group-hover:translate-x-1 transition-transform" />}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Toggle Auth Mode */}
|
||||
<div className="mt-6 text-center">
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
{isLogin ? "Don't have an account? " : 'Already have an account? '}
|
||||
<button
|
||||
onClick={() => setIsLogin(!isLogin)}
|
||||
className="text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors"
|
||||
>
|
||||
{isLogin ? 'Sign Up' : 'Sign In'}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="my-6 flex items-center gap-3">
|
||||
<div className="flex-1 h-px bg-white/20"></div>
|
||||
<span className="text-sm text-gray-500 dark:text-gray-400">or</span>
|
||||
<div className="flex-1 h-px bg-white/20"></div>
|
||||
</div>
|
||||
|
||||
{/* OAuth Buttons */}
|
||||
<div className="space-y-3">
|
||||
<button
|
||||
type="button"
|
||||
className="w-full py-2.5 bg-white/5 dark:bg-white/5 border border-white/20 hover:border-white/40 rounded-xl text-gray-900 dark:text-white font-medium transition-all duration-300 flex items-center justify-center gap-2"
|
||||
>
|
||||
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" />
|
||||
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" />
|
||||
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" />
|
||||
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" />
|
||||
</svg>
|
||||
Continue with Google
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Security Note */}
|
||||
<div className="mt-8 p-4 bg-blue-500/10 border border-blue-500/30 rounded-xl">
|
||||
<p className="text-sm text-blue-700 dark:text-blue-300 text-center">
|
||||
🔒 Your data is encrypted and secure. We never share your information.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,74 @@
|
||||
@import "tailwindcss";
|
||||
@import "./styles/variables.css";
|
||||
@import "./styles/theme.css";
|
||||
@import "./styles/utilities.css";
|
||||
@import "./styles/base.css";
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply antialiased;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.rounded-theme {
|
||||
@apply rounded-2xl;
|
||||
}
|
||||
|
||||
.rounded-theme-capped {
|
||||
@apply rounded-3xl;
|
||||
}
|
||||
|
||||
.glass {
|
||||
@apply backdrop-blur-md bg-white/10 border border-white/20 rounded-2xl;
|
||||
}
|
||||
|
||||
.glass-elevated {
|
||||
@apply backdrop-blur-xl bg-white/10 dark:bg-white/5 border border-white/20 dark:border-white/10 rounded-3xl shadow-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.w-content-width {
|
||||
width: var(--width-content-width);
|
||||
}
|
||||
|
||||
.max-w-content-width {
|
||||
max-width: var(--width-content-width);
|
||||
}
|
||||
|
||||
.mask-fade-top-long {
|
||||
mask-image: linear-gradient(to bottom, transparent 0%, black 20%);
|
||||
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 20%);
|
||||
}
|
||||
|
||||
.mask-fade-bottom {
|
||||
mask-image: linear-gradient(to top, transparent 0%, black 20%);
|
||||
-webkit-mask-image: linear-gradient(to top, transparent 0%, black 20%);
|
||||
}
|
||||
|
||||
.mask-fade-left {
|
||||
mask-image: linear-gradient(to right, transparent 0%, black 20%);
|
||||
-webkit-mask-image: linear-gradient(to right, transparent 0%, black 20%);
|
||||
}
|
||||
|
||||
.mask-fade-right {
|
||||
mask-image: linear-gradient(to left, transparent 0%, black 20%);
|
||||
-webkit-mask-image: linear-gradient(to left, transparent 0%, black 20%);
|
||||
}
|
||||
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.no-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,25 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./styles/variables.css";
|
||||
import "./globals.css";
|
||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
||||
import Tag from "@/tag/Tag";
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter", subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "EasyRecipes - AI-Powered Recipe Generation", description: "Discover amazing recipes with AI recipe generation, ingredient scanner, and smart pantry system. Create delicious meals with what you have.", keywords: "recipe generator, AI recipes, ingredient scanner, smart pantry, cooking app", openGraph: {
|
||||
title: "EasyRecipes - AI-Powered Recipe Generation", description: "Transform your cooking with AI-powered recipes and smart ingredient management.", siteName: "EasyRecipes", type: "website"
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
title: "EasyRecipes - AI-Powered Recipe Generator", description: "Generate delicious recipes from your ingredients using AI"};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<ServiceWrapper>
|
||||
<body
|
||||
className={`${inter.variable} antialiased`}
|
||||
>
|
||||
<Tag />
|
||||
{children}
|
||||
|
||||
<html lang="en">
|
||||
<body className={inter.variable}>
|
||||
{children}
|
||||
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@@ -1399,7 +1387,6 @@ export default function RootLayout({
|
||||
}}
|
||||
/>
|
||||
</body>
|
||||
</ServiceWrapper>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
236
src/app/page.tsx
236
src/app/page.tsx
@@ -1,250 +1,142 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import HeroBillboardTestimonial from '@/components/sections/hero/HeroBillboardTestimonial';
|
||||
import FeatureCardMedia from '@/components/sections/feature/FeatureCardMedia';
|
||||
import ProductCardThree from '@/components/sections/product/ProductCardThree';
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import HeroCarouselLogo from '@/components/sections/hero/heroCarouselLogo/HeroCarouselLogo';
|
||||
import TextAbout from '@/components/sections/about/TextAbout';
|
||||
import TestimonialCardFive from '@/components/sections/testimonial/TestimonialCardFive';
|
||||
import PricingCardThree from '@/components/sections/pricing/PricingCardThree';
|
||||
import ContactText from '@/components/sections/contact/ContactText';
|
||||
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
|
||||
import { Sparkles, CheckCircle, Star, Heart, Zap } from "lucide-react";
|
||||
import FeatureCardMedia from '@/components/sections/feature/FeatureCardMedia';
|
||||
import FooterMedia from '@/components/sections/footer/FooterMedia';
|
||||
import BlurBottomBackground from '@/components/background/BlurBottomBackground';
|
||||
|
||||
export default function LandingPage() {
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
defaultButtonVariant="expand-hover"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="floatingGradient"
|
||||
background="none"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="radial-glow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
<NavbarStyleFullscreen
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/features" },
|
||||
{ name: "Download", id: "/download" },
|
||||
{ name: "Generate", id: "/generate" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
{ name: "Features", id: "#features" },
|
||||
{ name: "Auth", id: "/auth" },
|
||||
{ name: "App", id: "/app" },
|
||||
{ name: "Contact", id: "#contact" }
|
||||
]}
|
||||
button={{ text: "Get Started", href: "/download" }}
|
||||
animateOnLoad={true}
|
||||
bottomLeftText="AI-Powered Recipes"
|
||||
bottomRightText="hello@easyrecipes.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
<HeroBillboardTestimonial
|
||||
title="Create Amazing Recipes with AI"
|
||||
description="Discover personalized recipes powered by artificial intelligence. Scan ingredients, manage your pantry, and cook like a chef with EasyRecipes."
|
||||
tag="AI-Powered Cooking"
|
||||
tagIcon={Sparkles}
|
||||
tagAnimation="slide-up"
|
||||
imageSrc="https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?w=800&q=80"
|
||||
imageAlt="AI recipe generation showcase"
|
||||
mediaAnimation="slide-up"
|
||||
background={{ variant: "sparkles-gradient" }}
|
||||
<HeroCarouselLogo
|
||||
logoText="EASYRECIPES"
|
||||
description="Transform your kitchen with AI-powered recipes. Discover delicious meals from ingredients you already have."
|
||||
buttons={[
|
||||
{ text: "Explore Recipes", href: "/features" },
|
||||
{ text: "Download App", href: "/download" }
|
||||
{ text: "Get Started", href: "/auth" },
|
||||
{ text: "Learn More", href: "#features" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
testimonials={[
|
||||
slides={[
|
||||
{
|
||||
name: "Emma Thompson", handle: "Home Chef", testimonial: "EasyRecipes transformed how I cook! The AI suggestions are spot-on for my ingredients.", rating: 5,
|
||||
imageSrc: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&q=80"
|
||||
imageSrc: "https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=1920&q=80", imageAlt: "Fresh ingredients"
|
||||
},
|
||||
{
|
||||
name: "Marcus Johnson", handle: "Busy Professional", testimonial: "Love the ingredient scanner! Saves me so much time figuring out what to cook.", rating: 5,
|
||||
imageSrc: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&q=80"
|
||||
imageSrc: "https://images.unsplash.com/photo-1495697542231-dc1d53f6f0bb?w=1920&q=80", imageAlt: "Cooking in kitchen"
|
||||
},
|
||||
{
|
||||
name: "Sarah Chen", handle: "Food Enthusiast", testimonial: "The smart pantry system is a game-changer. Never waste ingredients again!", rating: 5,
|
||||
imageSrc: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&q=80"
|
||||
imageSrc: "https://images.unsplash.com/photo-1495863359367-055fb6aae5e0?w=1920&q=80", imageAlt: "Finished dish"
|
||||
}
|
||||
]}
|
||||
testimonialRotationInterval={5000}
|
||||
useInvertedBackground={false}
|
||||
autoplayDelay={5000}
|
||||
showDimOverlay={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="features" data-section="features">
|
||||
<FeatureCardMedia
|
||||
title="Powerful Features for Smart Cooking"
|
||||
description="Everything you need to cook smarter, faster, and with less waste"
|
||||
tag="Core Features"
|
||||
tagIcon={CheckCircle}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={true}
|
||||
features={[
|
||||
{
|
||||
id: "1", tag: "AI Generation", title: "AI Recipe Generation", description: "Get personalized recipe suggestions based on your ingredients, dietary preferences, and cooking skill level. Our AI learns what you love to cook.", imageSrc: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=600&q=80&_wi=1", imageAlt: "AI recipe generation"
|
||||
id: "1", title: "Secure Authentication", description: "Create your account with email and password. Your data is encrypted and protected with industry-standard security.", tag: "Security First", imageSrc: "https://images.unsplash.com/photo-1555949519-ef32f108e557?w=600&q=80", imageAlt: "Secure lock icon"
|
||||
},
|
||||
{
|
||||
id: "2", tag: "Scanning", title: "Ingredient Scanner", description: "Simply take a photo of your ingredients or groceries. Our advanced scanner identifies items instantly and adds them to your pantry.", imageSrc: "https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=80&_wi=1", imageAlt: "Ingredient scanner technology"
|
||||
id: "2", title: "Personalized Profile", description: "Save your favorite recipes and manage your ingredient preferences. Your profile grows smarter with every recipe.", tag: "Your Kitchen", imageSrc: "https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&q=80", imageAlt: "User profile"
|
||||
},
|
||||
{
|
||||
id: "3", tag: "Management", title: "Smart Pantry System", description: "Track expiration dates, quantities, and nutritional info. Get notified before ingredients expire and receive smart shopping recommendations.", imageSrc: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?w=600&q=80&_wi=1", imageAlt: "Smart pantry management"
|
||||
id: "3", title: "AI Recipe Generation", description: "Enter your ingredients and let AI create personalized recipes just for you. Discover new dishes instantly.", tag: "AI Powered", imageSrc: "https://images.unsplash.com/photo-1498198788026-432a562a71cc?w=600&q=80", imageAlt: "AI technology"
|
||||
},
|
||||
{
|
||||
id: "4", title: "Session Management", description: "Seamless login experience with secure session handling. Your preferences are remembered across devices.", tag: "Always Connected", imageSrc: "https://images.unsplash.com/photo-1460925895917-aeb19be489c7?w=600&q=80", imageAlt: "Connected devices"
|
||||
},
|
||||
{
|
||||
id: "5", title: "Password Recovery", description: "Forgot your password? Our secure recovery system gets you back into your account quickly and safely.", tag: "Peace of Mind", imageSrc: "https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=600&q=80", imageAlt: "Recovery process"
|
||||
},
|
||||
{
|
||||
id: "6", title: "Liquid Glass Design", description: "Beautiful, modern UI with glass-morphism effects. Every interaction feels smooth and premium.", tag: "Design", imageSrc: "https://images.unsplash.com/photo-1561070791-2526d30994b5?w=600&q=80", imageAlt: "Modern design"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="download" data-section="download">
|
||||
<ProductCardThree
|
||||
products={[
|
||||
{
|
||||
id: "1", name: "iOS App", price: "Free", imageSrc: "https://images.unsplash.com/photo-1512941691920-25bda36dc643?w=400&q=80", imageAlt: "EasyRecipes iOS app", initialQuantity: 1
|
||||
},
|
||||
{
|
||||
id: "2", name: "Android App", price: "Free", imageSrc: "https://images.unsplash.com/photo-1526374965328-7f5ae4e8a83f?w=400&q=80", imageAlt: "EasyRecipes Android app", initialQuantity: 1
|
||||
},
|
||||
{
|
||||
id: "3", name: "Web Platform", price: "Free", imageSrc: "https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=400&q=80", imageAlt: "EasyRecipes web platform", initialQuantity: 1
|
||||
}
|
||||
]}
|
||||
title="Download EasyRecipes"
|
||||
description="Available on all your favorite platforms"
|
||||
tag="Get Started Now"
|
||||
tagIcon={Zap}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
title="Powerful Features for Your Kitchen"
|
||||
description="Everything you need to revolutionize your cooking experience with AI and secure authentication"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
gridVariant="three-columns-all-equal-width"
|
||||
tag="Features"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="about" data-section="about">
|
||||
<TextAbout
|
||||
tag="Why Choose EasyRecipes"
|
||||
tagIcon={Heart}
|
||||
title="Revolutionizing home cooking with AI-powered intelligence, making every meal delicious, sustainable, and personalized to your taste."
|
||||
useInvertedBackground={true}
|
||||
buttons={[
|
||||
{ text: "Learn Our Story", href: "#" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="testimonial" data-section="testimonial">
|
||||
<TestimonialCardFive
|
||||
testimonials={[
|
||||
{
|
||||
id: "1", name: "Jennifer Rodriguez, Nutritionist", date: "Date: 10 Jan 2025", title: "A nutritionist's dream app!", quote: "I recommend EasyRecipes to all my clients. The AI understands nutrition profiles perfectly and suggests balanced, delicious meals every time.", tag: "Healthcare Pro", avatarSrc: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=600&q=80&_wi=2"
|
||||
},
|
||||
{
|
||||
id: "2", name: "David Kim, Sustainability Advocate", date: "Date: 12 Jan 2025", title: "Reduces food waste dramatically!", quote: "This app has cut my food waste by 70%! The smart pantry notifications and AI-suggested recipes use up ingredients before they spoil.", tag: "Eco Warrior", avatarSrc: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=80&_wi=2"
|
||||
},
|
||||
{
|
||||
id: "3", name: "Lisa Wong, Busy Mom", date: "Date: 14 Jan 2025", title: "Meal planning made easy!", quote: "Between work and kids, I don't have time to plan meals. EasyRecipes does it for me and my family actually enjoys what I cook!", tag: "Parent", avatarSrc: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?w=600&q=80&_wi=2"
|
||||
},
|
||||
{
|
||||
id: "4", name: "Michael Chen, Food Blogger", date: "Date: 16 Jan 2025", title: "Creative cooking inspiration!", quote: "The AI suggestions are incredibly creative. I've discovered amazing flavor combinations I never would have thought of on my own!", tag: "Creator", avatarSrc: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=600&q=80&_wi=1"
|
||||
},
|
||||
{
|
||||
id: "5", name: "Amanda Foster, Culinary Student", date: "Date: 18 Jan 2025", title: "Learning tool and cooking companion!", quote: "Perfect for learning! The app explains why certain ingredients work together and teaches me technique while I cook.", tag: "Student Chef", avatarSrc: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=600&q=80&_wi=3"
|
||||
},
|
||||
{
|
||||
id: "6", name: "Robert Martinez, Tech Enthusiast", date: "Date: 20 Jan 2025", title: "Impressive AI technology!", quote: "As a tech person, I'm impressed by how advanced the AI is. It understands context, preferences, and adapts to your cooking style.", tag: "Tech Lover", avatarSrc: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&q=80", imageSrc: "https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=80&_wi=3"
|
||||
}
|
||||
]}
|
||||
title="What Chefs and Cooking Enthusiasts Say"
|
||||
description="Join thousands of users discovering new culinary possibilities"
|
||||
tag="Reviews"
|
||||
textboxLayout="default"
|
||||
title="EasyRecipes: Your AI Kitchen Assistant with Secure Authentication"
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="pricing" data-section="pricing">
|
||||
<PricingCardThree
|
||||
plans={[
|
||||
{
|
||||
id: "1", price: "Free", name: "Recipe Explorer", buttons: [
|
||||
{ text: "Start Free", href: "/download" }
|
||||
],
|
||||
features: [
|
||||
"50+ AI-generated recipes monthly", "Basic ingredient scanner", "Simple pantry tracking", "Standard recipe recommendations", "Community recipes access"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "2", badge: "Most Popular", badgeIcon: Sparkles,
|
||||
price: "$4.99/mo", name: "Culinary Pro", buttons: [
|
||||
{ text: "Subscribe Now", href: "/download" }
|
||||
],
|
||||
features: [
|
||||
"Unlimited AI recipe generation", "Advanced ingredient scanner with nutrition", "Smart pantry with expiration alerts", "Personalized meal planning", "Dietary preference customization", "Priority recipe updates"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "3", price: "$9.99/mo", name: "Chef Premium", buttons: [
|
||||
{ text: "Unlock Premium", href: "/download" }
|
||||
],
|
||||
features: [
|
||||
"Everything in Culinary Pro", "Advanced AI personalization", "Exclusive chef-curated recipes", "Nutritional analysis & meal prep", "Recipe scaling & conversions", "Priority support & new features", "Multi-user household access"
|
||||
]
|
||||
}
|
||||
]}
|
||||
title="Choose Your Cooking Journey"
|
||||
description="From home chefs to culinary enthusiasts"
|
||||
tag="Flexible Plans"
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactText
|
||||
text="Transform your cooking today with EasyRecipes. Get personalized AI recipes, smart ingredient management, and culinary inspiration in your pocket. Download now and start creating delicious meals!"
|
||||
animationType="entrance-slide"
|
||||
background={{ variant: "radial-gradient" }}
|
||||
buttons={[
|
||||
{ text: "Download App", href: "/download" },
|
||||
{ text: "Contact Support", href: "/contact" }
|
||||
{ text: "Create Account", href: "/auth" },
|
||||
{ text: "Try the App", href: "/app" }
|
||||
]}
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<BlurBottomBackground />
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
<FooterMedia
|
||||
imageSrc="https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=1920&q=80"
|
||||
imageAlt="Footer background"
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "/features" },
|
||||
{ label: "Download", href: "/download" },
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Help Center", href: "#" }
|
||||
{ label: "Security", href: "/" },
|
||||
{ label: "FAQ", href: "/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
{ label: "Blog", href: "/" },
|
||||
{ label: "Careers", href: "/" },
|
||||
{ label: "Press", href: "/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "Community", href: "#" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" }
|
||||
{ label: "Documentation", href: "/" },
|
||||
{ label: "Contact Us", href: "/" },
|
||||
{ label: "Privacy Policy", href: "/" },
|
||||
{ label: "Terms of Service", href: "/" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
copyrightText="© 2025 EasyRecipes | AI-Powered Cooking Made Easy"
|
||||
logoText="EasyRecipes"
|
||||
copyrightText="© 2025 EasyRecipes. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
|
||||
Reference in New Issue
Block a user