AdminLTE3

This commit is contained in:
2025-10-26 22:14:47 +09:00
parent 291fc63a4c
commit 9974811a3e
226 changed files with 88284 additions and 3406 deletions

View File

@@ -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;

View File

@@ -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);