Skip to content

Commit

Permalink
Merge pull request #959 from IkkiOcean/new_page_10
Browse files Browse the repository at this point in the history
Added Trending Products Page with Search, Sort, and Product Grid
  • Loading branch information
manikumarreddyu authored Nov 10, 2024
2 parents 1809400 + 7f2315f commit b455203
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 1 deletion.
120 changes: 120 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/Trending.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React, { useState } from "react";
import Header from "./components/THeader";
import Banner from "./components/Banner";
import SearchAndSort from "./components/SearchAndSort";
import ProductGrid from "./components/ProductGrid";

export default function TrendingProductsPage() {
const [sortBy, setSortBy] = useState("trending");
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(false);

// Filtering products based on search term
const filteredProducts = trendingProducts.filter((product) =>
product.name.toLowerCase().includes(searchTerm.toLowerCase())
);

// Sorting products based on selected criteria
const sortedProducts = [...filteredProducts].sort((a, b) => {
if (sortBy === "price") return a.price - b.price;
if (sortBy === "rating") return b.rating - a.rating;
return 0;
});

// Simulate loading state
const fetchData = async () => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
}, 2000);
};

React.useEffect(() => {
fetchData();
}, []);

return (
<div className="bg-gray-100">
<Header />
<Banner />
<div className="container mx-auto px-4 py-12">
{/* Search and Sort Component */}
<SearchAndSort
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
sortBy={sortBy}
setSortBy={setSortBy}
/>
{/* Loading state and Product Grid */}
{isLoading ? (
<div className="text-center py-12 text-xl text-gray-600">
Loading...
</div>
) : (
<ProductGrid sortedProducts={sortedProducts} />
)}
</div>
</div>
);
}

