Compare commits

...

5 Commits

7 changed files with 306 additions and 85 deletions
@@ -35,17 +35,72 @@ export const createAcademicsResearch = async (req, res) => {
to: emailList,
subject: "New Academics & Research Inquiry",
html: `
<h2>New Academics & Research Inquiry</h2>
<div style="font-family: Arial, sans-serif; background-color: #f4f6f8; padding: 20px;">
<p><b>Name:</b> ${fullName}</p>
<p><b>Phone:</b> ${number}</p>
<p><b>Email:</b> ${emailId || "-"}</p>
<div style="max-width: 600px; margin: auto; background: #ffffff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.05);">
<p><b>Course:</b> ${courseName || "-"}</p>
<p><b>Subject:</b> ${subject || "-"}</p>
<!-- Header -->
<div style="background-color: #0d6efd; color: #ffffff; padding: 20px;">
<h2 style="margin: 0;">GG Hospital</h2>
<p style="margin: 5px 0 0; font-size: 14px;">
New Academics & Research Inquiry
</p>
</div>
<p><b>Message:</b></p>
<p>${message || "-"}</p>
<!-- Body -->
<div style="padding: 20px; color: #333;">
<h3 style="margin-top: 0;">Contact Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Name:</b></td>
<td style="padding: 8px 0;">${fullName}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Phone:</b></td>
<td style="padding: 8px 0;">${number}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Email:</b></td>
<td style="padding: 8px 0;">${emailId || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Course:</b></td>
<td style="padding: 8px 0;">${courseName || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Subject:</b></td>
<td style="padding: 8px 0;">${subject || "-"}</td>
</tr>
</table>
<!-- Message Box -->
<div style="margin-top: 20px;">
<h3>Message</h3>
<div style="
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
">
${message ? message.replace(/\n/g, "<br/>") : "-"}
</div>
</div>
</div>
<!-- Footer -->
<div style="background: #f1f1f1; padding: 15px; text-align: center; font-size: 12px; color: #666;">
This message was sent from the GG Hospital website (Academics & Research Inquiry).
</div>
</div>
</div>
`,
});
}
@@ -38,14 +38,83 @@ export const createAppointment = async (req, res) => {
to: emailList,
subject: "New Appointment Booked",
html: `
<h2>New Appointment Booked</h2>
<p><b>Name:</b> ${name}</p>
<p><b>Phone:</b> ${mobileNumber}</p>
<p><b>Email:</b> ${email || "-"}</p>
<p><b>Doctor:</b> ${appointment.doctor?.name}</p>
<p><b>Department:</b> ${appointment.department?.name}</p>
<p><b>Date:</b> ${new Date(date).toLocaleDateString()}</p>
<p><b>Message:</b> ${message || "-"}</p>
<div style="font-family: Arial, sans-serif; background-color: #f4f6f8; padding: 20px;">
<div style="max-width: 600px; margin: auto; background: #ffffff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.05);">
<!-- Header -->
<div style="background-color: #0d6efd; color: #ffffff; padding: 20px;">
<h2 style="margin: 0;">GG Hospital</h2>
<p style="margin: 5px 0 0; font-size: 14px;">
New Appointment Booked
</p>
</div>
<!-- Body -->
<div style="padding: 20px; color: #333;">
<h3 style="margin-top: 0;">Patient Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Name:</b></td>
<td style="padding: 8px 0;">${name}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Phone:</b></td>
<td style="padding: 8px 0;">${mobileNumber}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Email:</b></td>
<td style="padding: 8px 0;">${email || "-"}</td>
</tr>
</table>
<h3 style="margin-top: 20px;">Appointment Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Doctor:</b></td>
<td style="padding: 8px 0;">${appointment.doctor?.name || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Department:</b></td>
<td style="padding: 8px 0;">${appointment.department?.name || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Date:</b></td>
<td style="padding: 8px 0;">
${new Date(date).toLocaleDateString()}
</td>
</tr>
</table>
<!-- Message Box -->
<div style="margin-top: 20px;">
<h3>Message</h3>
<div style="
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
">
${message ? message.replace(/\n/g, "<br/>") : "-"}
</div>
</div>
</div>
<!-- Footer -->
<div style="background: #f1f1f1; padding: 15px; text-align: center; font-size: 12px; color: #666;">
This appointment was booked via the GG Hospital website.
</div>
</div>
</div>
`,
});
}
@@ -39,18 +39,81 @@ export const createCandidate = async (req, res) => {
to: emailList,
subject: "New Job Application Received",
html: `
<h2>New Candidate Application</h2>
<div style="font-family: Arial, sans-serif; background-color: #f4f6f8; padding: 20px;">
<p><b>Name:</b> ${fullName}</p>
<p><b>Phone:</b> ${mobile}</p>
<p><b>Email:</b> ${email}</p>
<div style="max-width: 600px; margin: auto; background: #ffffff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.05);">
<p><b>Applied For:</b> ${candidate.career?.post || "-"}</p>
<p><b>Designation:</b> ${candidate.career?.designation || "-"}</p>
<!-- Header -->
<div style="background-color: #0d6efd; color: #ffffff; padding: 20px;">
<h2 style="margin: 0;">GG Hospital</h2>
<p style="margin: 5px 0 0; font-size: 14px;">
New Job Application Received
</p>
</div>
<p><b>Subject:</b> ${subject || "-"}</p>
<p><b>Cover Letter:</b></p>
<p>${coverLetter || "-"}</p>
<!-- Body -->
<div style="padding: 20px; color: #333;">
<h3 style="margin-top: 0;">Candidate Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Name:</b></td>
<td style="padding: 8px 0;">${fullName}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Phone:</b></td>
<td style="padding: 8px 0;">${mobile}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Email:</b></td>
<td style="padding: 8px 0;">${email}</td>
</tr>
</table>
<h3 style="margin-top: 20px;">Application Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Applied For:</b></td>
<td style="padding: 8px 0;">${candidate.career?.post || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Designation:</b></td>
<td style="padding: 8px 0;">${candidate.career?.designation || "-"}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Subject:</b></td>
<td style="padding: 8px 0;">${subject || "-"}</td>
</tr>
</table>
<!-- Cover Letter -->
<div style="margin-top: 20px;">
<h3>Cover Letter</h3>
<div style="
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
">
${coverLetter ? coverLetter.replace(/\n/g, "<br/>") : "-"}
</div>
</div>
</div>
<!-- Footer -->
<div style="background: #f1f1f1; padding: 15px; text-align: center; font-size: 12px; color: #666;">
This application was submitted via the GG Hospital careers page.
</div>
</div>
</div>
`,
});
}
+58 -6
View File
@@ -32,14 +32,66 @@ export const createInquiry = async (req, res) => {
to: emailList,
subject: "New Inquiry Received",
html: `
<h2>New Inquiry</h2>
<div style="font-family: Arial, sans-serif; background-color: #f4f6f8; padding: 20px;">
<p><b>Name:</b> ${fullName}</p>
<p><b>Phone:</b> ${number}</p>
<p><b>Email:</b> ${emailId}</p>
<div style="max-width: 600px; margin: auto; background: #ffffff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.05);">
<p><b>Subject:</b> ${subject}</p>
<p><b>Message:</b> ${message}</p>
<!-- Header -->
<div style="background-color: #0d6efd; color: #ffffff; padding: 20px;">
<h2 style="margin: 0;">GG Hospital</h2>
<p style="margin: 5px 0 0; font-size: 14px;">New Inquiry Received</p>
</div>
<!-- Body -->
<div style="padding: 20px; color: #333;">
<h3 style="margin-top: 0;">Contact Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Name:</b></td>
<td style="padding: 8px 0;">${fullName}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Phone:</b></td>
<td style="padding: 8px 0;">${number}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Email:</b></td>
<td style="padding: 8px 0;">${emailId}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Subject:</b></td>
<td style="padding: 8px 0;">${subject}</td>
</tr>
</table>
<!-- Message Box -->
<div style="margin-top: 20px;">
<h3>Message</h3>
<div style="
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
">
${message ? message.replace(/\n/g, "<br/>") : "-"}
</div>
</div>
</div>
<!-- Footer -->
<div style="background: #f1f1f1; padding: 15px; text-align: center; font-size: 12px; color: #666;">
This message was sent from the GG Hospital website contact form.
</div>
</div>
</div>
`,
});
}
+22 -36
View File
@@ -4,53 +4,40 @@ import prisma from "../prisma/client.js";
export const getAllNews = async (req, res) => {
try {
const page = parseInt(req.query.page);
const limit = parseInt(req.query.limit);
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const search = req.query.search?.trim() || "";
const includeImages = {
images: true,
};
if (!page && !limit) {
const news = await prisma.newsMedia.findMany({
include: includeImages,
orderBy: { createdAt: "desc" },
});
const response = news.map((n) => ({
Id: n.id.toString(),
Headline: n.headline,
Content: n.content,
FirstPara: n.firstPara,
SecondPara: n.secondPara,
Date: n.date,
Author: n.author,
Images: n.images.map((img) => ({
id: img.id,
image: img.url,
})),
}));
return res.status(200).json({
success: true,
data: response,
meta: null,
});
const searchFilter = search
? {
headline: {
contains: search,
mode: "insensitive",
},
}
: {};
const currentPage = page || 1;
const currentLimit = limit || 10;
const whereCondition = {
...searchFilter,
};
const skip = (currentPage - 1) * currentLimit;
const skip = (page - 1) * limit;
const [news, total] = await Promise.all([
prisma.newsMedia.findMany({
where: whereCondition,
include: includeImages,
orderBy: { createdAt: "desc" },
skip,
take: currentLimit,
take: limit,
}),
prisma.newsMedia.count({
where: whereCondition,
}),
prisma.newsMedia.count(),
]);
const response = news.map((n) => ({
@@ -72,9 +59,9 @@ export const getAllNews = async (req, res) => {
data: response,
meta: {
total,
page: currentPage,
limit: currentLimit,
totalPages: Math.ceil(total / currentLimit),
page,
limit,
totalPages: Math.ceil(total / limit),
},
});
} catch (error) {
@@ -85,7 +72,6 @@ export const getAllNews = async (req, res) => {
});
}
};
// GET NEWS BY ID
export const getNewsById = async (req, res) => {
+2 -2
View File
@@ -1,8 +1,8 @@
import apiClient from "@/api/client";
export const getNewsApi = async (page = 1, limit = 10) => {
export const getNewsApi = async (page = 1, limit = 10, search = "") => {
const res = await apiClient.get(
`/newsMedia/getAll?page=${page}&limit=${limit}`,
`/newsMedia/getAll?page=${page}&limit=${limit}&search=${search}`,
);
return res.data;
};
+8 -12
View File
@@ -73,7 +73,7 @@ export default function NewsPage() {
const fetchAll = useCallback(async () => {
setLoading(true);
try {
const res = await getNewsApi(currentPage, itemsPerPage);
const res = await getNewsApi(currentPage, itemsPerPage, searchText);
setNews(res?.data || []);
setTotalItems(res?.meta?.total || 0);
@@ -82,18 +82,12 @@ export default function NewsPage() {
} finally {
setLoading(false);
}
}, [currentPage, itemsPerPage]);
}, [currentPage, itemsPerPage, searchText]);
useEffect(() => {
fetchAll();
}, [fetchAll]);
const filteredNews = news.filter(
(item) =>
item.Headline?.toLowerCase().includes(searchText.toLowerCase()) ||
item.Author?.toLowerCase().includes(searchText.toLowerCase()),
);
const totalPages = Math.ceil(totalItems / itemsPerPage);
function handleChange(e: any) {
@@ -171,8 +165,10 @@ export default function NewsPage() {
<Input
placeholder="Filter headline..."
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
className="w-[250px] text-base"
onChange={(e) => {
setSearchText(e.target.value);
setCurrentPage(1); // reset page
}}
/>
<select
@@ -246,7 +242,7 @@ export default function NewsPage() {
<Loader2 className="h-8 w-8 animate-spin mx-auto text-primary" />
</TableCell>
</TableRow>
) : filteredNews.length === 0 ? (
) : news.length === 0 ? (
<TableRow>
<TableCell
colSpan={7}
@@ -256,7 +252,7 @@ export default function NewsPage() {
</TableCell>
</TableRow>
) : (
filteredNews.map((item) => (
news.map((item) => (
<TableRow key={item.Id} className="hover:bg-muted/50">
<TableCell className="font-mono text-xs">
{item.Id}