From cf89864444b5b7abc128e605006932f83a0f416e Mon Sep 17 00:00:00 2001
From: thesn10 <38666407+thesn10@users.noreply.github.com>
Date: Fri, 3 Jul 2026 13:05:39 +0200
Subject: [PATCH] Redesign listing detail
---
app/src/app/listing/[id].tsx | 139 +++++++++++++++++++++--------------
1 file changed, 85 insertions(+), 54 deletions(-)
diff --git a/app/src/app/listing/[id].tsx b/app/src/app/listing/[id].tsx
index 38515f7..67d8e1a 100644
--- a/app/src/app/listing/[id].tsx
+++ b/app/src/app/listing/[id].tsx
@@ -1,28 +1,60 @@
import type { JSX } from "react";
import type { ViewStyle } from "react-native";
import { useMemo, useState } from "react";
-import { Platform, ScrollView, View } from "react-native";
+import { Platform, ScrollView, StyleSheet, View, useWindowDimensions } from "react-native";
import { useLocalSearchParams } from "expo-router";
-import { Button, Chip, Separator, Typography, useToast } from "heroui-native";
+import { Button, Chip, Separator, Typography, useThemeColor, useToast } from "heroui-native";
+import { Ionicons } from "@expo/vector-icons";
+import Svg, { Defs, LinearGradient, RadialGradient, Rect, Stop } from "react-native-svg";
import type { Currency } from "@/data/mock";
import { PRODUCTS, RESOLVERS } from "@/data/mock";
import { availabilityInfo } from "@/lib/status";
+import { MICRO_LABEL_CLASS } from "@/lib/typography";
import { AppHeader } from "@/components/AppHeader";
import { StatusChip } from "@/components/StatusChip";
import { ResolverCard } from "@/components/ResolverCard";
import { ListingCard } from "@/components/ListingCard";
+import { MonoText } from "@/components/MonoText";
+import { PageContainer } from "@/components/PageContainer";
import { useModals } from "@/state/modals";
-// react-native-web supports CSS `position: sticky`, but React Native's own
-// ViewStyle type doesn't include it — cast is required to use it web-only.
-const stickyBoxStyle: ViewStyle | undefined =
- Platform.OS === "web" ? ({ position: "sticky", top: 84 } as ViewStyle) : undefined;
+const STICKY_BREAKPOINT = 1024;
+
+function HeroGradientOverlay({ gradientId }: { gradientId: string }): JSX.Element {
+ const highlightId = `${gradientId}-highlight`;
+ const fadeId = `${gradientId}-fade`;
+ return (
+
+ );
+}
export default function ListingDetailScreen(): JSX.Element {
const { id } = useLocalSearchParams<{ id: string }>();
const { toast } = useToast();
const { requestBuy } = useModals();
const [resolverId, setResolverId] = useState(0);
+ const { width } = useWindowDimensions();
+ const accentColor = useThemeColor("accent");
+
+ // react-native-web supports CSS `position: sticky`, but React Native's own
+ // ViewStyle type doesn't include it — cast is required to use it web-only.
+ const stickyBoxStyle: ViewStyle | undefined =
+ Platform.OS === "web" && width >= STICKY_BREAKPOINT
+ ? ({ position: "sticky", top: 92 } as ViewStyle)
+ : undefined;
const listing = useMemo(
() => PRODUCTS.find((product) => product.id === Number(id)) ?? PRODUCTS[0],
@@ -36,30 +68,36 @@ export default function ListingDetailScreen(): JSX.Element {
return (
-
-
+
+
- {listing.emoji}
+
+ {listing.emoji}
- {listing.name}
-
+
+ {listing.name}
+
+
{listing.desc}
+
+
+
Verified on Solana
-
+
{listing.seller}
-
+
-
- About this listing
-
-
+ About this listing
+
-
- Category
-
-
+ Category
+
{listing.cat}
-
- Available
-
-
+ Available
+
{listing.qty} units
-
- Currency
-
-
+ Currency
+
{listing.cur}
-
- Listing ID
-
-
+ Listing ID
+
{`#${listing.id}${listing.id}${listing.id}${listing.id}`}
-
+
@@ -109,7 +137,7 @@ export default function ListingDetailScreen(): JSX.Element {
{relatedProducts.length > 0 && (
Customers also bought
-
+
{relatedProducts.map((product) => (
))}
@@ -118,14 +146,19 @@ export default function ListingDetailScreen(): JSX.Element {
)}
-
+
- {listing.price}
-
+
+ {listing.price}
+
+
≈ {listing.usd} USD
-
-
+
+
@@ -134,9 +167,7 @@ export default function ListingDetailScreen(): JSX.Element {
{listing.alt.length > 0 && (
<>
-
- Pay with
-
+ Pay with
-
- Dispute Protection
-
+ Dispute Protection
{RESOLVERS.map((resolver) => (
setResolverId(resolver.id)}
/>
))}
-
+
Fee only charged if dispute is adjudicated.
@@ -179,29 +208,31 @@ export default function ListingDetailScreen(): JSX.Element {
-
+
✓ Final Payment
-
+
🛡 Dispute Cover
-
+
⬡ On-chain
-
+
Funds held in secure escrow until you confirm receipt.
-
+
);
}