forked from UKSOURCE/cms.hailearning.edu.vn
first commit
This commit is contained in:
322
controllers/campLocationController.js
Normal file
322
controllers/campLocationController.js
Normal file
@@ -0,0 +1,322 @@
|
||||
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' });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user