Analytics Dashboard
`
|
${rfq.id}
${rfq.category}
|
${rfq.demand} |
${rfq.value} |
${rfq.delivery} |
${rfq.destination} |
${rfq.closesIn} |
${rfq.marketRange} |
${rfq.yourQuote} |
|
`).join('');
}
// Quotes content loading
function loadQuotesContent() {
const tableBody = document.getElementById('quotesTableBody');
tableBody.innerHTML = supplierData.quotes.map(quote => `
| ${quote.id} |
${quote.rfqId} |
${quote.product} |
${quote.price} |
${quote.position} |
${quote.quantity} |
${quote.submitted} |
${quote.status}
|
|
`).join('');
}
// Inventory content loading
function loadInventoryContent() {
const tableBody = document.getElementById('inventoryTableBody');
tableBody.innerHTML = supplierData.inventory.map(item => `
|
${item.name}
${item.sku}
|
${item.category} |
${item.price} |
${item.stock} units
${item.status === 'Low Stock' ? ' Low Stock ' : ''}
|
${item.performance} |
${item.status}
|
|
`).join('');
}
// Compliance content loading
function loadComplianceContent() {
const detailsContainer = document.getElementById('complianceDetails');
const documentsContainer = document.getElementById('documentsContainer');
const expiriesContainer = document.getElementById('expiriesContainer');
// Compliance details
detailsContainer.innerHTML = supplierData.compliance.map(item => `
${item.color === 'green' ? '✓' : item.color === 'amber' ? '⚠' : '✗'}
${item.name}
Expires: ${item.expires}
`).join('');
// Documents
documentsContainer.innerHTML = supplierData.compliance.map(item => `
${item.name}
${item.status}
`).join('');
// Upcoming expiries
const expiringItems = supplierData.compliance.filter(item => item.color === 'amber' || item.color === 'red');
expiriesContainer.innerHTML = expiringItems.map(item => `
${item.name}
Expires: ${item.expires}
`).join('') || '
No upcoming expiries
';
}
// Messages content loading
function loadMessagesContent() {
const conversationsList = document.getElementById('conversationsList');
conversationsList.innerHTML = supplierData.conversations.map(conv => `
${conv.buyer}
${conv.time}
${conv.lastMessage}
RFQ: ${conv.rfqId}
${conv.unread ? '
' : ''}
`).join('');
}
// Analytics content loading
function loadAnalyticsContent() {
const ctx = document.getElementById('analyticsChart');
if (ctx && !charts.analytics) {
charts.analytics = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Won Quotes', 'Lost to Price', 'Lost to Delivery', 'Pending'],
datasets: [{
data: [45, 28, 15, 12],
backgroundColor: ['#10b981', '#ef4444', '#f59e0b', '#6b7280'],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
}
}
// Settings content loading
function loadSettingsContent() {
const notificationSettings = document.getElementById('notificationSettings');
const settings = [
{ name: 'RFQ Deadline Alerts', enabled: true },
{ name: 'Outbid Notifications', enabled: true },
{ name: 'Compliance Reminders', enabled: true },
{ name: 'Buyer Messages', enabled: true },
{ name: 'Weekly Performance Reports', enabled: false }
];
notificationSettings.innerHTML = settings.map(setting => `
`).join('');
}
// Utility functions
function updateCountdowns() {
const countdownElements = document.querySelectorAll('.countdown-timer');
countdownElements.forEach(element => {
const rfqId = element.closest('[data-rfq-id]')?.getAttribute('data-rfq-id');
if (rfqId) {
const rfq = supplierData.rfqs.find(r => r.id === rfqId);
if (rfq) {
const remaining = Math.max(0, rfq.closesInMs - Date.now());
const hours = Math.floor(remaining / (1000 * 60 * 60));
const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
element.textContent = remaining > 0 ? `${hours}h ${minutes}m` : 'Expired';
if (remaining <= 0) {
element.classList.add('text-red-600');
element.textContent = 'Expired';
}
}
}
});
}
function getStatusClass(status) {
const statusClasses = {
'Leading': 'bg-green-100 text-green-800',
'Outbid': 'bg-red-100 text-red-800',
'Won': 'bg-emerald-100 text-emerald-800',
'Lost': 'bg-gray-100 text-gray-800',
'Pending': 'bg-blue-100 text-blue-800'
};
return statusClasses[status] || 'bg-gray-100 text-gray-800';
}
function showNotification(message, type = 'success') {
const notification = document.getElementById('notificationTemplate').cloneNode(true);
notification.id = 'notification-' + Date.now();
notification.classList.remove('hidden');
const bgColors = {
'success': 'bg-green-500',
'error': 'bg-red-500',
'warning': 'bg-yellow-500',
'info': 'bg-blue-500'
};
notification.classList.add(bgColors[type]);
notification.querySelector('#notificationText').textContent = message;
document.body.appendChild(notification);
// Remove after 3 seconds
setTimeout(() => {
notification.remove();
}, 3000);
}
// Dashboard refresh functionality
function refreshDashboard() {
const spinner = document.getElementById('refreshSpinner');
spinner.classList.remove('hidden');
setTimeout(() => {
spinner.classList.add('hidden');
updateLastUpdated();
updateKPIs();
populateUrgentDeadlines();
populateOutbidAlerts();
showNotification('Dashboard refreshed successfully');
}, 1000);
}
function updateLastUpdated() {
document.getElementById('lastUpdated').textContent = 'just now';
}
function startAutoRefresh() {
if (autoRefreshEnabled) {
autoRefreshInterval = setInterval(() => {
if (currentView === 'dashboard') {
updateKPIs();
updateLastUpdated();
}
}, 30000); // Refresh every 30 seconds
}
}
function toggleAutoRefresh() {
autoRefreshEnabled = !autoRefreshEnabled;
const statusElement = document.getElementById('autoStatus');
if (autoRefreshEnabled) {
statusElement.textContent = 'ON';
statusElement.className = 'text-green-600 font-medium';
startAutoRefresh();
} else {
statusElement.textContent = 'OFF';
statusElement.className = 'text-red-600 font-medium';
if (autoRefreshInterval) {
clearInterval(autoRefreshInterval);
}
}
}
// Action functions
function submitQuoteForRFQ(rfqId) {
showNotification(`Quote submission initiated for ${rfqId}`);
// Update the RFQ status
const rfq = supplierData.rfqs.find(r => r.id === rfqId);
if (rfq) {
rfq.yourQuote = '
Vendigo - Supplier Dashboard
Supplier Dashboard
Strategic control center for your Vendigo operations
Last updated: just now
Auto-refresh: ON
Urgent Deadlines (48h)
3 urgent
Outbid Alerts
2 active
Revenue Trend (6 Months)
RFQs to Bid
View aggregated demand and submit competitive quotes
| RFQ ID / Category |
Demand |
Est. Value |
Delivery |
Destination |
Closes In |
Market Range |
Your Quote |
Actions |
My Quotes
Track and manage all submitted quotes
| Quote ID |
RFQ |
Product |
Your Price |
Position |
Quantity |
Submitted |
Status |
Actions |
Inventory Management
Manage your product catalog and stock levels
| Product / SKU |
Category |
Price |
Stock Level |
Performance |
Status |
Actions |
Compliance Management
Maintain certifications and regulatory compliance
Overall Score: 85%
Promotions & Marketing
Promotions management interface - Feature implementation in progress
Analytics Dashboard
c.id === conversationId);
if (!conversation) return;
// Mark as read
conversation.unread = false;
// Update header
document.getElementById('messageHeader').innerHTML = `
${conversation.buyer}
RFQ: ${conversation.rfqId}
`;
// Sample message thread
document.getElementById('messageContent').innerHTML = `
${conversation.lastMessage}
${conversation.time}
We can deliver within your timeframe. Please let me know if you need additional specifications.
1 hour ago
`;
// Refresh conversation list
loadMessagesContent();
}
function sendMessage() {
const messageText = document.getElementById('newMessageText').value.trim();
if (!messageText) return;
// Add message to conversation
const messageContent = document.getElementById('messageContent');
const messageDiv = document.createElement('div');
messageDiv.className = 'flex justify-end mt-4';
messageDiv.innerHTML = `
`;
messageContent.querySelector('.space-y-4').appendChild(messageDiv);
// Clear input
document.getElementById('newMessageText').value = '';
// Scroll to bottom
messageContent.scrollTop = messageContent.scrollHeight;
showNotification('Message sent successfully');
}
function saveProfile() {
const companyName = document.getElementById('companyName').value;
if (!companyName.trim()) {
showNotification('Company name is required', 'error');
return;
}
showNotification('Profile updated successfully');
}
// Filter functions
function applyRFQFilters() {
showNotification('Filters applied to RFQ list');
// In a real implementation, this would filter the table
}
function exportRFQs() {
showNotification('RFQ data exported to CSV');
}
function refreshRFQs() {
showNotification('RFQ data refreshed');
loadRFQsContent();
}
function exportQuotes() {
showNotification('Quote data exported to CSV');
}
function createNewQuote() {
showNotification('New quote creation initiated');
}
function bulkUpload() {
showNotification('Bulk upload interface opened');
}
function addProduct() {
showNotification('Add product form opened');
}
// Quick action functions
function quickSubmitQuote() {
showNotification('Quick quote submission started');
}
function quickUploadProduct() {
showNotification('Quick product upload started');
}
function quickUpdateCompliance() {
switchView('compliance');
}
function quickViewFeedback() {
showNotification('Buyer feedback panel opened');
}
// Calendar integration placeholder
function integrateCalendar() {
showNotification('Calendar integration - feature in development');
}
// Competitive pricing engine placeholder
function enableCompetitivePricing() {
showNotification('Competitive pricing engine enabled');
}
// WebSocket simulation for real-time updates
function simulateRealTimeUpdates() {
setInterval(() => {
if (Math.random() > 0.9) { // 10% chance every interval
const events = [
'New RFQ received',
'Quote status updated',
'Outbid alert triggered',
'Compliance document approved'
];
const randomEvent = events[Math.floor(Math.random() * events.length)];
showNotification(randomEvent, 'info');
// Update relevant data
if (currentView === 'dashboard') {
updateKPIs();
}
}
}, 10000); // Check every 10 seconds
}
// Initialize real-time simulation
setTimeout(simulateRealTimeUpdates, 5000); // Start after 5 seconds
// Performance analytics simulation
function trackPerformance() {
// Simulate performance tracking
const performanceData = {
pageLoadTime: Math.random() * 1000 + 500,
apiResponseTime: Math.random() * 200 + 50,
userInteractions: Math.floor(Math.random() * 100) + 50
};
console.log('Performance metrics:', performanceData);
}
// Track performance every minute
setInterval(trackPerformance, 60000);
// Error handling for charts
function handleChartError(chartName, error) {
console.error(`Chart ${chartName} error:`, error);
showNotification(`Chart loading issue - please refresh`, 'warning');
}
// Resize handler for responsive charts
window.addEventListener('resize', function() {
Object.keys(charts).forEach(chartName => {
if (charts[chartName]) {
charts[chartName].resize();
}
});
});
// Keyboard shortcuts
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + R for refresh
if ((e.ctrlKey || e.metaKey) && e.key === 'r') {
e.preventDefault();
refreshDashboard();
}
// Ctrl/Cmd + N for new quote
if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
e.preventDefault();
quickSubmitQuote();
}
});
// Prevent accidental page refresh
window.addEventListener('beforeunload', function(e) {
const hasUnsavedChanges = false; // Check for unsaved changes
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = '';
}
});
// Service Worker registration for offline capability (placeholder)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
// In a real implementation, register service worker here
console.log('Service Worker support detected');
});
}
// Initialize tooltips and other UI enhancements
function initializeUIEnhancements() {
// Add hover effects and tooltips
document.querySelectorAll('[data-tooltip]').forEach(element => {
element.addEventListener('mouseenter', function() {
// Show tooltip
});
element.addEventListener('mouseleave', function() {
// Hide tooltip
});
});
}
// Call UI enhancements after DOM is ready
setTimeout(initializeUIEnhancements, 1000);
// Accessibility improvements
function initializeAccessibility() {
// Add ARIA labels
document.querySelectorAll('button').forEach(button => {
if (!button.getAttribute('aria-label') && button.textContent.trim()) {
button.setAttribute('aria-label', button.textContent.trim());
}
});
// Add focus management
document.addEventListener('keydown', function(e) {
if (e.key === 'Tab') {
document.body.classList.add('keyboard-navigation');
}
});
document.addEventListener('mousedown', function() {
document.body.classList.remove('keyboard-navigation');
});
}
// Initialize accessibility features
setTimeout(initializeAccessibility, 500);
Vendigo - Supplier Dashboard
Supplier Dashboard
Strategic control center for your Vendigo operations
Last updated: just now
Auto-refresh: ON
Urgent Deadlines (48h)
3 urgent
Outbid Alerts
2 active
Revenue Trend (6 Months)
RFQs to Bid
View aggregated demand and submit competitive quotes
| RFQ ID / Category |
Demand |
Est. Value |
Delivery |
Destination |
Closes In |
Market Range |
Your Quote |
Actions |
My Quotes
Track and manage all submitted quotes
| Quote ID |
RFQ |
Product |
Your Price |
Position |
Quantity |
Submitted |
Status |
Actions |
Inventory Management
Manage your product catalog and stock levels
| Product / SKU |
Category |
Price |
Stock Level |
Performance |
Status |
Actions |
Compliance Management
Maintain certifications and regulatory compliance
Overall Score: 85%
Promotions & Marketing
Promotions management interface - Feature implementation in progress