first commit

This commit is contained in:
r2xrzh9q2z-lab
2026-02-02 11:07:09 +07:00
commit d1b931d547
286 changed files with 53992 additions and 0 deletions

View File

@@ -0,0 +1,363 @@
const {addBaseUrlToImages} = require("../utils/imageHelper");
const About = require("../models/about");
const AboutUs = require("../models/aboutUs");
// -------------------- Public (read-only) helpers --------------------
// Map stored About document back to the original aboutUs.json shape
function transformToAboutUs(doc) {
if (!doc) return null;
const hero = {
banner: doc.banner?.image || "",
title: doc.banner?.title || "",
breadcrumb: doc.banner?.text || "",
};
const stats = Array.isArray(doc.advantages?.items)
? doc.advantages.items.map((item) => ({
number: item.number || "",
description: item.title || "",
}))
: [];
const services = Array.isArray(doc.about?.paragraphs)
? doc.about.paragraphs.map((p) => ({title: "", description: p}))
: [];
const features = Array.isArray(doc.values?.items)
? doc.values.items.map((i) => ({
title: i.title || "",
description: i.text || "",
icon: i.icon || "",
}))
: [];
const events = Array.isArray(doc.academic_board?.members)
? doc.academic_board.members.map((m) => ({
imageUrl: m.image || "",
date: "",
title: m.title || "",
description: "",
authorName: m.name || "",
authorRole: "",
}))
: [];
return {
hero,
stats,
services,
features,
events,
};
}
// Get aboutUs data: prefer AboutUs collection, fallback to transforming About
const getAboutUsData = async () => {
// Prefer stored AboutUs document
const aboutUsDoc = await AboutUs.findOne().sort({updatedAt: -1});
if (aboutUsDoc)
return aboutUsDoc.toObject ? aboutUsDoc.toObject() : aboutUsDoc;
// Fallback: transform legacy About document into aboutUs shape
const about = await About.findOne().sort({updatedAt: -1});
if (!about) return null;
return transformToAboutUs(about);
};
// -------------------- Admin (CRUD on AboutUs model) helpers --------------------
// Default shape for AboutUs documents (matches data/aboutUs.json)
const getDefaultAboutUsData = () => ({
hero: {title: "", backgroundImage: ""},
introduction: {
subtitle: "",
title: "",
description: "",
mainImage: "",
services: [],
},
statistics: {
items: [],
},
accommodation: {
subtitle: "",
title: "",
description: "",
features: [],
},
activities: {
subtitle: "",
title: "",
description: "",
gallery: [],
},
newsletter: {
imagePath: "",
title: "",
description: "",
buttonText: "",
},
events: {
title: "",
items: [],
},
});
// Get latest stored AboutUs document or default (returned as plain object)
const getStoredAboutUs = async () => {
const aboutUs = await AboutUs.findOne().sort({updatedAt: -1});
if (!aboutUs) return getDefaultAboutUsData();
return aboutUs.toObject ? aboutUs.toObject() : aboutUs;
};
// -------------------- Public exports --------------------
// Public endpoint: return AboutUs JSON (previously rendered HTML)
exports.page = async (req, res) => {
try {
const aboutUsData = await getAboutUsData();
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processed = addBaseUrlToImages(aboutUsData || {}, baseUrl);
return res.json(processed);
} catch (err) {
console.error("aboutUs.page error:", err);
return res.status(500).json({ error: "Error loading about-us data" });
}
};
// API endpoint to return aboutUs JSON
exports.api = async (req, res) => {
try {
const aboutUsData = await getAboutUsData();
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processed = addBaseUrlToImages(aboutUsData || {}, baseUrl);
return res.json(processed);
} catch (err) {
console.error("aboutUs.api error:", err);
return res.status(500).json({error: "Error loading about-us data"});
}
};
// API endpoint to return an array of AboutUs records (for frontend listing)
exports.apiList = async (req, res) => {
try {
const docs = await AboutUs.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("aboutUs.apiList error:", err);
return res.status(500).json({ error: "Error loading about-us list" });
}
};
// -------------------- Admin exports --------------------
// Display AboutUs management page
exports.index = async (req, res) => {
try {
const data = await getStoredAboutUs();
const items = await AboutUs.find().sort({updatedAt: -1}).limit(10);
res.render("admin/aboutUs/index", {
layout: "layouts/main",
title: "About Us 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 About Us data");
res.redirect("/admin/dashboard");
}
};
// Display create form
exports.createForm = async (req, res) => {
try {
const data = getDefaultAboutUsData();
res.render("admin/aboutUs/create", {
layout: "layouts/main",
title: "Create About Us",
data,
currentPath: req.path,
user: req.session.user,
});
} catch (err) {
console.error(err);
req.flash("error_msg", "Error loading create form");
res.redirect("/admin/about-us");
}
};
// Create new AboutUs record
exports.create = async (req, res) => {
try {
const aboutUsData = {
hero: JSON.parse(req.body.hero || "{}"),
introduction: JSON.parse(req.body.introduction || "{}"),
statistics: JSON.parse(req.body.statistics || "{}"),
accommodation: JSON.parse(req.body.accommodation || "{}"),
activities: JSON.parse(req.body.activities || "{}"),
newsletter: JSON.parse(req.body.newsletter || "{}"),
events: JSON.parse(req.body.events || "{}"),
};
const newAboutUs = new AboutUs(aboutUsData);
await newAboutUs.save();
req.flash("success_msg", "About Us created successfully");
res.redirect("/admin/about-us");
} catch (err) {
console.error("Create error:", err);
req.flash("error_msg", `Create error: ${err.message || "Unknown"}`);
res.redirect("/admin/about-us/create");
}
};
// Display edit form
exports.editForm = async (req, res) => {
try {
const aboutUs = await AboutUs.findById(req.params.id);
if (!aboutUs) {
req.flash("error_msg", "About Us record not found");
return res.redirect("/admin/about-us");
}
res.render("admin/aboutUs/edit", {
layout: "layouts/main",
title: "Edit About Us",
data: aboutUs.toObject ? aboutUs.toObject() : aboutUs,
currentPath: req.path,
user: req.session.user,
});
} catch (err) {
console.error(err);
req.flash("error_msg", "Error loading edit form");
res.redirect("/admin/about-us");
}
};
// Update AboutUs record
exports.update = async (req, res) => {
try {
// Get current data
const currentData = await getStoredAboutUs();
// Parse form data
const sections = [
"hero",
"introduction",
"statistics",
"accommodation",
"activities",
"newsletter",
"events",
];
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/about-us"));
}
if (!hasChanges) {
req.flash("info_msg", "No changes were made");
return req.session.save(() => res.redirect("/admin/about-us"));
}
try {
// Only update existing document; do not create a new one here
if (!currentData || !currentData._id) {
req.flash("error_msg", "No existing About Us record to update. Create one first.");
return req.session.save(() => res.redirect("/admin/about-us"));
}
await AboutUs.findByIdAndUpdate(currentData._id, updatedData, {
new: true,
});
req.flash("success_msg", "About Us data updated successfully");
return req.session.save(() => res.redirect("/admin/about-us"));
} catch (dbError) {
console.error("Database error:", dbError);
req.flash("error_msg", `Database error: ${dbError.message || "Unknown"}`);
return req.session.save(() => res.redirect("/admin/about-us"));
}
} catch (err) {
console.error("Update error:", err);
req.flash("error_msg", `Update error: ${err.message || "Unknown"}`);
return req.session.save(() => res.redirect("/admin/about-us"));
}
};
// Delete AboutUs record
exports.delete = async (req, res) => {
try {
const aboutUs = await AboutUs.findById(req.params.id);
if (!aboutUs) {
req.flash("error_msg", "About Us record not found");
return res.redirect("/admin/about-us");
}
await AboutUs.findByIdAndDelete(req.params.id);
req.flash("success_msg", "About Us record deleted successfully");
res.redirect("/admin/about-us");
} catch (err) {
console.error("Delete error:", err);
req.flash("error_msg", `Delete error: ${err.message || "Unknown"}`);
res.redirect("/admin/about-us");
}
};
// Preview AboutUs record
exports.preview = async (req, res) => {
try {
const aboutUs = await AboutUs.findById(req.params.id);
if (!aboutUs) {
return res.status(404).json({error: "About Us record not found"});
}
const processedData = addBaseUrlToImages(aboutUs.toObject());
res.json(processedData);
} catch (err) {
console.error("Preview error:", err);
res.status(500).json({error: "Error loading preview data"});
}
};