diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 6a46746..14932fb 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,9 +1,4 @@
-# 📘 Issue Description
--
-
----
-
-## 🔍 Steps to Reproduce
+## 📘 Description
-
## ✅ Acceptance Criteria
@@ -15,3 +10,6 @@
## 📜 Additional Notes
-
+⚠ Do not apply until the ODHack begins.
+
+⚠ Read our guidelines before applying.
\ No newline at end of file
diff --git a/frontend/app/components/Bounded.tsx b/frontend/app/components/Bounded.tsx
deleted file mode 100644
index a90c26a..0000000
--- a/frontend/app/components/Bounded.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-interface BoundedProps {
- children: React.ReactNode;
- title: string;
-}
-
-const Bounded = ({ children, title }: BoundedProps) => {
- return (
-
- {title}
- {children}
-
- );
-};
-
-export default Bounded;
diff --git a/frontend/app/components/home/feature-section.tsx b/frontend/app/components/home/feature-section.tsx
new file mode 100644
index 0000000..70a3653
--- /dev/null
+++ b/frontend/app/components/home/feature-section.tsx
@@ -0,0 +1,92 @@
+import { BarChart3, Coins, Lock, Shield, Users, Zap } from "lucide-react";
+
+export function FeatureSection() {
+ const features = [
+ {
+ icon: ,
+ title: "Smart Contract Escrow",
+ description: (
+ <>
+ Automated protection with Stellar smart contracts. Trustless Work API
+ abstracts the complexities of smart contract configuration. It
+ leverages the blockchain to ensure transactions are secure and
+ transparent, providing fairness without bias in the marketplace. Read
+ more on
+
+ Trustless Work
+
+ >
+ ),
+ gradient: "from-blue-500 to-cyan-500",
+ },
+ {
+ icon: ,
+ title: "Lightning Settlement",
+ description: "3-5 second finality on Stellar network",
+ gradient: "from-yellow-500 to-orange-500",
+ },
+ {
+ icon: ,
+ title: "Non-Custodial Trading",
+ description: "Keep full control of your assets",
+ gradient: "from-purple-500 to-pink-500",
+ },
+ {
+ icon: ,
+ title: "Multi-Asset Support",
+ description: "Trade any Stellar-based token",
+ gradient: "from-green-500 to-emerald-500",
+ },
+ {
+ icon: ,
+ title: "DAO Governance",
+ description: "Community-driven protocol decisions",
+ gradient: "from-red-500 to-pink-500",
+ },
+ {
+ icon: ,
+ title: "Real-Time Analytics",
+ description: "Advanced trading metrics & insights",
+ gradient: "from-indigo-500 to-purple-500",
+ },
+ ];
+
+ return (
+
+
+
+ Built for the Future of Finance
+
+
+ Leveraging the power of Stellar blockchain to provide a secure,
+ efficient, and truly decentralized trading experience.
+
+
+ {features.map((feature) => (
+
+
+
+
+ {feature.icon}
+
+
{feature.title}
+
{feature.description}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/frontend/app/components/ui/hero-section.tsx b/frontend/app/components/home/hero-section.tsx
similarity index 97%
rename from frontend/app/components/ui/hero-section.tsx
rename to frontend/app/components/home/hero-section.tsx
index 83d2789..85a7095 100644
--- a/frontend/app/components/ui/hero-section.tsx
+++ b/frontend/app/components/home/hero-section.tsx
@@ -1,8 +1,8 @@
-import { Button } from "@/app/components/ui/button";
import { ArrowRight } from "lucide-react";
import Link from "next/link";
-import * as React from "react";
-import { SafeSwapLogo } from "./SafeSwapLogo";
+
+import { SafeSwapLogo } from "@/app/components/shared/safe-swap-logo";
+import { Button } from "@/app/components/ui/button";
export function HeroSection() {
return (
diff --git a/frontend/app/components/ui/stats-section.tsx b/frontend/app/components/home/stats-section.tsx
similarity index 97%
rename from frontend/app/components/ui/stats-section.tsx
rename to frontend/app/components/home/stats-section.tsx
index 91dc239..963c523 100644
--- a/frontend/app/components/ui/stats-section.tsx
+++ b/frontend/app/components/home/stats-section.tsx
@@ -1,5 +1,3 @@
-import * as React from "react";
-
export function StatsSection() {
return (
diff --git a/frontend/app/components/ui/add-product-modal.tsx b/frontend/app/components/marketplace/add-product-modal.tsx
similarity index 85%
rename from frontend/app/components/ui/add-product-modal.tsx
rename to frontend/app/components/marketplace/add-product-modal.tsx
index 9a6a356..fea7d79 100644
--- a/frontend/app/components/ui/add-product-modal.tsx
+++ b/frontend/app/components/marketplace/add-product-modal.tsx
@@ -1,15 +1,16 @@
import React from "react";
-import { Button } from "./button";
-import { Input } from "./input";
-import { Label } from "./label";
+
+import { Button } from "@/app/components/ui/button";
+import { Input } from "@/app/components/ui/input";
+import { Label } from "@/app/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "./select";
-import { Textarea } from "./textarea";
+} from "@/app/components/ui/select";
+import { Textarea } from "@/app/components/ui/textarea";
interface AddProductModalProps {
isOpen: boolean;
@@ -24,8 +25,8 @@ const AddProductModal: React.FC
= ({
return (
-
diff --git a/frontend/app/components/marketplace/breadcrumb-navigation.tsx b/frontend/app/components/marketplace/breadcrumb-navigation.tsx
new file mode 100644
index 0000000..8e837b6
--- /dev/null
+++ b/frontend/app/components/marketplace/breadcrumb-navigation.tsx
@@ -0,0 +1,24 @@
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from "@/app/components/ui/breadcrumb";
+
+export default function BreadcrumbNavigation() {
+ return (
+
+
+
+ Home
+
+
+
+ Marketplace
+
+
+
+ );
+}
diff --git a/frontend/app/components/marketplace/filters.tsx b/frontend/app/components/marketplace/filters.tsx
new file mode 100644
index 0000000..9fdd799
--- /dev/null
+++ b/frontend/app/components/marketplace/filters.tsx
@@ -0,0 +1,69 @@
+"use client";
+
+import { Checkbox, Slider } from "@radix-ui/themes";
+import { useState } from "react";
+
+import { SidebarContent, SidebarHeader } from "@/app/components/ui/sidebar";
+
+const Filters = () => {
+ const [priceRange, setPriceRange] = useState<[number, number]>([0, 1500]);
+ const [selectedCategories, setSelectedCategories] = useState
([]);
+
+ const handleCategoryChange = (category: string) => {
+ setSelectedCategories((prev) =>
+ prev.includes(category)
+ ? prev.filter((c) => c !== category)
+ : [...prev, category],
+ );
+ };
+
+ return (
+ <>
+
+ Filters
+
+
+
+
+
Price range
+
+ setPriceRange(value as [number, number])
+ }
+ className="mb-3"
+ />
+
+ ${priceRange[0]}
+ ${priceRange[1]}
+
+
+
+
Categories
+
+ {["Electronics", "Furniture", "Appliances", "Sports"].map(
+ (category) => (
+
+ handleCategoryChange(category)}
+ />
+
+
+ ),
+ )}
+
+
+
+
+ >
+ );
+};
+
+export default Filters;
diff --git a/frontend/app/components/marketplace/index.ts b/frontend/app/components/marketplace/index.ts
deleted file mode 100644
index b7492fc..0000000
--- a/frontend/app/components/marketplace/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ProductsPagination } from "./products-pagination";
diff --git a/frontend/app/components/marketplace/products-pagination.tsx b/frontend/app/components/marketplace/products-pagination.tsx
index 31bf175..1be064d 100644
--- a/frontend/app/components/marketplace/products-pagination.tsx
+++ b/frontend/app/components/marketplace/products-pagination.tsx
@@ -6,7 +6,7 @@ import {
PaginationLink,
PaginationNext,
PaginationPrevious,
-} from "../ui/pagination";
+} from "@/app/components/ui/pagination";
import {
Select,
SelectContent,
@@ -14,15 +14,12 @@ import {
SelectItem,
SelectTrigger,
SelectValue,
-} from "../ui/select";
+} from "@/app/components/ui/select";
export const ProductsPagination = () => {
return (
-
-
+
+
-
+
diff --git a/frontend/app/components/products/Images.tsx b/frontend/app/components/products/Images.tsx
index e849428..fbfd19e 100644
--- a/frontend/app/components/products/Images.tsx
+++ b/frontend/app/components/products/Images.tsx
@@ -1,46 +1,45 @@
import Image from "next/image";
-import React from "react";
interface ImageProps {
- images: {
- src: string;
- alt: string;
- }[];
+ images: {
+ src: string;
+ alt: string;
+ }[];
}
const Images = ({ images }: ImageProps) => {
- if (!images || images.length === 0) {
- return No images available
;
- }
+ if (!images || images.length === 0) {
+ return No images available
;
+ }
- const mainImage = images[0];
+ const mainImage = images[0];
- return (
-
-
+ return (
+
+
- {images.length > 1 && (
-
- {images.map((image, index) => (
-
- ))}
-
- )}
-
- );
+ {images.length > 1 && (
+
+ {images.map((image, index) => (
+
+ ))}
+
+ )}
+
+ );
};
export default Images;
diff --git a/frontend/app/components/products/ProductDetailModal.tsx b/frontend/app/components/products/ProductDetailModal.tsx
deleted file mode 100644
index 891f15d..0000000
--- a/frontend/app/components/products/ProductDetailModal.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import { Button } from "@/app/components/ui/button";
-import { ShoppingCart, Star } from "lucide-react";
-import ImageCarousel from "../ui/image-carrousel";
-
-interface Product {
- id: number;
- images: { src: string; alt: string }[];
- name: string;
- description: string;
- price: number;
- category: string;
-}
-
-function ProductDetailModal({
- isOpen,
- onClose,
- product,
-}: {
- isOpen: boolean;
- onClose: () => void;
- product: Product | null;
-}) {
- if (!product) return null;
- const renderStars = (rating: number) => {
- const filledStars = Math.floor(rating);
- const halfStars = rating % 1 >= 0.5 ? 1 : 0;
- const emptyStars = 5 - (filledStars + halfStars);
-
- return [
- ...Array(filledStars).fill("filled"),
- ...Array(halfStars).fill("half"),
- ...Array(emptyStars).fill("empty"),
- ];
- };
-
- const rating = 4.3;
-
- return (
-
-
-
-
-
-
- {product.name}
-
-
-
-
-
-
- {product.category}
-
-
- {product.price ? `$${product.price}` : "Price not available"}
-
-
- {product.description}
-
-
-
-
- {renderStars(rating).map((star, index) => {
- if (star === "filled") {
- return ;
- } else if (star === "half") {
- return (
-
- );
- } else {
- return (
-
- );
- }
- })}
-
- {rating.toFixed(1)} / 5
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default ProductDetailModal;
diff --git a/frontend/app/components/products/images-carrousel.tsx b/frontend/app/components/products/images-carrousel.tsx
new file mode 100644
index 0000000..c4e30b4
--- /dev/null
+++ b/frontend/app/components/products/images-carrousel.tsx
@@ -0,0 +1,50 @@
+import Image from "next/image";
+import * as React from "react";
+
+import { Card, CardContent } from "@/app/components/ui/card";
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselNext,
+ CarouselPrevious,
+} from "@/app/components/ui/carousel";
+
+interface ImagesCarouselProps {
+ images: { src: string; alt: string }[];
+}
+
+const ImagesCarousel: React.FC = ({ images }) => {
+ return (
+
+
+
+ {images.map((image, index) => (
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
+
+export default ImagesCarousel;
diff --git a/frontend/app/components/providers/theme-provider.tsx b/frontend/app/components/providers/theme-provider.tsx
index 0e2a2f1..fba8ad6 100644
--- a/frontend/app/components/providers/theme-provider.tsx
+++ b/frontend/app/components/providers/theme-provider.tsx
@@ -2,7 +2,6 @@
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes";
-import * as React from "react";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return {children};
diff --git a/frontend/app/components/shared/delivery-country.tsx b/frontend/app/components/shared/delivery-country.tsx
new file mode 100644
index 0000000..571bc2d
--- /dev/null
+++ b/frontend/app/components/shared/delivery-country.tsx
@@ -0,0 +1,48 @@
+import { MapPin } from "lucide-react";
+import Image from "next/image";
+
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue,
+} from "@/app/components/ui/select";
+
+export function DeliveryCountry() {
+ return (
+
+
+
Ship to
+
+
+ );
+}
+
+export default DeliveryCountry;
diff --git a/frontend/app/components/shared/footer.tsx b/frontend/app/components/shared/footer.tsx
new file mode 100644
index 0000000..2cdd8af
--- /dev/null
+++ b/frontend/app/components/shared/footer.tsx
@@ -0,0 +1,22 @@
+import Link from "next/link";
+
+import { SafeSwapLogo } from "@/app/components/shared/safe-swap-logo";
+
+export default function Footer() {
+ return (
+
+ );
+}
diff --git a/frontend/app/components/header/Header.tsx b/frontend/app/components/shared/header.tsx
similarity index 56%
rename from frontend/app/components/header/Header.tsx
rename to frontend/app/components/shared/header.tsx
index 1d5de3d..e5d73bb 100644
--- a/frontend/app/components/header/Header.tsx
+++ b/frontend/app/components/shared/header.tsx
@@ -1,16 +1,5 @@
"use client";
-import { SafeSwapLogo } from "@/app/components/ui/SafeSwapLogo";
-import { Button } from "@/app/components/ui/button";
-import DeliveryLocationButton from "@/app/components/ui/delivery-location-button";
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/app/components/ui/dropdown-menu";
-import { Input } from "@/app/components/ui/input";
-import { ThemeToggle } from "@/app/components/ui/theme-toggle";
import {
History,
List,
@@ -23,6 +12,18 @@ import {
import Link from "next/link";
import { useState } from "react";
+import DeliveryCountry from "@/app/components/shared/delivery-country";
+import { SafeSwapLogo } from "@/app/components/shared/safe-swap-logo";
+import { Button } from "@/app/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/app/components/ui/dropdown-menu";
+import { Input } from "@/app/components/ui/input";
+import { ThemeToggle } from "@/app/components/ui/theme-toggle";
+
export default function Header() {
const [searchTerm, setSearchTerm] = useState("");
const showSearchBar = searchTerm !== undefined && setSearchTerm !== undefined;
@@ -34,39 +35,41 @@ export default function Header() {
+
+
+
+ {showSearchBar ? (
+
+ setSearchTerm(e.target.value)}
+ className="w-full h-10 pr-10"
+ />
+
+
+ ) : null}
- {showSearchBar ? (
-
- setSearchTerm(e.target.value)}
- className="w-full h-8 pr-10"
- />
-
-
- ) : null}
-
-
-