const express = require('express'); const router = express.Router(); const multer = require('multer'); const path = require('path'); const { Portfolio, Service, Contact, User } = require('../../models'); // Multer configuration for file uploads const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, 'public/uploads/'); }, filename: (req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); } }); const upload = multer({ storage: storage, fileFilter: (req, file, cb) => { if (file.mimetype.startsWith('image/')) { cb(null, true); } else { cb(new Error('Only image files are allowed!'), false); } }, limits: { fileSize: 10 * 1024 * 1024 // 10MB } }); // Authentication middleware const requireAuth = (req, res, next) => { if (!req.session.user) { return res.status(401).json({ success: false, message: 'Authentication required' }); } next(); }; // Portfolio API Routes router.post('/portfolio', requireAuth, upload.array('images', 10), async (req, res) => { try { const { title, shortDescription, description, category, clientName, projectUrl, githubUrl, technologies, featured, isPublished } = req.body; // Process uploaded images const images = req.files ? req.files.map((file, index) => ({ url: `/uploads/${file.filename}`, alt: `${title} image ${index + 1}`, isPrimary: index === 0 })) : []; // Parse technologies let techArray = []; if (technologies) { try { techArray = JSON.parse(technologies); } catch (e) { techArray = technologies.split(',').map(t => t.trim()); } } const portfolio = await Portfolio.create({ title, shortDescription, description, category, clientName, projectUrl: projectUrl || null, githubUrl: githubUrl || null, technologies: techArray, images, featured: featured === 'on', isPublished: isPublished === 'on', status: 'completed', publishedAt: isPublished === 'on' ? new Date() : null }); res.json({ success: true, portfolio }); } catch (error) { console.error('Portfolio creation error:', error); res.status(500).json({ success: false, message: error.message }); } }); router.patch('/portfolio/:id', requireAuth, upload.array('images', 10), async (req, res) => { try { const portfolio = await Portfolio.findByPk(req.params.id); if (!portfolio) { return res.status(404).json({ success: false, message: 'Portfolio not found' }); } const updates = { ...req.body }; // Handle checkboxes updates.featured = updates.featured === 'on'; updates.isPublished = updates.isPublished === 'on'; // Process technologies if (updates.technologies) { try { updates.technologies = JSON.parse(updates.technologies); } catch (e) { updates.technologies = updates.technologies.split(',').map(t => t.trim()); } } // Process new images if (req.files && req.files.length > 0) { const newImages = req.files.map((file, index) => ({ url: `/uploads/${file.filename}`, alt: `${updates.title || portfolio.title} image ${index + 1}`, isPrimary: index === 0 && (!portfolio.images || portfolio.images.length === 0) })); updates.images = [...(portfolio.images || []), ...newImages]; } await portfolio.update(updates); res.json({ success: true, portfolio }); } catch (error) { console.error('Portfolio update error:', error); res.status(500).json({ success: false, message: error.message }); } }); router.delete('/portfolio/:id', requireAuth, async (req, res) => { try { const portfolio = await Portfolio.findByPk(req.params.id); if (!portfolio) { return res.status(404).json({ success: false, message: 'Portfolio not found' }); } await portfolio.destroy(); res.json({ success: true }); } catch (error) { console.error('Portfolio deletion error:', error); res.status(500).json({ success: false, message: error.message }); } }); // Services API Routes router.post('/services', requireAuth, async (req, res) => { try { const { name, description, shortDescription, icon, category, features, pricing, estimatedTime, isActive, featured, tags } = req.body; // Parse arrays let featuresArray = []; let tagsArray = []; let pricingObj = {}; if (features) { try { featuresArray = JSON.parse(features); } catch (e) { featuresArray = features.split(',').map(f => f.trim()); } } if (tags) { try { tagsArray = JSON.parse(tags); } catch (e) { tagsArray = tags.split(',').map(t => t.trim()); } } if (pricing) { try { pricingObj = JSON.parse(pricing); } catch (e) { pricingObj = { basePrice: pricing }; } } const service = await Service.create({ name, description, shortDescription, icon, category, features: featuresArray, pricing: pricingObj, estimatedTime, isActive: isActive === 'on', featured: featured === 'on', tags: tagsArray }); res.json({ success: true, service }); } catch (error) { console.error('Service creation error:', error); res.status(500).json({ success: false, message: error.message }); } }); router.delete('/services/:id', requireAuth, async (req, res) => { try { const service = await Service.findByPk(req.params.id); if (!service) { return res.status(404).json({ success: false, message: 'Service not found' }); } await service.destroy(); res.json({ success: true }); } catch (error) { console.error('Service deletion error:', error); res.status(500).json({ success: false, message: error.message }); } }); // Contacts API Routes router.patch('/contacts/:id', requireAuth, async (req, res) => { try { const contact = await Contact.findByPk(req.params.id); if (!contact) { return res.status(404).json({ success: false, message: 'Contact not found' }); } await contact.update(req.body); res.json({ success: true, contact }); } catch (error) { console.error('Contact update error:', error); res.status(500).json({ success: false, message: error.message }); } }); router.delete('/contacts/:id', requireAuth, async (req, res) => { try { const contact = await Contact.findByPk(req.params.id); if (!contact) { return res.status(404).json({ success: false, message: 'Contact not found' }); } await contact.destroy(); res.json({ success: true }); } catch (error) { console.error('Contact deletion error:', error); res.status(500).json({ success: false, message: error.message }); } }); // Telegram notification for contact router.post('/contacts/:id/telegram', requireAuth, async (req, res) => { try { const contact = await Contact.findByPk(req.params.id); if (!contact) { return res.status(404).json({ success: false, message: 'Contact not found' }); } // Send Telegram notification (we'll implement this with Telegram bot) const telegramService = require('../../services/telegram'); await telegramService.sendContactNotification(contact); res.json({ success: true }); } catch (error) { console.error('Telegram notification error:', error); res.status(500).json({ success: false, message: error.message }); } }); module.exports = router;