mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-26 06:09:41 +00:00
refactor: handle kyc journey for customers
This commit is contained in:
@ -3,4 +3,5 @@ export enum NotificationScope {
|
||||
TASK_COMPLETED = 'TASK_COMPLETED',
|
||||
GIFT_RECEIVED = 'GIFT_RECEIVED',
|
||||
OTP = 'OTP',
|
||||
USER_INVITED = 'USER_INVITED',
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { MailerModule } from '@nestjs-modules/mailer';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { forwardRef, Module } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { TwilioModule } from 'nestjs-twilio';
|
||||
@ -21,7 +21,7 @@ import { FirebaseService, NotificationsService, TwilioService } from './services
|
||||
useFactory: buildMailerOptions,
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
UserModule,
|
||||
forwardRef(() => UserModule),
|
||||
],
|
||||
providers: [NotificationsService, FirebaseService, NotificationsRepository, TwilioService],
|
||||
exports: [NotificationsService],
|
||||
|
@ -25,36 +25,6 @@ export class NotificationsService {
|
||||
private readonly mailerService: MailerService,
|
||||
) {}
|
||||
|
||||
async sendPushNotification(userId: string, title: string, body: string) {
|
||||
this.logger.log(`Sending push notification to user ${userId}`);
|
||||
// Get the device tokens for the user
|
||||
|
||||
const tokens = await this.deviceService.getTokens(userId);
|
||||
|
||||
if (!tokens.length) {
|
||||
this.logger.log(`No device tokens found for user ${userId} but notification created in the database`);
|
||||
return;
|
||||
}
|
||||
// Send the notification
|
||||
return this.firebaseService.sendNotification(tokens, title, body);
|
||||
}
|
||||
|
||||
async sendSMS(to: string, body: string) {
|
||||
this.logger.log(`Sending SMS to ${to}`);
|
||||
await this.twilioService.sendSMS(to, body);
|
||||
}
|
||||
|
||||
async sendEmail({ to, subject, data, template }: SendEmailRequestDto) {
|
||||
this.logger.log(`Sending email to ${to}`);
|
||||
await this.mailerService.sendMail({
|
||||
to,
|
||||
subject,
|
||||
template,
|
||||
context: { ...data },
|
||||
});
|
||||
this.logger.log(`Email sent to ${to}`);
|
||||
}
|
||||
|
||||
async getNotifications(userId: string, pageOptionsDto: PageOptionsRequestDto) {
|
||||
this.logger.log(`Getting notifications for user ${userId}`);
|
||||
const [[notifications, count], unreadCount] = await Promise.all([
|
||||
@ -77,6 +47,18 @@ export class NotificationsService {
|
||||
return this.notificationRepository.markAsRead(userId);
|
||||
}
|
||||
|
||||
async sendEmailAsync(data: SendEmailRequestDto) {
|
||||
this.logger.log(`emitting ${EventType.NOTIFICATION_CREATED} event`);
|
||||
const notification = await this.createNotification({
|
||||
recipient: data.to,
|
||||
title: data.subject,
|
||||
message: '',
|
||||
scope: NotificationScope.USER_INVITED,
|
||||
channel: NotificationChannel.EMAIL,
|
||||
});
|
||||
return this.eventEmitter.emit(EventType.NOTIFICATION_CREATED, notification, data.data);
|
||||
}
|
||||
|
||||
async sendOtpNotification(sendOtpRequest: ISendOtp, otp: string) {
|
||||
this.logger.log(`Sending OTP to ${sendOtpRequest.recipient}`);
|
||||
const notification = await this.createNotification({
|
||||
@ -92,10 +74,42 @@ export class NotificationsService {
|
||||
return this.eventEmitter.emit(EventType.NOTIFICATION_CREATED, notification);
|
||||
}
|
||||
|
||||
private async sendPushNotification(userId: string, title: string, body: string) {
|
||||
this.logger.log(`Sending push notification to user ${userId}`);
|
||||
// Get the device tokens for the user
|
||||
|
||||
const tokens = await this.deviceService.getTokens(userId);
|
||||
|
||||
if (!tokens.length) {
|
||||
this.logger.log(`No device tokens found for user ${userId} but notification created in the database`);
|
||||
return;
|
||||
}
|
||||
// Send the notification
|
||||
return this.firebaseService.sendNotification(tokens, title, body);
|
||||
}
|
||||
|
||||
private async sendSMS(to: string, body: string) {
|
||||
this.logger.log(`Sending SMS to ${to}`);
|
||||
await this.twilioService.sendSMS(to, body);
|
||||
}
|
||||
|
||||
private async sendEmail({ to, subject, data, template }: SendEmailRequestDto) {
|
||||
this.logger.log(`Sending email to ${to}`);
|
||||
await this.mailerService.sendMail({
|
||||
to,
|
||||
subject,
|
||||
template,
|
||||
context: { ...data },
|
||||
});
|
||||
this.logger.log(`Email sent to ${to}`);
|
||||
}
|
||||
|
||||
private getTemplateFromNotification(notification: Notification) {
|
||||
switch (notification.scope) {
|
||||
case NotificationScope.OTP:
|
||||
return 'otp';
|
||||
case NotificationScope.USER_INVITED:
|
||||
return 'user-invite';
|
||||
default:
|
||||
return 'otp';
|
||||
}
|
||||
@ -115,8 +129,8 @@ export class NotificationsService {
|
||||
return this.sendEmail({
|
||||
to: notification.recipient!,
|
||||
subject: notification.title,
|
||||
data,
|
||||
template: this.getTemplateFromNotification(notification),
|
||||
data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
71
src/common/modules/notification/templates/user-invite.hbs
Normal file
71
src/common/modules/notification/templates/user-invite.hbs
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>You're Invited!</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
.header {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.content {
|
||||
font-size: 16px;
|
||||
color: #555;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background-color: #007bff;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
padding: 12px 20px;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.footer {
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.link {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">You're Invited to Join Us!</div>
|
||||
<p class="content">
|
||||
You've been invited to join our platform. Click the button below to accept the invitation and set up your account.
|
||||
</p>
|
||||
<a href="{{inviteLink}}" class="btn">Accept Invitation</a>
|
||||
<p class="content">
|
||||
If the button above doesn't work, you can copy and paste this link into your browser:<br>
|
||||
<a href="{{inviteLink}}" class="link">{{inviteLink}}</a>
|
||||
</p>
|
||||
<div class="footer">
|
||||
If you didn’t request this invitation, please ignore this email.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user