124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { PrismaClient, User } from '@prisma/client';
|
|
import ApiError from '@/common/utils/helper/ApiError';
|
|
import * as bcrypt from 'bcryptjs';
|
|
import { UserPersonalInfoSchema } from '@/common/utils/validation/user/addPersonalInfo.validation';
|
|
@Injectable()
|
|
export class UserService {
|
|
constructor(private prisma: PrismaClient) { }
|
|
|
|
async getUserById(userId: number) {
|
|
return this.prisma.user.findUnique({
|
|
where: { id: userId, isActive: true },
|
|
});
|
|
}
|
|
|
|
async addPersonalInfo(userId: number, data: UserPersonalInfoSchema) {
|
|
return await this.prisma.$transaction(async (tx) => {
|
|
const updatedUser = await tx.user.update({
|
|
where: { id: userId },
|
|
data: {
|
|
firstName: data.firstName,
|
|
lastName: data.lastName ?? null,
|
|
genderName: data.genderName,
|
|
dateOfBirth: data.dateOfBirth
|
|
? new Date(data.dateOfBirth)
|
|
: null,
|
|
isProfileUpdated: true,
|
|
},
|
|
});
|
|
|
|
return updatedUser;
|
|
});
|
|
}
|
|
|
|
async getAllInterestDetails() {
|
|
return await this.prisma.interests.findMany({
|
|
where: { isActive: true },
|
|
select: {
|
|
id: true,
|
|
interestName: true,
|
|
interestColor: true,
|
|
interestImage: true,
|
|
displayOrder: true
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
async getUserByMobileNumber(mobileNumber: string): Promise<User | null> {
|
|
return this.prisma.user.findFirst({
|
|
where: { mobileNumber: mobileNumber, isActive: true },
|
|
});
|
|
}
|
|
|
|
async verifyHostOtp(mobileNumber: string, otp: string): Promise<boolean> {
|
|
const user = await this.prisma.user.findFirst({
|
|
where: { mobileNumber: mobileNumber, isActive: true },
|
|
select: {
|
|
id: true,
|
|
mobileNumber: true,
|
|
UserOtp: {
|
|
where: { isActive: true, isVerified: false },
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 1,
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!user) {
|
|
throw new ApiError(404, 'User not found.');
|
|
}
|
|
|
|
const userOtp = user.UserOtp[0];
|
|
|
|
if (!userOtp) {
|
|
throw new ApiError(400, 'No OTP found.');
|
|
}
|
|
|
|
if (new Date() > userOtp.expiresOn) {
|
|
throw new ApiError(400, 'OTP has expired.');
|
|
}
|
|
|
|
const isMatch = await bcrypt.compare(otp, userOtp.otpCode);
|
|
|
|
if (!isMatch) {
|
|
throw new ApiError(400, 'Invalid OTP.');
|
|
}
|
|
|
|
await this.prisma.userOtp.update({
|
|
where: { id: userOtp.id },
|
|
data: {
|
|
isVerified: true,
|
|
verifiedOn: new Date(),
|
|
isActive: false,
|
|
},
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
async setUserPasscode(userId: number, userPasscode: string): Promise<User> {
|
|
// Validate passcode format (6 digits)
|
|
if (!userPasscode || userPasscode.length !== 6 || !/^\d{6}$/.test(userPasscode)) {
|
|
throw new ApiError(400, 'Passcode must be exactly 6 digits');
|
|
}
|
|
|
|
// Hash the passcode
|
|
const hashedPasscode = await bcrypt.hash(userPasscode, 10);
|
|
|
|
// Update user with passcode
|
|
const updatedUser = await this.prisma.user.update({
|
|
where: { id: userId },
|
|
data: {
|
|
userPasscode: hashedPasscode,
|
|
},
|
|
});
|
|
|
|
if (!updatedUser) {
|
|
throw new ApiError(400, 'Failed to set passcode');
|
|
}
|
|
|
|
return updatedUser;
|
|
}
|
|
} |