forked from UKSOURCE/cms.hailearning.edu.vn
323 lines
10 KiB
JavaScript
323 lines
10 KiB
JavaScript
const { addBaseUrlToImages } = require('../utils/imageHelper');
|
|
const CampLocation = require('../models/campLocation');
|
|
|
|
// -------------------- Public (read-only) helpers --------------------
|
|
// Get camp location data from MongoDB
|
|
const getCampLocationData = async () => {
|
|
const campLocation = await CampLocation.findOne().sort({ updatedAt: -1 });
|
|
if (!campLocation) return null;
|
|
return campLocation.toObject ? campLocation.toObject() : campLocation;
|
|
};
|
|
|
|
// -------------------- Admin (CRUD on CampLocation model) helpers --------------------
|
|
// Default shape for CampLocation documents
|
|
const getDefaultCampLocationData = () => ({
|
|
metadata: { title: '', description: '', keywords: '' },
|
|
hero: { title: '', subtitle: '', backgroundImage: '' },
|
|
camps: [],
|
|
locations: [],
|
|
locationsSection: { title: '', description: '' },
|
|
intro: { title: '', description: '' },
|
|
map: {
|
|
coordinates: { lat: 0, lng: 0 },
|
|
zoom: 15,
|
|
location: '',
|
|
markerTitle: '',
|
|
tileLayer: {
|
|
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
|
attribution: '',
|
|
maxZoom: 18,
|
|
minZoom: 0
|
|
}
|
|
},
|
|
faq: [],
|
|
faqSection: { title: '', description: '' },
|
|
welcomeQuote: { text: '', author: '' },
|
|
securityConcept: { title: '', description: '', items: [] }
|
|
});
|
|
|
|
// Get latest stored CampLocation document or default
|
|
const getStoredCampLocation = async () => {
|
|
const campLocation = await CampLocation.findOne().sort({ updatedAt: -1 });
|
|
if (!campLocation) return getDefaultCampLocationData();
|
|
return campLocation.toObject ? campLocation.toObject() : campLocation;
|
|
};
|
|
|
|
// -------------------- Public exports --------------------
|
|
// API endpoint to return camp location JSON
|
|
exports.api = async (req, res) => {
|
|
try {
|
|
const campLocationData = await getCampLocationData();
|
|
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
|
|
const processed = addBaseUrlToImages(campLocationData || {}, baseUrl);
|
|
return res.json(processed);
|
|
} catch (err) {
|
|
console.error('campLocation.api error:', err);
|
|
return res.status(500).json({ error: 'Error loading camp location data' });
|
|
}
|
|
};
|
|
|
|
// API endpoint to return an array of CampLocation records (for frontend listing)
|
|
exports.apiList = async (req, res) => {
|
|
try {
|
|
const docs = await CampLocation.find().sort({ updatedAt: -1 }).lean();
|
|
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
|
|
const processed = (docs || []).map((d) => addBaseUrlToImages(d || {}, baseUrl));
|
|
return res.json(processed);
|
|
} catch (err) {
|
|
console.error('campLocation.apiList error:', err);
|
|
return res.status(500).json({ error: 'Error loading camp location list' });
|
|
}
|
|
};
|
|
|
|
// -------------------- Admin exports --------------------
|
|
// Display camp location management page
|
|
exports.index = async (req, res) => {
|
|
try {
|
|
// Set cache control headers to prevent caching
|
|
res.set({
|
|
'Cache-Control': 'no-store, no-cache, must-revalidate, private',
|
|
'Pragma': 'no-cache',
|
|
'Expires': '0'
|
|
});
|
|
|
|
const data = await getStoredCampLocation();
|
|
const items = await CampLocation.find().sort({ updatedAt: -1 }).limit(10);
|
|
|
|
res.render('admin/campLocation/index', {
|
|
layout: 'layouts/main',
|
|
title: 'Camp Location Management',
|
|
data,
|
|
items,
|
|
frontendUrl: process.env.FRONTEND_URL || `${req.protocol}://${req.get('host')}`,
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
req.flash('error_msg', 'Error loading camp location data');
|
|
res.redirect('/admin/dashboard');
|
|
}
|
|
};
|
|
|
|
// Display create form
|
|
exports.createForm = async (req, res) => {
|
|
try {
|
|
const data = getDefaultCampLocationData();
|
|
|
|
res.render('admin/campLocation/create', {
|
|
layout: 'layouts/main',
|
|
title: 'Create Camp Location',
|
|
data,
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
req.flash('error_msg', 'Error loading create form');
|
|
res.redirect('/admin/camp-location');
|
|
}
|
|
};
|
|
|
|
// Create new CampLocation record
|
|
exports.create = async (req, res) => {
|
|
try {
|
|
const campLocationData = {
|
|
metadata: JSON.parse(req.body.metadata || '{}'),
|
|
hero: JSON.parse(req.body.hero || '{}'),
|
|
camps: JSON.parse(req.body.camps || '[]'),
|
|
locations: JSON.parse(req.body.locations || '[]'),
|
|
locationsSection: JSON.parse(req.body.locationsSection || '{}'),
|
|
intro: JSON.parse(req.body.intro || '{}'),
|
|
map: JSON.parse(req.body.map || '{}'),
|
|
faq: JSON.parse(req.body.faq || '[]'),
|
|
faqSection: JSON.parse(req.body.faqSection || '{}'),
|
|
welcomeQuote: JSON.parse(req.body.welcomeQuote || '{}'),
|
|
securityConcept: JSON.parse(req.body.securityConcept || '{}')
|
|
};
|
|
|
|
const newCampLocation = new CampLocation(campLocationData);
|
|
await newCampLocation.save();
|
|
|
|
req.flash('success_msg', 'Camp Location created successfully');
|
|
res.redirect('/admin/camp-location');
|
|
} catch (err) {
|
|
console.error('Create error:', err);
|
|
req.flash('error_msg', `Create error: ${err.message || 'Unknown'}`);
|
|
res.redirect('/admin/camp-location/create');
|
|
}
|
|
};
|
|
|
|
// Display edit form
|
|
exports.editForm = async (req, res) => {
|
|
try {
|
|
const campLocation = await CampLocation.findById(req.params.id);
|
|
|
|
if (!campLocation) {
|
|
req.flash('error_msg', 'Camp Location record not found');
|
|
return res.redirect('/admin/camp-location');
|
|
}
|
|
|
|
res.render('admin/campLocation/edit', {
|
|
layout: 'layouts/main',
|
|
title: 'Edit Camp Location',
|
|
data: campLocation.toObject ? campLocation.toObject() : campLocation,
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
req.flash('error_msg', 'Error loading edit form');
|
|
res.redirect('/admin/camp-location');
|
|
}
|
|
};
|
|
|
|
// Update CampLocation record
|
|
exports.update = async (req, res) => {
|
|
try {
|
|
// Get current data
|
|
const currentData = await getStoredCampLocation();
|
|
|
|
// List of sections to update
|
|
const sections = [
|
|
'metadata',
|
|
'hero',
|
|
'camps',
|
|
'locations',
|
|
'locationsSection',
|
|
'intro',
|
|
'map',
|
|
'faq',
|
|
'faqSection',
|
|
'welcomeQuote',
|
|
'securityConcept'
|
|
];
|
|
const errors = [];
|
|
let hasChanges = false;
|
|
|
|
// Create updated data object
|
|
const updatedData = {
|
|
...(currentData.toObject ? currentData.toObject() : currentData)
|
|
};
|
|
|
|
// Process each section
|
|
sections.forEach((section) => {
|
|
try {
|
|
if (!req.body[section]) {
|
|
console.warn(`No data for section: ${section}`);
|
|
return;
|
|
}
|
|
|
|
const newSectionData = JSON.parse(req.body[section]);
|
|
const currentSectionData = currentData[section];
|
|
const sectionHasChanges =
|
|
JSON.stringify(newSectionData) !== JSON.stringify(currentSectionData);
|
|
|
|
if (sectionHasChanges) {
|
|
updatedData[section] = newSectionData;
|
|
hasChanges = true;
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error processing section ${section}:`, error);
|
|
errors.push(`Error processing ${section} data: ${error.message}`);
|
|
}
|
|
});
|
|
|
|
if (errors.length > 0) {
|
|
req.flash('error_msg', `Data processing error: ${errors[0]}`);
|
|
return req.session.save(() => res.redirect('/admin/camp-location'));
|
|
}
|
|
|
|
if (!hasChanges) {
|
|
req.flash('info_msg', 'No changes were made');
|
|
return req.session.save(() => res.redirect('/admin/camp-location'));
|
|
}
|
|
|
|
try {
|
|
// Only update existing document; do not create a new one here
|
|
if (!currentData || !currentData._id) {
|
|
req.flash('error_msg', 'No existing Camp Location record to update. Create one first.');
|
|
return req.session.save(() => res.redirect('/admin/camp-location'));
|
|
}
|
|
|
|
// Update document and ensure it's saved to MongoDB
|
|
const updatedDoc = await CampLocation.findByIdAndUpdate(
|
|
currentData._id,
|
|
updatedData,
|
|
{
|
|
new: true,
|
|
runValidators: true,
|
|
useFindAndModify: false
|
|
}
|
|
);
|
|
|
|
// Verify the update was successful
|
|
if (!updatedDoc) {
|
|
throw new Error('Failed to update document');
|
|
}
|
|
|
|
// Force a save to ensure MongoDB commits the changes
|
|
await updatedDoc.save();
|
|
|
|
console.log('✓ Camp location updated successfully in MongoDB');
|
|
console.log('✓ Document ID:', updatedDoc._id);
|
|
console.log('✓ Updated at:', updatedDoc.updatedAt);
|
|
|
|
req.flash('success_msg', 'Camp location data updated successfully');
|
|
// Redirect back to the same page with cache-busting parameter to force refresh
|
|
const timestamp = Date.now();
|
|
return req.session.save(() => res.redirect(`/admin/camp-location?updated=${timestamp}`));
|
|
} catch (dbError) {
|
|
console.error('Database error:', dbError);
|
|
req.flash('error_msg', `Database error: ${dbError.message || 'Unknown'}`);
|
|
return req.session.save(() => res.redirect('/admin/camp-location'));
|
|
}
|
|
} catch (err) {
|
|
console.error('Update error:', err);
|
|
req.flash('error_msg', `Update error: ${err.message || 'Unknown'}`);
|
|
return req.session.save(() => res.redirect('/admin/camp-location'));
|
|
}
|
|
};
|
|
|
|
// Delete CampLocation record
|
|
exports.delete = async (req, res) => {
|
|
try {
|
|
const campLocation = await CampLocation.findById(req.params.id);
|
|
|
|
if (!campLocation) {
|
|
req.flash('error_msg', 'Camp Location record not found');
|
|
return res.redirect('/admin/camp-location');
|
|
}
|
|
|
|
await CampLocation.findByIdAndDelete(req.params.id);
|
|
|
|
req.flash('success_msg', 'Camp Location record deleted successfully');
|
|
res.redirect('/admin/camp-location');
|
|
} catch (err) {
|
|
console.error('Delete error:', err);
|
|
req.flash('error_msg', `Delete error: ${err.message || 'Unknown'}`);
|
|
res.redirect('/admin/camp-location');
|
|
}
|
|
};
|
|
|
|
// Preview CampLocation record
|
|
exports.preview = async (req, res) => {
|
|
try {
|
|
const campLocation = await CampLocation.findById(req.params.id);
|
|
|
|
if (!campLocation) {
|
|
return res.status(404).json({ error: 'Camp Location record not found' });
|
|
}
|
|
|
|
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
|
|
const processedData = addBaseUrlToImages(
|
|
campLocation.toObject ? campLocation.toObject() : campLocation,
|
|
baseUrl
|
|
);
|
|
res.json(processedData);
|
|
} catch (err) {
|
|
console.error('Preview error:', err);
|
|
res.status(500).json({ error: 'Error loading preview data' });
|
|
}
|
|
};
|