tinfo-web-server / controllers /siteContentController.js
Faridaqurr
initial backend
e8c33fa
Raw
History Blame Contribute Delete
5.45 kB
const SiteContent = require('../models/SiteContent');
const { asyncController } = require('../utils/asyncController');
const DEFAULT_SITE_CONTENT = {
welcome: {
title: 'ITS IT Department Kiosk',
subtitle:
"Hi I'm ITS IT Department Kiosk, I can help you explore our department, meet our faculty, and discover our achievements.",
cta: 'Start Exploring',
footerHint: 'Touch anywhere to begin',
},
mainMenu: {
title: 'Department of Information Technology',
subtitle: 'What would you like to explore?',
footerHint: 'Touch any card to explore that section',
modules: [
{
key: 'aboutus',
label: 'About Us',
subtitle: 'Learn about our department',
bg: '#3b82f6',
href: '/aboutus',
iconImage: '',
},
{
key: 'profile',
label: 'Faculty Profiles',
subtitle: 'Meet our expert faculty',
bg: '#8b5cf6',
href: '/profile',
iconImage: '',
},
{
key: 'admission',
label: 'Admissions/Other Info',
subtitle: 'Join our program',
bg: '#06b6d4',
href: '/admission',
iconImage: '',
},
{
key: 'achievement',
label: 'Achievements/News',
subtitle: 'Our success stories',
bg: '#f97316',
href: '/achievement',
iconImage: '',
},
{
key: 'announcement',
label: 'Announcements',
subtitle: 'Latest updates and news',
bg: '#22c55e',
href: '/announcement',
iconImage: '',
},
],
},
};
const sanitizeCopy = (value, fallback) => {
if (!value || typeof value !== 'object') return fallback;
return {
title: String(value.title || fallback.title).trim(),
subtitle: String(value.subtitle || fallback.subtitle).trim(),
cta: String(value.cta || fallback.cta).trim(),
footerHint: String(value.footerHint || fallback.footerHint).trim(),
};
};
const toKeySlug = (value = '') =>
String(value)
.toLowerCase()
.trim()
.replace(/[^a-z0-9\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-');
const sanitizeModule = (item = {}, fallback = {}) => ({
key: String(item.key || fallback.key || '').trim(),
label: String(item.label || fallback.label || '').trim(),
subtitle: String(item.subtitle || fallback.subtitle || '').trim(),
bg: String(item.bg || fallback.bg || '#3b82f6').trim(),
href: String(item.href || fallback.href || '').trim(),
iconImage: String(item.iconImage || fallback.iconImage || '').trim(),
});
const sanitizeMainMenu = (value) => {
const fallback = DEFAULT_SITE_CONTENT.mainMenu;
const modules = Array.isArray(value?.modules) && value.modules.length
? value.modules
: fallback.modules;
return {
title: value?.title || fallback.title,
subtitle: value?.subtitle || fallback.subtitle,
footerHint: value?.footerHint || fallback.footerHint,
modules: modules
.map((item, index) => {
const moduleItem = sanitizeModule(item, fallback.modules[index] || {});
const generatedKey = toKeySlug(moduleItem.key || moduleItem.label || moduleItem.href || `card-${index + 1}`);
return {
...moduleItem,
key: generatedKey || `card-${index + 1}`,
};
})
.filter((item) => item.label),
};
};
const normalizeSiteContent = (doc) => ({
welcome: sanitizeCopy(doc?.welcome?.EN || doc?.welcome, DEFAULT_SITE_CONTENT.welcome),
mainMenu: sanitizeMainMenu(doc?.mainMenu),
});
const getSiteContent = asyncController(async (req, res) => {
const doc = await SiteContent.findOne({ slug: 'main' }).lean();
res.json(normalizeSiteContent(doc));
});
const updateSiteContent = asyncController(async (req, res) => {
const { welcome, mainMenu } = req.body;
const payload = {};
if (welcome && typeof welcome === 'object') {
const source = welcome.EN && typeof welcome.EN === 'object' ? welcome.EN : welcome;
payload.welcome = {
title: String(source?.title || '').trim(),
subtitle: String(source?.subtitle || '').trim(),
cta: String(source?.cta || '').trim(),
footerHint: String(source?.footerHint || '').trim(),
};
}
if (mainMenu && typeof mainMenu === 'object') {
payload.mainMenu = {
title: String(mainMenu?.title || '').trim(),
subtitle: String(mainMenu?.subtitle || '').trim(),
footerHint: String(mainMenu?.footerHint || '').trim(),
modules: Array.isArray(mainMenu?.modules)
? mainMenu.modules
.map((item, index) => {
const moduleItem = sanitizeModule(item);
const generatedKey = toKeySlug(moduleItem.key || moduleItem.label || moduleItem.href || `card-${index + 1}`);
return {
...moduleItem,
key: generatedKey || `card-${index + 1}`,
};
})
.filter((item) => item.label)
: [],
};
}
if (!Object.keys(payload).length) {
return res.status(400).json({ message: 'No fields provided to update' });
}
const doc = await SiteContent.findOneAndUpdate(
{ slug: 'main' },
{ $set: payload },
{ returnDocument: 'after', upsert: true, runValidators: true }
);
if (!doc) {
return res.status(500).json({ message: 'Failed to persist site content' });
}
res.json(normalizeSiteContent(doc));
}, { defaultStatus: 400 });
module.exports = { getSiteContent, updateSiteContent };