From 711ed1e3cfa6ec19cd4ad52a5d85bb8eb6fe5583 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Wed, 21 Jan 2026 20:02:02 -0600 Subject: [PATCH] asdasd --- public/app.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++ public/index.html | 35 ++++++++++++++++++++++++- server.js | 53 ++++++++++++++++++++++++++++++++++--- 3 files changed, 151 insertions(+), 4 deletions(-) diff --git a/public/app.js b/public/app.js index 212b788..666fa7c 100644 --- a/public/app.js +++ b/public/app.js @@ -4,17 +4,29 @@ let quotes = []; let currentQuoteId = null; let currentCustomerId = null; let itemCounter = 0; +let currentLogoFile = null; // Initialize app document.addEventListener('DOMContentLoaded', () => { loadCustomers(); loadQuotes(); setDefaultDate(); + checkCurrentLogo(); // Setup form handlers document.getElementById('customer-form').addEventListener('submit', handleCustomerSubmit); document.getElementById('quote-form').addEventListener('submit', handleQuoteSubmit); document.getElementById('quote-tax-exempt').addEventListener('change', updateTotals); + + // Setup logo upload handler + document.getElementById('logo-upload').addEventListener('change', (e) => { + const file = e.target.files[0]; + if (file) { + currentLogoFile = file; + document.getElementById('logo-filename').textContent = file.name; + document.getElementById('upload-btn').disabled = false; + } + }); }); // Tab Management @@ -29,6 +41,61 @@ function showTab(tabName) { loadQuotes(); } else if (tabName === 'customers') { loadCustomers(); + } else if (tabName === 'settings') { + checkCurrentLogo(); + } +} + +// Logo Management +async function checkCurrentLogo() { + try { + const response = await fetch('/api/logo-info'); + if (response.ok) { + const data = await response.json(); + if (data.hasLogo) { + document.getElementById('logo-preview').classList.remove('hidden'); + document.getElementById('logo-image').src = data.logoPath + '?t=' + Date.now(); + } + } + } catch (error) { + console.error('Error checking logo:', error); + } +} + +async function uploadLogo() { + if (!currentLogoFile) { + alert('Please select a file first'); + return; + } + + const formData = new FormData(); + formData.append('logo', currentLogoFile); + + const statusDiv = document.getElementById('upload-status'); + statusDiv.innerHTML = '

Uploading...

'; + + try { + const response = await fetch('/api/upload-logo', { + method: 'POST', + body: formData + }); + + if (response.ok) { + const data = await response.json(); + statusDiv.innerHTML = '

✓ Logo uploaded successfully!

'; + document.getElementById('logo-preview').classList.remove('hidden'); + document.getElementById('logo-image').src = data.path + '?t=' + Date.now(); + document.getElementById('upload-btn').disabled = true; + currentLogoFile = null; + document.getElementById('logo-filename').textContent = ''; + document.getElementById('logo-upload').value = ''; + } else { + const error = await response.json(); + statusDiv.innerHTML = `

✗ Error: ${error.error}

`; + } + } catch (error) { + console.error('Upload error:', error); + statusDiv.innerHTML = '

✗ Upload failed

'; } } diff --git a/public/index.html b/public/index.html index ecba362..a581ac2 100644 --- a/public/index.html +++ b/public/index.html @@ -27,6 +27,7 @@
+
@@ -88,6 +89,38 @@ + + + @@ -257,4 +290,4 @@ - + \ No newline at end of file diff --git a/server.js b/server.js index fb56664..b2d6552 100644 --- a/server.js +++ b/server.js @@ -277,6 +277,9 @@ app.post('/api/quotes', async (req, res) => { }); app.put('/api/quotes/:id', async (req, res) => { + console.log('PUT /api/quotes/:id called with id:', req.params.id); + console.log('Request body:', JSON.stringify(req.body, null, 2)); + const client = await pool.connect(); try { await client.query('BEGIN'); @@ -363,12 +366,35 @@ app.post('/api/upload-logo', upload.single('logo'), (req, res) => { if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } + + // Save as "current_logo" for easy access + const logoPath = path.join(__dirname, 'uploads', 'current_logo' + path.extname(req.file.filename)); + fs.renameSync(req.file.path, logoPath); + res.json({ - filename: req.file.filename, - path: `/uploads/${req.file.filename}` + filename: 'current_logo' + path.extname(req.file.filename), + path: `/uploads/current_logo${path.extname(req.file.filename)}` }); }); +// Get logo info +app.get('/api/logo-info', (req, res) => { + const uploadsDir = path.join(__dirname, 'uploads'); + const possibleExtensions = ['.png', '.jpg', '.jpeg', '.gif']; + + for (const ext of possibleExtensions) { + const logoPath = path.join(uploadsDir, 'current_logo' + ext); + if (fs.existsSync(logoPath)) { + return res.json({ + hasLogo: true, + logoPath: `/uploads/current_logo${ext}` + }); + } + } + + res.json({ hasLogo: false }); +}); + // Generate PDF app.post('/api/quotes/:id/pdf', async (req, res) => { let browser; @@ -469,6 +495,27 @@ function generateQuoteHTML(quote) { return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; }; + // Check for logo file + let logoHTML = '
BA
'; + + const uploadsDir = path.join(__dirname, 'uploads'); + const possibleExtensions = ['.png', '.jpg', '.jpeg', '.gif']; + + for (const ext of possibleExtensions) { + const logoPath = path.join(uploadsDir, 'current_logo' + ext); + if (fs.existsSync(logoPath)) { + try { + const logoBuffer = fs.readFileSync(logoPath); + const logoBase64 = logoBuffer.toString('base64'); + const mimeType = ext === '.png' ? 'image/png' : 'image/jpeg'; + logoHTML = `Logo`; + } catch (err) { + console.error('Error reading logo file:', err); + } + break; + } + } + let itemsHTML = ''; quote.items.forEach(item => { itemsHTML += ` @@ -686,7 +733,7 @@ function generateQuoteHTML(quote) {
-
BA
+ ${logoHTML}

Bay Area Affiliates, Inc.

1001 Blucher Street