const trendingProducts = [
{
id: 1,
name: "Smart Irrigation System",
price: 299.99,
rating: 4.8,
reviews: 120,
image:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTTkXzsfqi9x6H46rC1Ir7k2WEQ1V0lVv8ONA&s",
tag: "Trending Now",
},
{
id: 2,
name: "Organic Fertilizer Pack",
price: 49.99,
rating: 4.5,
reviews: 85,
image: "https://m.media-amazon.com/images/I/91Y3l-BVm-L.jpg",
tag: "Hot Deal",
},
{
id: 3,
name: "Drone Crop Sprayer",
price: 1299.99,
rating: 4.9,
reviews: 200,
image:
"https://5.imimg.com/data5/ANDROID/Default/2022/4/AA/WY/ED/14166347/product-jpeg-500x500.jpg",
tag: "Top Rated",
},
{
id: 4,
name: "Soil pH Tester",
price: 29.99,
rating: 4.2,
reviews: 60,
image: "https://m.media-amazon.com/images/I/71933Pfn55L.jpg",
tag: "Trending Now",
},
{
id: 5,
name: "Hydroponic Growing Kit",
price: 199.99,
rating: 4.7,
reviews: 150,
image:
"https://m.media-amazon.com/images/I/81n3GQOCOQL._AC_UF1000,1000_QL80_.jpg",
tag: "Hot Deal",
},
{
id: 6,
name: "Weather Station",
price: 149.99,
rating: 4.6,
reviews: 95,
image:
"https://5.imimg.com/data5/YN/KT/YB/SELLER-5098190/weather-station.jpg",
tag: "Top Rated",
},
];
37 changes: 37 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/components/Banner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export default function Banner() {
return (
<div className="bg-green-100 py-12 md:py-16">
<div className="container mx-auto px-6 md:px-12 text-center">
{/* Heading */}
<h2 className="text-4xl font-bold text-green-800 mb-4 leading-tight md:text-5xl">
Trending in AgroTech
</h2>

{/* Description */}
<p className="text-xl text-green-700 mb-6 md:text-2xl">
Discover the latest and most popular agricultural innovations! Stay
ahead with new technologies.
</p>

{/* Call to Action */}
<div className="flex justify-center space-x-4">
<button className="bg-green-500 text-white py-3 px-6 rounded-lg text-lg hover:bg-green-600 transition duration-300">
Learn More
</button>
<button className="bg-transparent border-2 border-green-500 text-green-500 py-3 px-6 rounded-lg text-lg hover:bg-green-50 transition duration-300">
Explore Products
</button>
</div>

{/* Image Section (Optional for added visual appeal) */}
<div className="mt-8">
<img
src="/assets/agriculture-banner.jpg"
alt="Agriculture Innovations"
className="mx-auto w-full h-[60vh] object-cover rounded-lg shadow-lg transition duration-300 ease-in-out transform hover:scale-105"
/>
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import ProductCard from "./TProductCard";

export default function ProductGrid({ sortedProducts }) {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
{sortedProducts.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Search, ChevronDown } from "lucide-react";

export default function SearchAndSort({
searchTerm,
setSearchTerm,
sortBy,
setSortBy,
}) {
return (
<div className="flex flex-col md:flex-row justify-between items-center mb-8 px-4 md:px-8">
{/* Search Input */}
<div className="relative w-full md:w-72 mb-4 md:mb-0">
<label htmlFor="search" className="text-sm text-gray-600 mb-2 block">
Search Products
</label>
<input
id="search"
type="text"
placeholder="Search products..."
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500 transition duration-200 ease-in-out"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
aria-label="Search products"
/>
<Search className="absolute left-3 top-2.5 text-gray-400" size={20} />
</div>

{/* Sort By Dropdown */}
<div className="relative w-full md:w-56">
<label htmlFor="sortBy" className="text-sm text-gray-600 mb-2 block">
Sort By
</label>
<select
id="sortBy"
className="w-full appearance-none bg-white border border-gray-300 rounded-lg px-4 py-2 pr-8 focus:outline-none focus:ring-2 focus:ring-green-500 transition duration-200 ease-in-out"
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
aria-label="Sort products by"
>
<option value="trending">Trending Now</option>
<option value="price">Price: Low to High</option>
<option value="rating">Top Rated</option>
<option value="newest">Newest Arrivals</option>
<option value="discount">Discounted</option>
</select>
<ChevronDown
className="absolute right-3 top-2.5 text-gray-400 pointer-events-none"
size={20}
/>
</div>

{/* Filter Button */}
<div className="w-full md:w-32 mt-4 md:mt-0">
<button
className="w-full bg-green-500 text-white py-2 rounded-lg hover:bg-green-600 transition duration-200 ease-in-out"
onClick={() => alert("Filters Applied")}
>
Apply Filters
</button>
</div>
</div>
);
}
32 changes: 32 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/components/THeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export default function Header() {
return (
<header className="bg-green-600 text-white py-4 shadow-md">
<div className="container mx-auto flex justify-between items-center px-6">
{/* Logo and Title */}
<div className="flex items-center space-x-3">
<img
src="/assets/logo.png"
alt="AgroShop Logo"
className="w-8 h-8 object-cover rounded-full"
/>
<h1 className="text-3xl font-bold">AgroShop</h1>
</div>

{/* Navigation Links */}
<nav className="hidden md:flex space-x-6 text-lg">
<a href="/" className="hover:text-green-300 transition duration-200 ease-in-out">Home</a>
<a href="/products" className="hover:text-green-300 transition duration-200 ease-in-out">Products</a>
<a href="/about" className="hover:text-green-300 transition duration-200 ease-in-out">About Us</a>
<a href="/contact" className="hover:text-green-300 transition duration-200 ease-in-out">Contact</a>
</nav>

{/* Mobile Menu Button */}
<div className="md:hidden flex items-center">
<button className="text-white text-2xl">
<i className="fa fa-bars"></i>
</button>
</div>
</div>
</header>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Star } from "lucide-react";

export default function ProductCard({ product }) {
return (
<div className="bg-white rounded-lg shadow-lg overflow-hidden transition-transform transform hover:scale-105">
{/* Product Image and Tag */}
<div className="relative">
<img
src={product.image}
alt={product.name}
className="w-full h-48 object-cover transition duration-300 ease-in-out hover:opacity-80"
/>
<span className="absolute top-2 right-2 bg-green-500 text-white px-3 py-1 rounded-full text-sm font-semibold">
{product.tag}
</span>
</div>

{/* Product Details */}
<div className="p-4 space-y-4">
<div className="flex justify-between items-center">
<h3 className="text-xl font-semibold text-gray-900 truncate">
{product.name}
</h3>
<span className="text-gray-500 text-sm">
{product.stock} in stock
</span>
</div>

{/* Rating and Reviews */}
<div className="flex items-center space-x-2">
<span className="text-yellow-500 flex items-center">
<Star className="fill-current" size={16} />
<span className="ml-1">{product.rating}</span>
</span>
<span className="text-gray-600 text-sm">
({product.reviews} reviews)
</span>
</div>

{/* Price */}
<p className="text-green-600 font-bold text-2xl">
${product.price.toFixed(2)}
</p>

{/* Add to Cart Button */}
<button className="w-full bg-green-500 text-white py-2 rounded-lg hover:bg-green-600 focus:outline-none transition duration-300">
Add to Cart
</button>
</div>

{/* Hover Effect */}
<div className="p-4 mt-4 text-center">
<span className="text-sm text-gray-500">
Free shipping on orders over $50!
</span>
</div>
</div>
);
}
6 changes: 5 additions & 1 deletion frontend/src/MainContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,14 @@ import FlashSale from './AgroShopAI/components/Pages/components/SalePage';


import WaterManagement from './components/models/WaterManagement';

import TrendingProductsPage from './AgroShopAI/components/Pages/Trending';

import AffiliateProgramPage from './AgroShopAI/components/Pages/Affiliate';




const MainContent = () => {
UseScrollToTop();
const location = useLocation(); // Get the current route
Expand Down Expand Up @@ -211,7 +215,7 @@ const MainContent = () => {
<Route path="/agri/affiliate" element={<AffiliateProgramPage />} />
<Route path="/agri/sale" element={<FlashSale/>} />
<Route path="/discussion" element={<DiscussionForum />} />

<Route path="/agri/trend" element={<TrendingProductsPage/>} />

</Routes>
{checkShop ? <ShopFooter /> : <Footer />}
Expand Down

0 comments on commit b455203

Please sign in to comment.