diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/CreateNewActivity.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/CreateNewActivity.ts index cd77d0e..7530059 100644 --- a/src/modules/host/handlers/Activity_Hub/OnBoarding/CreateNewActivity.ts +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/CreateNewActivity.ts @@ -186,23 +186,17 @@ export const handler = safeHandler( const uploadedActivityMedia: Array<{ mediaType?: string; mediaFileName: string }> = []; for (const file of files.filter( - (f) => f.fieldName === 'activityImages' || f.fieldName === 'activityVideos', + (f) => f.fieldName === 'images' || f.fieldName === 'videos' )) { const s3Key = `ActivityOnboarding/Activity_${activityPayload.activityXid}/Media/${Date.now()}_${file.fileName}`; - if (s3Key.length > 900) { - throw new ApiError(400, 'Generated S3 key too long'); - } - - await s3 - .upload({ - Bucket: config.aws.bucketName, - Key: s3Key, - Body: file.buffer, - ContentType: file.mimeType, - ACL: 'private', - }) - .promise(); + await s3.upload({ + Bucket: config.aws.bucketName, + Key: s3Key, + Body: file.buffer, + ContentType: file.mimeType, + ACL: 'private', + }).promise(); uploadedActivityMedia.push({ mediaType: file.mimeType, @@ -210,6 +204,7 @@ export const handler = safeHandler( }); } + /* 🔥 MERGE ACTIVITY MEDIA */ const existingMedia = Array.isArray(activityPayload.media) ? activityPayload.media @@ -218,44 +213,40 @@ export const handler = safeHandler( /* 9️⃣ PROCESS VENUE MEDIA UPLOADS */ // Group venue files by index: venueImages[0], venueImages[1], etc. - const venueFilesMap: Map> = new Map(); + const venueFilesMap = new Map(); for (const file of files) { - // Match patterns like: venueImages[0], venueVideos[1], etc. - const match = file.fieldName.match(/^venue(Images|Videos)\[(\d+)\]$/); - if (match) { - const venueIndex = parseInt(match[2], 10); - if (!venueFilesMap.has(venueIndex)) { - venueFilesMap.set(venueIndex, []); - } - venueFilesMap.get(venueIndex)!.push(file); + const match = file.fieldName.match(/^venueFiles(\d+)$/); + if (!match) continue; + + const venueIndex = Number(match[1]); + + if (!venueFilesMap.has(venueIndex)) { + venueFilesMap.set(venueIndex, []); } + + venueFilesMap.get(venueIndex)!.push(file); } + // Upload venue files and attach to corresponding venues if (Array.isArray(activityPayload.venues)) { for (let i = 0; i < activityPayload.venues.length; i++) { const venue = activityPayload.venues[i]; const venueFiles = venueFilesMap.get(i) || []; - const uploadedVenueMedia: Array<{ mediaType?: string; mediaFileName: string }> = []; + const uploadedVenueMedia = []; for (const file of venueFiles) { const s3Key = `ActivityOnboarding/Activity_${activityPayload.activityXid}/Venue_${i}/Media/${Date.now()}_${file.fileName}`; - if (s3Key.length > 900) { - throw new ApiError(400, 'Generated S3 key too long for venue media'); - } - - await s3 - .upload({ - Bucket: config.aws.bucketName, - Key: s3Key, - Body: file.buffer, - ContentType: file.mimeType, - ACL: 'private', - }) - .promise(); + await s3.upload({ + Bucket: config.aws.bucketName, + Key: s3Key, + Body: file.buffer, + ContentType: file.mimeType, + ACL: 'private', + }).promise(); uploadedVenueMedia.push({ mediaType: file.mimeType, @@ -263,12 +254,11 @@ export const handler = safeHandler( }); } - // Merge with existing venue media - const existingVenueMedia = Array.isArray(venue.media) ? venue.media : []; - venue.media = [...existingVenueMedia, ...uploadedVenueMedia]; + venue.media = [...(venue.media || []), ...uploadedVenueMedia]; } } + /* 🔟 VALIDATION */ let parsedDto: CreateActivityInput; diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index e865867..51c575b 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -1704,7 +1704,7 @@ export class HostService { } async getAllDetailsOfActivityAndVenue(activityXid: number) { - return await this.prisma.activities.findMany({ + const activity = await this.prisma.activities.findFirst({ where: { id: activityXid, isActive: true }, select: { id: true, @@ -1728,6 +1728,38 @@ export class HostService { activityTypeName: true, } }, + ActivitiesMedia: { + where: { + isActive: true + }, + select: { + id: true, + mediaType: true, + mediaFileName: true, + } + }, + ActivityVenues: { + where: { + isActive: true + }, + select: { + id: true, + venueName: true, + venueCapacity: true, + availableSeats: true, + isMinPeopleReqMandatory: true, + minPeopleRequired: true, + minReqfullfilledBeforeMins: true, + venueDescription: true, + ActivityVenueArtifacts: { + select: { + id: true, + mediaType: true, + mediaFileName: true + } + } + } + }, ActivityPickUpDetails: { where: { isActive: true, @@ -1936,6 +1968,46 @@ export class HostService { } }) + + if (!activity) { + throw new ApiError(404, 'Activity not found'); + } + + if (Array.isArray(activity.ActivitiesMedia)) { + for (const media of activity.ActivitiesMedia) { + if (!media?.mediaFileName) continue; + + const filePath = media.mediaFileName; + + // ✅ Robust S3 key extraction + const key = filePath.startsWith('http') + ? new URL(filePath).pathname.replace(/^\/+/, '') + : filePath; + + (media as any).presignedUrl = await getPresignedUrl(bucket, key); + } + } + + if (Array.isArray(activity.ActivityVenues)) { + for (const venue of activity.ActivityVenues) { + if (!Array.isArray(venue.ActivityVenueArtifacts)) continue; + + for (const artifact of venue.ActivityVenueArtifacts) { + if (!artifact?.mediaFileName) continue; + + const filePath = artifact.mediaFileName; + + // ✅ Robust S3 key extraction + const key = filePath.startsWith('http') + ? new URL(filePath).pathname.replace(/^\/+/, '') + : filePath; + + (artifact as any).preSignedURL = await getPresignedUrl(bucket, key); + } + } + } + + return activity; } async createActivity(