Files
Sizzy e22a8dc248 chnages
chnages
2026-07-01 01:10:13 +05:45

137 lines
3.7 KiB
JavaScript

// ============================================================
// publicContentController.js — Public, read-only website content
// ============================================================
// These endpoints power the public marketing pages. They expose
// only ACTIVE / PUBLISHED rows. No authentication is required.
// ============================================================
const pool = require('../db');
// GET /api/content/solutions
async function getSolutions(req, res, next) {
try {
const result = await pool.query(
`SELECT id, title, summary, description, icon
FROM solutions
WHERE is_active = true
ORDER BY sort_order ASC, id ASC`
);
return res.json({ solutions: result.rows });
} catch (err) {
next(err);
}
}
// GET /api/content/case-studies
async function getCaseStudies(req, res, next) {
try {
const result = await pool.query(
`SELECT id, title, client, industry, summary, outcome, image_url, created_at
FROM case_studies
ORDER BY created_at DESC, id DESC`
);
return res.json({ caseStudies: result.rows });
} catch (err) {
next(err);
}
}
// GET /api/content/feedback
async function getFeedback(req, res, next) {
try {
const result = await pool.query(
`SELECT id, customer_name, company, rating, comment, created_at
FROM feedback
WHERE is_published = true
ORDER BY created_at DESC, id DESC`
);
// Average rating for a quick "social proof" headline figure
const avg = result.rows.length
? result.rows.reduce((sum, r) => sum + r.rating, 0) / result.rows.length
: 0;
return res.json({
feedback: result.rows,
averageRating: Math.round(avg * 10) / 10,
count: result.rows.length,
});
} catch (err) {
next(err);
}
}
// GET /api/content/articles
async function getArticles(req, res, next) {
try {
const result = await pool.query(
`SELECT id, slug, title, excerpt, cover_image, author, published_at
FROM articles
WHERE is_published = true
ORDER BY published_at DESC, id DESC`
);
return res.json({ articles: result.rows });
} catch (err) {
next(err);
}
}
// GET /api/content/articles/:slug
async function getArticleBySlug(req, res, next) {
try {
const { slug } = req.params;
const result = await pool.query(
`SELECT id, slug, title, excerpt, body, cover_image, author, published_at
FROM articles
WHERE slug = $1 AND is_published = true`,
[slug]
);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'Article not found.' });
}
return res.json({ article: result.rows[0] });
} catch (err) {
next(err);
}
}
// GET /api/content/events
async function getEvents(req, res, next) {
try {
const result = await pool.query(
`SELECT id, title, description, location, event_date, is_upcoming, cover_image
FROM events
ORDER BY event_date DESC NULLS LAST, id DESC`
);
return res.json({
upcoming: result.rows.filter(e => e.is_upcoming),
past: result.rows.filter(e => !e.is_upcoming),
});
} catch (err) {
next(err);
}
}
// GET /api/content/gallery
async function getGallery(req, res, next) {
try {
const result = await pool.query(
`SELECT g.id, g.image_url, g.caption, g.created_at, e.title AS event_title
FROM gallery_images g
LEFT JOIN events e ON e.id = g.event_id
ORDER BY g.created_at DESC, g.id DESC`
);
return res.json({ gallery: result.rows });
} catch (err) {
next(err);
}
}
module.exports = {
getSolutions,
getCaseStudies,
getFeedback,
getArticles,
getArticleBySlug,
getEvents,
getGallery,
};