forked from UKSOURCE/cms.hailearning.edu.vn
feat: Implement core admin panel functionalities including appointment, contact, and pricing management with associated models, controllers, views, and routes.
This commit is contained in:
193
controllers/pricingController.js
Normal file
193
controllers/pricingController.js
Normal file
@@ -0,0 +1,193 @@
|
||||
const Pricing = require("../models/pricing");
|
||||
|
||||
// ==================== CMS ADMIN FUNCTIONS ====================
|
||||
|
||||
// Render admin page for pricing management
|
||||
exports.index = async (req, res) => {
|
||||
try {
|
||||
let pricing = await Pricing.findOne({ name: "default" });
|
||||
|
||||
// If no data in DB, try to load from JSON file
|
||||
if (!pricing) {
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const jsonPath = path.join(__dirname, "../data/pricing.json");
|
||||
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
const jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
|
||||
pricing = await Pricing.migrateFromJson(jsonData);
|
||||
} else {
|
||||
// Create default pricing
|
||||
pricing = await Pricing.create({
|
||||
name: "default",
|
||||
hero: {
|
||||
title: "Pricing Plan",
|
||||
backgroundImage: "/assets/img/inner-page/breadcrumb.jpg",
|
||||
shapeImage: "/assets/img/inner-page/shape.png",
|
||||
breadcrumb: [
|
||||
{ text: "Home", link: "/" },
|
||||
{ text: "Pricing Plan", link: "" },
|
||||
],
|
||||
},
|
||||
pricingSection: {
|
||||
subtitle: "pricing plan",
|
||||
heading: "Flexible Plans to Suit Every Traveler",
|
||||
description: "Choose the plan that fits your visa needs and enjoy expert guidance every step of the way.",
|
||||
},
|
||||
plans: {
|
||||
monthly: [],
|
||||
yearly: [],
|
||||
},
|
||||
testimonials: {
|
||||
subtitle: "What Our Clients Say",
|
||||
heading: "Immigration Success Stories",
|
||||
buttonText: "View All Review",
|
||||
buttonLink: "/contact",
|
||||
buttonIcon: "fa-solid fa-arrow-right",
|
||||
image: "",
|
||||
items: [],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.render("admin/pricing/index", {
|
||||
layout: "layouts/main",
|
||||
title: "Pricing Management",
|
||||
data: pricing,
|
||||
user: req.session.user,
|
||||
frontendUrl: process.env.FRONTEND_URL || "http://localhost:3000",
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error loading pricing admin page:", err);
|
||||
req.flash("error", "Error loading pricing data");
|
||||
res.redirect("/admin/dashboard");
|
||||
}
|
||||
};
|
||||
|
||||
// Update pricing data
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const { hero, pricingSection, plans, testimonials } = req.body;
|
||||
|
||||
// Parse JSON strings if needed
|
||||
const heroData = typeof hero === "string" ? JSON.parse(hero) : hero;
|
||||
const pricingSectionData = typeof pricingSection === "string" ? JSON.parse(pricingSection) : pricingSection;
|
||||
const plansData = typeof plans === "string" ? JSON.parse(plans) : plans;
|
||||
const testimonialsData = typeof testimonials === "string" ? JSON.parse(testimonials) : testimonials;
|
||||
|
||||
let pricing = await Pricing.findOne({ name: "default" });
|
||||
|
||||
if (pricing) {
|
||||
pricing.hero = heroData;
|
||||
pricing.pricingSection = pricingSectionData;
|
||||
pricing.plans = plansData;
|
||||
pricing.testimonials = testimonialsData;
|
||||
await pricing.save();
|
||||
} else {
|
||||
pricing = await Pricing.create({
|
||||
name: "default",
|
||||
hero: heroData,
|
||||
pricingSection: pricingSectionData,
|
||||
plans: plansData,
|
||||
testimonials: testimonialsData,
|
||||
});
|
||||
}
|
||||
|
||||
req.flash("success", "Pricing data updated successfully");
|
||||
res.redirect("/admin/pricing");
|
||||
} catch (err) {
|
||||
console.error("Error updating pricing:", err);
|
||||
req.flash("error", "Error updating pricing data");
|
||||
res.redirect("/admin/pricing");
|
||||
}
|
||||
};
|
||||
|
||||
// API to get pricing data (admin)
|
||||
exports.getPricingData = async (req, res) => {
|
||||
try {
|
||||
let pricing = await Pricing.findOne({ name: "default" });
|
||||
|
||||
if (!pricing) {
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const jsonPath = path.join(__dirname, "../data/pricing.json");
|
||||
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
const jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
|
||||
pricing = await Pricing.migrateFromJson(jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: pricing,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error getting pricing data:", err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: "Error loading pricing data",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Public API to get pricing page data (for frontend)
|
||||
exports.api = async (req, res) => {
|
||||
try {
|
||||
let pricing = await Pricing.findOne({ name: "default" });
|
||||
|
||||
if (!pricing) {
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const jsonPath = path.join(__dirname, "../data/pricing.json");
|
||||
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
const jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
|
||||
pricing = await Pricing.migrateFromJson(jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pricing) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: "Pricing data not found",
|
||||
});
|
||||
}
|
||||
|
||||
const backendUrl = process.env.BACKEND_URL || "http://localhost:3001";
|
||||
|
||||
const getFullUrl = (path) => {
|
||||
if (!path || path.startsWith("http")) return path;
|
||||
return `${backendUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
||||
};
|
||||
|
||||
// Convert to plain object to modify properties safely
|
||||
const pricingData = pricing.toObject ? pricing.toObject() : pricing;
|
||||
|
||||
if (pricingData.hero) {
|
||||
pricingData.hero.backgroundImage = getFullUrl(pricingData.hero.backgroundImage);
|
||||
pricingData.hero.shapeImage = getFullUrl(pricingData.hero.shapeImage);
|
||||
}
|
||||
|
||||
if (pricingData.testimonials) {
|
||||
pricingData.testimonials.image = getFullUrl(pricingData.testimonials.image);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
hero: pricingData.hero,
|
||||
pricingSection: pricingData.pricingSection,
|
||||
plans: pricingData.plans,
|
||||
testimonials: pricingData.testimonials,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error getting pricing API data:", err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: "Error loading pricing data",
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user