diff --git a/frontend/app/components/ui/card.tsx b/frontend/app/components/ui/card.tsx new file mode 100644 index 0000000..7500a1c --- /dev/null +++ b/frontend/app/components/ui/card.tsx @@ -0,0 +1,76 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } \ No newline at end of file diff --git a/frontend/app/components/ui/checkbox.tsx b/frontend/app/components/ui/checkbox.tsx new file mode 100644 index 0000000..94d214f --- /dev/null +++ b/frontend/app/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } \ No newline at end of file diff --git a/frontend/app/components/ui/hero-section.tsx b/frontend/app/components/ui/hero-section.tsx index ae33cec..9b80d35 100644 --- a/frontend/app/components/ui/hero-section.tsx +++ b/frontend/app/components/ui/hero-section.tsx @@ -1,56 +1,63 @@ + import { Button } from "@/app/components/ui/button"; import { ArrowRight, Wallet } from "lucide-react"; +import Link from "next/link"; import * as React from "react"; export function HeroSection() { - return ( -
- {/* Gradient Background */} -
- - {/* Animated Grid Background */} -
- -
-
- - - - - Live on Stellar Network -
- -

- The Future of - Secure Trading -

- -

- Experience trustless trading with built-in Stellar escrow protection. - Your gateway to secure, decentralized commerce. -

- -
- - -
- - {/* Live Stats Ticker */} -
-
- - Network Status: Active -
-
24h Volume: $1.2M
-
Gas: 0.001 XLM
-
-
-
- ); + return ( +
+ {/* Gradient Background */} +
+ + {/* Animated Grid Background */} +
+ +
+
+ + + + + Live on Stellar Network +
+ +

+ The Future of + Secure Trading +

+ +

+ Experience trustless trading with built-in Stellar escrow protection. + Your gateway to secure, decentralized commerce. +

+ +
+ + + + +
+ + {/* Live Stats Ticker */} +
+
+ + Network Status: Active +
+
24h Volume: $1.2M
+
Gas: 0.001 XLM
+
+
+
+ ); } diff --git a/frontend/app/components/ui/input.tsx b/frontend/app/components/ui/input.tsx new file mode 100644 index 0000000..7030e99 --- /dev/null +++ b/frontend/app/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } \ No newline at end of file diff --git a/frontend/app/components/ui/sidebar.tsx b/frontend/app/components/ui/sidebar.tsx new file mode 100644 index 0000000..206228b --- /dev/null +++ b/frontend/app/components/ui/sidebar.tsx @@ -0,0 +1,102 @@ +import React, { createContext, useContext, useState, ReactNode } from "react"; +import { cn } from "@/lib/utils"; +import { X, Menu } from "lucide-react"; + +interface SidebarContextType { + isOpen: boolean; + toggleSidebar: () => void; +} + +const SidebarContext = createContext(undefined); + +export const SidebarProvider = ({ children }: { children: ReactNode }) => { + const [isOpen, setIsOpen] = useState(false); + const toggleSidebar = () => setIsOpen(!isOpen); + + return ( + + {children} + + ); +}; + +export const useSidebar = () => { + const context = useContext(SidebarContext); + if (!context) { + throw new Error("useSidebar must be used within a SidebarProvider"); + } + return context; +}; + +export const Sidebar = React.forwardRef>( + ({ className, ...props }, ref) => { + const { isOpen } = useSidebar(); + return ( +
+ ); + } +); +Sidebar.displayName = "Sidebar"; + +export const SidebarHeader = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ {props.children} + +
+ ) +); +SidebarHeader.displayName = "SidebarHeader"; + +export const SidebarContent = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +SidebarContent.displayName = "SidebarContent"; + +export const SidebarTrigger = React.forwardRef>( + ({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar(); + return ( + + ); + } +); +SidebarTrigger.displayName = "SidebarTrigger"; + +export const SidebarClose = React.forwardRef>( + ({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar(); + return ( + + ); + } +); +SidebarClose.displayName = "SidebarClose"; + +// export { SidebarProvider, Sidebar, SidebarHeader, SidebarContent, SidebarTrigger, SidebarClose }; diff --git a/frontend/app/components/ui/slider.tsx b/frontend/app/components/ui/slider.tsx new file mode 100644 index 0000000..43e5919 --- /dev/null +++ b/frontend/app/components/ui/slider.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" + +import { cn } from "@/lib/utils" + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)) +Slider.displayName = SliderPrimitive.Root.displayName + +export { Slider } \ No newline at end of file diff --git a/frontend/app/marketplace/page.tsx b/frontend/app/marketplace/page.tsx new file mode 100644 index 0000000..178d7d5 --- /dev/null +++ b/frontend/app/marketplace/page.tsx @@ -0,0 +1,172 @@ +'use client'; +import { useState, Dispatch, SetStateAction } from 'react'; +import { Slider } from "@/app/components/ui/slider"; +import { Checkbox } from "@/app/components/ui/checkbox"; +import { Button } from "@/app/components/ui/button"; +import { Input } from "@/app/components/ui/input"; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/app/components/ui/card"; +import { Sidebar, SidebarContent, SidebarHeader, SidebarProvider, SidebarTrigger } from "@/app/components/ui/sidebar"; +import { Search, Menu as HamIcon } from "lucide-react"; + +interface Product { + id: number; + name: string; + price: number; + category: string; +} + +interface SidebarComponentProps { + priceRange: [number, number]; + setPriceRange: Dispatch>; + selectedCategories: string[]; + handleCategoryChange: (category: string) => void; +} + +interface HeaderComponentProps { + searchTerm: string; + setSearchTerm: Dispatch>; +} + +interface ProductListProps { + products: Product[]; +} + +const products: Product[] = [ + { id: 1, name: "Laptop Pro", price: 1299, category: "Electronics" }, + { id: 2, name: "Smartphone X", price: 699, category: "Electronics" }, + { id: 3, name: "Ergonomic Chair", price: 299, category: "Furniture" }, + { id: 4, name: "Coffee Maker", price: 89, category: "Appliances" }, + { id: 5, name: "Running Shoes", price: 129, category: "Sports" }, + { id: 6, name: "Wireless Earbuds", price: 159, category: "Electronics" }, +]; + +export default function Marketplace() { + const [priceRange, setPriceRange] = useState<[number, number]>([0, 1500]); + const [selectedCategories, setSelectedCategories] = useState([]); + const [searchTerm, setSearchTerm] = useState(""); + + const handleCategoryChange = (category: string) => { + setSelectedCategories(prev => + prev.includes(category) + ? prev.filter(c => c !== category) + : [...prev, category] + ); + }; + + const filteredProducts = products.filter(product => + (searchTerm === "" || product.name.toLowerCase().includes(searchTerm.toLowerCase())) && + (selectedCategories.length === 0 || selectedCategories.includes(product.category)) && + product.price >= priceRange[0] && product.price <= priceRange[1] + ); + + return ( + +
+ +
+ + +
+
+
+ ); +} + +function SidebarComponent({ priceRange, setPriceRange, selectedCategories, handleCategoryChange }: SidebarComponentProps) { + return ( + + +

Filters

+
+ +
+
+

Price range

+ +
+ ${priceRange[0]} + ${priceRange[1]} +
+
+
+

Categories

+
+ {["Electronics", "Furniture", "Appliances", "Sports"].map((category) => ( +
+ handleCategoryChange(category)} + /> + +
+ ))} +
+
+
+
+
+ ); +} + +function HeaderComponent({ searchTerm, setSearchTerm }: HeaderComponentProps) { + return ( +
+ + + +
+ setSearchTerm(e.target.value)} + className="w-[16rem] h-[3rem]" + /> + +
+
+ ); +} + +function ProductList({ products }: ProductListProps) { + return ( +
+

Products

+
+ {products?.map((product) => ( + + + {product.name} + + +

{product.category}

+
+ + ${product.price} + + +
+ ))} +
+
+ ); +}