feat: add sales-first Rank landing

This commit is contained in:
OpenClaw Bot
2026-05-23 22:03:59 +02:00
parent c0f97eac5f
commit 934a29b8d2
4 changed files with 124 additions and 17 deletions
+20
View File
@@ -51,6 +51,25 @@ const profiles = {
},
};
const state = { ideas: [], milestones: [], activity: [], activeId: null, selected: null, profileId: localStorage.getItem('rank-profile') || 'mvp', undo: null, recentPlacement: null };
const sampleBacklog = {
format: 'prioritix-feature-set-v1',
name: 'Messy SaaS launch backlog',
features: [
{ title: 'Mobile sorting flow feels clumsy', description: 'Users can capture ideas, but the phone flow makes prioritizing feel like work instead of relief.', labels: ['Mobile', 'Activation'], impact: 9, effort: 4, confidence: 8, urgency: 8 },
{ title: 'Team voting on every feature', description: 'Stakeholders want input, but voting may create politics before the product has a clear decision model.', labels: ['Collaboration'], impact: 7, effort: 7, confidence: 4, urgency: 5 },
{ title: 'Export roadmap for sales calls', description: 'Turn sorted decisions into something founders can share with clients or internal buyers.', labels: ['Sales', 'Export'], impact: 8, effort: 5, confidence: 7, urgency: 7 },
{ title: 'Dark mode polish', description: 'Nice for taste, but unlikely to decide whether anyone trusts the core prioritization.', labels: ['Polish'], impact: 4, effort: 3, confidence: 8, urgency: 2 },
{ title: 'AI explains why an idea moved', description: 'Every ranking should show a reason, risk, and what evidence would change the decision.', labels: ['Trust', 'AI'], impact: 9, effort: 6, confidence: 6, urgency: 8 }
]
};
function loadSampleBacklog(){
const input = $('#featureSetInput');
if(!input) return;
input.value = JSON.stringify(sampleBacklog, null, 2);
document.querySelector('#feature-sets')?.scrollIntoView({ behavior:'smooth', block:'start' });
toast('Sample backlog loaded. Import it or replace it with your own chaos.');
}
const $ = (sel, root=document) => root.querySelector(sel);
const $$ = (sel, root=document) => Array.from(root.querySelectorAll(sel));
const featureDeck = $('#featureDeck'); const sortingGrid = $('#sortingGrid'); const timeline = $('#timeline');
@@ -168,6 +187,7 @@ async function reorderOnTimeline(id,e){ const line=e.currentTarget; const idea=s
function openDetail(id){ const idea=state.ideas.find(i=>i.id===id); if(!idea) return; state.selected=id; detailForm.title.value=idea.title||''; detailForm.description.value=idea.description||''; detailForm.labels.value=(idea.labels||[]).join(', '); detailForm.impact.value=idea.impact??5; detailForm.effort.value=idea.effort??5; detailForm.confidence.value=idea.confidence??5; detailForm.urgency.value=idea.urgency??5; detailForm.notes.value=idea.notes||''; $('#detailCategory').textContent=categoryOf(idea); $('.detail-head .chip').textContent=zoneFor(idea).label; detail.classList.add('open'); detail.setAttribute('aria-hidden','false'); }
function closeDetail(){ detail.classList.remove('open'); detail.setAttribute('aria-hidden','true'); state.selected=null; }
async function archiveIdea(id=state.selected){ if(!id) return; const previous=state.ideas.find(i=>i.id===id); try{ await api(`/api/ideas/${id}`,{method:'PATCH',body:{archived:true,status:'remove'}}); state.ideas = state.ideas.filter(i=>i.id!==id); closeDetail(); render(); toast('Removed', previous ? () => undoIdea({...previous, archived:false}) : null); } catch(error){ toast(error.message); } }
$('#sampleBacklog')?.addEventListener('click', loadSampleBacklog);
$('#featureSetFile')?.addEventListener('change', async e => {
const file = e.currentTarget.files?.[0];
if(!file) return;