402 lines
9.8 KiB
JavaScript
402 lines
9.8 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { body, validationResult } = require('express-validator');
|
|
const { User, Portfolio, Service, Contact, SiteSettings } = require('../models');
|
|
|
|
// Authentication middleware
|
|
const requireAuth = (req, res, next) => {
|
|
if (!req.session.user) {
|
|
return res.redirect('/admin/login');
|
|
}
|
|
next();
|
|
};
|
|
|
|
// Admin login page
|
|
router.get('/login', (req, res) => {
|
|
if (req.session.user) {
|
|
return res.redirect('/admin/dashboard');
|
|
}
|
|
|
|
res.render('admin/login', {
|
|
title: req.t('admin.login'),
|
|
error: null
|
|
});
|
|
});
|
|
|
|
// Admin login POST
|
|
router.post('/login', async (req, res) => {
|
|
try {
|
|
const { email, password } = req.body;
|
|
|
|
const user = await User.findOne({
|
|
where: {
|
|
email: email,
|
|
isActive: true
|
|
}
|
|
});
|
|
if (!user || !(await user.comparePassword(password))) {
|
|
return res.render('admin/login', {
|
|
title: req.t('admin.login'),
|
|
error: req.t('errors.invalid_credentials')
|
|
});
|
|
}
|
|
|
|
await user.updateLastLogin();
|
|
|
|
req.session.user = {
|
|
id: user.id,
|
|
email: user.email,
|
|
name: user.name,
|
|
role: user.role
|
|
};
|
|
|
|
res.redirect('/admin/dashboard');
|
|
} catch (error) {
|
|
console.error('Admin login error:', error);
|
|
res.render('admin/login', {
|
|
title: req.t('admin.login'),
|
|
error: req.t('errors.server_error')
|
|
});
|
|
}
|
|
});
|
|
|
|
// Admin logout
|
|
router.post('/logout', (req, res) => {
|
|
req.session.destroy(err => {
|
|
if (err) {
|
|
console.error('Logout error:', err);
|
|
}
|
|
res.redirect('/admin/login');
|
|
});
|
|
});
|
|
|
|
// Dashboard (default route)
|
|
router.get('/', requireAuth, async (req, res) => {
|
|
res.redirect('/admin/dashboard');
|
|
});
|
|
|
|
// Dashboard
|
|
router.get('/dashboard', requireAuth, async (req, res) => {
|
|
try {
|
|
const [
|
|
portfolioCount,
|
|
servicesCount,
|
|
contactsCount,
|
|
recentContacts,
|
|
recentPortfolio
|
|
] = await Promise.all([
|
|
Portfolio.count({ where: { isPublished: true } }),
|
|
Service.count({ where: { isActive: true } }),
|
|
Contact.count(),
|
|
Contact.findAll({
|
|
order: [['createdAt', 'DESC']],
|
|
limit: 5
|
|
}),
|
|
Portfolio.findAll({
|
|
where: { isPublished: true },
|
|
order: [['createdAt', 'DESC']],
|
|
limit: 5
|
|
})
|
|
]);
|
|
|
|
const stats = {
|
|
portfolioCount: portfolioCount,
|
|
servicesCount: servicesCount,
|
|
contactsCount: contactsCount,
|
|
usersCount: await User.count()
|
|
};
|
|
|
|
res.render('admin/dashboard', {
|
|
title: req.t('admin.dashboard'),
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
stats,
|
|
recentContacts,
|
|
recentPortfolio
|
|
});
|
|
} catch (error) {
|
|
console.error('Dashboard error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading dashboard'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Portfolio management
|
|
router.get('/portfolio', requireAuth, async (req, res) => {
|
|
try {
|
|
const page = parseInt(req.query.page) || 1;
|
|
const limit = 20;
|
|
const skip = (page - 1) * limit;
|
|
|
|
const [portfolio, total] = await Promise.all([
|
|
Portfolio.findAll({
|
|
order: [['createdAt', 'DESC']],
|
|
offset: skip,
|
|
limit: limit
|
|
}),
|
|
Portfolio.count()
|
|
]);
|
|
|
|
const totalPages = Math.ceil(total / limit);
|
|
|
|
res.render('admin/portfolio/list', {
|
|
title: 'Portfolio Management - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
portfolio,
|
|
pagination: {
|
|
current: page,
|
|
total: totalPages,
|
|
hasNext: page < totalPages,
|
|
hasPrev: page > 1
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Portfolio list error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading portfolio'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Add portfolio item
|
|
router.get('/portfolio/add', requireAuth, (req, res) => {
|
|
res.render('admin/portfolio/add', {
|
|
title: 'Add Portfolio Item - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user
|
|
});
|
|
});
|
|
|
|
// Edit portfolio item
|
|
router.get('/portfolio/edit/:id', requireAuth, async (req, res) => {
|
|
try {
|
|
const portfolio = await Portfolio.findByPk(req.params.id);
|
|
|
|
if (!portfolio) {
|
|
return res.status(404).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Portfolio item not found'
|
|
});
|
|
}
|
|
|
|
res.render('admin/portfolio/edit', {
|
|
title: 'Edit Portfolio Item - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
portfolio
|
|
});
|
|
} catch (error) {
|
|
console.error('Portfolio edit error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading portfolio item'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Services management
|
|
router.get('/services', requireAuth, async (req, res) => {
|
|
try {
|
|
const page = parseInt(req.query.page) || 1;
|
|
const limit = 20;
|
|
const skip = (page - 1) * limit;
|
|
|
|
const [services, total] = await Promise.all([
|
|
Service.findAll({
|
|
order: [['createdAt', 'DESC']],
|
|
offset: skip,
|
|
limit: limit
|
|
}),
|
|
Service.count()
|
|
]);
|
|
|
|
const totalPages = Math.ceil(total / limit);
|
|
|
|
res.render('admin/services/list', {
|
|
title: 'Services Management - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
services,
|
|
pagination: {
|
|
current: page,
|
|
total: totalPages,
|
|
hasNext: page < totalPages,
|
|
hasPrev: page > 1
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Services list error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading services'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Add service
|
|
router.get('/services/add', requireAuth, (req, res) => {
|
|
res.render('admin/services/add', {
|
|
title: 'Add Service - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user
|
|
});
|
|
});
|
|
|
|
// Edit service
|
|
router.get('/services/edit/:id', requireAuth, async (req, res) => {
|
|
try {
|
|
const service = await Service.findByPk(req.params.id);
|
|
|
|
if (!service) {
|
|
return res.status(404).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Service not found'
|
|
});
|
|
}
|
|
|
|
const availablePortfolio = await Portfolio.findAll({
|
|
where: { isPublished: true },
|
|
attributes: ['title', 'category']
|
|
});
|
|
|
|
res.render('admin/services/edit', {
|
|
title: 'Edit Service - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
service,
|
|
availablePortfolio
|
|
});
|
|
} catch (error) {
|
|
console.error('Service edit error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading service'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Contacts management
|
|
router.get('/contacts', requireAuth, async (req, res) => {
|
|
try {
|
|
const page = parseInt(req.query.page) || 1;
|
|
const limit = 20;
|
|
const skip = (page - 1) * limit;
|
|
const status = req.query.status;
|
|
|
|
let whereClause = {};
|
|
if (status && status !== 'all') {
|
|
whereClause.status = status;
|
|
}
|
|
|
|
const [contacts, total] = await Promise.all([
|
|
Contact.findAll({
|
|
where: whereClause,
|
|
order: [['createdAt', 'DESC']],
|
|
offset: skip,
|
|
limit: limit
|
|
}),
|
|
Contact.count({ where: whereClause })
|
|
]);
|
|
|
|
const totalPages = Math.ceil(total / limit);
|
|
|
|
res.render('admin/contacts/list', {
|
|
title: 'Contacts Management - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
contacts,
|
|
currentStatus: status || 'all',
|
|
pagination: {
|
|
current: page,
|
|
total: totalPages,
|
|
hasNext: page < totalPages,
|
|
hasPrev: page > 1
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Contacts list error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading contacts'
|
|
});
|
|
}
|
|
});
|
|
|
|
// View contact details
|
|
router.get('/contacts/:id', requireAuth, async (req, res) => {
|
|
try {
|
|
const contact = await Contact.findByPk(req.params.id);
|
|
|
|
if (!contact) {
|
|
return res.status(404).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Contact not found'
|
|
});
|
|
}
|
|
|
|
// Mark as read
|
|
if (!contact.isRead) {
|
|
contact.isRead = true;
|
|
await contact.save();
|
|
}
|
|
|
|
res.render('admin/contacts/view', {
|
|
title: 'Contact Details - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
contact
|
|
});
|
|
} catch (error) {
|
|
console.error('Contact view error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading contact'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Settings
|
|
router.get('/settings', requireAuth, async (req, res) => {
|
|
try {
|
|
const settings = await SiteSettings.findOne() || await SiteSettings.create({});
|
|
|
|
res.render('admin/settings', {
|
|
title: 'Site Settings - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user,
|
|
settings
|
|
});
|
|
} catch (error) {
|
|
console.error('Settings error:', error);
|
|
res.status(500).render('admin/error', {
|
|
title: 'Error - Admin Panel',
|
|
layout: 'admin/layout',
|
|
message: 'Error loading settings'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Media gallery
|
|
router.get('/media', requireAuth, (req, res) => {
|
|
res.render('admin/media', {
|
|
title: 'Media Gallery - Admin Panel',
|
|
layout: 'admin/layout',
|
|
user: req.session.user
|
|
});
|
|
});
|
|
|
|
module.exports = router; |