VB
Vendigo Buyers Club
Global B2B Marketplace
U
12 years bicycle parts manufacturer
Shenzhen Best Bicycle Co., Ltd
🚲
Mountain Bicycle
$28.50
⚙️
MTB Front Fork
$54
🔧
Bike Parts
$19.50
🛡️
Trade Assurance protects your orders
Supplier features
Store reviews
Product features
Price (USD)
Country/Region
Showing 10,000+ products
No RFQs available. Create your first RFQ to get started!
';
return;
}
rfqList.innerHTML = userRFQs.map(rfq => {
const rfqQuotes = quotes.filter(q => q.rfqId === rfq.id);
return `
${rfq.id}
${rfq.productName}
Quantity:
${rfq.quantity} ${rfq.unit}
Target Price:
$${rfq.targetPrice > 0 ? rfq.targetPrice.toFixed(2) : 'Not specified'}
Quotes Received:
${rfqQuotes.length}
${currentUser.type === 'buyer' && rfqQuotes.length > 0 ?
`` :
''}
${currentUser.type === 'supplier' ?
`` :
''}
Product: ${rfq.productName}
Quantity: ${rfq.quantity} ${rfq.unit}
Target Price: $${rfq.targetPrice > 0 ? rfq.targetPrice.toFixed(2) : 'Not specified'} `; document.getElementById('submitQuoteModal').classList.add('active'); } function submitQuote(event) { event.preventDefault(); const rfqId = document.getElementById('quoteRFQId').value; const newQuote = { id: 'QUOTE-' + Date.now(), rfqId, supplierId: currentUser.id, supplierName: currentUser.name, supplierCompany: currentUser.company, unitPrice: parseFloat(document.getElementById('quoteUnitPrice').value), moq: parseInt(document.getElementById('quoteMOQ').value), deliveryTime: parseInt(document.getElementById('quoteDeliveryTime').value), paymentTerms: document.getElementById('quotePaymentTerms').value, shippingMethod: document.getElementById('quoteShippingMethod').value, notes: document.getElementById('quoteNotes').value, validity: parseInt(document.getElementById('quoteValidity').value), status: 'submitted', createdAt: new Date().toISOString() }; quotes.push(newQuote); const rfq = rfqs.find(r => r.id === rfqId); if (rfq) { rfq.status = 'quoted'; rfq.quotesReceived = quotes.filter(q => q.rfqId === rfqId).length; } saveToStorage(); closeModal('submitQuoteModal'); event.target.reset(); alert('✅ Quote submitted successfully!'); if (currentUser.type === 'supplier') { updateSupplierStats(); } } function compareQuotes(rfqId) { const rfq = rfqs.find(r => r.id === rfqId); if (!rfq) return; const rfqQuotes = quotes.filter(q => q.rfqId === rfqId); if (rfqQuotes.length === 0) { alert('No quotes available'); return; } const lowestPrice = Math.min(...rfqQuotes.map(q => q.unitPrice)); const content = document.getElementById('compareQuotesContent'); content.innerHTML = `
${rfq.productName}
Total Quotes: ${rfqQuotes.length}
${rfqQuotes.map(quote => {
const totalPrice = quote.unitPrice * rfq.quantity;
const isBestPrice = quote.unitPrice === lowestPrice;
return `
`;
document.getElementById('compareQuotesModal').classList.add('active');
}
function acceptQuote(quoteId) {
const quote = quotes.find(q => q.id === quoteId);
if (!quote) return;
const rfq = rfqs.find(r => r.id === quote.rfqId);
if (!rfq) return;
if (confirm(`Accept quote from ${quote.supplierCompany} for $${quote.unitPrice} per unit?`)) {
quote.status = 'accepted';
rfq.status = 'accepted';
const newOrder = {
id: 'ORDER-' + Date.now(),
rfqId: rfq.id,
quoteId: quote.id,
buyerId: rfq.buyerId,
supplierId: quote.supplierId,
productName: rfq.productName,
quantity: rfq.quantity,
unitPrice: quote.unitPrice,
totalAmount: rfq.quantity * quote.unitPrice,
status: 'confirmed',
createdAt: new Date().toISOString()
};
orders.push(newOrder);
saveToStorage();
alert('✅ Quote accepted! Order created.\\n\\nOrder ID: ' + newOrder.id);
closeModal('compareQuotesModal');
updateBuyerStats();
}
}
// Dashboard Functions
function switchBuyerTab(event, tab) {
document.querySelectorAll('#buyerDashboard .dashboard-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('#buyerDashboard .dashboard-content').forEach(c => c.classList.remove('active'));
event.target.classList.add('active');
document.getElementById('buyer' + tab.charAt(0).toUpperCase() + tab.slice(1)).classList.add('active');
if (tab === 'overview') updateBuyerStats();
else if (tab === 'rfqs') renderBuyerRFQs();
else if (tab === 'orders') renderBuyerOrders();
}
function switchSupplierTab(event, tab) {
document.querySelectorAll('#supplierDashboard .dashboard-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('#supplierDashboard .dashboard-content').forEach(c => c.classList.remove('active'));
event.target.classList.add('active');
document.getElementById('supplier' + tab.charAt(0).toUpperCase() + tab.slice(1)).classList.add('active');
if (tab === 'overview') updateSupplierStats();
else if (tab === 'rfqs') renderSupplierRFQs();
else if (tab === 'products') renderSupplierProducts();
else if (tab === 'orders') renderSupplierOrders();
}
function updateBuyerStats() {
if (!currentUser || currentUser.type !== 'buyer') return;
const userRFQs = rfqs.filter(r => r.buyerId === currentUser.id);
const userQuotes = quotes.filter(q => userRFQs.some(r => r.id === q.rfqId));
const userOrders = orders.filter(o => o.buyerId === currentUser.id);
const totalSpent = userOrders.reduce((sum, o) => sum + o.totalAmount, 0);
document.getElementById('buyerActiveRFQs').textContent = userRFQs.filter(r => r.status !== 'accepted').length;
document.getElementById('buyerQuotesReceived').textContent = userQuotes.length;
document.getElementById('buyerTotalOrders').textContent = userOrders.length;
document.getElementById('buyerTotalSpent').textContent = '$' + totalSpent.toFixed(2);
renderBuyerRecentRFQs();
}
function updateSupplierStats() {
if (!currentUser || currentUser.type !== 'supplier') return;
const supplierQuotes = quotes.filter(q => q.supplierId === currentUser.id);
const supplierProducts = products.filter(p => p.supplierId === currentUser.id);
const supplierOrders = orders.filter(o => o.supplierId === currentUser.id);
const totalRevenue = supplierOrders.reduce((sum, o) => sum + o.totalAmount, 0);
document.getElementById('supplierRFQCount').textContent = rfqs.length;
document.getElementById('supplierQuotesSubmitted').textContent = supplierQuotes.length;
document.getElementById('supplierProductsCount').textContent = supplierProducts.length;
document.getElementById('supplierRevenue').textContent = '$' + totalRevenue.toFixed(2);
renderSupplierRecentRFQs();
}
function renderBuyerRecentRFQs() {
const container = document.getElementById('buyerRecentRFQs');
const userRFQs = rfqs.filter(r => r.buyerId === currentUser.id).slice(0, 5);
if (userRFQs.length === 0) {
container.innerHTML = '
${isBestPrice ? '
`;
}).join('')}
🏆 Best Price
' : ''}
${quote.supplierCompany}
$${quote.unitPrice.toFixed(2)}
Total: $${totalPrice.toFixed(2)}
MOQ: ${quote.moq}
Delivery: ${quote.deliveryTime} days
Payment: ${quote.paymentTerms}
Shipping: ${quote.shippingMethod}
No RFQs created yet
';
return;
}
container.innerHTML = userRFQs.map(rfq => {
const rfqQuotes = quotes.filter(q => q.rfqId === rfq.id);
return `
${rfq.id}
${rfq.productName}
Quantity: ${rfq.quantity} ${rfq.unit} | Quotes: ${rfqQuotes.length}
${rfqQuotes.length > 0 ?
`` :
'Waiting for quotes...
'}
No RFQs yet. Create your first RFQ!
';
return;
}
container.innerHTML = userRFQs.map(rfq => {
const rfqQuotes = quotes.filter(q => q.rfqId === rfq.id);
return `
${rfq.id}
${rfq.productName}
Quantity:
${rfq.quantity} ${rfq.unit}
Target Price:
$${rfq.targetPrice > 0 ? rfq.targetPrice.toFixed(2) : 'Not specified'}
Quotes Received:
${rfqQuotes.length}
Created:
${new Date(rfq.createdAt).toLocaleDateString()}
Waiting for supplier quotes...
'}
No orders yet
';
return;
}
container.innerHTML = userOrders.map(order => `
${order.id}
${order.productName}
Quantity:
${order.quantity}
Unit Price:
$${order.unitPrice.toFixed(2)}
Total Amount:
$${order.totalAmount.toFixed(2)}
Order Date:
${new Date(order.createdAt).toLocaleDateString()}
No RFQ opportunities available
';
return;
}
container.innerHTML = recentRFQs.map(rfq => {
const hasQuoted = quotes.some(q => q.rfqId === rfq.id && q.supplierId === currentUser.id);
return `
${rfq.id}
${rfq.productName}
Quantity: ${rfq.quantity} ${rfq.unit} | Target Price: $${rfq.targetPrice > 0 ? rfq.targetPrice.toFixed(2) : 'N/A'}
${!hasQuoted ?
`` :
'✓ Quote Submitted
'}
No RFQ opportunities available
';
return;
}
container.innerHTML = rfqs.map(rfq => {
const hasQuoted = quotes.some(q => q.rfqId === rfq.id && q.supplierId === currentUser.id);
return `
${rfq.id}
${rfq.productName}
Buyer: ${rfq.buyerCompany}
Quantity:
${rfq.quantity} ${rfq.unit}
Target Price:
$${rfq.targetPrice > 0 ? rfq.targetPrice.toFixed(2) : 'Not specified'}
Delivery Location:
${rfq.deliveryLocation}
Posted:
${new Date(rfq.createdAt).toLocaleDateString()}
Requirements:
${rfq.requirements}
${!hasQuoted ?
`` :
'${rfq.requirements}
✓ You have submitted a quote for this RFQ
'}
No products listed yet. Add your first product!
';
return;
}
container.innerHTML = supplierProducts.map(product => `
${product.name.charAt(0)}
${product.name}
${product.description}
Price: $${product.priceMin.toFixed(2)} - $${product.priceMax.toFixed(2)}
MOQ: ${product.moq} ${product.unit}
Category: ${getCategoryName(product.category)}
No orders yet
';
return;
}
container.innerHTML = supplierOrders.map(order => `
${order.id}
${order.productName}
Quantity:
${order.quantity}
Unit Price:
$${order.unitPrice.toFixed(2)}
Total Revenue:
$${order.totalAmount.toFixed(2)}
Order Date:
${new Date(order.createdAt).toLocaleDateString()}
${provider}
$${totalCost}
Delivery: ${info.days} days