// ============================================= // PrintPro - Admin Panel Script // ============================================= // --- DEFAULT PRICING (same as frontend) --- const DEFAULT_PRICING = { products: { 'business-cards': { name: 'Business Cards', icon: 'credit-card', image: 'http://static.photos/office/320x240/42', basePrice: 19.00, sizes: [ { id: '3.5x2', name: '3.5" x 2"', price: 0 }, { id: '3.5x2-rounded', name: '3.5" x 2" Rounded', price: 4 }, { id: '3.5x2-square', name: '3.5" x 3.5" Square', price: 6 } ], paperTypes: [ { id: '14pt-gloss', name: '14pt Gloss', price: 0 }, { id: '16pt-matte', name: '16pt Matte', price: 6 }, { id: '14pt-uncoated', name: '14pt Uncoated', price: 3 }, { id: '16pt-silk', name: '16pt Silk', price: 8 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'matte', name: 'Matte Coating', price: 5 }, { id: 'gloss', name: 'Gloss Coating', price: 5 }, { id: 'uv', name: 'UV Spot Gloss', price: 12 }, { id: 'foil', name: 'Foil Stamp', price: 18 } ], quantityTiers: [ { min: 50, max: 250, multiplier: 1.0, label: '50-250' }, { min: 251, max: 500, multiplier: 0.75, label: '251-500' }, { min: 501, max: 1000, multiplier: 0.55, label: '501-1K' }, { min: 1001, max: 2500, multiplier: 0.40, label: '1K-2.5K' }, { min: 2501, max: 5000, multiplier: 0.30, label: '2.5K-5K' }, { min: 5001, max: 10000, multiplier: 0.22, label: '5K-10K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 15 }, { id: 'express', name: 'Express (1-2 days)', price: 30 } ], defaultQuantity: 500 }, 'flyers': { name: 'Flyers', icon: 'file-text', image: 'http://static.photos/office/320x240/55', basePrice: 35.00, sizes: [ { id: '8.5x11', name: '8.5" x 11"', price: 0 }, { id: '5.5x8.5', name: '5.5" x 8.5"', price: -3 }, { id: '11x17', name: '11" x 17"', price: 8 } ], paperTypes: [ { id: '100lb-gloss', name: '100lb Gloss', price: 0 }, { id: '80lb-matte', name: '80lb Matte', price: -2 }, { id: '100lb-uncoated', name: '100lb Uncoated', price: 2 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'matte', name: 'Matte Coating', price: 8 }, { id: 'gloss', name: 'Gloss Coating', price: 8 } ], quantityTiers: [ { min: 50, max: 250, multiplier: 1.0, label: '50-250' }, { min: 251, max: 500, multiplier: 0.70, label: '251-500' }, { min: 501, max: 1000, multiplier: 0.50, label: '501-1K' }, { min: 1001, max: 5000, multiplier: 0.35, label: '1K-5K' }, { min: 5001, max: 10000, multiplier: 0.25, label: '5K-10K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 20 }, { id: 'express', name: 'Express (1-2 days)', price: 40 } ], defaultQuantity: 250 }, 'brochures': { name: 'Brochures', icon: 'book-open', image: 'http://static.photos/office/320x240/67', basePrice: 55.00, sizes: [ { id: '8.5x11-bi', name: '8.5"x11" Bi-Fold', price: 0 }, { id: '8.5x11-tri', name: '8.5"x11" Tri-Fold', price: 3 }, { id: '11x17-bi', name: '11"x17" Bi-Fold', price: 10 } ], paperTypes: [ { id: '100lb-gloss', name: '100lb Gloss', price: 0 }, { id: '80lb-matte', name: '80lb Matte', price: -3 }, { id: '100lb-silk', name: '100lb Silk', price: 5 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'matte', name: 'Matte Coating', price: 10 }, { id: 'gloss', name: 'Gloss Coating', price: 10 } ], quantityTiers: [ { min: 25, max: 100, multiplier: 1.0, label: '25-100' }, { min: 101, max: 250, multiplier: 0.70, label: '101-250' }, { min: 251, max: 500, multiplier: 0.52, label: '251-500' }, { min: 501, max: 1000, multiplier: 0.40, label: '501-1K' }, { min: 1001, max: 5000, multiplier: 0.30, label: '1K-5K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 25 }, { id: 'express', name: 'Express (1-2 days)', price: 50 } ], defaultQuantity: 100 }, 'banners': { name: 'Banners', icon: 'flag', image: 'http://static.photos/office/320x240/78', basePrice: 45.00, sizes: [ { id: '24x36', name: '24" x 36"', price: 0 }, { id: '36x48', name: '36" x 48"', price: 15 }, { id: '48x72', name: '48" x 72"', price: 35 } ], paperTypes: [ { id: 'vinyl', name: '13oz Vinyl', price: 0 }, { id: 'mesh', name: 'Mesh Vinyl', price: 8 }, { id: 'fabric', name: 'Fabric', price: 20 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'grommets', name: 'Grommets', price: 5 }, { id: 'pole-pockets', name: 'Pole Pockets', price: 10 } ], quantityTiers: [ { min: 1, max: 5, multiplier: 1.0, label: '1-5' }, { min: 6, max: 10, multiplier: 0.80, label: '6-10' }, { min: 11, max: 25, multiplier: 0.65, label: '11-25' }, { min: 26, max: 50, multiplier: 0.50, label: '26-50' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 20 }, { id: 'express', name: 'Express (1-2 days)', price: 45 } ], defaultQuantity: 1 }, 'stickers': { name: 'Stickers & Labels', icon: 'sticky-note', image: 'http://static.photos/office/320x240/91', basePrice: 25.00, sizes: [ { id: '2x2', name: '2" x 2"', price: 0 }, { id: '3x3', name: '3" x 3"', price: 5 }, { id: '4x4', name: '4" x 4"', price: 8 }, { id: 'custom-die', name: 'Custom Die-Cut', price: 15 } ], paperTypes: [ { id: 'white-vinyl', name: 'White Vinyl', price: 0 }, { id: 'clear-vinyl', name: 'Clear Vinyl', price: 5 }, { id: 'metallic', name: 'Metallic', price: 10 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'matte-lam', name: 'Matte Laminate', price: 6 }, { id: 'gloss-lam', name: 'Gloss Laminate', price: 6 } ], quantityTiers: [ { min: 50, max: 250, multiplier: 1.0, label: '50-250' }, { min: 251, max: 500, multiplier: 0.70, label: '251-500' }, { min: 501, max: 1000, multiplier: 0.48, label: '501-1K' }, { min: 1001, max: 2500, multiplier: 0.35, label: '1K-2.5K' }, { min: 2501, max: 5000, multiplier: 0.25, label: '2.5K-5K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 12 }, { id: 'express', name: 'Express (1-2 days)', price: 28 } ], defaultQuantity: 250 }, 'postcards': { name: 'Postcards', icon: 'mail', image: 'http://static.photos/office/320x240/33', basePrice: 28.00, sizes: [ { id: '4x6', name: '4" x 6"', price: 0 }, { id: '5x7', name: '5" x 7"', price: 4 }, { id: '6x9', name: '6" x 9"', price: 7 }, { id: '6x11', name: '6" x 11"', price: 10 } ], paperTypes: [ { id: '14pt-gloss', name: '14pt Gloss', price: 0 }, { id: '16pt-matte', name: '16pt Matte', price: 5 }, { id: '14pt-uncoated', name: '14pt Uncoated', price: 2 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'matte', name: 'Matte Coating', price: 5 }, { id: 'gloss', name: 'Gloss Coating', price: 5 }, { id: 'uv-front', name: 'UV Front Only', price: 8 } ], quantityTiers: [ { min: 100, max: 500, multiplier: 1.0, label: '100-500' }, { min: 501, max: 1000, multiplier: 0.72, label: '501-1K' }, { min: 1001, max: 2500, multiplier: 0.52, label: '1K-2.5K' }, { min: 2501, max: 5000, multiplier: 0.38, label: '2.5K-5K' }, { min: 5001, max: 10000, multiplier: 0.28, label: '5K-10K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 12 }, { id: 'express', name: 'Express (1-2 days)', price: 28 } ], defaultQuantity: 500 }, 'letterhead': { name: 'Letterhead', icon: 'file', image: 'http://static.photos/office/320x240/44', basePrice: 40.00, sizes: [ { id: '8.5x11', name: '8.5" x 11"', price: 0 }, { id: '8.5x14', name: '8.5" x 14"', price: 5 } ], paperTypes: [ { id: '24lb-bond', name: '24lb Bond', price: 0 }, { id: '28lb-bond', name: '28lb Bond', price: 5 }, { id: '32lb-bond', name: '32lb Bond', price: 10 }, { id: 'linen', name: 'Linen Finish', price: 15 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'watermark', name: 'Watermark', price: 8 } ], quantityTiers: [ { min: 100, max: 500, multiplier: 1.0, label: '100-500' }, { min: 501, max: 1000, multiplier: 0.70, label: '501-1K' }, { min: 1001, max: 2500, multiplier: 0.48, label: '1K-2.5K' }, { min: 2501, max: 5000, multiplier: 0.35, label: '2.5K-5K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 18 }, { id: 'express', name: 'Express (1-2 days)', price: 38 } ], defaultQuantity: 500 }, 'envelopes': { name: 'Envelopes', icon: 'mail-open', image: 'http://static.photos/office/320x240/56', basePrice: 32.00, sizes: [ { id: '10-standard', name: '#10 Standard', price: 0 }, { id: 'a7', name: 'A7 (5.25x7.25)', price: 3 }, { id: 'a2', name: 'A2 (4.375x5.75)', price: 0 } ], paperTypes: [ { id: '24lb-white', name: '24lb White Wove', price: 0 }, { id: '28lb-white', name: '28lb White Wove', price: 4 }, { id: 'kraft', name: 'Kraft Brown', price: 3 } ], finishing: [ { id: 'none', name: 'None', price: 0 }, { id: 'window', name: 'Window', price: 5 }, { id: 'peel-seal', name: 'Peel & Seal', price: 4 } ], quantityTiers: [ { min: 100, max: 500, multiplier: 1.0, label: '100-500' }, { min: 501, max: 1000, multiplier: 0.72, label: '501-1K' }, { min: 1001, max: 2500, multiplier: 0.52, label: '1K-2.5K' }, { min: 2501, max: 5000, multiplier: 0.36, label: '2.5K-5K' } ], turnaround: [ { id: 'standard', name: 'Standard (5-7 days)', price: 0 }, { id: 'rush', name: 'Rush (3-4 days)', price: 15 }, { id: 'express', name: 'Express (1-2 days)', price: 32 } ], defaultQuantity: 250 } } }; // --- STATE --- let pricing = null; let editingProductKey = null; let editingData = null; // --- AUTH --- const ADMIN_CREDENTIALS = { username: 'admin', password: 'admin123' }; let isLoggedIn = sessionStorage.getItem('printpro_admin_loggedin') === 'true'; // --- DOM --- const loginScreen = document.getElementById('loginScreen'); const dashboard = document.getElementById('dashboard'); const loginForm = document.getElementById('loginForm'); const loginError = document.getElementById('loginError'); const editModal = document.getElementById('editModal'); const modalProductName = document.getElementById('modalProductName'); const modalContent = document.getElementById('modalContent'); const productCards = document.getElementById('productCards'); const toast = document.getElementById('toast'); const toastMsg = document.getElementById('toastMsg'); // --- INIT --- function getPricing() { const stored = localStorage.getItem('printpro_pricing'); if (stored) { try { return JSON.parse(stored); } catch (e) { return JSON.parse(JSON.stringify(DEFAULT_PRICING)); } } const def = JSON.parse(JSON.stringify(DEFAULT_PRICING)); localStorage.setItem('printpro_pricing', JSON.stringify(def)); return def; } function savePricingToStorage(data) { localStorage.setItem('printpro_pricing', JSON.stringify(data)); // Dispatch events to notify the frontend window.dispatchEvent(new Event('pricingUpdated')); // Also try to notify other tabs via storage event localStorage.setItem('printpro_pricing_updated', Date.now().toString()); updateLastSaved(); } function updateLastSaved() { const now = new Date(); const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); document.getElementById('statLastSaved').textContent = timeStr; localStorage.setItem('printpro_last_saved', timeStr); } // --- LOGIN --- loginForm.addEventListener('submit', (e) => { e.preventDefault(); const username = document.getElementById('username').value.trim(); const password = document.getElementById('password').value.trim(); if (username === ADMIN_CREDENTIALS.username && password === ADMIN_CREDENTIALS.password) { isLoggedIn = true; sessionStorage.setItem('printpro_admin_loggedin', 'true'); loginScreen.classList.add('hidden'); dashboard.classList.remove('hidden'); initDashboard(); showToast('Welcome back, Admin! 👋'); } else { loginError.textContent = 'Invalid username or password.'; loginError.classList.remove('hidden'); document.getElementById('password').classList.add('border-red-500'); setTimeout(() => { document.getElementById('password').classList.remove('border-red-500'); loginError.classList.add('hidden'); }, 2500); } }); function logout() { isLoggedIn = false; sessionStorage.removeItem('printpro_admin_loggedin'); dashboard.classList.add('hidden'); loginScreen.classList.remove('hidden'); document.getElementById('password').value = ''; loginError.classList.add('hidden'); } // --- TOAST --- function showToast(message) { toastMsg.textContent = message; toast.classList.remove('hidden'); void toast.offsetWidth; toast.classList.add('toast'); setTimeout(() => { toast.classList.add('hidden'); toast.classList.remove('toast'); }, 3000); } // --- DASHBOARD --- function initDashboard() { pricing = getPricing(); updateStats(); renderProductCards(); lucide.createIcons(); } function updateStats() { const products = pricing.products; const keys = Object.keys(products); const totalBase = keys.reduce((sum, k) => sum + products[k].basePrice, 0); const avgPrice = totalBase / keys.length; const totalTiers = keys.reduce((sum, k) => sum + products[k].quantityTiers.length, 0); document.getElementById('statProducts').textContent = keys.length; document.getElementById('statAvgPrice').textContent = '$' + avgPrice.toFixed(2); document.getElementById('statTiers').textContent = totalTiers; document.getElementById('statLastSaved').textContent = localStorage.getItem('printpro_last_saved') || 'Never'; } function renderProductCards() { const products = pricing.products; productCards.innerHTML = Object.entries(products).map(([key, product]) => `
Product Key: ${key}
Sizes
${product.sizes.length} options
Paper Types
${product.paperTypes.length} options
Finishing
${product.finishing.length} options
Tiers
${product.quantityTiers.length} tiers
The starting price before any options or quantity discounts.