fix: Remove infinite loop in loadData
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useStore } from '@/lib/store'
|
||||||
import { api } from '@/lib/api'
|
import { api } from '@/lib/api'
|
||||||
import { Header } from '@/components/Header'
|
import { Header } from '@/components/Header'
|
||||||
import { Footer } from '@/components/Footer'
|
import { Footer } from '@/components/Footer'
|
||||||
@ -36,6 +37,7 @@ interface Listing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function BrowseListingsPage() {
|
export default function BrowseListingsPage() {
|
||||||
|
const { isAuthenticated, checkAuth, isLoading: authLoading } = useStore()
|
||||||
const [listings, setListings] = useState<Listing[]>([])
|
const [listings, setListings] = useState<Listing[]>([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
const [searchQuery, setSearchQuery] = useState('')
|
||||||
@ -48,6 +50,10 @@ export default function BrowseListingsPage() {
|
|||||||
loadListings()
|
loadListings()
|
||||||
}, [sortBy, verifiedOnly])
|
}, [sortBy, verifiedOnly])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAuth()
|
||||||
|
}, [checkAuth])
|
||||||
|
|
||||||
const loadListings = async () => {
|
const loadListings = async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
@ -195,6 +201,37 @@ export default function BrowseListingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Contact gate hint (consistent with /buy/[slug]) */}
|
||||||
|
{!authLoading && !isAuthenticated && (
|
||||||
|
<div className="mb-8 p-4 border border-accent/20 bg-accent/5 rounded-2xl animate-slide-up">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="w-10 h-10 bg-accent/10 border border-accent/20 rounded-xl flex items-center justify-center text-accent shrink-0">
|
||||||
|
<Lock className="w-5 h-5" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<p className="text-sm font-semibold text-foreground">Contact requires login</p>
|
||||||
|
<p className="text-sm text-foreground-muted mt-1">
|
||||||
|
Listing details are public. To protect sellers from spam, inquiries are only available for logged-in accounts.
|
||||||
|
</p>
|
||||||
|
<div className="mt-3 flex flex-wrap gap-3">
|
||||||
|
<Link
|
||||||
|
href="/login?redirect=/buy"
|
||||||
|
className="inline-flex items-center gap-2 px-4 py-2 bg-accent text-background font-medium rounded-xl hover:bg-accent-hover transition-all"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/register?redirect=/buy"
|
||||||
|
className="inline-flex items-center gap-2 px-4 py-2 border border-border bg-background-secondary/30 text-foreground font-medium rounded-xl hover:border-accent/40 transition-all"
|
||||||
|
>
|
||||||
|
Register
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Listings Grid */}
|
{/* Listings Grid */}
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
@ -268,10 +305,18 @@ export default function BrowseListingsPage() {
|
|||||||
|
|
||||||
{/* View CTA */}
|
{/* View CTA */}
|
||||||
<div className="mt-4 pt-4 border-t border-border/50 flex items-center justify-between">
|
<div className="mt-4 pt-4 border-t border-border/50 flex items-center justify-between">
|
||||||
<span className="text-sm text-foreground-muted flex items-center gap-1">
|
<div className="text-sm text-foreground-muted">
|
||||||
<Eye className="w-3 h-3" />
|
<span className="flex items-center gap-1">
|
||||||
View Details
|
<Eye className="w-3 h-3" />
|
||||||
</span>
|
View Details
|
||||||
|
</span>
|
||||||
|
{!isAuthenticated && (
|
||||||
|
<span className="mt-1 flex items-center gap-1 text-xs text-foreground-subtle">
|
||||||
|
<Lock className="w-3 h-3" />
|
||||||
|
Login to contact
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<ExternalLink className="w-4 h-4 text-foreground-subtle group-hover:text-accent transition-colors" />
|
<ExternalLink className="w-4 h-4 text-foreground-subtle group-hover:text-accent transition-colors" />
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -685,11 +685,10 @@ export default function PortfolioPage() {
|
|||||||
} catch { setListedDomains(new Set()) }
|
} catch { setListedDomains(new Set()) }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to load portfolio:', err)
|
console.error('Failed to load portfolio:', err)
|
||||||
showToast('Failed to load portfolio', 'error')
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}, [showToast])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => { loadData() }, [loadData])
|
useEffect(() => { loadData() }, [loadData])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user