feat: add per-domain registrar price comparison (register + renew)
Some checks are pending
CI / lint (push) Waiting to run
Deploy / deploy (push) Waiting to run

This commit is contained in:
Adrian Miesikowski 2026-02-17 23:24:12 +01:00
parent b5d632e887
commit 75300a1005

View File

@ -51,10 +51,10 @@
</div>
<div class="card">
<h2>TOP domen</h2>
<h2>TOP domen + porównanie cen (rejestracja / odnowienie)</h2>
<div class="table-wrap">
<table>
<thead><tr><th>Domena</th><th>TLD</th><th>Score</th><th>Status</th></tr></thead>
<thead><tr><th>Domena</th><th>TLD</th><th>Score</th><th>Status</th><th>Oferty (top 3)</th></tr></thead>
<tbody id="rows"></tbody>
</table>
</div>
@ -63,6 +63,7 @@
<script>
let domains = [];
let priceItems = [];
function money(v){ return (v===null || v===undefined || Number.isNaN(Number(v))) ? '—' : `${Number(v).toFixed(2)} zł`; }
@ -71,6 +72,39 @@ function domainCheckUrl(domain){
return `https://www.whois.com/whois/${d}`;
}
function registrarDomainUrl(name, domain){
const d = encodeURIComponent(domain);
const n = (name || '').toLowerCase();
if(n.includes('cyber')) return `https://cyberfolks.pl/domeny-rejestracja/?slowa=${d}`;
if(n.includes('home.pl')) return `https://home.pl/szukaj/?query=${d}`;
if(n.includes('nazwa')) return `https://www.nazwa.pl/sprawdz-domene/?domain=${d}`;
if(n.includes('ovh')) return `https://www.ovhcloud.com/pl/domains/?domain=${d}`;
if(n.includes('aftermarket')) return `https://aftermarket.pl/szukaj/${d}`;
if(n.includes('porkbun')) return `https://porkbun.com/checkout/search?q=${d}`;
return domainCheckUrl(domain);
}
async function loadPrices(){
const u = new URL('./api.php', location.href);
u.searchParams.set('action','prices');
const d = await (await fetch(u)).json();
priceItems = d.items || [];
}
function topOffersByTld(tld){
const offers = priceItems
.filter(x => x.tld === tld && x.register_price !== null && x.renew_price !== null)
.map(x => ({
registrar: x.registrar,
register: Number(x.register_price),
renew: Number(x.renew_price),
twoYear: Number(x.register_price) + Number(x.renew_price)
}))
.filter(x => !Number.isNaN(x.register) && !Number.isNaN(x.renew))
.sort((a,b) => a.twoYear - b.twoYear);
return offers.slice(0,3);
}
async function loadDomains(){
const q = document.getElementById('q').value.trim();
const tld = document.getElementById('tld').value;
@ -91,16 +125,26 @@ function renderRows(){
for(const d of domains.slice(0,300)){
const tr = document.createElement('tr');
const checkUrl = domainCheckUrl(d.domain);
const offers = topOffersByTld(d.tld);
const offersHtml = offers.length
? offers.map(o => {
const link = registrarDomainUrl(o.registrar, d.domain);
return `<div><a href='${link}' target='_blank'>${o.registrar}</a>: reg ${money(o.register)} / odn ${money(o.renew)} <span class='muted'>(2l: ${money(o.twoYear)})</span></div>`;
}).join('')
: `<span class='muted'>Brak danych cenowych dla .${d.tld}</span>`;
tr.innerHTML = `<td><a href='${checkUrl}' target='_blank'><b>${d.domain}</b></a> ${d.is_new ? `<span class='chip'>NEW</span>` : ''}</td>
<td>.${d.tld}</td>
<td>${d.score}</td>
<td>${d.status || 'available'}</td>`;
<td>${d.status || 'available'}</td>
<td>${offersHtml}</td>`;
rows.appendChild(tr);
}
}
async function refreshAll(){
await loadDomains();
await loadPrices();
renderRows();
}
@ -113,6 +157,7 @@ function setupAutoRefresh(){
if(enabled){
autoTimer = setInterval(async()=>{
await loadDomains();
await loadPrices();
renderRows();
}, 60000);
}