From 7569b54d605c005203e6250b829a6de16f89bbc2 Mon Sep 17 00:00:00 2001 From: Mayank Mishra Date: Tue, 17 Feb 2026 11:48:06 +0530 Subject: [PATCH] sending presigned urls in the get by id of acitivity details and fixed the issue of check availability --- .../activities/checkAvailabilityDetails.ts | 2 +- src/modules/user/services/user.service.ts | 207 ++++++++++++++---- 2 files changed, 169 insertions(+), 40 deletions(-) diff --git a/src/modules/user/handlers/activities/checkAvailabilityDetails.ts b/src/modules/user/handlers/activities/checkAvailabilityDetails.ts index 84febca..1391000 100644 --- a/src/modules/user/handlers/activities/checkAvailabilityDetails.ts +++ b/src/modules/user/handlers/activities/checkAvailabilityDetails.ts @@ -81,7 +81,7 @@ export const handler = safeHandler(async ( }); // derive check-in/out from all room slots (earliest start, latest end) - const allSlots = rooms.flatMap(r => r.slots || []); + const allSlots = Venues.flatMap(r => r.slots || []); const startTimes = allSlots.map(s => s.startTime).filter(Boolean); const endTimes = allSlots.map(s => s.endTime).filter(Boolean); const checkInTime = startTimes.length ? startTimes.sort()[0] : null; diff --git a/src/modules/user/services/user.service.ts b/src/modules/user/services/user.service.ts index e324dec..e81e810 100644 --- a/src/modules/user/services/user.service.ts +++ b/src/modules/user/services/user.service.ts @@ -28,6 +28,16 @@ import config from '@/config/config'; // return R * c; // } +const attachPresignedUrl = async (file: string | null | undefined) => { + if (!file) return null; + + const key = file.startsWith('http') + ? new URL(file).pathname.replace(/^\/+/, '') + : file; + + return await getPresignedUrl(bucket, key); +}; + async function findOrCreateLocation( tx: any, { @@ -277,7 +287,14 @@ async function rankAndPaginateActivities( // activityDurationMins: activity.activityDurationMins, // sustainabilityScore: activity.sustainabilityScore, // cheapestPrice, - energyLevel: activity.activityType.energyLevel, + energyLevel: activity.activityType.energyLevel + ? { + ...activity.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + activity.activityType.energyLevel.energyIcon + ), + } + : null, media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia), }; }) @@ -618,7 +635,7 @@ export class UserService { return { userAddressDetails, interests: [], - otherStatesActivities: null, + otherStatesActivities: null, overSeasActivities: null, }; } @@ -813,7 +830,14 @@ export class UserService { activityId: activity.id, activityTitle: activity.activityTitle, hypeCount: activity.hypeCount, - energyLevel: activity.activityType.energyLevel, + energyLevel: activity.activityType.energyLevel + ? { + ...activity.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + activity.activityType.energyLevel.energyIcon + ), + } + : null, media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia), })) ); @@ -889,29 +913,42 @@ export class UserService { activityDurationMins: activity.activityDurationMins, sustainabilityScore: activity.sustainabilityScore, cheapestPrice, - energyLevel: activity.activityType.energyLevel, + energyLevel: activity.activityType.energyLevel + ? { + ...activity.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + activity.activityType.energyLevel.energyIcon + ), + } + : null, media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia), }; }) ); - const interestsWithActivities = [...userInterests] - .sort((a, b) => - a.interest.interestName.localeCompare(b.interest.interestName) - ) - .map(ui => ({ - interestId: ui.interest.id, - interestName: ui.interest.interestName, - interestColor: ui.interest.interestColor, - interestImage: ui.interest.interestImage, - displayOrder: ui.interest.displayOrder, - page, - limit, - hasMore: formattedActivities.length === limit, - activities: formattedActivities - .filter(a => a.interestXid === ui.interestXid) - .map(({ interestXid, ...rest }) => rest), - })); + const interestsWithActivities = await Promise.all( + [...userInterests] + .sort((a, b) => + a.interest.interestName.localeCompare(b.interest.interestName) + ) + .map(async (ui) => ({ + interestId: ui.interest.id, + interestName: ui.interest.interestName, + interestColor: ui.interest.interestColor, + interestImage: ui.interest.interestImage, + interestImagePresignedUrl: await attachPresignedUrl( + ui.interest.interestImage + ), + displayOrder: ui.interest.displayOrder, + page, + limit, + hasMore: formattedActivities.length === limit, + activities: formattedActivities + .filter(a => a.interestXid === ui.interestXid) + .map(({ interestXid, ...rest }) => rest), + })) + ); + @@ -1052,23 +1089,34 @@ export class UserService { interestXid: a.activityType.interestXid, activityId: a.id, activityTitle: a.activityTitle, - energyLevel: a.activityType.energyLevel, + energyLevel: { + ...a.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + a.activityType.energyLevel?.energyIcon + ), + }, media: await attachMediaWithPresignedUrl(a.ActivitiesMedia), })) ); - const interestsWithActivities = otherInterests.map(interest => ({ - interestId: interest.id, - interestName: interest.interestName, - interestColor: interest.interestColor, - interestImage: interest.interestImage, - page, - limit, - hasMore: formattedOtherInterestActivities.length === limit, - activities: formattedOtherInterestActivities.filter( - a => a.interestXid === interest.id - ).map(({ interestXid, ...rest }) => rest), - })); + const interestsWithActivities = await Promise.all( + otherInterests.map(async (interest) => ({ + interestId: interest.id, + interestName: interest.interestName, + interestColor: interest.interestColor, + interestImage: interest.interestImage, + interestImagePresignedUrl: await attachPresignedUrl( + interest.interestImage + ), + page, + limit, + hasMore: formattedOtherInterestActivities.length === limit, + activities: formattedOtherInterestActivities + .filter(a => a.interestXid === interest.id) + .map(({ interestXid, ...rest }) => rest), + })) + ); + /* ===================================================== 4️⃣ MOST HYPED @@ -1118,7 +1166,12 @@ export class UserService { activityId: act.id, activityTitle: act.activityTitle, hypeCount: g._count.activityXid, - energyLevel: act.activityType.energyLevel, + energyLevel: { + ...act.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + act.activityType.energyLevel?.energyIcon + ), + }, media: await attachMediaWithPresignedUrl(act.ActivitiesMedia), }; }) @@ -1225,7 +1278,12 @@ export class UserService { activities: await Promise.all( newArrivalsRaw.map(async a => ({ activityTitle: a.activityTitle, - energyLevel: a.activityType.energyLevel, + energyLevel: { + ...a.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + a.activityType.energyLevel?.energyIcon + ), + }, media: await attachMediaWithPresignedUrl(a.ActivitiesMedia), })) ), @@ -1239,7 +1297,12 @@ export class UserService { activities: await Promise.all( otherStatesRaw.map(async a => ({ activityTitle: a.activityTitle, - energyLevel: a.activityType.energyLevel, + energyLevel: { + ...a.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + a.activityType.energyLevel?.energyIcon + ), + }, media: await attachMediaWithPresignedUrl(a.ActivitiesMedia), })) ), @@ -1253,7 +1316,12 @@ export class UserService { activities: await Promise.all( overseasRaw.map(async a => ({ activityTitle: a.activityTitle, - energyLevel: a.activityType.energyLevel, + energyLevel: { + ...a.activityType.energyLevel, + presignedUrl: await attachPresignedUrl( + a.activityType.energyLevel?.energyIcon + ), + }, media: await attachMediaWithPresignedUrl(a.ActivitiesMedia), })) ), @@ -1435,7 +1503,8 @@ export class UserService { amenities: { select: { id: true, - amenitiesName: true + amenitiesName: true, + amenitiesIcon: true } } } @@ -1501,6 +1570,54 @@ export class UserService { }, }) + // ================= PRESIGNED URL SECTION ================= + + // 1️⃣ Activity Media + if (Array.isArray(activity?.ActivitiesMedia)) { + activity.ActivitiesMedia = await Promise.all( + activity.ActivitiesMedia.map(async (m: any) => ({ + ...m, + presignedUrl: await attachPresignedUrl(m.mediaFileName), + })) + ); + } + + // 2️⃣ Energy Level Icon + if (activity?.activityType?.energyLevel?.energyIcon) { + activity.activityType.energyLevel.energyIcon = + await attachPresignedUrl( + activity.activityType.energyLevel.energyIcon + ); + } + + // 3️⃣ Navigation Mode Icons + if (Array.isArray(activity?.ActivityNavigationModes)) { + await Promise.all( + activity.ActivityNavigationModes.map(async (item: any) => { + if (item?.navigationMode?.navigationModeIcon) { + item.navigationMode.presignedUrl = + await attachPresignedUrl( + item.navigationMode.navigationModeIcon + ); + } + }) + ); + } + + // 4️⃣ Amenities Icons (IMPORTANT: make sure amenitiesIcon is selected in Prisma) + if (Array.isArray(activity?.ActivityAmenities)) { + await Promise.all( + activity.ActivityAmenities.map(async (item: any) => { + if (item?.amenities?.amenitiesIcon) { + item.amenities.presignedUrl = + await attachPresignedUrl( + item.amenities.amenitiesIcon + ); + } + }) + ); + } + const interestedCount = await tx.userBucketInterested.count({ where: { activityXid, @@ -1508,9 +1625,21 @@ export class UserService { }, }) + const prices = activity.ActivityVenues + .flatMap(v => v.ActivityPrices.map(p => p.sellPrice)) + .filter(p => p !== null) as number[]; + + const cheapestPrice = prices.length > 0 ? Math.min(...prices) : null; + + const totalCapacity = activity.ActivityVenues + .map(v => v.venueCapacity ?? 0) + .reduce((sum, capacity) => sum + capacity, 0); + return { activity, interestedCount, + cheapestPrice, + totalCapacity, rating: 0, // ⭐ Placeholder, implement rating logic as needed distance: 0 }