Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72ccfef498 | |||
| 67dd981fc3 | |||
| b61160d424 | |||
| 6246fb8a98 | |||
| eb9a36ca38 | |||
| 7d0711fa12 | |||
| 25ce1007e5 | |||
| 9d17ce6163 | |||
| a1113f31cf | |||
| 212dafd864 | |||
| fa9c466286 | |||
| c74295ff8a | |||
| b462ddd553 | |||
| c0eefcb803 | |||
| e24491952b | |||
| 575005a59a | |||
| 3682f2cfdf | |||
| 9761d07ebf | |||
| 9208036b0f | |||
| 124ce99cfb | |||
| 8935383ef9 | |||
| f15928fb51 | |||
| 526f185500 | |||
| 24c66e59c0 | |||
| 588e13b79f | |||
| b24b6a7699 |
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&_wi=3"
|
||||
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>
|
||||
);
|
||||
}
|
||||
114
src/app/contact/page.tsx
Normal file
114
src/app/contact/page.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import ContactCenter from '@/components/sections/contact/ContactCenter';
|
||||
import TextAbout from '@/components/sections/about/TextAbout';
|
||||
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
|
||||
import { Mail, Heart, Sparkles } from "lucide-react";
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="floatingGradient"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="radial-glow"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/features" },
|
||||
{ name: "Download", id: "/download" },
|
||||
{ name: "Generate", id: "/generate" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
]}
|
||||
button={{ text: "Get Started", href: "/download" }}
|
||||
animateOnLoad={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact-main" data-section="contact-main">
|
||||
<ContactCenter
|
||||
tag="Get in Touch"
|
||||
title="We'd Love to Hear From You"
|
||||
description="Have feedback, questions, or feature requests? Contact our team and we'll get back to you within 24 hours. We're always excited to connect with our community!"
|
||||
tagIcon={Mail}
|
||||
background={{ variant: "sparkles-gradient" }}
|
||||
useInvertedBackground={false}
|
||||
inputPlaceholder="Enter your email"
|
||||
buttonText="Send Message"
|
||||
onSubmit={(email) => console.log('Contact request:', email)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="about-contact" data-section="about-contact">
|
||||
<TextAbout
|
||||
tag="Connect With Us"
|
||||
tagIcon={Heart}
|
||||
title="Our support team is dedicated to helping you get the most out of EasyRecipes. Reach out anytime for assistance, feedback, or partnership inquiries."
|
||||
useInvertedBackground={true}
|
||||
buttons={[
|
||||
{ text: "Email Us", href: "#" },
|
||||
{ text: "Follow Us", href: "#" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="newsletter" data-section="newsletter">
|
||||
<ContactCenter
|
||||
tag="Stay Updated"
|
||||
title="Subscribe to Our Newsletter"
|
||||
description="Get weekly AI recipe ideas, cooking tips, and exclusive updates about new EasyRecipes features delivered to your inbox."
|
||||
tagIcon={Sparkles}
|
||||
background={{ variant: "radial-gradient" }}
|
||||
useInvertedBackground={false}
|
||||
inputPlaceholder="Your email address"
|
||||
buttonText="Subscribe"
|
||||
termsText="We respect your privacy and will never share your email. Unsubscribe anytime."
|
||||
onSubmit={(email) => console.log('Newsletter signup:', email)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "/features" },
|
||||
{ label: "Download", href: "/download" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Help Center", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "Community", href: "#" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
copyrightText="© 2025 EasyRecipes | AI-Powered Cooking Made Easy"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
114
src/app/download/page.tsx
Normal file
114
src/app/download/page.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import HeroSignup from '@/components/sections/hero/HeroSignup';
|
||||
import SocialProofOne from '@/components/sections/socialProof/SocialProofOne';
|
||||
import ContactCenter from '@/components/sections/contact/ContactCenter';
|
||||
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
|
||||
import { Download, Users, Sparkles } from "lucide-react";
|
||||
|
||||
export default function DownloadPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="floatingGradient"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="radial-glow"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/features" },
|
||||
{ name: "Download", id: "/download" },
|
||||
{ name: "Generate", id: "/generate" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
]}
|
||||
button={{ text: "Get Started", href: "/download" }}
|
||||
animateOnLoad={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="hero-download" data-section="hero-download">
|
||||
<HeroSignup
|
||||
background={{ variant: "sparkles-gradient" }}
|
||||
tag="Download Now"
|
||||
tagIcon={Download}
|
||||
title="Get EasyRecipes on Your Phone"
|
||||
description="Download the EasyRecipes app and start creating amazing AI-powered recipes today. Available on iOS, Android, and web."
|
||||
inputPlaceholder="Enter your email for download link"
|
||||
buttonText="Send Download Link"
|
||||
onSubmit={(email) => console.log('Download request:', email)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="social-proof" data-section="social-proof">
|
||||
<SocialProofOne
|
||||
names={["Apple App Store", "Google Play Store", "Amazon Appstore", "Web Browser"]}
|
||||
title="Available Everywhere"
|
||||
description="Download EasyRecipes from your preferred platform"
|
||||
tag="Multi-Platform"
|
||||
tagIcon={Users}
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
showCard={true}
|
||||
speed={40}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact-download" data-section="contact-download">
|
||||
<ContactCenter
|
||||
tag="Questions?"
|
||||
title="Need Help Getting Started?"
|
||||
description="Have questions about downloading or using EasyRecipes? Our support team is here to help."
|
||||
tagIcon={Sparkles}
|
||||
background={{ variant: "radial-gradient" }}
|
||||
useInvertedBackground={false}
|
||||
inputPlaceholder="Your email address"
|
||||
buttonText="Contact Support"
|
||||
onSubmit={(email) => console.log('Support request:', email)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "/features" },
|
||||
{ label: "Download", href: "/download" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Help Center", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "Community", href: "#" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
copyrightText="© 2025 EasyRecipes | AI-Powered Cooking Made Easy"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
143
src/app/features/page.tsx
Normal file
143
src/app/features/page.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import FeatureCardEight from '@/components/sections/feature/FeatureCardEight';
|
||||
import MetricCardEleven from '@/components/sections/metrics/MetricCardEleven';
|
||||
import ContactCenter from '@/components/sections/contact/ContactCenter';
|
||||
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
|
||||
import { Sparkles, TrendingUp, Zap } from "lucide-react";
|
||||
|
||||
export default function FeaturesPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="floatingGradient"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="radial-glow"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/features" },
|
||||
{ name: "Download", id: "/download" },
|
||||
{ name: "Generate", id: "/generate" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
]}
|
||||
button={{ text: "Get Started", href: "/download" }}
|
||||
animateOnLoad={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="features-timeline" data-section="features-timeline">
|
||||
<FeatureCardEight
|
||||
features={[
|
||||
{
|
||||
id: 1,
|
||||
title: "Scan Your Ingredients", description: "Point your camera at groceries or pantry items. Our AI recognizes ingredients instantly and adds them to your smart pantry with full nutritional data.", imageSrc: "https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=80&_wi=4", imageAlt: "Ingredient scanning step"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Get AI-Powered Suggestions", description: "Based on your ingredients, diet, and taste preferences, our AI generates personalized recipe recommendations instantly. Learn why ingredients work together.", imageSrc: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=600&q=80&_wi=4", imageAlt: "AI recipe suggestions"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Manage Your Smart Pantry", description: "Track ingredient quantities and expiration dates. Get smart notifications before items expire and receive shopping recommendations based on your cooking habits.", imageSrc: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?w=600&q=80&_wi=3", imageAlt: "Smart pantry management"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "Cook & Learn", description: "Follow step-by-step recipes with timing guidance, ingredient ratios, and cooking techniques. Share your creations and discover recipes from other home chefs.", imageSrc: "https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=600&q=80&_wi=2", imageAlt: "Cooking and learning"
|
||||
}
|
||||
]}
|
||||
title="How EasyRecipes Works"
|
||||
description="Four simple steps to amazing meals"
|
||||
tag="Step-by-Step Guide"
|
||||
tagIcon={Zap}
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
buttonAnimation="slide-up"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="metrics" data-section="metrics">
|
||||
<MetricCardEleven
|
||||
metrics={[
|
||||
{
|
||||
id: "1", value: "500K+", title: "Recipes Generated", description: "AI-powered recipes created monthly by our users", imageSrc: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=600&q=80&_wi=5", imageAlt: "Recipes generated"
|
||||
},
|
||||
{
|
||||
id: "2", value: "95%", title: "Food Waste Reduced", description: "Average reduction in household food waste", imageSrc: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?w=600&q=80&_wi=4", imageAlt: "Waste reduction"
|
||||
},
|
||||
{
|
||||
id: "3", value: "2.5M+", title: "Ingredients Scanned", description: "Accurately identified by our scanner technology", imageSrc: "https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=80&_wi=5", imageAlt: "Ingredients scanned"
|
||||
},
|
||||
{
|
||||
id: "4", value: "4.8★", title: "User Rating", description: "Average rating across all app stores", imageSrc: "https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=600&q=80&_wi=3", imageAlt: "User satisfaction"
|
||||
}
|
||||
]}
|
||||
title="EasyRecipes by the Numbers"
|
||||
description="Join millions of home chefs worldwide"
|
||||
tag="Impact"
|
||||
tagIcon={TrendingUp}
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
animationType="slide-up"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact-features" data-section="contact-features">
|
||||
<ContactCenter
|
||||
tag="Ready to Cook?"
|
||||
title="Start Your AI Cooking Journey Today"
|
||||
description="Get instant access to personalized recipes, smart pantry management, and culinary inspiration."
|
||||
tagIcon={Sparkles}
|
||||
background={{ variant: "sparkles-gradient" }}
|
||||
useInvertedBackground={false}
|
||||
inputPlaceholder="Enter your email"
|
||||
buttonText="Get Started Free"
|
||||
onSubmit={(email) => console.log('Email:', email)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "/features" },
|
||||
{ label: "Download", href: "/download" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Help Center", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "Community", href: "#" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
copyrightText="© 2025 EasyRecipes | AI-Powered Cooking Made Easy"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
266
src/app/generate/page.tsx
Normal file
266
src/app/generate/page.tsx
Normal file
@@ -0,0 +1,266 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import HeroBillboardTestimonial from '@/components/sections/hero/HeroBillboardTestimonial';
|
||||
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
|
||||
import { Sparkles, Mail } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function GeneratePage() {
|
||||
const [ingredients, setIngredients] = useState<string[]>([]);
|
||||
const [currentInput, setCurrentInput] = useState("");
|
||||
const [recipes, setRecipes] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const [userEmail, setUserEmail] = useState("");
|
||||
|
||||
const handleGmailLogin = async () => {
|
||||
try {
|
||||
// Simulate Gmail OAuth flow
|
||||
const response = await fetch("/api/auth/gmail", {
|
||||
method: "POST"});
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setUserEmail(data.email);
|
||||
setIsLoggedIn(true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gmail login failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="floatingGradient"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="radial-glow"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "/features" },
|
||||
{ name: "Download", id: "/download" },
|
||||
{ name: "Generate", id: "/generate" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
]}
|
||||
button={{ text: "Get Started", href: "/download" }}
|
||||
animateOnLoad={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
<HeroBillboardTestimonial
|
||||
title="Generate Recipes from Your Ingredients"
|
||||
description="Enter the ingredients you have on hand and let our AI create delicious recipe suggestions just for you. Create amazing meals with what you already have!"
|
||||
background={{ variant: "sparkles-gradient" }}
|
||||
useInvertedBackground={false}
|
||||
testimonials={[
|
||||
{
|
||||
name: "Sarah Johnson", handle: "Home Chef", testimonial: "This app changed how I cook! No more food waste.", rating: 5
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="generator" data-section="generator" className="w-full py-20 px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
{/* Login Section */}
|
||||
{!isLoggedIn && (
|
||||
<div className="mb-12 text-center">
|
||||
<h2 className="text-2xl font-bold mb-4">Sign in to Get Started</h2>
|
||||
<button
|
||||
onClick={handleGmailLogin}
|
||||
className="flex items-center justify-center gap-2 bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg font-semibold transition-colors"
|
||||
>
|
||||
<Mail size={20} />
|
||||
Sign in with Gmail
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Generator Section */}
|
||||
{isLoggedIn && (
|
||||
<div className="space-y-8">
|
||||
<div className="text-center mb-8">
|
||||
<p className="text-lg text-gray-600 mb-2">Logged in as: {userEmail}</p>
|
||||
</div>
|
||||
|
||||
{/* Ingredient Input */}
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-lg">
|
||||
<h3 className="text-xl font-bold mb-4">Add Your Ingredients</h3>
|
||||
<div className="flex gap-2 mb-4">
|
||||
<input
|
||||
type="text"
|
||||
value={currentInput}
|
||||
onChange={(e) => setCurrentInput(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
placeholder="e.g., chicken, tomatoes, garlic"
|
||||
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
/>
|
||||
<button
|
||||
onClick={addIngredient}
|
||||
className="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-semibold transition-colors"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Ingredients List */}
|
||||
{ingredients.length > 0 && (
|
||||
<div className="mb-6">
|
||||
<h4 className="font-semibold mb-3">Your Ingredients:</h4>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{ingredients.map((ingredient, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center gap-2 bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-100 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span>{ingredient}</span>
|
||||
<button
|
||||
onClick={() => removeIngredient(index)}
|
||||
className="text-blue-600 dark:text-blue-300 hover:text-blue-800 font-bold"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Generate Button */}
|
||||
<button
|
||||
onClick={generateRecipes}
|
||||
disabled={loading || ingredients.length === 0}
|
||||
className="w-full px-6 py-3 bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white rounded-lg font-semibold transition-colors"
|
||||
>
|
||||
{loading ? "Generating..." : "Generate Recipes"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Recipes Results */}
|
||||
{recipes.length > 0 && (
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-2xl font-bold mb-6">AI-Generated Recipes</h3>
|
||||
{recipes.map((recipe, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-lg"
|
||||
>
|
||||
<h4 className="text-xl font-bold mb-2">{recipe.name}</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{recipe.description}
|
||||
</p>
|
||||
<div className="mb-4">
|
||||
<h5 className="font-semibold mb-2">Ingredients:</h5>
|
||||
<ul className="list-disc pl-5 space-y-1 text-gray-700 dark:text-gray-300">
|
||||
{recipe.ingredients?.map((ing: string, i: number) => (
|
||||
<li key={i}>{ing}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<h5 className="font-semibold mb-2">Instructions:</h5>
|
||||
<p className="text-gray-700 dark:text-gray-300">
|
||||
{recipe.instructions}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-between text-sm text-gray-500">
|
||||
<span>⏱ {recipe.cookTime} mins</span>
|
||||
<span>👥 Serves {recipe.servings}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "/features" },
|
||||
{ label: "Download", href: "/download" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Help Center", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "Community", href: "#" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
copyrightText="© 2025 EasyRecipes | AI-Powered Cooking Made Easy"
|
||||
/>
|
||||
</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,48 +1,25 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Halant } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import { Inter_Tight } from "next/font/google";
|
||||
import "./styles/variables.css";
|
||||
import "./globals.css";
|
||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
||||
import Tag from "@/tag/Tag";
|
||||
|
||||
const halant = Halant({
|
||||
variable: "--font-halant", subsets: ["latin"],
|
||||
weight: ["300", "400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter", subsets: ["latin"],
|
||||
});
|
||||
|
||||
const interTight = Inter_Tight({
|
||||
variable: "--font-inter-tight", subsets: ["latin"],
|
||||
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "FoodHub - Fast Food Delivery App", description: "Order delicious meals from top restaurants and enjoy fast delivery. Browse hundreds of restaurants, track your order in real-time, and enjoy exclusive member discounts.", keywords: "food delivery, meal ordering, restaurant app, fast delivery, online food order", openGraph: {
|
||||
title: "FoodHub - Fast Food Delivery App", description: "Order delicious meals from top restaurants with fast delivery. Download FoodHub today!", siteName: "FoodHub", 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={`${halant.variable} ${inter.variable} ${interTight.variable} antialiased`}
|
||||
>
|
||||
<Tag />
|
||||
{children}
|
||||
|
||||
<html lang="en">
|
||||
<body className={inter.variable}>
|
||||
{children}
|
||||
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@@ -1410,7 +1387,6 @@ export default function RootLayout({
|
||||
}}
|
||||
/>
|
||||
</body>
|
||||
</ServiceWrapper>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
253
src/app/page.tsx
253
src/app/page.tsx
@@ -1,249 +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 { Zap, CheckCircle, Star, Heart, Sparkles } 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="elastic-effect"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="soft"
|
||||
contentWidth="compact"
|
||||
sizing="mediumSizeLargeTitles"
|
||||
background="noise"
|
||||
cardStyle="layered-gradient"
|
||||
primaryButtonStyle="shadow"
|
||||
defaultButtonVariant="expand-hover"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="none"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="light"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="FoodHub"
|
||||
<NavbarStyleFullscreen
|
||||
brandName="EasyRecipes"
|
||||
navItems={[
|
||||
{ name: "Home", id: "hero" },
|
||||
{ name: "How It Works", id: "features" },
|
||||
{ name: "Restaurants", id: "product" },
|
||||
{ name: "Offers", id: "pricing" }
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "#features" },
|
||||
{ name: "Auth", id: "/auth" },
|
||||
{ name: "App", id: "/app" },
|
||||
{ name: "Contact", id: "#contact" }
|
||||
]}
|
||||
button={{ text: "Order Now", href: "#hero" }}
|
||||
animateOnLoad={true}
|
||||
bottomLeftText="AI-Powered Recipes"
|
||||
bottomRightText="hello@easyrecipes.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
<HeroBillboardTestimonial
|
||||
title="Delicious Food, Delivered Fast"
|
||||
description="Order from your favorite restaurants and enjoy fresh meals delivered right to your door. Fast, reliable, and always delicious."
|
||||
tag="Quick Delivery"
|
||||
tagIcon={Zap}
|
||||
tagAnimation="slide-up"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/side-view-family-eating-together_23-2150671588.jpg"
|
||||
imageAlt="Food delivery service 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: "Order Now", href: "#" },
|
||||
{ text: "Browse Restaurants", href: "#product" }
|
||||
{ text: "Get Started", href: "/auth" },
|
||||
{ text: "Learn More", href: "#features" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
testimonials={[
|
||||
slides={[
|
||||
{
|
||||
name: "Sarah Johnson", handle: "Regular Customer", testimonial: "Amazing app! My food arrived hot and fresh within 30 minutes.", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg?_wi=1"
|
||||
imageSrc: "https://images.unsplash.com/photo-1495521821757-a1efb6729352?w=1920&q=80&_wi=1", imageAlt: "Fresh ingredients"
|
||||
},
|
||||
{
|
||||
name: "Marcus Chen", handle: "Food Lover", testimonial: "Best delivery service I've used. Great selection of restaurants!", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg?_wi=2"
|
||||
imageSrc: "https://images.unsplash.com/photo-1495697542231-dc1d53f6f0bb?w=1920&q=80", imageAlt: "Cooking in kitchen"
|
||||
},
|
||||
{
|
||||
name: "Emma Wilson", handle: "Busy Professional", testimonial: "Super convenient. I order lunch here every other day!", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg?_wi=3"
|
||||
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="How It Works"
|
||||
description="Get delicious meals delivered in three simple steps"
|
||||
tag="Simple Process"
|
||||
tagIcon={CheckCircle}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={true}
|
||||
features={[
|
||||
{
|
||||
id: "1", tag: "Step 1", title: "Browse Restaurants", description: "Explore hundreds of restaurants and cuisines in your area. Filter by ratings, cuisine type, or delivery time.", imageSrc: "http://img.b2bpic.net/free-photo/side-view-couple-eating-pizza-doner-wrapped-lavash-served-with-french-fries-sauces-table-table_140725-12112.jpg?_wi=1", imageAlt: "Browse restaurants"
|
||||
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: "Step 2", title: "Select Your Meal", description: "Browse menus, read reviews, and add your favorite dishes to your cart with just a few taps.", imageSrc: "http://img.b2bpic.net/free-photo/pagliatelle-with-meat-jte-table_140725-6761.jpg?_wi=1", imageAlt: "Select meals"
|
||||
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: "Step 3", title: "Fast Delivery", description: "Track your order in real-time and receive your food fresh and hot at your doorstep.", imageSrc: "http://img.b2bpic.net/free-photo/homemade-mexican-taco-boats-recipe-idea_53876-95999.jpg?_wi=1", imageAlt: "Fast delivery service"
|
||||
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="product" data-section="product">
|
||||
<ProductCardThree
|
||||
products={[
|
||||
{
|
||||
id: "1", name: "Pizza Palace", price: "$15.99", imageSrc: "http://img.b2bpic.net/free-photo/side-view-couple-eating-pizza-doner-wrapped-lavash-served-with-french-fries-sauces-table-table_140725-12112.jpg?_wi=2", imageAlt: "Pizza Palace restaurant", initialQuantity: 1
|
||||
},
|
||||
{
|
||||
id: "2", name: "Sushi Express", price: "$22.50", imageSrc: "http://img.b2bpic.net/free-photo/pagliatelle-with-meat-jte-table_140725-6761.jpg?_wi=2", imageAlt: "Sushi Express restaurant", initialQuantity: 1
|
||||
},
|
||||
{
|
||||
id: "3", name: "Fresh Bowls", price: "$12.99", imageSrc: "http://img.b2bpic.net/free-photo/homemade-mexican-taco-boats-recipe-idea_53876-95999.jpg?_wi=2", imageAlt: "Fresh Bowls restaurant", initialQuantity: 1
|
||||
}
|
||||
]}
|
||||
title="Featured Restaurants"
|
||||
description="Discover top-rated restaurants and exclusive menu items"
|
||||
tag="Popular Now"
|
||||
tagIcon={Star}
|
||||
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 FoodHub"
|
||||
tagIcon={Heart}
|
||||
title="We bring your favorite restaurants and cuisines to your fingertips with unbeatable speed, quality, and selection."
|
||||
useInvertedBackground={true}
|
||||
buttons={[
|
||||
{ text: "Learn More", href: "#" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="testimonial" data-section="testimonial">
|
||||
<TestimonialCardFive
|
||||
testimonials={[
|
||||
{
|
||||
id: "1", name: "Jessica Martinez, Food Blogger", date: "Date: 15 Jan 2025", title: "Best delivery service in town!", quote: "I've tried many delivery apps, but FoodHub stands out with their speed and quality. The restaurants are always fresh and the drivers are professional.", tag: "Premium Member", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/side-view-couple-eating-pizza-doner-wrapped-lavash-served-with-french-fries-sauces-table-table_140725-12112.jpg?_wi=3"
|
||||
},
|
||||
{
|
||||
id: "2", name: "David Thompson, Corporate Worker", date: "Date: 18 Jan 2025", title: "Perfect for lunch breaks", quote: "I use FoodHub almost every day for lunch. The variety is amazing and delivery is always on time. Highly recommended!", tag: "Regular User", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/pagliatelle-with-meat-jte-table_140725-6761.jpg?_wi=3"
|
||||
},
|
||||
{
|
||||
id: "3", name: "Amanda Lee, Student", date: "Date: 20 Jan 2025", title: "Affordable and delicious", quote: "Great prices, diverse restaurant selection, and lightning-fast delivery. This app has saved me so much time during exam season!", tag: "Student Discount", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/homemade-mexican-taco-boats-recipe-idea_53876-95999.jpg?_wi=3"
|
||||
},
|
||||
{
|
||||
id: "4", name: "Robert Garcia, Family Dad", date: "Date: 22 Jan 2025", title: "Family favorite", quote: "My whole family loves FoodHub. Easy to use, great restaurants, and the loyalty rewards program is fantastic!", tag: "Family Plan", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/side-view-couple-eating-pizza-doner-wrapped-lavash-served-with-french-fries-sauces-table-table_140725-12112.jpg?_wi=4"
|
||||
},
|
||||
{
|
||||
id: "5", name: "Sofia Patel, Foodie", date: "Date: 24 Jan 2025", title: "Incredible variety", quote: "From street food to fine dining, FoodHub has it all. Their restaurant selection and curation is top-notch!", tag: "Food Explorer", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/pagliatelle-with-meat-jte-table_140725-6761.jpg?_wi=4"
|
||||
},
|
||||
{
|
||||
id: "6", name: "Michael Chen, Busy Executive", date: "Date: 25 Jan 2025", title: "Saves me hours every week", quote: "As someone with a hectic schedule, FoodHub is a lifesaver. Consistent quality and reliability every single time.", tag: "Business User", avatarSrc: "http://img.b2bpic.net/free-photo/closeup-young-female-professional-making-eye-contact-against-colored-background_662251-651.jpg", imageSrc: "http://img.b2bpic.net/free-photo/homemade-mexican-taco-boats-recipe-idea_53876-95999.jpg?_wi=4"
|
||||
}
|
||||
]}
|
||||
title="What Our Customers Say"
|
||||
description="Thousands of happy customers enjoy fresh meals delivered daily"
|
||||
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: "Casual Diner", buttons: [
|
||||
{ text: "Get Started", href: "#" }
|
||||
],
|
||||
features: [
|
||||
"Full restaurant access", "Standard delivery", "Real-time tracking", "Multiple payment methods"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "2", badge: "Most Popular", badgeIcon: Sparkles,
|
||||
price: "$9.99/mo", name: "Premium Member", buttons: [
|
||||
{ text: "Subscribe Now", href: "#" }
|
||||
],
|
||||
features: [
|
||||
"$2 off each order", "Free delivery on all orders", "Priority customer support", "Exclusive member restaurants", "Birthday bonus credit"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "3", price: "$19.99/mo", name: "VIP Plus", buttons: [
|
||||
{ text: "Get VIP Access", href: "#" }
|
||||
],
|
||||
features: [
|
||||
"Everything in Premium", "$5 off each order", "Free premium restaurant access", "Dedicated concierge support", "Monthly reward points"
|
||||
]
|
||||
}
|
||||
]}
|
||||
title="Special Offers & Promotions"
|
||||
description="Save more with our exclusive membership plans"
|
||||
tag="Limited Time"
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactText
|
||||
text="Ready to satisfy your cravings? Download FoodHub today and enjoy delicious meals delivered to your door. Join thousands of happy customers!"
|
||||
animationType="entrance-slide"
|
||||
background={{ variant: "radial-gradient" }}
|
||||
buttons={[
|
||||
{ text: "Download App", href: "#" },
|
||||
{ text: "Contact Us", href: "#" }
|
||||
{ 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&_wi=2"
|
||||
imageAlt="Footer background"
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "How It Works", href: "#features" },
|
||||
{ label: "Browse Restaurants", href: "#product" },
|
||||
{ label: "Pricing Plans", href: "#pricing" },
|
||||
{ label: "Download App", href: "#" }
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "Pricing", href: "/" },
|
||||
{ label: "Security", href: "/" },
|
||||
{ label: "FAQ", href: "/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "#about" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Blog", href: "/" },
|
||||
{ label: "Careers", href: "/" },
|
||||
{ label: "Press", href: "/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Support", items: [
|
||||
{ label: "Help Center", href: "#" },
|
||||
{ label: "Contact Us", href: "#contact" },
|
||||
{ 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 FoodHub | Delicious meals delivered fast"
|
||||
logoText="EasyRecipes"
|
||||
copyrightText="© 2025 EasyRecipes. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
--accent: #ffffff;
|
||||
--background-accent: #ffffff; */
|
||||
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #120a00e6;
|
||||
--primary-cta: #ff8c42;
|
||||
--background: #f8f5ff;
|
||||
--card: #f1ecff;
|
||||
--foreground: #1a0f3f;
|
||||
--primary-cta: #8b5cf6;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #120a00e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #c4c4c4;
|
||||
--accent: #c4a8f9;
|
||||
--background-accent: #ddd6fe;
|
||||
|
||||
/* text sizing - set by ThemeProvider */
|
||||
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
|
||||
|
||||
Reference in New Issue
Block a user