Skip to content

fix: mail template return type to Promises#458

Open
VulpritProoze wants to merge 2 commits intoPSITS-UCMAIN:stagingfrom
VulpritProoze:ram/mail-template-fix
Open

fix: mail template return type to Promises#458
VulpritProoze wants to merge 2 commits intoPSITS-UCMAIN:stagingfrom
VulpritProoze:ram/mail-template-fix

Conversation

@VulpritProoze
Copy link
Copy Markdown
Contributor

This pull request fixes the issue of not being able to synchronously track when email templates resolve. For example, when forgot password is sent, there is no way to track when that was resolved, resulting in a weird issue where success message seems to appear first before the email was actually sent.

The configuration edited in this PR is only in mail.template. Core logic for changing the handling of email template resolution will need to be changed on controllers that uses these mail templates.

Copilot AI review requested due to automatic review settings February 23, 2026 16:08
@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 23, 2026

@VulpritProoze is attempting to deploy a commit to the PSITS-UCMAIN's projects Team on Vercel.

A member of the Team first needs to authorize it.

@VulpritProoze VulpritProoze changed the base branch from master to staging February 23, 2026 16:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new/expanded client-side-ts frontend setup (UI primitives, auth route-guards, and Axios auth refresh) along with project documentation and tooling configuration.

Changes:

  • Added a large set of reusable UI primitives/components (Radix/shadcn-style) under src/components/ui.
  • Implemented frontend auth infrastructure: AuthProvider wiring, shared Axios instance with refresh-queue logic, and route guard components.
  • Added/updated project docs and developer tooling/config files (ESLint, workspace docs, structure guide).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
client-side-ts/src/components/ui/empty.tsx Adds “Empty state” UI building blocks
client-side-ts/src/components/ui/dropdown-menu.tsx Adds dropdown menu primitives based on Radix
client-side-ts/src/components/ui/drawer.tsx Adds drawer primitives (vaul)
client-side-ts/src/components/ui/dialog.tsx Adds dialog primitives based on Radix
client-side-ts/src/components/ui/context-menu.tsx Adds context menu primitives based on Radix
client-side-ts/src/components/ui/command.tsx Adds command palette primitives (cmdk + dialog)
client-side-ts/src/components/ui/collapsible.tsx Adds collapsible primitives (Radix)
client-side-ts/src/components/ui/checkbox.tsx Adds checkbox primitive (Radix)
client-side-ts/src/components/ui/chart.tsx Adds chart helpers/wrappers (Recharts)
client-side-ts/src/components/ui/carousel.tsx Adds carousel wrapper (Embla)
client-side-ts/src/components/ui/card.tsx Adds card primitives
client-side-ts/src/components/ui/calendar.tsx Adds calendar wrapper (react-day-picker)
client-side-ts/src/components/ui/button.tsx Adds button primitive + variants (CVA)
client-side-ts/src/components/ui/button-group.tsx Adds button-group wrapper components
client-side-ts/src/components/ui/breadcrumb.tsx Adds breadcrumb components
client-side-ts/src/components/ui/badge.tsx Adds badge primitive + variants (CVA)
client-side-ts/src/components/ui/avatar.tsx Adds avatar primitives (Radix)
client-side-ts/src/components/ui/aspect-ratio.tsx Adds aspect ratio primitive (Radix)
client-side-ts/src/components/ui/alert.tsx Adds alert primitive + variants (CVA)
client-side-ts/src/components/ui/alert-dialog.tsx Adds alert-dialog primitives (Radix)
client-side-ts/src/components/ui/accordion.tsx Adds accordion primitives (Radix)
client-side-ts/src/components/common/StudentCampusRouteGuard.tsx Adds student + campus constrained route guard
client-side-ts/src/components/common/RouteGuards.tsx Adds simple role-based guard wrappers
client-side-ts/src/components/common/ProtectedRoute.tsx Adds core route guard logic (auth/role/campus)
client-side-ts/src/components/common/OptimizedImage.tsx Adds optimized image component with framer-motion
client-side-ts/src/components/common/Header.tsx Adds app header/navigation component
client-side-ts/src/components/common/Footer.tsx Adds app footer component
client-side-ts/src/components/common/CampusView.tsx Adds role/campus-based conditional rendering wrapper
client-side-ts/src/components/common/BackgroundText.tsx Adds background text presentation component
client-side-ts/src/components/common/AdminCampusRouteGuard.tsx Adds admin + campus constrained route guard
client-side-ts/src/api/backendApi.ts Adds backend base URL helper
client-side-ts/src/api/axios.ts Adds shared Axios instance with token attach/refresh queue
client-side-ts/src/App.tsx Wires router + auth provider
client-side-ts/package.json Adds/updates frontend dependencies and scripts
client-side-ts/index.html Updates base HTML template
client-side-ts/eslint.config.js Adds ESLint configuration (TS + prettier)
client-side-ts/docs/AUTH_V2_FRONTEND.md Documents frontend auth usage patterns
client-side-ts/components.json Adds shadcn/ui config file
client-side-ts/README.md Adds default Vite/React template README
client-side-ts/FILE_STRUCTURE_GUIDE.md Adds repository file-structure conventions
client-side-ts/.gitignore Adds frontend gitignore entries (incl. .env)
GEMINI.md Adds workspace context documentation
.vscode/settings.json Adds editor defaults (prettier + tailwind lint settings)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client-side-ts/src/components/ui/empty.tsx
Comment thread client-side-ts/src/components/ui/carousel.tsx
Comment thread client-side-ts/src/components/ui/chart.tsx
Comment thread client-side-ts/src/components/common/ProtectedRoute.tsx
Comment thread client-side-ts/src/components/common/ProtectedRoute.tsx
Comment thread client-side-ts/src/components/common/Footer.tsx
Comment thread client-side-ts/src/components/common/OptimizedImage.tsx
Comment thread client-side-ts/src/components/common/OptimizedImage.tsx
Comment thread client-side-ts/src/components/common/OptimizedImage.tsx
Comment thread client-side-ts/src/components/common/OptimizedImage.tsx
@VulpritProoze
Copy link
Copy Markdown
Contributor Author

