fix: remove prescreen tab, use bulk bar select+prescreen only

- drop standalone Pre-screen tab (textarea upload) — confusing duplicate
- bulk bar Pre-screen Selected button is the only entry point now
- add prescreening flag with loading state on button + double-click guard
- remove dead prescreenInput/prescreenRunning/prescreenResult state vars and runPrescreen()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-04 20:00:50 +02:00
parent ad03107f0d
commit db93401a81

View File

@@ -102,7 +102,6 @@ textarea{width:100%;resize:vertical;font-family:monospace;font-size:12px}
<button class="tab-btn" :class="{active:tab==='browse'}" @click="tab='browse';loadDomains()">Browse</button>
<button class="tab-btn" :class="{active:tab==='validator'}" @click="tab='validator';loadValStatus()">Validator</button>
<button class="tab-btn" :class="{active:tab==='pipeline'}" @click="tab='pipeline';loadLeads()">B2B Pipeline</button>
<button class="tab-btn" :class="{active:tab==='prescreen'}" @click="tab='prescreen'">Pre-screen</button>
<button class="tab-btn" :class="{active:tab==='export'}" @click="tab='export'">Export</button>
</div>
</div>
@@ -160,7 +159,10 @@ textarea{width:100%;resize:vertical;font-family:monospace;font-size:12px}
<!-- Bulk bar (visible when items selected) -->
<div class="bulk-bar" x-show="selected.length>0">
<span style="color:var(--accent);font-weight:600;font-size:12px" x-text="selected.length+' selected'"></span>
<button class="btn-ok btn-sm" @click="prescreenSelected()">Pre-screen Selected</button>
<button class="btn-ok btn-sm" @click="prescreenSelected()" :disabled="prescreening">
<span x-show="!prescreening">Pre-screen Selected</span>
<span x-show="prescreening">Screening…</span>
</button>
<button class="btn-primary btn-sm" @click="assessSelected()">B2B Assess Selected</button>
<button class="btn-secondary btn-sm" @click="selected=[]">Clear</button>
</div>
@@ -381,22 +383,6 @@ textarea{width:100%;resize:vertical;font-family:monospace;font-size:12px}
</div>
<!-- ══════════════════════ PRE-SCREEN ══════════════════════ -->
<div x-show="tab==='prescreen'" class="section-pad" style="padding-top:16px">
<p style="color:var(--muted);font-size:12px;margin-bottom:12px">
<strong style="color:var(--text)">Phase 1</strong> — HTTP check: marks domains live / dead / parked / redirect / error.<br>
<strong style="color:var(--text)">Phase 2</strong> — DeepSeek classifies niche (beauty_cosmetics, fashion_retail…) and site type (ecommerce, corporate…).<br>
Paste up to 200 domains, one per line. Results saved automatically — then use Browse to filter by beauty + ecommerce.
</p>
<textarea x-model="prescreenInput" rows="12" placeholder="domain1.com&#10;domain2.es&#10;domain3.fr&#10;…"></textarea>
<div style="display:flex;gap:10px;margin-top:10px;align-items:center;flex-wrap:wrap">
<button class="btn-primary" @click="runPrescreen()" :disabled="prescreenRunning">
<span x-show="!prescreenRunning">Run Pre-screen</span>
<span x-show="prescreenRunning">Running…</span>
</button>
<span x-show="prescreenResult" style="font-size:12px" x-text="prescreenResult"></span>
</div>
</div>
<!-- ══════════════════════ EXPORT ══════════════════════ -->
<div x-show="tab==='export'" class="section-pad" style="padding-top:24px">
<div class="card" style="max-width:460px">
@@ -444,7 +430,7 @@ function app() {
valSt: {running:false,processed:0,live:0,dead:0,error:0,parked:0,redirect:0,skipped:0,offset:0,rate:0},
valTld: '', valRescan: false,
toasts: [],
prescreenInput: '', prescreenRunning: false, prescreenResult: '',
prescreening: false,
exportQuality: '', exportCountry: '',
f: {keyword:'', tld:'', prescreen_status:'live', niche:'beauty_cosmetics',
site_type:'ecommerce', country:'', limit:'100', page:1},
@@ -530,7 +516,8 @@ function app() {
},
async prescreenSelected() {
if (!this.selected.length) return;
if (!this.selected.length || this.prescreening) return;
this.prescreening = true;
this.notify(`Pre-screening ${this.selected.length} domains…`, 'info');
try {
const chunks = [];
@@ -549,6 +536,7 @@ function app() {
this.selected = [];
await this.loadDomains();
} catch(e) { this.notify('Pre-screen failed: '+e.message, 'error'); }
finally { this.prescreening = false; }
},
async assessSelected() {
@@ -601,22 +589,6 @@ function app() {
.catch(()=> this.notify('Copy failed', 'error'));
},
async runPrescreen() {
const lines = this.prescreenInput.split('\n').map(l=>l.trim()).filter(Boolean);
if (!lines.length) { this.notify('No domains entered', 'error'); return; }
if (lines.length > 200) { this.notify('Max 200 per batch', 'error'); return; }
this.prescreenRunning = true; this.prescreenResult = '';
try {
const d = await fetch('/api/prescreen/batch', {
method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify({domains: lines}),
}).then(r=>r.json());
this.prescreenResult = `${d.live} live · ☠ ${d.dead} dead · 🅿 ${d.parked} parked · ↗ ${d.redirect} redirect · 🏷 ${d.classified} classified`;
this.notify(this.prescreenResult, 'success');
} catch(e) { this.notify('Failed: '+e.message, 'error'); }
finally { this.prescreenRunning = false; }
},
async startValidator() {
const p = new URLSearchParams();
if (this.valTld) p.set('tld', this.valTld);