From e0b53dd7fea6f71ea579e164a70ccb2ca71908d8 Mon Sep 17 00:00:00 2001 From: "yves.gugger" Date: Wed, 10 Dec 2025 16:00:34 +0100 Subject: [PATCH] fix: Smart 'Best' label + tooltips for TLD detail pages BEST VALUE LOGIC: - 'Best' badge only shown when: 1. Cheapest registration price AND 2. No renewal trap (renewal <= 1.5x registration) - New 'Cheap Start' badge for cheapest with renewal trap Shows warning: 'Cheapest registration but high renewal costs' TOOLTIPS ADDED: Stats Cards: - Buy (1y): 'Lowest first-year registration price...' - Renew (1y): 'Annual renewal price after first year' or 'Warning: Renewal is Xx the registration price' - 1y Change: 'Price change over the last 12 months' - 3y Change: 'Price change over the last 3 years' Registrar Table Headers: - Register: 'First year registration price' - Renew: 'Annual renewal price' - Transfer: 'Transfer from another registrar' Registrar Table Cells: - Registration price: 'First year: $X.XX' - Renewal price: 'Annual renewal: $X.XX' or trap warning - Transfer price: 'Transfer from another registrar: $X.XX' - AlertTriangle icon: 'Renewal trap: Xx registration price' - Best badge: 'Best overall value: lowest registration...' - Cheap Start badge: 'Cheapest registration but high renewal...' - Visit link: 'Register at {registrar}' Applied to both: - /command/pricing/[tld] (Command Center) - /tld-pricing/[tld] (Public) --- .../src/app/command/pricing/[tld]/page.tsx | 184 +++++++++++------- frontend/src/app/tld-pricing/[tld]/page.tsx | 160 +++++++++------ 2 files changed, 221 insertions(+), 123 deletions(-) diff --git a/frontend/src/app/command/pricing/[tld]/page.tsx b/frontend/src/app/command/pricing/[tld]/page.tsx index f46e031..2c1104e 100644 --- a/frontend/src/app/command/pricing/[tld]/page.tsx +++ b/frontend/src/app/command/pricing/[tld]/page.tsx @@ -406,28 +406,38 @@ export default function CommandTldDetailPage() { {/* Stats Grid - All info from table */}
- - - 0 ? '+' : ''}${details.price_change_1y.toFixed(0)}%`} - icon={details.price_change_1y > 0 ? TrendingUp : details.price_change_1y < 0 ? TrendingDown : Minus} - /> - 0 ? '+' : ''}${details.price_change_3y.toFixed(0)}%`} - icon={BarChart3} - /> +
+ +
+
+ +
+
+ 0 ? '+' : ''}${details.price_change_1y.toFixed(0)}%`} + icon={details.price_change_1y > 0 ? TrendingUp : details.price_change_1y < 0 ? TrendingDown : Minus} + /> +
+
+ 0 ? '+' : ''}${details.price_change_3y.toFixed(0)}%`} + icon={BarChart3} + /> +
{/* Risk Level */} @@ -506,55 +516,95 @@ export default function CommandTldDetailPage() { Registrar - Register - Renew - Transfer + Register + Renew + Transfer - {details.registrars.map((registrar, idx) => ( - - -
- {registrar.name} - {idx === 0 && ( - Cheapest - )} -
- - - - ${registrar.registration_price.toFixed(2)} - - - -
- ${registrar.renewal_price.toFixed(2)} - {registrar.renewal_price / registrar.registration_price > 2 && ( - - )} -
- - - ${registrar.transfer_price.toFixed(2)} - - - - Visit - - - - - ))} + {details.registrars.map((registrar, idx) => { + const hasRenewalTrap = registrar.renewal_price / registrar.registration_price > 1.5 + const isBestValue = idx === 0 && !hasRenewalTrap + + return ( + + +
+ {registrar.name} + {isBestValue && ( + + Best + + )} + {idx === 0 && hasRenewalTrap && ( + + Cheap Start + + )} +
+ + + + ${registrar.registration_price.toFixed(2)} + + + +
+ + ${registrar.renewal_price.toFixed(2)} + + {hasRenewalTrap && ( + + )} +
+ + + + ${registrar.transfer_price.toFixed(2)} + + + + + Visit + + + + + ) + })} diff --git a/frontend/src/app/tld-pricing/[tld]/page.tsx b/frontend/src/app/tld-pricing/[tld]/page.tsx index 538477d..a488a17 100644 --- a/frontend/src/app/tld-pricing/[tld]/page.tsx +++ b/frontend/src/app/tld-pricing/[tld]/page.tsx @@ -690,7 +690,10 @@ export default function TldDetailPage() { {/* Quick Stats - All data from table */}
-
+

Buy (1y)

{isAuthenticated ? (

${details.pricing.min.toFixed(2)}

@@ -698,7 +701,12 @@ export default function TldDetailPage() { )}
-
+

Renew (1y)

{isAuthenticated ? (
@@ -706,14 +714,17 @@ export default function TldDetailPage() { ${details.min_renewal_price.toFixed(2)}

{renewalInfo?.isTrap && ( - + )}
) : ( )}
-
+

1y Change

{isAuthenticated ? (

)}

-
+

3y Change

{isAuthenticated ? (

Registrar - + Register - + Renew - + Transfer - {details.registrars.map((registrar, i) => ( - - -

- {registrar.name} - {i === 0 && ( - - Best - + {details.registrars.map((registrar, i) => { + const hasRenewalTrap = registrar.renewal_price / registrar.registration_price > 1.5 + const isBestValue = i === 0 && !hasRenewalTrap + + return ( + + +
+ {registrar.name} + {isBestValue && ( + + Best + + )} + {i === 0 && hasRenewalTrap && ( + + Cheap Start + + )} +
+ + + + ${registrar.registration_price.toFixed(2)} + + + + + ${registrar.renewal_price.toFixed(2)} + + {hasRenewalTrap && ( + )} -
- - - - ${registrar.registration_price.toFixed(2)} - - - - - ${registrar.renewal_price.toFixed(2)} - - {registrar.renewal_price > registrar.registration_price * 1.5 && ( - - )} - - - - ${registrar.transfer_price.toFixed(2)} - - - - - Visit - - - - - ))} + + + + ${registrar.transfer_price.toFixed(2)} + + + + + Visit + + + + + ) + })}