Pull request overview

This PR introduces a new/expanded client-side-ts frontend setup (UI primitives, auth route-guards, and Axios auth refresh) along with project documentation and tooling configuration.

Changes:

  • Added a large set of reusable UI primitives/components (Radix/shadcn-style) under src/components/ui.
  • Implemented frontend auth infrastructure: AuthProvider wiring, shared Axios instance with refresh-queue logic, and route guard components.
  • Added/updated project docs and developer tooling/config files (ESLint, workspace docs, structure guide).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
client-side-ts/src/components/ui/empty.tsx Adds “Empty state” UI building blocks
client-side-ts/src/components/ui/dropdown-menu.tsx Adds dropdown menu primitives based on Radix
client-side-ts/src/components/ui/drawer.tsx Adds drawer primitives (vaul)
client-side-ts/src/components/ui/dialog.tsx Adds dialog primitives based on Radix
client-side-ts/src/components/ui/context-menu.tsx Adds context menu primitives based on Radix
client-side-ts/src/components/ui/command.tsx Adds command palette primitives (cmdk + dialog)
client-side-ts/src/components/ui/collapsible.tsx Adds collapsible primitives (Radix)
client-side-ts/src/components/ui/checkbox.tsx Adds checkbox primitive (Radix)
client-side-ts/src/components/ui/chart.tsx Adds chart helpers/wrappers (Recharts)
client-side-ts/src/components/ui/carousel.tsx Adds carousel wrapper (Embla)
client-side-ts/src/components/ui/card.tsx Adds card primitives
client-side-ts/src/components/ui/calendar.tsx Adds calendar wrapper (react-day-picker)
client-side-ts/src/components/ui/button.tsx Adds button primitive + variants (CVA)
client-side-ts/src/components/ui/button-group.tsx Adds button-group wrapper components
client-side-ts/src/components/ui/breadcrumb.tsx Adds breadcrumb components
client-side-ts/src/components/ui/badge.tsx Adds badge primitive + variants (CVA)
client-side-ts/src/components/ui/avatar.tsx Adds avatar primitives (Radix)
client-side-ts/src/components/ui/aspect-ratio.tsx Adds aspect ratio primitive (Radix)
client-side-ts/src/components/ui/alert.tsx Adds alert primitive + variants (CVA)
client-side-ts/src/components/ui/alert-dialog.tsx Adds alert-dialog primitives (Radix)
client-side-ts/src/components/ui/accordion.tsx Adds accordion primitives (Radix)
client-side-ts/src/components/common/StudentCampusRouteGuard.tsx Adds student + campus constrained route guard
client-side-ts/src/components/common/RouteGuards.tsx Adds simple role-based guard wrappers
client-side-ts/src/components/common/ProtectedRoute.tsx Adds core route guard logic (auth/role/campus)
client-side-ts/src/components/common/OptimizedImage.tsx Adds optimized image component with framer-motion
client-side-ts/src/components/common/Header.tsx Adds app header/navigation component
client-side-ts/src/components/common/Footer.tsx Adds app footer component
client-side-ts/src/components/common/CampusView.tsx Adds role/campus-based conditional rendering wrapper
client-side-ts/src/components/common/BackgroundText.tsx Adds background text presentation component
client-side-ts/src/components/common/AdminCampusRouteGuard.tsx Adds admin + campus constrained route guard
client-side-ts/src/api/backendApi.ts Adds backend base URL helper
client-side-ts/src/api/axios.ts Adds shared Axios instance with token attach/refresh queue
client-side-ts/src/App.tsx Wires router + auth provider
client-side-ts/package.json Adds/updates frontend dependencies and scripts
client-side-ts/index.html Updates base HTML template
client-side-ts/eslint.config.js Adds ESLint configuration (TS + prettier)
client-side-ts/docs/AUTH_V2_FRONTEND.md Documents frontend auth usage patterns
client-side-ts/components.json Adds shadcn/ui config file
client-side-ts/README.md Adds default Vite/React template README
client-side-ts/FILE_STRUCTURE_GUIDE.md Adds repository file-structure conventions
client-side-ts/.gitignore Adds frontend gitignore entries (incl. .env)
GEMINI.md Adds workspace context documentation
.vscode/settings.json Adds editor defaults (prettier + tailwind lint settings)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

