fix: Ensure consistent price calculations across all pages

PROBLEM:
- TLD prices in overview table differed from detail page
- Detail page was recalculating prices instead of using API data

SOLUTION:
1. Updated Frontend API types to include all backend fields:
   - getTldCompare: Added type, description, registry, introduced,
     cheapest_registrar, cheapest_price, price_range
   - getTldHistory: Added type, description, registry, trend,
     trend_reason, source

2. Fixed TLD Detail Page:
   - Now uses price_range from Compare API directly
   - Removed manual price recalculation
   - Uses trend/trend_reason from History API
   - All values now match Overview table exactly

RESULT:
- Prices are now 100% consistent:
  - Overview table shows avg_registration_price from /overview API
  - Detail page shows pricing.avg from /compare API (same values)
  - Trending cards show current_price from /trending API (same values)
  - All calculated using get_avg_price() in backend
This commit is contained in:
yves.gugger
2025-12-08 11:55:16 +01:00
parent 74670cf9e5
commit fa3d65acde
3 changed files with 39 additions and 31 deletions

View File

@ -54,16 +54,20 @@ interface TldDetails {
interface TldHistory {
tld: string
type?: string
description?: string
registry?: string
current_price: number
price_change_7d: number
price_change_30d: number
price_change_90d: number
trend?: string
trend_reason?: string
trend: string
trend_reason: string
history: Array<{
date: string
price: number
}>
source?: string
}
interface DomainCheckResult {
@ -420,42 +424,30 @@ export default function TldDetailPage() {
])
if (historyData && compareData) {
const registrars = compareData.registrars || []
const sortedRegistrars = [...registrars].sort((a, b) =>
// Sort registrars by price for display
const sortedRegistrars = [...(compareData.registrars || [])].sort((a, b) =>
a.registration_price - b.registration_price
)
const minPrice = sortedRegistrars[0]?.registration_price || historyData.current_price || 0
const maxPrice = sortedRegistrars[sortedRegistrars.length - 1]?.registration_price || historyData.current_price || 0
const avgPrice = registrars.length > 0
? registrars.reduce((sum, r) => sum + r.registration_price, 0) / registrars.length
: historyData.current_price || 0
// Determine trend from price change
const trend = historyData.price_change_30d > 5 ? 'up'
: historyData.price_change_30d < -5 ? 'down'
: 'stable'
// Use API data directly for consistency with overview table
setDetails({
tld: compareData.tld || tld,
type: 'generic',
description: `Domain extension .${tld}`,
registry: 'Various',
introduced: 0,
trend: trend,
trend_reason: trend === 'up' ? 'Price increase' : trend === 'down' ? 'Price decrease' : 'Stable pricing',
type: compareData.type || 'generic',
description: compareData.description || `Domain extension .${tld}`,
registry: compareData.registry || 'Various',
introduced: compareData.introduced || 0,
trend: historyData.trend || 'stable',
trend_reason: historyData.trend_reason || 'Price tracking available',
pricing: {
avg: avgPrice,
min: minPrice,
max: maxPrice,
// Use price_range from API for consistency with overview
avg: compareData.price_range?.avg || historyData.current_price || 0,
min: compareData.price_range?.min || historyData.current_price || 0,
max: compareData.price_range?.max || historyData.current_price || 0,
},
registrars: sortedRegistrars,
cheapest_registrar: sortedRegistrars[0]?.name || 'N/A',
})
setHistory({
...historyData,
trend: trend,
trend_reason: trend === 'up' ? 'Price increase' : trend === 'down' ? 'Price decrease' : 'Stable pricing',
cheapest_registrar: compareData.cheapest_registrar || sortedRegistrars[0]?.name || 'N/A',
})
setHistory(historyData)
} else {
setError('Failed to load TLD data')
}

View File

@ -262,27 +262,43 @@ class ApiClient {
async getTldHistory(tld: string, days = 90) {
return this.request<{
tld: string
type: string
description: string
registry: string
current_price: number
price_change_7d: number
price_change_30d: number
price_change_90d: number
trend: string
trend_reason: string
history: Array<{
date: string
price: number
}>
source: string
}>(`/tld-prices/${tld}/history?days=${days}`)
}
async getTldCompare(tld: string) {
return this.request<{
tld: string
type: string
description: string
registry: string
introduced: number | null
registrars: Array<{
name: string
registration_price: number
renewal_price: number
transfer_price: number
features: string[]
}>
cheapest_registrar: string
cheapest_price: number
price_range: {
min: number
max: number
avg: number
}
}>(`/tld-prices/${tld}/compare`)
}

File diff suppressed because one or more lines are too long