Compare commits

..

2 Commits

Author SHA1 Message Date
fa3d65acde 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
2025-12-08 11:55:16 +01:00
74670cf9e5 fix: Correct portfolio import and TypeScript errors
- Fixed import: get_current_user from app.api.deps (not app.api.auth)
- Removed empty routes folder
- Fixed TldHistory interface (optional trend fields)
- Fixed DomainCheckResult interface (nullable fields)
- Fixed loadData function to compute values from available API data
2025-12-08 11:26:35 +01:00
4 changed files with 39 additions and 15 deletions

View File

@ -7,7 +7,7 @@ from sqlalchemy import select, func, and_
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db from app.database import get_db
from app.api.auth import get_current_user from app.api.deps import get_current_user
from app.models.user import User from app.models.user import User
from app.models.portfolio import PortfolioDomain, DomainValuation from app.models.portfolio import PortfolioDomain, DomainValuation
from app.services.valuation import valuation_service from app.services.valuation import valuation_service

View File

@ -54,24 +54,29 @@ interface TldDetails {
interface TldHistory { interface TldHistory {
tld: string tld: string
type?: string
description?: string
registry?: string
current_price: number current_price: number
price_change_7d: number price_change_7d: number
price_change_30d: number price_change_30d: number
price_change_90d: number price_change_90d: number
trend: string trend: string
trend_reason: string
history: Array<{ history: Array<{
date: string date: string
price: number price: number
}> }>
source?: string
} }
interface DomainCheckResult { interface DomainCheckResult {
domain: string domain: string
is_available: boolean is_available: boolean
status: string status: string
registrar?: string registrar?: string | null
creation_date?: string creation_date?: string | null
expiration_date?: string expiration_date?: string | null
} }
// Registrar URLs with affiliate parameters // Registrar URLs with affiliate parameters
@ -419,26 +424,28 @@ export default function TldDetailPage() {
]) ])
if (historyData && compareData) { if (historyData && compareData) {
const registrars = compareData.registrars || [] // Sort registrars by price for display
const priceRange = compareData.price_range || { min: 0, max: 0, avg: 0 } const sortedRegistrars = [...(compareData.registrars || [])].sort((a, b) =>
a.registration_price - b.registration_price
)
// Use API data directly for consistency with overview table
setDetails({ setDetails({
tld: compareData.tld || tld, tld: compareData.tld || tld,
type: compareData.type || 'generic', type: compareData.type || 'generic',
description: compareData.description || `Domain extension .${tld}`, description: compareData.description || `Domain extension .${tld}`,
registry: compareData.registry || 'Unknown', registry: compareData.registry || 'Various',
introduced: compareData.introduced || 0, introduced: compareData.introduced || 0,
trend: historyData.trend || 'stable', trend: historyData.trend || 'stable',
trend_reason: historyData.trend_reason || 'Price tracking available', trend_reason: historyData.trend_reason || 'Price tracking available',
pricing: { pricing: {
avg: priceRange.avg || historyData.current_price || 0, // Use price_range from API for consistency with overview
min: priceRange.min || historyData.current_price || 0, avg: compareData.price_range?.avg || historyData.current_price || 0,
max: priceRange.max || historyData.current_price || 0, min: compareData.price_range?.min || historyData.current_price || 0,
max: compareData.price_range?.max || historyData.current_price || 0,
}, },
registrars: registrars.sort((a: { registration_price: number }, b: { registration_price: number }) => registrars: sortedRegistrars,
a.registration_price - b.registration_price cheapest_registrar: compareData.cheapest_registrar || sortedRegistrars[0]?.name || 'N/A',
),
cheapest_registrar: compareData.cheapest_registrar || registrars[0]?.name || 'N/A',
}) })
setHistory(historyData) setHistory(historyData)
} else { } else {

View File

@ -262,27 +262,43 @@ class ApiClient {
async getTldHistory(tld: string, days = 90) { async getTldHistory(tld: string, days = 90) {
return this.request<{ return this.request<{
tld: string tld: string
type: string
description: string
registry: string
current_price: number current_price: number
price_change_7d: number price_change_7d: number
price_change_30d: number price_change_30d: number
price_change_90d: number price_change_90d: number
trend: string
trend_reason: string
history: Array<{ history: Array<{
date: string date: string
price: number price: number
}> }>
source: string
}>(`/tld-prices/${tld}/history?days=${days}`) }>(`/tld-prices/${tld}/history?days=${days}`)
} }
async getTldCompare(tld: string) { async getTldCompare(tld: string) {
return this.request<{ return this.request<{
tld: string tld: string
type: string
description: string
registry: string
introduced: number | null
registrars: Array<{ registrars: Array<{
name: string name: string
registration_price: number registration_price: number
renewal_price: number renewal_price: number
transfer_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`) }>(`/tld-prices/${tld}/compare`)
} }

File diff suppressed because one or more lines are too long