disregard broskie's review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • server-side/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +40 to +57
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(
`Error sending membershipRequestReceipt email for ${studentEmail}: ${error.message}`
);
resolve({
status: false,
message: `Error sending membershipRequestReceipt email for ${studentEmail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent membershipRequestReceipt email for ${studentEmail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nodemailer (since v6.0) natively supports Promises when used without a callback. You can simplify this code by removing the manual Promise wrapper and directly awaiting transporter.sendMail(mailOptions), which returns a Promise. This eliminates the need for the callback pattern and the unused reject parameter.

Suggested change
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(
`Error sending membershipRequestReceipt email for ${studentEmail}: ${error.message}`
);
resolve({
status: false,
message: `Error sending membershipRequestReceipt email for ${studentEmail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent membershipRequestReceipt email for ${studentEmail}`,
});
}
});
});
try {
await transporter.sendMail(mailOptions);
return {
status: true,
message: `Successfully sent membershipRequestReceipt email for ${studentEmail}`,
};
} catch (error: any) {
console.error(
`Error sending membershipRequestReceipt email for ${studentEmail}: ${error.message}`
);
return {
status: false,
message: `Error sending membershipRequestReceipt email for ${studentEmail}`,
};
}

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +108
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(
`Error sending orderReceipt email for ${studentEmail}: ${error.message}`
);
resolve({
status: false,
message: `Error sending orderReceipt email for ${studentEmail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent orderReceipt email for ${studentEmail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nodemailer (since v6.0) natively supports Promises when used without a callback. You can simplify this code by removing the manual Promise wrapper and directly awaiting transporter.sendMail(mailOptions), which returns a Promise. This eliminates the need for the callback pattern and the unused reject parameter.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +171
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
console.error(
`Error sending forgotPassword email for ${studentMail}: ${err.message}`
);
resolve({
status: false,
message: `Error sending forgotPassword email for ${studentMail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent forgotPassword email for ${studentMail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nodemailer (since v6.0) natively supports Promises when used without a callback. You can simplify this code by removing the manual Promise wrapper and directly awaiting transporter.sendMail(mailOptions), which returns a Promise. This eliminates the need for the callback pattern and the unused reject parameter.

Suggested change
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
console.error(
`Error sending forgotPassword email for ${studentMail}: ${err.message}`
);
resolve({
status: false,
message: `Error sending forgotPassword email for ${studentMail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent forgotPassword email for ${studentMail}`,
});
}
});
});
try {
await transporter.sendMail(mailOptions);
return {
status: true,
message: `Successfully sent forgotPassword email for ${studentMail}`,
};
} catch (err: any) {
console.error(
`Error sending forgotPassword email for ${studentMail}: ${err.message}`
);
return {
status: false,
message: `Error sending forgotPassword email for ${studentMail}`,
};
}

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +57
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(
`Error sending membershipRequestReceipt email for ${studentEmail}: ${error.message}`
);
resolve({
status: false,
message: `Error sending membershipRequestReceipt email for ${studentEmail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent membershipRequestReceipt email for ${studentEmail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Promise resolves with status:false on email sending errors instead of rejecting. This makes it impossible for callers to use try/catch blocks to handle failures properly. Additionally, the reject parameter is never used. Consider either rejecting the Promise on errors, or document that callers must check the returned status object.

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +108
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(
`Error sending orderReceipt email for ${studentEmail}: ${error.message}`
);
resolve({
status: false,
message: `Error sending orderReceipt email for ${studentEmail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent orderReceipt email for ${studentEmail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Promise resolves with status:false on email sending errors instead of rejecting. This makes it impossible for callers to use try/catch blocks to handle failures properly. Additionally, the reject parameter is never used. Consider either rejecting the Promise on errors, or document that callers must check the returned status object.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +171
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
console.error(
`Error sending forgotPassword email for ${studentMail}: ${err.message}`
);
resolve({
status: false,
message: `Error sending forgotPassword email for ${studentMail}`,
});
} else {
resolve({
status: true,
message: `Successfully sent forgotPassword email for ${studentMail}`,
});
}
});
});
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Promise resolves with status:false on email sending errors instead of rejecting. This makes it impossible for callers to use try/catch blocks to handle failures properly. Additionally, the reject parameter is never used. Consider either rejecting the Promise on errors, or document that callers must check the returned status object.

Copilot uses AI. Check for mistakes.
@VulpritProoze VulpritProoze changed the title Fix: mail template return type to Promises fix: mail template return type to Promises Feb 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants