diff --git a/serverless/functions/user.yml b/serverless/functions/user.yml index 2b87151..bee41df 100644 --- a/serverless/functions/user.yml +++ b/serverless/functions/user.yml @@ -390,5 +390,20 @@ getFilteredLandingPageAllDetails: - ${file(./serverless/patterns/base.yml):pattern4} events: - httpApi: - path: /activities/get-filtered-landing-page-details + path: /user/activities/get-filtered-landing-page-details + method: get + +getAllBucketActivities: + handler: src/modules/user/handlers/activities/getAllBucketActivities.handler + memorySize: 512 + package: + patterns: + - 'src/modules/user/**' + - ${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/get-all-bucket-activities method: get \ No newline at end of file diff --git a/src/modules/user/handlers/activities/getAllBucketActivities.ts b/src/modules/user/handlers/activities/getAllBucketActivities.ts new file mode 100644 index 0000000..f05831f --- /dev/null +++ b/src/modules/user/handlers/activities/getAllBucketActivities.ts @@ -0,0 +1,46 @@ +import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +import { safeHandler } from '../../../../common/utils/handlers/safeHandler'; +import { prismaClient } from '../../../../common/database/prisma.lambda.service'; +import ApiError from '../../../../common/utils/helper/ApiError'; +import { UserService } from '../../services/user.service'; +import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser'; + +const userService = new UserService(prismaClient); + +export const handler = safeHandler(async ( + event: APIGatewayProxyEvent, + context?: Context +): Promise => { + // 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.'); + } + + // Verify token and get user info + const userInfo = await verifyUserToken(token); + const userId = Number(userInfo.id); + + if (!userId || isNaN(userId)) { + throw new ApiError(400, 'Invalid user ID'); + } + + // Fetch user with their HostHeader stepper info + const result = await userService.getAllBucketActivities( + userId + ); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + data: result, + }), + }; +}); + diff --git a/src/modules/user/services/filteredLandingPage.service.ts b/src/modules/user/services/filteredLandingPage.service.ts index 01becbf..cd6debb 100644 --- a/src/modules/user/services/filteredLandingPage.service.ts +++ b/src/modules/user/services/filteredLandingPage.service.ts @@ -400,7 +400,7 @@ export class FilteredLandingPageService { id: true, schoolCompanyXid: true, } - }) + }); const otherConnectionUsers = await tx.connectDetails.findMany({ where: { userXid: { notIn: [userId] }, isActive: true, schoolCompanyXid: { in: userConnectionDetails.map((u) => u.schoolCompanyXid) } }, @@ -408,7 +408,7 @@ export class FilteredLandingPageService { id: true, userXid: true, } - }) + }); const connectionUserIds = otherConnectionUsers.length > 0 @@ -450,7 +450,7 @@ export class FilteredLandingPageService { return acc; }, {} as any); - // Fetch activities for each activity type + // Fetch activities for each activity type with excluded activities filter const activitiesByActivityType = await Promise.all( activityTypesWithInterests.map(async (activityType) => { const activities = await tx.activities.findMany({ @@ -565,7 +565,6 @@ export class FilteredLandingPageService { // Group by interests for the final structure const interestsWithActivities = await Promise.all( Object.values(activityTypesByInterest).map(async (interestGroup: any) => { - // collect all activities belonging to this interest const activitiesForInterest = activitiesByActivityType .filter(a => a.interestXid === interestGroup.interest.id) @@ -580,11 +579,9 @@ export class FilteredLandingPageService { interestGroup.interest.interestImage ), displayOrder: interestGroup.interest.displayOrder, - page, limit, hasMore: activitiesForInterest.length === limit, - activities: activitiesForInterest }; }) @@ -596,6 +593,9 @@ export class FilteredLandingPageService { where: { isActive: true, isBucket: false, + activityXid: { + notIn: allUserExcludedActivityIds.length ? allUserExcludedActivityIds : [-1], + }, }, _count: { activityXid: true, diff --git a/src/modules/user/services/user.service.ts b/src/modules/user/services/user.service.ts index f124f0e..f169ffb 100644 --- a/src/modules/user/services/user.service.ts +++ b/src/modules/user/services/user.service.ts @@ -4256,4 +4256,70 @@ export class UserService { interestedCount, }; } + + async getAllBucketActivities(userXid: number) { + const bucketActivities = await this.prisma.userBucketInterested.findMany({ + where: { + userXid, + isBucket: true, + isActive: true, + }, + select: { + id: true, + bucketTypeName: true, + activityXid: true, + Activities: { + select: { + activityTitle: true, + ActivitiesMedia: { + where: { + isCoverImage: true, + isActive: true, + }, + select: { + mediaFileName: true, + }, + }, + }, + }, + }, + }); + + const ready: any[] = []; + const planning: any[] = []; + const oneDay: any[] = []; + + for (const item of bucketActivities) { + const media = item.Activities?.ActivitiesMedia?.[0]?.mediaFileName; + + let presignedUrl = null; + + if (media) { + presignedUrl = await attachPresignedUrl(media); + // your presigned url function + } + + const activityData = { + id: item.id, + activityXid: item.activityXid, + bucketTypeName: item.bucketTypeName, + activityTitle: item.Activities?.activityTitle, + coverImage: presignedUrl, + }; + + if (item.bucketTypeName === 'Ready') { + ready.push(activityData); + } else if (item.bucketTypeName === 'Planning') { + planning.push(activityData); + } else if (item.bucketTypeName === 'One-day') { + oneDay.push(activityData); + } + } + + return { + ready, + planning, + oneDay, + }; + } } \ No newline at end of file