Made add to bucket interested api and sending the count of bucket interested in the landing page api and surprise me api and sending the updated count in the add to bucket api
This commit is contained in:
@@ -346,4 +346,19 @@ getNearbyActivities:
|
||||
events:
|
||||
- httpApi:
|
||||
path: /user/activities/get-nearby-activities
|
||||
method: get
|
||||
method: get
|
||||
|
||||
addActivityToBucketInterested:
|
||||
handler: src/modules/user/handlers/activities/addToBucketInterested.handler
|
||||
memorySize: 384
|
||||
package:
|
||||
patterns:
|
||||
- 'src/modules/user/handlers/activities/**'
|
||||
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||
events:
|
||||
- httpApi:
|
||||
path: /user/activities/add-to-bucket-interested
|
||||
method: post
|
||||
@@ -0,0 +1,72 @@
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||
import { UserService } from '../../services/user.service';
|
||||
|
||||
const userService = new UserService(prismaClient);
|
||||
|
||||
export const handler = safeHandler(async (
|
||||
event: APIGatewayProxyEvent,
|
||||
context?: Context
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
// Extract token from headers
|
||||
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']
|
||||
if (!token) {
|
||||
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||
}
|
||||
|
||||
// Authenticate user using verifyUserToken
|
||||
const userInfo = await verifyUserToken(token);
|
||||
const userId = userInfo.id;
|
||||
|
||||
if (Number.isNaN(userId)) {
|
||||
throw new ApiError(400, 'User id must be a number');
|
||||
}
|
||||
|
||||
const user = await userService.getUserById(userId);
|
||||
if (!user) {
|
||||
throw new ApiError(404, 'User not found');
|
||||
}
|
||||
|
||||
// Parse request body
|
||||
let body: { activityXid: number; isBucket: boolean; bucketTypeName: string; };
|
||||
|
||||
try {
|
||||
body = event.body ? JSON.parse(event.body) : {};
|
||||
} catch (error) {
|
||||
throw new ApiError(400, 'Invalid JSON in request body');
|
||||
}
|
||||
|
||||
const { activityXid, isBucket, bucketTypeName } = body;
|
||||
|
||||
// Validate required fields
|
||||
if (
|
||||
typeof activityXid !== 'number' ||
|
||||
typeof isBucket !== 'boolean' ||
|
||||
!bucketTypeName
|
||||
) {
|
||||
throw new ApiError(400, 'Required fields missing or invalid');
|
||||
}
|
||||
|
||||
|
||||
// Set the passcode
|
||||
const counts = await userService.addToBucketInterested(userId, isBucket, bucketTypeName, activityXid);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
success: true,
|
||||
message: `Activity added to ${isBucket ? 'bucket' : 'interested'} successfully`,
|
||||
data: {
|
||||
bucketCount: counts.bucketCount,
|
||||
interestedCount: counts.interestedCount,
|
||||
}
|
||||
}),
|
||||
};
|
||||
});
|
||||
@@ -709,6 +709,29 @@ export class UserService {
|
||||
};
|
||||
}
|
||||
|
||||
const userBucketInterested = await tx.userBucketInterested.findMany({
|
||||
where: {
|
||||
userXid: userId,
|
||||
isActive: true,
|
||||
},
|
||||
select: {
|
||||
activityXid: true,
|
||||
isBucket: true,
|
||||
},
|
||||
});
|
||||
|
||||
const userBucketActivityIds = userBucketInterested
|
||||
.filter(u => u.isBucket)
|
||||
.map(u => u.activityXid);
|
||||
|
||||
const userInterestedActivityIds = userBucketInterested
|
||||
.filter(u => !u.isBucket)
|
||||
.map(u => u.activityXid);
|
||||
|
||||
const allUserExcludedActivityIds = userBucketInterested.map(
|
||||
u => u.activityXid,
|
||||
);
|
||||
|
||||
const userConnectionDetails = await tx.connectDetails.findMany({
|
||||
where: { userXid: userId, isActive: true },
|
||||
select: {
|
||||
@@ -762,6 +785,11 @@ export class UserService {
|
||||
activityTypeXid: {
|
||||
in: activitiyTypesOfUserInterests.map((at) => at.id),
|
||||
},
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
},
|
||||
skip,
|
||||
take: limit,
|
||||
@@ -842,7 +870,12 @@ export class UserService {
|
||||
// IF user wants the standard 4-step ranking applied TO the most hyped items:
|
||||
const mostHypedActivitiesRaw = await tx.activities.findMany({
|
||||
where: {
|
||||
id: { in: mostHypedActivityIds },
|
||||
id: {
|
||||
in: mostHypedActivityIds,
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1],
|
||||
},
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
@@ -966,6 +999,11 @@ export class UserService {
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
createdAt: { gte: new Date(Date.now() - 31 * 24 * 60 * 60 * 1000) },
|
||||
};
|
||||
|
||||
@@ -984,6 +1022,11 @@ export class UserService {
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
};
|
||||
|
||||
if (effectiveCountryXid) {
|
||||
@@ -1010,6 +1053,11 @@ export class UserService {
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
deletedAt: null,
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1034,6 +1082,11 @@ export class UserService {
|
||||
amInternalStatus:
|
||||
ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
deletedAt: null,
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -1076,6 +1129,11 @@ export class UserService {
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
id: {
|
||||
notIn: allUserExcludedActivityIds.length
|
||||
? allUserExcludedActivityIds
|
||||
: [-1], // prevent empty notIn issue
|
||||
},
|
||||
};
|
||||
|
||||
if (effectiveCountryXid) {
|
||||
@@ -1152,6 +1210,8 @@ export class UserService {
|
||||
loggedInNetworkCount: 0,
|
||||
citiesInNetworkCount: 0,
|
||||
rating: 0,
|
||||
interestedCount: userInterestedActivityIds.length,
|
||||
bucketCount: userBucketActivityIds.length,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
@@ -1237,6 +1297,32 @@ export class UserService {
|
||||
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const userBucketInterested = await tx.userBucketInterested.findMany({
|
||||
where: {
|
||||
userXid: userId,
|
||||
isActive: true,
|
||||
},
|
||||
select: {
|
||||
activityXid: true,
|
||||
isBucket: true,
|
||||
},
|
||||
});
|
||||
|
||||
const bucketActivityIds = userBucketInterested
|
||||
.filter(u => u.isBucket)
|
||||
.map(u => u.activityXid);
|
||||
|
||||
const interestedActivityIds = userBucketInterested
|
||||
.filter(u => !u.isBucket)
|
||||
.map(u => u.activityXid);
|
||||
|
||||
const excludedActivityIds = userBucketInterested.map(
|
||||
u => u.activityXid,
|
||||
);
|
||||
|
||||
const safeExcludedIds =
|
||||
excludedActivityIds.length > 0 ? excludedActivityIds : [-1];
|
||||
|
||||
/* =====================================================
|
||||
CONNECTION INTEREST MAP
|
||||
===================================================== */
|
||||
@@ -1270,7 +1356,6 @@ export class UserService {
|
||||
where: {
|
||||
userXid: { in: connectionUserIds },
|
||||
isActive: true,
|
||||
isBucket: true,
|
||||
},
|
||||
_count: { activityXid: true },
|
||||
});
|
||||
@@ -1302,6 +1387,9 @@ export class UserService {
|
||||
const otherInterestActivities = await tx.activities.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
id: { notIn: safeExcludedIds },
|
||||
...excludeUserInterestCondition,
|
||||
},
|
||||
skip,
|
||||
@@ -1388,7 +1476,16 @@ export class UserService {
|
||||
).length;
|
||||
|
||||
const hypedActivities = await tx.activities.findMany({
|
||||
where: { id: { in: mostHypedGrouped.map((h) => h.activityXid) } },
|
||||
where: {
|
||||
id: {
|
||||
in: mostHypedGrouped.map((h) => h.activityXid),
|
||||
notIn: safeExcludedIds,
|
||||
},
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
isActive: true,
|
||||
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
activityTitle: true,
|
||||
@@ -1427,7 +1524,10 @@ export class UserService {
|
||||
5️⃣ NEW ARRIVALS
|
||||
===================================================== */
|
||||
const newArrivalsWhere = {
|
||||
id: { notIn: safeExcludedIds },
|
||||
isActive: true,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
createdAt: { gte: new Date(Date.now() - 31 * 24 * 60 * 60 * 1000) },
|
||||
...excludeUserInterestCondition,
|
||||
};
|
||||
@@ -1457,6 +1557,9 @@ export class UserService {
|
||||
===================================================== */
|
||||
const otherStatesWhere: any = {
|
||||
isActive: true,
|
||||
id: { notIn: safeExcludedIds },
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
...excludeUserInterestCondition,
|
||||
};
|
||||
if (effectiveCountryXid)
|
||||
@@ -1466,6 +1569,9 @@ export class UserService {
|
||||
|
||||
const overseasWhere: any = {
|
||||
isActive: true,
|
||||
id: { notIn: safeExcludedIds },
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||
...excludeUserInterestCondition,
|
||||
};
|
||||
if (effectiveCountryXid)
|
||||
@@ -1513,6 +1619,8 @@ export class UserService {
|
||||
return {
|
||||
pagination: { page, limit },
|
||||
interests: interestsWithActivities,
|
||||
interestedCount: interestedActivityIds.length,
|
||||
bucketCount: bucketActivityIds.length,
|
||||
|
||||
mostHypedActivities: {
|
||||
page,
|
||||
@@ -3500,4 +3608,59 @@ export class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
async addToBucketInterested(
|
||||
userXid: number,
|
||||
isBucket: boolean,
|
||||
bucketTypeName: string,
|
||||
activityXid: number
|
||||
) {
|
||||
const activityExists = await this.prisma.activities.findFirst({
|
||||
where: { id: activityXid, isActive: true },
|
||||
});
|
||||
|
||||
if (!activityExists) {
|
||||
throw new ApiError(404, 'Activity not found');
|
||||
}
|
||||
|
||||
const existing = await this.prisma.userBucketInterested.findFirst({
|
||||
where: { userXid, activityXid },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new ApiError(400, 'Activity already added');
|
||||
}
|
||||
|
||||
await this.prisma.userBucketInterested.create({
|
||||
data: {
|
||||
userXid,
|
||||
activityXid,
|
||||
isBucket,
|
||||
bucketTypeName,
|
||||
},
|
||||
});
|
||||
|
||||
// ✅ Get updated counts
|
||||
const [bucketCount, interestedCount] = await Promise.all([
|
||||
this.prisma.userBucketInterested.count({
|
||||
where: {
|
||||
userXid,
|
||||
isBucket: true,
|
||||
isActive: true,
|
||||
},
|
||||
}),
|
||||
this.prisma.userBucketInterested.count({
|
||||
where: {
|
||||
userXid,
|
||||
isBucket: false,
|
||||
isActive: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
bucketCount,
|
||||
interestedCount,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user