mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
ready to test
Testing Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
/***********************************************************************************************************************************************************************
|
||||
* File Name: achievements.data.js
|
||||
* Type of Program: Data
|
||||
* Description: Static registry of all available achievements (badges and milestones).
|
||||
* Add a new achievement here — no other code changes needed.
|
||||
*
|
||||
* Available keys:
|
||||
* Badge:
|
||||
* early_access — registered before Dec 31, 2026
|
||||
* premium_first_time — first premium tier purchase
|
||||
* exclusive_first_time — first exclusive tier purchase
|
||||
* Milestone:
|
||||
* first_course_completed — completed first course
|
||||
* courses_completed_5 — completed 5 courses
|
||||
* courses_completed_10 — completed 10 courses
|
||||
* perfect_quiz_score — perfect score on a quiz
|
||||
* profile_completed — filled out full profile
|
||||
* first_referral — referred a user
|
||||
*
|
||||
* Author: Kenneth Obsequio (@lash0000)
|
||||
* Date Created: Jun. 19, 2026
|
||||
***********************************************************************************************************************************************************************/
|
||||
'use strict';
|
||||
|
||||
// ─── Early Access cutoff ──────────────────────────────────────────────────────
|
||||
|
||||
const EARLY_ACCESS_CUTOFF = new Date('2026-12-31T23:59:59Z');
|
||||
|
||||
// ─── Achievement Registry ─────────────────────────────────────────────────────
|
||||
// To add a new achievement — add an entry here. No other code changes needed.
|
||||
//
|
||||
// trigger categories (for documentation only, not enforced):
|
||||
// auth — registration / login events
|
||||
// tier — subscription purchase events
|
||||
// course — course / lesson / quiz events
|
||||
// profile — profile completion events
|
||||
// social — referral / community events
|
||||
|
||||
const ACHIEVEMENT_REGISTRY = {
|
||||
|
||||
// ── Auth ───────────────────────────────────────────────────────────────────
|
||||
early_access: {
|
||||
key: 'early_access',
|
||||
type: 'badge',
|
||||
label: 'Early Access',
|
||||
description: 'Registered during the Philproperties beta period (before Dec 31, 2026).',
|
||||
trigger: 'auth',
|
||||
},
|
||||
|
||||
// ── Tier ───────────────────────────────────────────────────────────────────
|
||||
premium_first_time: {
|
||||
key: 'premium_first_time',
|
||||
type: 'badge',
|
||||
label: 'Premium Member',
|
||||
description: 'Purchased a Premium tier plan for the first time.',
|
||||
trigger: 'tier',
|
||||
},
|
||||
exclusive_first_time: {
|
||||
key: 'exclusive_first_time',
|
||||
type: 'badge',
|
||||
label: 'Exclusive Member',
|
||||
description: 'Purchased an Exclusive tier plan for the first time.',
|
||||
trigger: 'tier',
|
||||
},
|
||||
|
||||
// ── Course ─────────────────────────────────────────────────────────────────
|
||||
first_course_completed: {
|
||||
key: 'first_course_completed',
|
||||
type: 'milestone',
|
||||
label: 'First Course Completed',
|
||||
description: 'Completed your very first course on Philproperties.',
|
||||
trigger: 'course',
|
||||
},
|
||||
courses_completed_5: {
|
||||
key: 'courses_completed_5',
|
||||
type: 'milestone',
|
||||
label: 'Learning Streak',
|
||||
description: 'Completed 5 courses.',
|
||||
trigger: 'course',
|
||||
},
|
||||
courses_completed_10: {
|
||||
key: 'courses_completed_10',
|
||||
type: 'milestone',
|
||||
label: 'Knowledge Builder',
|
||||
description: 'Completed 10 courses.',
|
||||
trigger: 'course',
|
||||
},
|
||||
perfect_quiz_score: {
|
||||
key: 'perfect_quiz_score',
|
||||
type: 'milestone',
|
||||
label: 'Perfect Score',
|
||||
description: 'Achieved a perfect score on a quiz.',
|
||||
trigger: 'course',
|
||||
},
|
||||
|
||||
// ── Profile ────────────────────────────────────────────────────────────────
|
||||
profile_completed: {
|
||||
key: 'profile_completed',
|
||||
type: 'milestone',
|
||||
label: 'Profile Complete',
|
||||
description: 'Filled out all personal profile information.',
|
||||
trigger: 'profile',
|
||||
},
|
||||
|
||||
// ── Social ─────────────────────────────────────────────────────────────────
|
||||
first_referral: {
|
||||
key: 'first_referral',
|
||||
type: 'milestone',
|
||||
label: 'Referral Champion',
|
||||
description: 'Successfully referred a user to Philproperties.',
|
||||
trigger: 'social',
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
EARLY_ACCESS_CUTOFF,
|
||||
ACHIEVEMENT_REGISTRY,
|
||||
};
|
||||
+47
-74
@@ -1,116 +1,89 @@
|
||||
const CLOSING = `Regards,\nPhilproperties IT Team\n\nThis is an automated message from STARR System. Please do not reply.`;
|
||||
|
||||
const build = (body) => `${body.trim()}\n\n${CLOSING}`;
|
||||
|
||||
export const emailTemplates = {
|
||||
OTP: ({ otp, expiryMinutes = 10 }) => ({
|
||||
subject: "Email OTP Verification - STARR System",
|
||||
title: "Email Verification",
|
||||
body: `
|
||||
<p>Dear User,</p>
|
||||
text: build(`
|
||||
Dear User,
|
||||
|
||||
<p>Please use the One-Time Password (OTP) below to verify your email address.
|
||||
This code is valid for <strong>${expiryMinutes} minutes</strong>.</p>
|
||||
Please use the One-Time Password (OTP) below to verify your email address. This code is valid for ${expiryMinutes} minutes.
|
||||
|
||||
<div style="margin:24px 0;font-size:32px;font-weight:bold;letter-spacing:8px;text-align:center;color:#1d4ed8">
|
||||
${otp}
|
||||
</div>
|
||||
${otp}
|
||||
|
||||
<p style="font-size:13px;color:#6b7280">
|
||||
For security reasons, please do not share this code with anyone.
|
||||
If you did not request this, please contact the administrator.
|
||||
</p>
|
||||
`,
|
||||
For security reasons, please do not share this code with anyone. If you did not request this, please contact the administrator.
|
||||
`),
|
||||
}),
|
||||
|
||||
WELCOME: ({ name }) => ({
|
||||
subject: "Welcome to STARR System",
|
||||
title: `Welcome Aboard!`,
|
||||
body: `
|
||||
<p>Dear ${name},</p>
|
||||
text: build(`
|
||||
Dear ${name},
|
||||
|
||||
<p>We are pleased to welcome you to the STARR System. Your account has been successfully created and is now ready for use.</p>
|
||||
We are pleased to welcome you to the STARR System. Your account has been successfully created and is now ready for use.
|
||||
|
||||
<p>You may now access your dashboard and begin using the available services.</p>
|
||||
You may now access your dashboard and begin using the available services.
|
||||
|
||||
<p style="margin-top:16px">We look forward to supporting you.</p>
|
||||
`,
|
||||
We look forward to supporting you.
|
||||
`),
|
||||
}),
|
||||
|
||||
PASSWORD_CHANGED: () => ({
|
||||
subject: "Password Update Confirmation - STARR System",
|
||||
title: "Password Successfully Updated",
|
||||
body: `
|
||||
<p>Dear User,</p>
|
||||
text: build(`
|
||||
Dear User,
|
||||
|
||||
<p>This is to confirm that your account password has been successfully changed.</p>
|
||||
This is to confirm that your account password has been successfully changed.
|
||||
|
||||
<p>If you did not perform this action, please reset your password immediately or contact support.</p>
|
||||
If you did not perform this action, please reset your password immediately or contact support.
|
||||
|
||||
<p style="margin-top:16px">For your security, we recommend using a strong and unique password.</p>
|
||||
`,
|
||||
For your security, we recommend using a strong and unique password.
|
||||
`),
|
||||
}),
|
||||
|
||||
ADDED_TO_GROUP: ({ groupName }) => ({
|
||||
subject: "Group Assignment Notification",
|
||||
title: "Added to Group",
|
||||
body: `
|
||||
<p>Dear User,</p>
|
||||
subject: "Group Assignment Notification - STARR System",
|
||||
text: build(`
|
||||
Dear User,
|
||||
|
||||
<p>You have been assigned to the group <strong>${groupName}</strong> in the STARR System.</p>
|
||||
You have been assigned to the group "${groupName}" in the STARR System.
|
||||
|
||||
<p>This assignment grants you access to shared resources and collaboration tools within the group.</p>
|
||||
This assignment grants you access to shared resources and collaboration tools within the group.
|
||||
|
||||
<p style="margin-top:16px">Please log in to your account to view group details.</p>
|
||||
`,
|
||||
Please log in to your account to view group details.
|
||||
`),
|
||||
}),
|
||||
|
||||
TASK_ASSIGNED: ({ taskTitle, dueDate }) => ({
|
||||
subject: "New Task Assignment",
|
||||
title: "Task Assigned",
|
||||
body: `
|
||||
<p>Dear User,</p>
|
||||
subject: "New Task Assignment - STARR System",
|
||||
text: build(`
|
||||
Dear User,
|
||||
|
||||
<p>You have been assigned a new task in the STARR System.</p>
|
||||
You have been assigned a new task in the STARR System.
|
||||
|
||||
<div style="margin:16px 0;padding:12px;border:1px solid #e5e7eb;border-radius:6px">
|
||||
<strong>Task:</strong> ${taskTitle}
|
||||
</div>
|
||||
Task: ${taskTitle}
|
||||
Due Date: ${dueDate}
|
||||
|
||||
<p><strong>Due Date:</strong> ${dueDate}</p>
|
||||
|
||||
<p style="margin-top:16px">Kindly ensure completion within the specified timeframe.</p>
|
||||
`,
|
||||
Kindly ensure completion within the specified timeframe.
|
||||
`),
|
||||
}),
|
||||
|
||||
ADD_STAFF: ({ name, email, password, expiryHours = 24 }) => ({
|
||||
subject: "Your Staff Account Has Been Created - STARR System",
|
||||
title: "Staff Account Created",
|
||||
body: `
|
||||
<p>Dear ${name},</p>
|
||||
text: build(`
|
||||
Dear ${name},
|
||||
|
||||
<p>Your staff account has been successfully created in the STARR System.
|
||||
Below are your login credentials:</p>
|
||||
Your staff account has been successfully created in the STARR System. Below are your login credentials:
|
||||
|
||||
<div style="margin:24px 0;padding:16px;border:1px solid #e5e7eb;border-radius:6px;background:#f9fafb">
|
||||
<table style="width:100%;font-size:14px">
|
||||
<tr>
|
||||
<td style="padding:6px 0;color:#6b7280;width:100px"><strong>Email</strong></td>
|
||||
<td style="padding:6px 0">${email}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:6px 0;color:#6b7280"><strong>Password</strong></td>
|
||||
<td style="padding:6px 0;font-size:18px;color:#1d4ed8">${password}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
Email: ${email}
|
||||
Password: ${password}
|
||||
|
||||
<p>⚠️ This temporary password is valid for <strong>${expiryHours} hours</strong>.
|
||||
You will be required to change it upon first login.</p>
|
||||
This temporary password is valid for ${expiryHours} hours. You will be required to change it upon first login.
|
||||
|
||||
<p>If you did not request this account or believe this was created in error,
|
||||
please contact your administrator immediately to have it deactivated.</p>
|
||||
If you did not request this account or believe this was created in error, please contact your administrator immediately to have it deactivated.
|
||||
|
||||
<p style="margin-top:16px;font-size:13px;color:#6b7280">
|
||||
For security, please do not share your credentials with anyone.
|
||||
If you need a new password, contact your administrator.
|
||||
</p>
|
||||
`,
|
||||
For security, please do not share your credentials with anyone. If you need a new password, contact your administrator.
|
||||
`),
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/***********************************************************************************************************************************************************************
|
||||
* File Name: notifications.data.js
|
||||
* Type of Program: Data
|
||||
* Description: Central registry of all notification types for both admin and
|
||||
* client (user) notifications.
|
||||
*
|
||||
* Each entry describes one notification type:
|
||||
* type {string} — stored in the DB 'type' column
|
||||
* scope {string} — 'admin' | 'user' | 'both'
|
||||
* trigger {string} — what fires it (cron | event | manual)
|
||||
* build {function} — takes a data payload, returns the object
|
||||
* ready to pass to AdminNotification.create()
|
||||
* or UserNotification.create() / bulkCreate()
|
||||
*
|
||||
* To add a new notification type:
|
||||
* 1. Add an entry in the relevant section below.
|
||||
* 2. Call NOTIFICATION_REGISTRY.<key>.build(data) at the trigger
|
||||
* site (controller, cron, service).
|
||||
* No other changes needed.
|
||||
*
|
||||
* Current types:
|
||||
* Admin : task_overdue
|
||||
* User : user_task_overdue, achievement, course_unlocked,
|
||||
* certificate_issued, task_reminder, announcement
|
||||
*
|
||||
* Author: Kenneth Obsequio (@lash0000)
|
||||
* Date Created: Jun. 19, 2026
|
||||
***********************************************************************************************************************************************************************/
|
||||
'use strict';
|
||||
|
||||
const NOTIFICATION_REGISTRY = {
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// ADMIN notifications (scope: 'admin')
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── Task ──────────────────────────────────────────────────────────────────
|
||||
task_overdue: {
|
||||
type: 'task_overdue',
|
||||
scope: 'admin',
|
||||
trigger: 'cron',
|
||||
build({ count, task_list_ids = [] }) {
|
||||
return {
|
||||
type: 'task_overdue',
|
||||
title: 'Tasks Overdue',
|
||||
message: `${count} task${count === 1 ? ' was' : 's were'} automatically marked as overdue.`,
|
||||
data: { count, task_list_ids },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ── User Registration ─────────────────────────────────────────────────────
|
||||
user_registration: {
|
||||
type: 'user_registration',
|
||||
scope: 'admin',
|
||||
trigger: 'event',
|
||||
build({ groupName, groupCode, userEmail }) {
|
||||
return {
|
||||
type: 'user_registration',
|
||||
title: 'New User Registered',
|
||||
message: `A new user registered in ${groupName}.`,
|
||||
data: { groupName, groupCode, userEmail },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// USER notifications (scope: 'user')
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── Task ──────────────────────────────────────────────────────────────────
|
||||
user_task_overdue: {
|
||||
type: 'task',
|
||||
scope: 'user',
|
||||
trigger: 'cron',
|
||||
build({ count, task_list_ids = [] }) {
|
||||
const label = count === 1 ? '1 task has' : `${count} tasks have`;
|
||||
return {
|
||||
type: 'task',
|
||||
title: 'Tasks Overdue',
|
||||
message: `${label} passed their deadline and been marked as overdue.`,
|
||||
data: { count, task_list_ids },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
task_reminder: {
|
||||
type: 'task',
|
||||
scope: 'user',
|
||||
trigger: 'cron',
|
||||
build({ taskName, deadline }) {
|
||||
return {
|
||||
type: 'task',
|
||||
title: 'Task Deadline Approaching',
|
||||
message: `"${taskName}" is due on ${new Date(deadline).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}.`,
|
||||
data: { taskName, deadline },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ── Achievement ───────────────────────────────────────────────────────────
|
||||
achievement: {
|
||||
type: 'achievement',
|
||||
scope: 'user',
|
||||
trigger: 'event',
|
||||
build({ label, description, key }) {
|
||||
return {
|
||||
type: 'achievement',
|
||||
title: label,
|
||||
message: description,
|
||||
data: { key },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ── Course ────────────────────────────────────────────────────────────────
|
||||
course_unlocked: {
|
||||
type: 'course',
|
||||
scope: 'user',
|
||||
trigger: 'event',
|
||||
build({ courseTitle }) {
|
||||
return {
|
||||
type: 'course',
|
||||
title: 'New Course Available',
|
||||
message: `"${courseTitle}" has been added to your learning library.`,
|
||||
data: { courseTitle },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
certificate_issued: {
|
||||
type: 'course',
|
||||
scope: 'user',
|
||||
trigger: 'event',
|
||||
build({ courseTitle, courseUuid }) {
|
||||
return {
|
||||
type: 'course',
|
||||
title: 'Certificate Issued',
|
||||
message: `Congratulations! Your certificate for "${courseTitle}" is ready.`,
|
||||
data: { courseTitle, courseUuid },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ── Welcome ───────────────────────────────────────────────────────────────
|
||||
welcome: {
|
||||
type: 'announcement',
|
||||
scope: 'user',
|
||||
trigger: 'event',
|
||||
build({ groupName, groupCode, accType }) {
|
||||
const greeting = accType === 'admin'
|
||||
? 'Welcome, Administrator!'
|
||||
: accType === 'staff'
|
||||
? 'Welcome to the Philproperties team!'
|
||||
: 'Welcome to Philproperties!';
|
||||
return {
|
||||
type: 'announcement',
|
||||
title: 'Welcome to Philproperties',
|
||||
message: groupName ? `${greeting} You have been added to ${groupName}.` : greeting,
|
||||
data: { groupName, groupCode, accType },
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// ── Platform ──────────────────────────────────────────────────────────────
|
||||
announcement: {
|
||||
type: 'announcement',
|
||||
scope: 'user',
|
||||
trigger: 'manual',
|
||||
build({ title, body }) {
|
||||
return {
|
||||
type: 'announcement',
|
||||
title,
|
||||
message: body,
|
||||
data: {},
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = { NOTIFICATION_REGISTRY };
|
||||
Reference in New Issue
Block a user