Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions components/nft-gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { Loader2 } from 'lucide-react';
import Image from 'next/image';
import { useRouter } from 'next/navigation'; // ✅ CHANGE 1: Added useRouter import
import React, { useState, useEffect } from 'react';

import { Badge } from '@/components/ui/badge';
Expand All @@ -25,9 +26,11 @@ interface Story {
salesCount: number;
royaltyPercentage?: number;
}

export function NFTGallery() {
const [stories, setStories] = useState<Story[]>([]);
const [isLoading, setIsLoading] = useState(true);
const router = useRouter();

useEffect(() => {
fetchStories();
Expand All @@ -45,7 +48,6 @@ export function NFTGallery() {
}
};

// Add a filter for best sellers based on a hypothetical salesCount property
const bestSellers =
stories
?.filter((story) => story.salesCount > 0)
Expand All @@ -58,6 +60,7 @@ export function NFTGallery() {
</div>
);
}

return (
<div className="flex flex-col gap-6 px-2 py-6 max-w-7xl mx-auto">
<h2 className="text-2xl font-bold text-foreground pl-2">NFT Gallery</h2>
Expand Down Expand Up @@ -88,15 +91,19 @@ export function NFTGallery() {
</div>
<p className="line-clamp-3">{story.content}</p>
</CardContent>
<CardFooter className="flex justify-between items-center">
<CardFooter className="flex justify-between items-center gap-2">
<span className="text-sm text-muted-foreground">
By {story.author}
</span>
<span className="text-sm font-medium">
Price: {story.price} ETH
{story.price} ETH
</span>
<Button variant="outline" size="sm">
View Details
<Button
variant="default"
size="sm"
onClick={() => router.push(`/nft/${story.id}`)}
>
Buy Now
</Button>
Comment on lines +101 to 107
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# 1. Search for NFT detail page route
fd -type f \( -name "page.tsx" -o -name "page.ts" \) | xargs grep -l "nft\|NFT" 2>/dev/null || echo "No NFT pages found with grep"
fd -type f -path "*/nft/*" \( -name "page.tsx" -o -name "page.ts" \) 2>/dev/null || echo "No nft directory route found"

# 2. Check the actual nft.js server file for _id handling
if [ -f "server/routes/nft.js" ]; then
  echo "=== server/routes/nft.js content ===" 
  cat -n "server/routes/nft.js"
else
  echo "server/routes/nft.js not found"
  fd -type f -name "nft.js" 
fi

# 3. Search for any API transformation or id aliasing
rg -n "id|_id" --type ts --type tsx -A 2 -B 2 | head -100

Repository: IndieHub25/GroqTales

Length of output: 30238


🏁 Script executed:

# 4. List all app/page routes to understand structure
fd -type f -path "*/app/*" \( -name "page.tsx" -o -name "page.ts" \) 2>/dev/null | head -20

# 5. Search for any nft-related routes or files
fd -type f -name "*nft*" 2>/dev/null

Repository: IndieHub25/GroqTales

Length of output: 46


🏁 Script executed:

# 6. Check nft-gallery.tsx to understand what data structure is being used
if [ -f "components/nft-gallery.tsx" ]; then
  echo "=== nft-gallery.tsx ===" 
  cat -n "components/nft-gallery.tsx" | head -150
else
  fd -type f -name "nft-gallery.tsx"
fi

Repository: IndieHub25/GroqTales

Length of output: 4603


🏁 Script executed:

# Search for /api/stories endpoint
fd -type f -name "route.ts" -o -name "route.js" | xargs grep -l "stories" 2>/dev/null || echo "Searching in app directory..."
find . -path "*/app/*" -type f \( -name "route.ts" -o -name "route.js" \) | head -20

# Also search for any stories API handler
rg -l "stories" --type ts --type js | grep -E "(api|route)" | head -10

Repository: IndieHub25/GroqTales

Length of output: 1172


🏁 Script executed:

# List the app directory structure to understand routing
find . -path "*/app/*" -type d | head -20

Repository: IndieHub25/GroqTales

Length of output: 510


🏁 Script executed:

# Search more broadly for stories endpoint
rg "api/stories|/stories" --type ts --type js -A 3 | head -50

Repository: IndieHub25/GroqTales

Length of output: 2332


🏁 Script executed:

# Search for /api/stories route in Next.js app directory
find ./app/api -name "route.ts" -o -name "route.js" | xargs grep -l "stories" 2>/dev/null || echo "No stories route found in app/api"

# Check if there's a stories folder in app/api
ls -la ./app/api/ | grep stories || echo "No stories directory"
fd "stories" ./app/api 2>/dev/null || echo "stories not in app/api"

# Check next.config for rewrites/proxying
if [ -f "next.config.js" ] || [ -f "next.config.ts" ] || [ -f "next.config.mjs" ]; then
  echo "=== next.config files ===" 
  cat next.config.* 2>/dev/null | head -100
fi

Repository: IndieHub25/GroqTales

Length of output: 2469


🏁 Script executed:

# Search for where /api/stories is actually handled
rg "GET.*stories|api/stories" -A 5 | head -60

Repository: IndieHub25/GroqTales

Length of output: 3032


🏁 Script executed:

# Check the stories.js server file to see response structure
cat -n server/routes/stories.js | head -150

Repository: IndieHub25/GroqTales

Length of output: 5091


🏁 Script executed:

# Search for middleware or response transformation
rg "api/stories|middleware" -A 3 -B 3 | head -80

Repository: IndieHub25/GroqTales

Length of output: 50377


🏁 Script executed:

# Look for middleware files
fd "middleware" -type f 2>/dev/null

Repository: IndieHub25/GroqTales

Length of output: 46


🏁 Script executed:

# Check if there's a proxy setup or fetch wrapper
rg "fetch.*stories|axios.*stories" -A 5 | head -60

Repository: IndieHub25/GroqTales

Length of output: 2178


🏁 Script executed:

# Verify the exact response being received - check if /api/stories is actually a Next.js route
fd -type f \( -name "page.tsx" -o -name "layout.tsx" \) -path "*/app/*" | xargs grep -l "fetch.*stories" 2>/dev/null | head -5

Repository: IndieHub25/GroqTales

Length of output: 234


🏁 Script executed:

# Check all Next.js route handlers in app/api directory
find ./app/api -name "route.ts" -o -name "route.js" 2>/dev/null | xargs -I {} sh -c 'echo "=== {} ===" && head -30 {}'

Repository: IndieHub25/GroqTales

Length of output: 18824


🏁 Script executed:

# Specifically look for stories endpoint - check if /api/stories exists anywhere
rg "export.*GET|export.*POST.*stories" -A 10 ./app/api 2>/dev/null | head -80

Repository: IndieHub25/GroqTales

Length of output: 5043


🏁 Script executed:

# Search for any adapter or data transformation for stories response
rg "stories.*data|data.*pagination" ./app -B 2 -A 2 | head -60

Repository: IndieHub25/GroqTales

Length of output: 1322


Three critical blocking issues prevent NFT purchase flow:

  1. Missing /api/stories endpoint — The component calls fetch('/api/stories') but no Next.js route handler exists at /app/api/stories/. The backend has /api/v1/stories (Express), not accessible to the frontend via /api/stories. This will fail immediately with a 404.

  2. Response structure mismatch — Even if the endpoint existed, the backend returns { data: stories[], pagination: {...} } but the code does setStories(data) expecting a stories array. This would set the entire response object as state instead of the array.

  3. _id vs id field mismatch — The backend query uses .lean() (line 86 in server/routes/stories.js), which strips Mongoose virtuals. MongoDB documents have _id, not id. The frontend expects story.id (line 19 in nft-gallery.tsx interface), so router.push('/nft/' + story.id) will navigate to /nft/undefined.

  4. Missing /nft/[id] detail page — No app/nft/[id]/page.tsx exists. Even if the above issues were fixed, clicking "Buy Now" would 404.

Current code (lines 101-107)
                <Button
                  variant="default"
                  size="sm"
                  onClick={() => router.push(`/nft/${story.id}`)}
                >
                  Buy Now
                </Button>

Implement: (1) create /app/api/stories/route.ts that proxies to backend and transforms _idid in response, (2) ensure response is the stories array directly, (3) add /app/nft/[id]/page.tsx, and (4) verify data shape matches frontend interface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/nft-gallery.tsx` around lines 101 - 107, Create an API proxy route
(app/api/stories/route.ts) that fetches from the backend /api/v1/stories,
extracts response.data (the stories array), maps each item to convert _id → id
(since server/routes/stories.js uses .lean()), and returns that stories array as
the JSON response; update the frontend code to call fetch('/api/stories') and
pass the returned array into setStories(storiesArray) (not the wrapper object),
ensure the frontend Story interface and uses of story.id (e.g.,
router.push(`/nft/${story.id}`) and the Button onClick) expect id:string, and
add a detail page component (app/nft/[id]/page.tsx) that fetches the single
story via the proxy (or a new proxy endpoint app/api/stories/[id]/route.ts) and
renders the NFT detail so clicking "Buy Now" does not 404.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Chithra582 update with missing endpoints and correct mismatched fields

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

</CardFooter>
</Card>
Expand All @@ -109,4 +116,4 @@ export function NFTGallery() {
</div>
</div>
);
}
}
Loading