import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { removeBase64Prefix } from '@app/common/helper/removeBase64Prefix'; import { RegionRepository } from '@app/common/modules/region/repositories'; import { TimeZoneRepository } from '@app/common/modules/timezone/repositories'; import { UserEntity } from '@app/common/modules/user/entities'; import { UserRepository } from '@app/common/modules/user/repositories'; import { BadRequestException, HttpException, HttpStatus, Injectable, } from '@nestjs/common'; import { UpdateNameDto, UpdateProfilePictureDataDto, UpdateRegionDataDto, UpdateTimezoneDataDto, } from './../dtos/update.user.dto'; @Injectable() export class UserService { constructor( private readonly userRepository: UserRepository, private readonly regionRepository: RegionRepository, private readonly timeZoneRepository: TimeZoneRepository, ) {} async getUserDetailsByUserUuid(userUuid: string) { try { const user = await this.userRepository.findOne({ where: { uuid: userUuid, }, relations: ['region', 'timezone', 'roleType', 'project'], }); if (!user) { throw new BadRequestException('Invalid room UUID'); } // Use the utility function to remove the base64 prefix const cleanedProfilePicture = removeBase64Prefix(user.profilePicture); return { uuid: user?.uuid, email: user?.email, firstName: user?.firstName, lastName: user?.lastName, profilePicture: cleanedProfilePicture, region: user?.region, timeZone: user?.timezone, hasAcceptedWebAgreement: user?.hasAcceptedWebAgreement, webAgreementAcceptedAt: user?.webAgreementAcceptedAt, hasAcceptedAppAgreement: user?.hasAcceptedAppAgreement, appAgreementAcceptedAt: user?.appAgreementAcceptedAt, role: user?.roleType, project: user?.project, }; } catch (err) { if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException } else { throw new HttpException('User not found', HttpStatus.NOT_FOUND); } } } async updateProfilePictureByUserUuid( userUuid: string, updateProfilePictureDataDto: UpdateProfilePictureDataDto, ) { try { await this.userRepository.update( { uuid: userUuid }, { ...updateProfilePictureDataDto }, ); const updatedUser = await this.getUserDetailsByUserUuid(userUuid); // Use the utility function to remove the base64 prefix const cleanedProfilePicture = removeBase64Prefix( updatedUser.profilePicture, ); return { uuid: updatedUser.uuid, firstName: updatedUser.firstName, lastName: updatedUser.lastName, profilePicture: cleanedProfilePicture, region: updatedUser.region, timeZoneUuid: updatedUser.timeZone, }; } catch (err) { if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException } else { throw new HttpException('User not found', HttpStatus.NOT_FOUND); } } } async updateRegionByUserUuid( userUuid: string, updateRegionDataDto: UpdateRegionDataDto, ) { try { const user = await this.getUserDetailsByUserUuid(userUuid); if (!user) { throw new HttpException('User not found', HttpStatus.NOT_FOUND); } // Ensure the region UUID is provided if (!updateRegionDataDto.regionUuid) { throw new BadRequestException('Region UUID is required'); } // Ensure the region exists const region = await this.regionRepository.findOne({ where: { uuid: updateRegionDataDto.regionUuid, }, }); if (!region) { throw new BadRequestException('Invalid region UUID'); } await this.userRepository.update( { uuid: userUuid }, { region: region, }, ); const updatedUser = await this.getUserDetailsByUserUuid(userUuid); if (!updatedUser.region) { throw new BadRequestException('Region update failed'); } // Use the utility function to remove the base64 prefix const cleanedProfilePicture = removeBase64Prefix( updatedUser.profilePicture, ); return { uuid: updatedUser.uuid, firstName: updatedUser.firstName, lastName: updatedUser.lastName, profilePicture: cleanedProfilePicture, region: updatedUser.region, timeZoneUuid: updatedUser.timeZone, }; } catch (err) { throw new HttpException( err.message || 'User not found', HttpStatus.NOT_FOUND, ); } } async updateTimezoneByUserUuid( userUuid: string, updateTimezoneDataDto: UpdateTimezoneDataDto, ) { try { const user = await this.getUserDetailsByUserUuid(userUuid); if (!user) { throw new HttpException('User not found', HttpStatus.NOT_FOUND); } // Ensure the region UUID is provided if (!updateTimezoneDataDto.timezoneUuid) { throw new BadRequestException('Timezone UUID is required'); } // Ensure the region exists const timezone = await this.timeZoneRepository.findOne({ where: { uuid: updateTimezoneDataDto.timezoneUuid, }, }); if (!timezone) { throw new BadRequestException('Invalid timezone UUID'); } await this.userRepository.update( { uuid: userUuid }, { timezone: timezone, }, ); const updatedUser = await this.getUserDetailsByUserUuid(userUuid); if (!updatedUser.timeZone) { throw new BadRequestException('Timezone update failed'); } // Use the utility function to remove the base64 prefix const cleanedProfilePicture = removeBase64Prefix( updatedUser.profilePicture, ); return { uuid: updatedUser.uuid, firstName: updatedUser.firstName, lastName: updatedUser.lastName, profilePicture: cleanedProfilePicture, region: updatedUser.region, timeZoneUuid: updatedUser.timeZone, }; } catch (err) { throw new HttpException( err.message || 'User not found', HttpStatus.NOT_FOUND, ); } } async updateNameByUserUuid(userUuid: string, updateNameDto: UpdateNameDto) { try { const user = await this.getUserDetailsByUserUuid(userUuid); if (!user) { throw new HttpException('User not found', HttpStatus.NOT_FOUND); } if (!updateNameDto.firstName || !updateNameDto.lastName) { throw new BadRequestException('First Name and Last Name is required'); } await this.userRepository.update( { uuid: userUuid }, { firstName: updateNameDto.firstName, lastName: updateNameDto.lastName, }, ); const updatedUser = await this.getUserDetailsByUserUuid(userUuid); if (!updatedUser.firstName || !updatedUser.lastName) { throw new BadRequestException('First Name and Last Name update failed'); } // Use the utility function to remove the base64 prefix const cleanedProfilePicture = removeBase64Prefix( updatedUser.profilePicture, ); return { uuid: updatedUser.uuid, firstName: updatedUser.firstName, lastName: updatedUser.lastName, profilePicture: cleanedProfilePicture, region: updatedUser.region, timeZoneUuid: updatedUser.timeZone, }; } catch (err) { throw new HttpException( err.message || 'User not found', HttpStatus.NOT_FOUND, ); } } async acceptWebAgreement(userUuid: string) { await this.userRepository.update( { uuid: userUuid }, { hasAcceptedWebAgreement: true, webAgreementAcceptedAt: new Date(), }, ); return new SuccessResponseDto({ statusCode: HttpStatus.OK, success: true, message: 'Web agreement accepted successfully', }); } async findOneById(id: string): Promise { return await this.userRepository.findOne({ where: { uuid: id } }); } async deleteUser(uuid: string) { const user = await this.findOneById(uuid); if (!user) { throw new BadRequestException('User not found'); } return await this.userRepository.update({ uuid }, { isActive: false }); } async deleteUserProfile(uuid: string) { const user = await this.findOneById(uuid); if (!user) { throw new BadRequestException('User not found'); } return this.userRepository.delete({ uuid }); } }