ShubhraSaha's picture
Design a fully working, production-grade inline Context Selection feature inside the existing Superfuel Workflow page (dark theme). The page must match the screenshot exactly: left sidebar, a header with the workflow title “Add Competitor Keywords to the Bullet Points,” and a numbered vertical list of workflow steps. Add a fully functional Select Context button on Step 1 (“Get ASIN from Context”) that expands an inline Context Selection Panel beneath Step 1 (not a separate page or full-screen drawer). The panel must support three tabs: Manual Input, Search & Filters, Saved Contexts. Use the Superfuel x shadcn style: Inter font, 8px grid, dark palette (background #0B0C0F, panel #131417, borders #2B2C2F, text #E6E6E6, secondary text #A0A3A8, accent #2563EB), 8px radii, subtle shadows, and 150ms ease motion. All copy must match the tone: concise, factual, and technical.
9839720 verified
document.addEventListener('DOMContentLoaded', function() {
// Mock product data
const mockProducts = [
{"asin":"B08PP5MSVB","title":"Runner Pro Shoe - Blue","image":"https://via.placeholder.com/64","metrics":{"sales_30":1423,"cvr_30":0.18,"clicks_30":921}},
{"asin":"B09XYZ1234","title":"Trail Grip Shoe - Black","image":"https://via.placeholder.com/64","metrics":{"sales_30":543,"cvr_30":0.12,"clicks_30":320}},
{"asin":"B07ABC9876","title":"Daily Comfort Sneaker","image":"https://via.placeholder.com/64","metrics":{"sales_30":12,"cvr_30":0.02,"clicks_30":4}},
{"asin":"B0A1B2C3D4","title":"Performance Running Shorts","image":"https://via.placeholder.com/64","metrics":{"sales_30":876,"cvr_30":0.15,"clicks_30":421}},
{"asin":"B0D5E6F7G8","title":"Athletic Compression Socks","image":"https://via.placeholder.com/64","metrics":{"sales_30":321,"cvr_30":0.08,"clicks_30":154}},
{"asin":"B0H9I8J7K6","title":"Yoga Mat - Extra Thick","image":"https://via.placeholder.com/64","metrics":{"sales_30":654,"cvr_30":0.22,"clicks_30":298}},
{"asin":"B0L1M2N3O4","title":"Adjustable Dumbbell Set","image":"https://via.placeholder.com/64","metrics":{"sales_30":432,"cvr_30":0.14,"clicks_30":187}},
{"asin":"B0P5Q6R7S8","title":"Foam Roller - High Density","image":"https://via.placeholder.com/64","metrics":{"sales_30":189,"cvr_30":0.07,"clicks_30":92}},
{"asin":"B0T9U8V7W6","title":"Resistance Bands Set","image":"https://via.placeholder.com/64","metrics":{"sales_30":567,"cvr_30":0.19,"clicks_30":301}},
{"asin":"B0X1Y2Z3A4","title":"Jump Rope - Weighted","image":"https://via.placeholder.com/64","metrics":{"sales_30":234,"cvr_30":0.11,"clicks_30":123}}
];
// DOM Elements
const selectContextBtn = document.getElementById('selectContextBtn');
const contextPanel = document.getElementById('contextPanel');
const parseBtn = document.getElementById('parseBtn');
const asinInput = document.getElementById('asinInput');
const previewSection = document.getElementById('previewSection');
const previewGrid = document.getElementById('previewGrid');
const totalValidCount = document.getElementById('totalValidCount');
const selectAllBtn = document.getElementById('selectAllBtn');
const deselectAllBtn = document.getElementById('deselectAllBtn');
const selectedCountText = document.getElementById('selectedCountText');
const applySelectionBtn = document.getElementById('applySelectionBtn');
const saveContextCheckbox = document.getElementById('saveContextCheckbox');
const contextNameInput = document.getElementById('contextNameInput');
const tabButtons = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
const toast = document.getElementById('toast');
const confirmModal = document.getElementById('confirmModal');
const modalCount = document.getElementById('modalCount');
const confirmInput = document.getElementById('confirmInput');
const cancelConfirmBtn = document.getElementById('cancelConfirmBtn');
const proceedConfirmBtn = document.getElementById('proceedConfirmBtn');
// State
let selectedProducts = [];
let currentTab = 'manual';
// Event Listeners
selectContextBtn.addEventListener('click', toggleContextPanel);
parseBtn.addEventListener('click', parseAsins);
selectAllBtn.addEventListener('click', selectAllProducts);
deselectAllBtn.addEventListener('click', deselectAllProducts);
applySelectionBtn.addEventListener('click', applySelection);
saveContextCheckbox.addEventListener('change', toggleSaveContextInput);
tabButtons.forEach(button => {
button.addEventListener('click', () => switchTab(button.dataset.tab));
});
confirmInput.addEventListener('input', checkConfirmation);
cancelConfirmBtn.addEventListener('click', closeConfirmModal);
proceedConfirmBtn.addEventListener('click', confirmAndApply);
// Functions
function toggleContextPanel() {
contextPanel.classList.toggle('hidden');
if (!contextPanel.classList.contains('hidden')) {
// Focus first input when panel opens
if (currentTab === 'manual') {
asinInput.focus();
}
}
}
function switchTab(tabName) {
currentTab = tabName;
// Update tab button states
tabButtons.forEach(button => {
if (button.dataset.tab === tabName) {
button.classList.add('active-tab');
} else {
button.classList.remove('active-tab');
}
});
// Show/hide tab contents
tabContents.forEach(content => {
if (content.id === `${tabName}Tab`) {
content.classList.remove('hidden');
} else {
content.classList.add('hidden');
}
});
}
function parseAsins() {
const asinsText = asinInput.value.trim();
if (!asinsText) {
return;
}
// Simulate API call
setTimeout(() => {
// Validate ASINs (mock)
const validProducts = mockProducts.slice(0, 10); // Just show first 10 for demo
const totalCount = 142; // Mock total count
// Update UI
renderProductPreview(validProducts);
totalValidCount.textContent = totalCount;
previewSection.classList.remove('hidden');
// Update selected count
updateSelectedCount();
}, 300);
}
function renderProductPreview(products) {
previewGrid.innerHTML = '';
products.forEach(product => {
const productCard = document.createElement('div');
productCard.className = 'product-card bg-[#1E1F23] rounded-md p-3 cursor-pointer';
productCard.dataset.asin = product.asin;
productCard.innerHTML = `
<div class="flex">
<div class="flex-shrink-0 mr-3">
<img src="${product.image}" alt="${product.title}" class="w-16 h-16 object-cover rounded">
</div>
<div class="flex-1 min-w-0">
<h4 class="text-sm font-medium truncate-2-lines" title="${product.title}">${product.title}</h4>
<div class="flex items-center mt-1">
<span class="bg-[#131417] text-xs px-1.5 py-0.5 rounded font-mono">${product.asin}</span>
</div>
<div class="flex flex-wrap gap-1.5 mt-2">
<span class="bg-[#1A1C21] text-xs px-1.5 py-0.5 rounded">Sales: ${product.metrics.sales_30}</span>
<span class="bg-[#1A1C21] text-xs px-1.5 py-0.5 rounded">CVR: ${(product.metrics.cvr_30 * 100).toFixed(1)}%</span>
<span class="bg-[#1A1C21] text-xs px-1.5 py-0.5 rounded">Clicks: ${product.metrics.clicks_30}</span>
</div>
</div>
<div class="ml-2 flex-shrink-0">
<input type="checkbox" class="product-checkbox" data-asin="${product.asin}">
</div>
</div>
`;
// Add event listeners
const checkbox = productCard.querySelector('.product-checkbox');
checkbox.addEventListener('change', () => toggleProductSelection(product.asin, checkbox.checked));
productCard.addEventListener('click', (e) => {
if (e.target.tagName !== 'INPUT') {
checkbox.checked = !checkbox.checked;
toggleProductSelection(product.asin, checkbox.checked);
}
});
previewGrid.appendChild(productCard);
});
}
function toggleProductSelection(asin, isSelected) {
if (isSelected && !selectedProducts.includes(asin)) {
selectedProducts.push(asin);
} else if (!isSelected) {
selectedProducts = selectedProducts.filter(a => a !== asin);
}
// Update UI
updateSelectedCount();
highlightSelectedCards();
}
function selectAllProducts() {
const checkboxes = document.querySelectorAll('.product-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = true;
if (!selectedProducts.includes(checkbox.dataset.asin)) {
selectedProducts.push(checkbox.dataset.asin);
}
});
updateSelectedCount();
highlightSelectedCards();
}
function deselectAllProducts() {
const checkboxes = document.querySelectorAll('.product-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = false;
});
selectedProducts = [];
updateSelectedCount();
highlightSelectedCards();
}
function highlightSelectedCards() {
const productCards = document.querySelectorAll('.product-card');
productCards.forEach(card => {
if (selectedProducts.includes(card.dataset.asin)) {
card.classList.add('selected');
} else {
card.classList.remove('selected');
}
});
}
function updateSelectedCount() {
const count = selectedProducts.length;
selectedCountText.textContent = `Selected: ${count} product${count !== 1 ? 's' : ''}`;
// Show warning if count is large
if (count > 500) {
selectedCountText.innerHTML += ` <span class="text-yellow-400">(Large selection)</span>`;
}
}
function toggleSaveContextInput() {
if (saveContextCheckbox.checked) {
contextNameInput.classList.remove('hidden');
contextNameInput.focus();
} else {
contextNameInput.classList.add('hidden');
}
}
function applySelection() {
const count = selectedProducts.length;
if (count === 0) {
showToast('Please select at least one product');
return;
}
if (count > 5000) {
showConfirmModal(count);
return;
}
if (count > 500) {
// Soft warning - just proceed
proceedWithApply();
} else {
proceedWithApply();
}
}
function showConfirmModal(count) {
modalCount.textContent = count.toLocaleString();
confirmModal.classList.remove('hidden');
confirmInput.value = '';
proceedConfirmBtn.disabled = true;
}
function closeConfirmModal() {
confirmModal.classList.add('hidden');
}
function checkConfirmation() {
proceedConfirmBtn.disabled = confirmInput.value.trim().toUpperCase() !== 'CONFIRM';
}
function confirmAndApply() {
closeConfirmModal();
proceedWithApply();
}
function proceedWithApply() {
const contextName = saveContextCheckbox.checked ? contextNameInput.value.trim() : null;
// Simulate API call
setTimeout(() => {
// Update step 1 subtitle
const subtitle = document.querySelector('#contextPanel + div p');
subtitle.textContent = `Context: ${selectedProducts.length} product${selectedProducts.length !== 1 ? 's' : ''} selected`;
if (contextName) {
subtitle.textContent += ` (Saved as "${contextName}")`;
}
// Close panel
contextPanel.classList.add('hidden');
// Show success toast
showToast('Context applied successfully');
// Reset selection for next time
selectedProducts = [];
asinInput.value = '';
previewSection.classList.add('hidden');
saveContextCheckbox.checked = false;
contextNameInput.classList.add('hidden');
contextNameInput.value = '';
}, 500);
}
function showToast(message) {
const toastMessage = document.getElementById('toastMessage');
toastMessage.textContent = message;
toast.classList.remove('hidden');
setTimeout(() => {
toast.classList.add('hidden');
}, 3000);
}
// Initialize
switchTab('manual');
});