diff --git a/frontend/src/app/terminal/intel/page.tsx b/frontend/src/app/terminal/intel/page.tsx index 7f0a08b..462326e 100755 --- a/frontend/src/app/terminal/intel/page.tsx +++ b/frontend/src/app/terminal/intel/page.tsx @@ -92,33 +92,50 @@ export default function IntelPage() { setLoading(true) setError(null) try { - const response = await api.getTldOverview(500, 0, 'popularity') - console.log('TLD API Response:', response) + // Fetch multiple pages to get more TLDs (API limit is 100 per request) + const allTlds: TLDData[] = [] + let totalRecords = 0 - if (!response || !response.tlds) { + for (let offset = 0; offset < 500; offset += 100) { + const response = await api.getTldOverview(100, offset, 'popularity') + + if (!response || !response.tlds || response.tlds.length === 0) { + break + } + + totalRecords = response.total || 0 + + const mapped: TLDData[] = response.tlds.map((tld: any) => ({ + tld: tld.tld || '', + min_price: tld.min_registration_price || 0, + avg_price: tld.avg_registration_price || 0, + max_price: tld.max_registration_price || 0, + min_renewal_price: tld.min_renewal_price || 0, + avg_renewal_price: tld.avg_renewal_price || 0, + price_change_7d: tld.price_change_7d || 0, + price_change_1y: tld.price_change_1y || 0, + price_change_3y: tld.price_change_3y || 0, + risk_level: tld.risk_level || 'low', + risk_reason: tld.risk_reason || '', + popularity_rank: tld.popularity_rank, + type: tld.type, + })) + + allTlds.push(...mapped) + + // Stop if we got less than requested (no more data) + if (response.tlds.length < 100) break + } + + if (allTlds.length === 0) { setError('No TLD data available') setTldData([]) setTotal(0) return } - const mapped: TLDData[] = (response.tlds || []).map((tld: any) => ({ - tld: tld.tld || '', - min_price: tld.min_registration_price || 0, - avg_price: tld.avg_registration_price || 0, - max_price: tld.max_registration_price || 0, - min_renewal_price: tld.min_renewal_price || 0, - avg_renewal_price: tld.avg_renewal_price || 0, - price_change_7d: tld.price_change_7d || 0, - price_change_1y: tld.price_change_1y || 0, - price_change_3y: tld.price_change_3y || 0, - risk_level: tld.risk_level || 'low', - risk_reason: tld.risk_reason || '', - popularity_rank: tld.popularity_rank, - type: tld.type, - })) - setTldData(mapped) - setTotal(response.total || mapped.length) + setTldData(allTlds) + setTotal(totalRecords || allTlds.length) } catch (err: any) { console.error('Failed to load TLD data:', err) setError(err.message || 'Failed to load TLD data') diff --git a/frontend/src/app/terminal/market/page.tsx b/frontend/src/app/terminal/market/page.tsx index c800ebc..60cba53 100644 --- a/frontend/src/app/terminal/market/page.tsx +++ b/frontend/src/app/terminal/market/page.tsx @@ -10,6 +10,8 @@ import { Diamond, Zap, ChevronDown, + ChevronLeft, + ChevronRight, Plus, Check, TrendingUp, @@ -17,6 +19,7 @@ import { Clock, Search, Eye, + EyeOff, ShieldCheck, Store, Gavel, @@ -123,8 +126,13 @@ export default function MarketPage() { const [trackedDomains, setTrackedDomains] = useState>(new Set()) const [trackingInProgress, setTrackingInProgress] = useState(null) + + // Pagination + const [page, setPage] = useState(1) + const [totalPages, setTotalPages] = useState(1) + const ITEMS_PER_PAGE = 50 - const loadData = useCallback(async () => { + const loadData = useCallback(async (currentPage = 1) => { setLoading(true) try { const result = await api.getMarketFeed({ @@ -136,7 +144,8 @@ export default function MarketPage() { sortBy: sortField === 'score' ? 'score' : sortField === 'price' ? (sortDirection === 'asc' ? 'price_asc' : 'price_desc') : sortField === 'time' ? 'time' : 'newest', - limit: 100 + limit: ITEMS_PER_PAGE, + offset: (currentPage - 1) * ITEMS_PER_PAGE }) setItems(result.items || []) @@ -146,6 +155,7 @@ export default function MarketPage() { auctionCount: result.auction_count, highScore: (result.items || []).filter(i => i.pounce_score >= 80).length }) + setTotalPages(Math.ceil((result.total || 0) / ITEMS_PER_PAGE)) } catch (error) { console.error('Failed to load market data:', error) setItems([]) @@ -154,7 +164,15 @@ export default function MarketPage() { } }, [sourceFilter, searchQuery, priceRange, sortField, sortDirection, tldFilter]) - useEffect(() => { loadData() }, [loadData]) + useEffect(() => { + setPage(1) + loadData(1) + }, [loadData]) + + const handlePageChange = useCallback((newPage: number) => { + setPage(newPage) + loadData(newPage) + }, [loadData]) const handleRefresh = useCallback(async () => { setRefreshing(true) @@ -171,12 +189,42 @@ export default function MarketPage() { } }, [sortField]) + // Load user's tracked domains on mount + useEffect(() => { + const loadTrackedDomains = async () => { + try { + const result = await api.getDomains(1, 100) + const domainSet = new Set(result.items.map(d => d.domain)) + setTrackedDomains(domainSet) + } catch (error) { + console.error('Failed to load tracked domains:', error) + } + } + loadTrackedDomains() + }, []) + const handleTrack = useCallback(async (domain: string) => { - if (trackedDomains.has(domain) || trackingInProgress) return + if (trackingInProgress) return setTrackingInProgress(domain) + try { - await api.addDomain(domain) - setTrackedDomains(prev => new Set([...Array.from(prev), domain])) + if (trackedDomains.has(domain)) { + // Find and delete the domain + const result = await api.getDomains(1, 100) + const domainToDelete = result.items.find(d => d.domain === domain) + if (domainToDelete) { + await api.deleteDomain(domainToDelete.id) + setTrackedDomains(prev => { + const next = new Set(Array.from(prev)) + next.delete(domain) + return next + }) + } + } else { + // Add the domain + await api.addDomain(domain) + setTrackedDomains(prev => new Set([...Array.from(prev), domain])) + } } catch (error) { console.error(error) } finally { @@ -425,6 +473,34 @@ export default function MarketPage() { Score: {item.pounce_score} {displayTime || 'Instant'} + {/* Mobile Actions */} +
+ + + {isPounce ? 'Buy' : 'Bid'} + {!isPounce && } + +
{/* Desktop */} @@ -504,20 +580,21 @@ export default function MarketPage() {
@@ -542,6 +619,63 @@ export default function MarketPage() { })}
)} + + {/* Pagination */} + {!loading && totalPages > 1 && ( +
+
+ Page {page} of {totalPages} ยท {stats.total} domains +
+
+ + + {/* Page Numbers */} +
+ {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { + let pageNum: number + if (totalPages <= 5) { + pageNum = i + 1 + } else if (page <= 3) { + pageNum = i + 1 + } else if (page >= totalPages - 2) { + pageNum = totalPages - 4 + i + } else { + pageNum = page - 2 + i + } + + return ( + + ) + })} +
+ + +
+
+ )} )