Feture #52: Social Media Integration, BugFix: #89 Sates as ng-select, send Listing as EMail to friend
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Body, Controller, Post } from '@nestjs/common';
|
||||
import { User } from 'src/models/db.model';
|
||||
import { ShareByEMail, User } from 'src/models/db.model';
|
||||
import { ErrorResponse, MailInfo } from '../models/main.model';
|
||||
import { MailService } from './mail.service.js';
|
||||
|
||||
@@ -18,4 +18,8 @@ export class MailController {
|
||||
sendSubscriptionConfirmation(@Body() user: User): Promise<void | ErrorResponse> {
|
||||
return this.mailService.sendSubscriptionConfirmation(user);
|
||||
}
|
||||
@Post('send2Friend')
|
||||
send2Friend(@Body() shareByEMail: ShareByEMail): Promise<void | ErrorResponse> {
|
||||
return this.mailService.send2Friend(shareByEMail);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import path, { join } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { ZodError } from 'zod';
|
||||
import { SenderSchema, User } from '../models/db.model.js';
|
||||
import { SenderSchema, ShareByEMail, ShareByEMailSchema, User } from '../models/db.model.js';
|
||||
import { ErrorResponse, MailInfo, isEmpty } from '../models/main.model.js';
|
||||
import { UserService } from '../user/user.service.js';
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -96,4 +96,33 @@ export class MailService {
|
||||
},
|
||||
});
|
||||
}
|
||||
async send2Friend(shareByEMail: ShareByEMail): Promise<void | ErrorResponse> {
|
||||
try {
|
||||
const validatedSender = ShareByEMailSchema.parse(shareByEMail);
|
||||
} catch (error) {
|
||||
if (error instanceof ZodError) {
|
||||
const formattedErrors = error.errors.map(err => ({
|
||||
field: err.path.join('.'),
|
||||
message: err.message,
|
||||
}));
|
||||
throw new BadRequestException(formattedErrors);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
await this.mailerService.sendMail({
|
||||
to: shareByEMail.recipientEmail,
|
||||
from: `"Bizmatch.net" <info@bizmatch.net>`,
|
||||
subject: `${shareByEMail.type === 'business' ? 'Business' : 'Commercial Property'} For Sale: ${shareByEMail.listingTitle}`,
|
||||
//template: './inquiry', // `.hbs` extension is appended automatically
|
||||
template: join(__dirname, '../..', 'mail/templates/send2Friend.hbs'),
|
||||
context: {
|
||||
name: shareByEMail.name,
|
||||
email: shareByEMail.email,
|
||||
listingTitle: shareByEMail.listingTitle,
|
||||
url: shareByEMail.url,
|
||||
id: shareByEMail.id,
|
||||
type: shareByEMail.type,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
73
bizmatch-server/src/mail/templates/send2Friend.hbs
Normal file
73
bizmatch-server/src/mail/templates/send2Friend.hbs
Normal file
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Notification</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
color: #333333;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.email-container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #dddddd;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.header h1 {
|
||||
font-size: 24px;
|
||||
color: #333333;
|
||||
}
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.content p {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.content .plan-info {
|
||||
font-weight: bold;
|
||||
color: #0056b3;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #888888;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="email-container">
|
||||
<div class="header">
|
||||
<h1>Notification</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Hello,</p>
|
||||
|
||||
<p>Your friend {{name}} ({{email}}) believed you might find this <b>{{#if (eq type "commercialProperty")}}Commercial Property{{else if (eq type "business")}}Business{{/if}} for sale listing </b> on <a href="{{url}}">bizmatch.net</a> interesting.</p>
|
||||
|
||||
<span class="info-value"><a href="{{url}}/listing/{{id}}">{{listingTitle}}</a></span>
|
||||
|
||||
<p>Bizmatch is one of the most reliable platforms for buying and selling businesses.</p>
|
||||
|
||||
<p>Best regards,</p>
|
||||
<p>The Bizmatch Support Team</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>© 2024 Bizmatch. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -301,3 +301,13 @@ export const SenderSchema = z.object({
|
||||
comments: z.string().min(10, { message: 'Comments must be at least 10 characters long' }),
|
||||
});
|
||||
export type Sender = z.infer<typeof SenderSchema>;
|
||||
export const ShareByEMailSchema = z.object({
|
||||
name: z.string().min(6, { message: 'Name must be at least 6 characters long' }),
|
||||
recipientEmail: z.string().email({ message: 'Invalid email address' }),
|
||||
email: z.string().email({ message: 'Invalid email address' }),
|
||||
listingTitle: z.string().optional().nullable(),
|
||||
url: z.string().url({ message: 'Invalid URL format' }).optional().nullable(),
|
||||
id: z.string().optional().nullable(),
|
||||
type: ListingsCategoryEnum,
|
||||
});
|
||||
export type ShareByEMail = z.infer<typeof ShareByEMailSchema>;
|
||||
|
||||
Reference in New Issue
Block a user