Files
cms.uldp.edu.vn/controllers/insuranceController.js
r2xrzh9q2z-lab d1b931d547 first commit
2026-02-02 11:07:09 +07:00

496 lines
14 KiB
JavaScript

const Insurance = require("../models/insurance");
const { addBaseUrlToImages } = require("../utils/imageHelper");
// API để lấy insurance data (cho frontend)
exports.api = async (req, res) => {
try {
const language = req.query.lang || "en";
// Sử dụng getDefault để đảm bảo luôn có data
const insurance = await Insurance.getDefault(language);
// Trả về data với cấu trúc mới
const insuranceData = insurance.toObject();
// Sử dụng helper để thêm base URL vào đường dẫn ảnh
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processedData = addBaseUrlToImages(insuranceData, baseUrl);
// Trả về trực tiếp hero, page, content (không wrap trong object)
res.json({
hero: processedData.hero,
page: processedData.page,
content: processedData.content
});
} catch (error) {
console.error("API Error:", error);
res.status(500).json({
success: false,
error: "Error loading insurance data",
message: error.message
});
}
};
// API để lấy toàn bộ insurance data (cho admin)
exports.getInsuranceData = async (req, res) => {
try {
const language = req.query.lang || "en";
const insurance = await Insurance.findOne({ name: "default", language: language });
if (!insurance) {
return res.status(404).json({
success: false,
error: "Insurance data not found"
});
}
const insuranceData = insurance.toObject();
// Thêm base URL vào đường dẫn ảnh
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processedData = addBaseUrlToImages(insuranceData, baseUrl);
res.json({
success: true,
data: processedData
});
} catch (error) {
console.error("Error getting insurance data:", error);
res.status(500).json({
success: false,
error: "Error loading insurance data"
});
}
};
// API để lấy data theo ngôn ngữ
exports.getByLanguage = async (req, res) => {
try {
const language = req.params.lang || "en";
const insurance = await Insurance.findOne({ name: "default", language: language });
if (!insurance) {
return res.status(404).json({
success: false,
error: "Insurance data not found"
});
}
const insuranceData = insurance.toObject();
// Thêm base URL vào đường dẫn ảnh
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processedData = addBaseUrlToImages(insuranceData, baseUrl);
res.json({
success: true,
data: {
hero: processedData.hero,
page: processedData.page,
content: processedData.content
}
});
} catch (error) {
console.error("Error getting insurance by language:", error);
res.status(500).json({
success: false,
error: "Error loading insurance data"
});
}
};
// Render admin view
exports.index = async (req, res) => {
try {
// Luôn đảm bảo có default data
const insurance = await Insurance.getDefault("en");
const data = insurance.toObject();
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
res.render("admin/insurance/index", {
title: "Insurance Management",
layout: "layouts/main",
data,
frontendUrl,
currentPath: req.path,
user: req.session.user
});
} catch (error) {
console.error("Error in insurance index:", error);
req.flash("error_msg", "An error occurred while loading the page");
res.redirect("/admin/dashboard");
}
};
// Seed data từ JSON file (cấu trúc mới)
exports.seed = async (req, res) => {
try {
const fs = require('fs').promises;
const path = require('path');
// Đọc file JSON
const jsonPath = path.join(__dirname, '../data/insurance.json');
const jsonData = JSON.parse(await fs.readFile(jsonPath, 'utf8'));
console.log('Seeding insurance from JSON...');
// Migrate từ cấu trúc cũ sang mới
const insurance = await Insurance.migrateFromJson(jsonData, "en");
res.json({
success: true,
message: "Insurance data seeded successfully",
data: {
id: insurance._id,
hero: insurance.hero,
page: insurance.page,
content: insurance.content
}
});
} catch (error) {
console.error("Error seeding insurance:", error);
res.status(500).json({
success: false,
error: error.message || "Error seeding insurance data"
});
}
};
// API preview cho admin (tạo HTML preview)
exports.preview = async (req, res) => {
try {
const { hero, page, content } = req.body;
// Parse JSON strings
const parseJson = (data) => {
if (!data) return null;
if (typeof data === "string") {
try {
return JSON.parse(data);
} catch (e) {
console.error("JSON parse error:", e);
return null;
}
}
return data;
};
const heroData = parseJson(hero) || {};
const pageData = parseJson(page) || {};
const contentData = parseJson(content) || {};
// Thêm base URL vào đường dẫn ảnh cho preview
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const processedHeroData = addBaseUrlToImages(heroData, baseUrl);
// Render preview HTML
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${pageData.title || 'Insurance Preview'}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Arial, sans-serif; }
.hero-section {
background: linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)),
url('${processedHeroData.backgroundImage || ''}');
background-size: cover;
background-position: center;
color: white;
padding: 100px 20px;
text-align: center;
}
.page-header {
padding: 40px 20px;
background: #f8f9fa;
}
.content-section {
padding: 40px 20px;
}
.content-item {
margin-bottom: 20px;
}
</style>
</head>
<body>
<!-- Hero Section -->
<div class="hero-section">
<h1>${heroData.title || 'Insurance'}</h1>
<p>${heroData.subtitle || ''}</p>
</div>
<!-- Page Header -->
<div class="page-header">
<div class="container">
<h2>${pageData.title || 'Insurance Information'}</h2>
${pageData.divider !== false ? '<hr>' : ''}
</div>
</div>
<!-- Content Section -->
<div class="content-section">
<div class="container">
${renderContentItems(contentData.content || [])}
</div>
</div>
</body>
</html>
`;
res.send(html);
} catch (error) {
console.error("Error generating preview:", error);
res.status(500).send("Error generating preview");
}
};
// Helper function để render content items
function renderContentItems(contentItems) {
if (!Array.isArray(contentItems) || contentItems.length === 0) {
return '<p>No content available.</p>';
}
return contentItems.map(item => {
switch (item.type) {
case 'header':
return `<h${item.level || 2} class="content-item">${item.text}</h${item.level || 2}>`;
case 'paragraph':
return `<p class="content-item">${item.text}</p>`;
case 'section':
return `
<div class="content-item">
<h3>${item.title}</h3>
<p>${item.content}</p>
</div>
`;
case 'list':
const listItems = (item.items || []).map(li => `<li>${li}</li>`).join('');
return `<ul class="content-item">${listItems}</ul>`;
case 'note':
return `<div class="alert alert-info content-item">${item.text}</div>`;
case 'embed':
if (item.source === 'youtube') {
return `
<div class="content-item">
<iframe width="${item.width || 560}" height="${item.height || 315}"
src="${item.url || item.embed}"
frameborder="0" allowfullscreen></iframe>
${item.caption ? `<p class="text-muted mt-2">${item.caption}</p>` : ''}
</div>
`;
}
return '';
default:
return '';
}
}).join('');
}
// API để tạo insurance mới (cho các ngôn ngữ khác)
exports.create = async (req, res) => {
try {
const { hero, page, content, language } = req.body;
if (!language) {
return res.status(400).json({
success: false,
error: "Language is required"
});
}
// Kiểm tra đã tồn tại chưa
const existing = await Insurance.findOne({ name: "default", language: language });
if (existing) {
return res.status(400).json({
success: false,
error: "Insurance already exists for this language"
});
}
// Parse JSON nếu cần
const parseJson = (data) => {
if (!data) return null;
if (typeof data === "string") {
try {
return JSON.parse(data);
} catch (e) {
console.error("JSON parse error:", e);
return null;
}
}
return data;
};
const insurance = new Insurance({
name: "default",
language: language,
hero: parseJson(hero) || {},
page: parseJson(page) || {},
content: parseJson(content) || {},
version: "2.0.0",
isActive: true,
migratedFromOldStructure: false
});
await insurance.save();
res.json({
success: true,
message: "Insurance created successfully for language: " + language,
data: insurance
});
} catch (error) {
console.error("Error creating insurance:", error);
res.status(500).json({
success: false,
error: error.message || "Error creating insurance"
});
}
};
// Cập nhật dữ liệu insurance (CẬP NHẬT CẤU TRÚC MỚI)
exports.update = async (req, res) => {
try {
const { hero, page, content } = req.body;
// Parse JSON strings
const parseJson = (data) => {
if (!data) return null;
if (typeof data === "string") {
try {
return JSON.parse(data);
} catch (e) {
console.error("JSON parse error:", e);
return null;
}
}
return data;
};
// Parse all data với cấu trúc mới
const heroData = parseJson(hero) || {};
const pageData = parseJson(page) || {};
const contentData = parseJson(content) || {};
// Normalize embed blocks (convert YouTube watch URLs to /embed/ URLs)
function extractYouTubeId(url) {
const regex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/;
const match = url.match(regex);
return match ? match[1] : null;
}
if (contentData && Array.isArray(contentData.content)) {
contentData.content.forEach(item => {
if (item.type === 'embed' && item.source === 'youtube') {
if (item.url && item.url.includes('watch?v=')) {
const videoId = extractYouTubeId(item.url);
if (videoId) {
item.url = `https://www.youtube.com/embed/${videoId}`;
item.videoId = videoId;
}
}
if (item.embed && item.embed.includes('watch?v=')) {
const videoId = extractYouTubeId(item.embed);
if (videoId) {
item.embed = `https://www.youtube.com/embed/${videoId}`;
item.videoId = videoId;
}
}
}
});
}
// Tìm hoặc tạo insurance
let insurance = await Insurance.findOne({ name: "default", language: "en" });
if (!insurance) {
insurance = new Insurance({
name: "default",
language: "en",
hero: heroData,
page: pageData,
content: contentData,
version: "2.0.0",
isActive: true
});
} else {
insurance.hero = heroData;
insurance.page = pageData;
insurance.content = contentData;
insurance.version = "2.0.0";
}
await insurance.save();
req.flash("success_msg", "Insurance updated successfully");
res.redirect("/admin/insurance");
} catch (err) {
console.error("Error updating insurance:", err);
req.flash("error_msg", err.message || "Error updating insurance");
res.redirect("/admin/insurance");
}
};
// API để xóa insurance (theo ngôn ngữ)
exports.delete = async (req, res) => {
try {
const language = req.params.lang;
if (!language) {
return res.status(400).json({
success: false,
error: "Language parameter is required"
});
}
// Không cho phép xóa tiếng Anh mặc định
if (language === "en") {
return res.status(400).json({
success: false,
error: "Cannot delete default English insurance data"
});
}
const result = await Insurance.deleteOne({ name: "default", language: language });
if (result.deletedCount === 0) {
return res.status(404).json({
success: false,
error: "Insurance not found for this language"
});
}
res.json({
success: true,
message: "Insurance deleted successfully for language: " + language
});
} catch (error) {
console.error("Error deleting insurance:", error);
res.status(500).json({
success: false,
error: error.message || "Error deleting insurance"
});
}
};