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' }); } };