AdminLTE3
This commit is contained in:
@@ -29,6 +29,29 @@ const requireAuth = (req, res, next) => {
|
||||
next();
|
||||
};
|
||||
|
||||
// Add stats middleware
|
||||
const addStats = async (req, res, next) => {
|
||||
try {
|
||||
if (req.session.user) {
|
||||
const [portfolioCount, servicesCount, contactsCount] = await Promise.all([
|
||||
Portfolio.count({ where: { isPublished: true } }),
|
||||
Service.count({ where: { isActive: true } }),
|
||||
Contact.count()
|
||||
]);
|
||||
|
||||
res.locals.stats = {
|
||||
portfolioCount,
|
||||
servicesCount,
|
||||
contactsCount
|
||||
};
|
||||
}
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('Stats middleware error:', error);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
// Admin login page
|
||||
router.get('/login', (req, res) => {
|
||||
if (req.session.user) {
|
||||
@@ -479,12 +502,12 @@ router.post('/banners/:id/click', async (req, res) => {
|
||||
});
|
||||
|
||||
// Banner Editor (legacy route)
|
||||
router.get('/banner-editor', requireAuth, async (req, res) => {
|
||||
router.get('/banner-editor', requireAuth, addStats, async (req, res) => {
|
||||
res.redirect('/admin/banners');
|
||||
});
|
||||
|
||||
// Portfolio management
|
||||
router.get('/portfolio', requireAuth, async (req, res) => {
|
||||
router.get('/portfolio', requireAuth, addStats, async (req, res) => {
|
||||
try {
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = 20;
|
||||
@@ -504,6 +527,7 @@ router.get('/portfolio', requireAuth, async (req, res) => {
|
||||
res.render('admin/portfolio/list', {
|
||||
title: 'Portfolio Management - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'portfolio',
|
||||
user: req.session.user,
|
||||
portfolio,
|
||||
pagination: {
|
||||
@@ -944,7 +968,7 @@ router.post('/portfolio/preview', requireAuth, upload.array('images', 10), async
|
||||
});
|
||||
|
||||
// Services management
|
||||
router.get('/services', requireAuth, async (req, res) => {
|
||||
router.get('/services', requireAuth, addStats, async (req, res) => {
|
||||
try {
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = 20;
|
||||
@@ -964,6 +988,7 @@ router.get('/services', requireAuth, async (req, res) => {
|
||||
res.render('admin/services/list', {
|
||||
title: 'Services Management - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'services',
|
||||
user: req.session.user,
|
||||
services,
|
||||
pagination: {
|
||||
@@ -1232,7 +1257,7 @@ router.patch('/services/:id/toggle-active', requireAuth, async (req, res) => {
|
||||
});
|
||||
|
||||
// Contacts management
|
||||
router.get('/contacts', requireAuth, async (req, res) => {
|
||||
router.get('/contacts', requireAuth, addStats, async (req, res) => {
|
||||
try {
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = 20;
|
||||
@@ -1259,6 +1284,7 @@ router.get('/contacts', requireAuth, async (req, res) => {
|
||||
res.render('admin/contacts/list', {
|
||||
title: 'Contacts Management - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'contacts',
|
||||
user: req.session.user,
|
||||
contacts,
|
||||
currentStatus: status || 'all',
|
||||
@@ -1315,13 +1341,14 @@ router.get('/contacts/:id', requireAuth, async (req, res) => {
|
||||
});
|
||||
|
||||
// Settings
|
||||
router.get('/settings', requireAuth, async (req, res) => {
|
||||
router.get('/settings', requireAuth, addStats, async (req, res) => {
|
||||
try {
|
||||
const settings = await SiteSettings.findOne() || await SiteSettings.create({});
|
||||
|
||||
res.render('admin/settings', {
|
||||
title: 'Site Settings - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'settings',
|
||||
user: req.session.user,
|
||||
settings
|
||||
});
|
||||
@@ -1336,16 +1363,17 @@ router.get('/settings', requireAuth, async (req, res) => {
|
||||
});
|
||||
|
||||
// Media gallery
|
||||
router.get('/media', requireAuth, (req, res) => {
|
||||
router.get('/media', requireAuth, addStats, (req, res) => {
|
||||
res.render('admin/media', {
|
||||
title: 'Media Gallery - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'media',
|
||||
user: req.session.user
|
||||
});
|
||||
});
|
||||
|
||||
// Telegram bot configuration and testing
|
||||
router.get('/telegram', requireAuth, async (req, res) => {
|
||||
router.get('/telegram', requireAuth, addStats, async (req, res) => {
|
||||
try {
|
||||
const telegramService = require('../services/telegram');
|
||||
|
||||
@@ -1364,6 +1392,7 @@ router.get('/telegram', requireAuth, async (req, res) => {
|
||||
res.render('admin/telegram', {
|
||||
title: 'Telegram Bot - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'telegram',
|
||||
user: req.session.user,
|
||||
botConfigured: telegramService.isEnabled,
|
||||
botToken: telegramService.botToken || '',
|
||||
@@ -1608,4 +1637,23 @@ router.post('/telegram/send', requireAuth, [
|
||||
}
|
||||
});
|
||||
|
||||
// Settings page
|
||||
router.get('/settings', requireAuth, addStats, (req, res) => {
|
||||
res.render('admin/settings', {
|
||||
title: 'Site Settings - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
user: req.session.user
|
||||
});
|
||||
});
|
||||
|
||||
// Banner editor page
|
||||
router.get('/banner-editor', requireAuth, addStats, (req, res) => {
|
||||
res.render('admin/banner-editor', {
|
||||
title: 'Banner Editor - Admin Panel',
|
||||
layout: 'admin/layout',
|
||||
currentPage: 'banner-editor',
|
||||
user: req.session.user
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -216,6 +216,114 @@ router.post('/services', requireAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/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' });
|
||||
}
|
||||
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
shortDescription,
|
||||
icon,
|
||||
category,
|
||||
features,
|
||||
pricing,
|
||||
estimatedTime,
|
||||
isActive,
|
||||
featured,
|
||||
tags,
|
||||
order,
|
||||
seo
|
||||
} = req.body;
|
||||
|
||||
// Parse arrays and objects
|
||||
let featuresArray = [];
|
||||
let tagsArray = [];
|
||||
let pricingObj = {};
|
||||
let seoObj = {};
|
||||
|
||||
if (features) {
|
||||
if (Array.isArray(features)) {
|
||||
featuresArray = features;
|
||||
} else {
|
||||
try {
|
||||
featuresArray = JSON.parse(features);
|
||||
} catch (e) {
|
||||
featuresArray = features.split(',').map(f => f.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tags) {
|
||||
if (Array.isArray(tags)) {
|
||||
tagsArray = tags;
|
||||
} else {
|
||||
try {
|
||||
tagsArray = JSON.parse(tags);
|
||||
} catch (e) {
|
||||
tagsArray = tags.split(',').map(t => t.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pricing) {
|
||||
if (typeof pricing === 'object') {
|
||||
pricingObj = pricing;
|
||||
} else {
|
||||
try {
|
||||
pricingObj = JSON.parse(pricing);
|
||||
} catch (e) {
|
||||
pricingObj = { basePrice: pricing };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (seo) {
|
||||
if (typeof seo === 'object') {
|
||||
seoObj = seo;
|
||||
} else {
|
||||
try {
|
||||
seoObj = JSON.parse(seo);
|
||||
} catch (e) {
|
||||
seoObj = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updateData = {
|
||||
name,
|
||||
description,
|
||||
shortDescription,
|
||||
icon,
|
||||
category,
|
||||
features: featuresArray,
|
||||
pricing: pricingObj,
|
||||
estimatedTime,
|
||||
isActive: Boolean(isActive),
|
||||
featured: Boolean(featured),
|
||||
tags: tagsArray,
|
||||
order: order ? parseInt(order) : 0,
|
||||
seo: seoObj
|
||||
};
|
||||
|
||||
// Remove undefined values
|
||||
Object.keys(updateData).forEach(key => {
|
||||
if (updateData[key] === undefined) {
|
||||
delete updateData[key];
|
||||
}
|
||||
});
|
||||
|
||||
await service.update(updateData);
|
||||
res.json({ success: true, service });
|
||||
} catch (error) {
|
||||
console.error('Service update 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);
|
||||
|
||||
Reference in New Issue
Block a user