diff --git a/src/app/api/mobile/bookmarks/route.ts b/src/app/api/mobile/bookmarks/route.ts new file mode 100644 index 000000000..4b3b997dd --- /dev/null +++ b/src/app/api/mobile/bookmarks/route.ts @@ -0,0 +1,49 @@ +import db from '@/db'; +import { NextResponse, NextRequest } from 'next/server'; + +export async function GET(req: NextRequest) { + try { + const user = JSON.parse(req.headers.get('g') || ''); + const userId = user?.id; + if (!user) { + return NextResponse.json({ message: 'User Not Found' }, { status: 400 }); + } + const userBookmarks = await db.bookmark.findMany({ + where: { + userId, + }, + include: { + content: { + include: { + parent: { + select: { + id: true, + courses: true, + }, + }, + courses: { + select: { + courseId: true, + contentId: true, + }, + }, + }, + }, + }, + orderBy: { + createdAt: 'desc', + }, + }); + + return NextResponse.json({ + message: 'User bookmarks fetched successfully', + data: userBookmarks, + }); + } catch (error) { + console.log(error); + return NextResponse.json( + { message: 'Error fetching user bookmarks', error }, + { status: 500 }, + ); + } +} diff --git a/src/app/api/mobile/courses/[courseId]/[collectionId]/[contentId]/route.ts b/src/app/api/mobile/courses/[courseId]/[collectionId]/[contentId]/route.ts index 47e27e375..d907b84b1 100644 --- a/src/app/api/mobile/courses/[courseId]/[collectionId]/[contentId]/route.ts +++ b/src/app/api/mobile/courses/[courseId]/[collectionId]/[contentId]/route.ts @@ -1,34 +1,78 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { getExtraCourses } from '../../../route'; -async function checkUserContentAccess(userId: string, contentId: string) { - const userContent = await db.content.findFirst({ +async function checkUserContentAccess( + userId: string, + collectionId: string, + courseId: string, +) { + // First check if user has directly purchased the course + const purchasedCourse = await db.course.findFirst({ where: { - id: parseInt(contentId, 10), - courses: { + id: parseInt(courseId, 10), + purchasedBy: { some: { - course: { - purchasedBy: { - some: { - userId, - }, - }, + userId, + }, + }, + }, + }); + + if (!purchasedCourse) { + // If not directly purchased, check if user has access through extra courses logic + const purchasedCourses = await db.course.findMany({ + where: { + purchasedBy: { + some: { + userId, }, }, }, + }); + + const allCourses = await db.course.findMany(); + const extraCourses = getExtraCourses(purchasedCourses, allCourses); + + const hasAccess = extraCourses.some( + (course) => course.id === parseInt(courseId, 10), + ); + + if (!hasAccess) { + return false; + } + } + + // Verify that the collection belongs to the course + const checkCourse = await db.content.findFirst({ + where: { + id: parseInt(collectionId, 10), + courses: { + some: { + courseId: parseInt(courseId, 10), + }, + }, }, }); - return userContent !== null; + + return checkCourse !== null; } export async function GET( req: NextRequest, - { params }: { params: { contentId: string } }, + { + params, + }: { params: { contentId: string; courseId: string; collectionId: string } }, ) { try { - const { contentId } = params; + const { contentId, courseId, collectionId } = params; const user = JSON.parse(req.headers.get('g') || ''); - const userContentAccess = await checkUserContentAccess(user.id, contentId); + const userContentAccess = await checkUserContentAccess( + user.id, + collectionId, + courseId, + ); + console.log('userContentAccess: ', userContentAccess); if (!userContentAccess) { return NextResponse.json( { message: 'User does not have access to this content' }, @@ -38,6 +82,7 @@ export async function GET( const contents = await db.content.findUnique({ where: { id: parseInt(contentId, 10), + parentId: parseInt(collectionId, 10), }, select: { id: true, @@ -54,6 +99,14 @@ export async function GET( NotionMetadata: true, }, }); + if (!contents) { + return NextResponse.json( + { + message: 'Content not found', + }, + { status: 404 }, + ); + } return NextResponse.json({ message: 'Content fetched successfully', data: contents, diff --git a/src/app/api/mobile/courses/[courseId]/[collectionId]/route.ts b/src/app/api/mobile/courses/[courseId]/[collectionId]/route.ts index e6a8e715a..3442efe45 100644 --- a/src/app/api/mobile/courses/[courseId]/[collectionId]/route.ts +++ b/src/app/api/mobile/courses/[courseId]/[collectionId]/route.ts @@ -1,41 +1,66 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { getExtraCourses } from '../../route'; -async function checkUserCollectionAccess(userId: string, collectionId: string) { - const userCollection = await db.content.findFirst({ +async function checkUserCollectionAccess( + userId: string, + collectionId: string, + courseId: string, +) { + // First check if user has directly purchased the course + const purchasedCourse = await db.course.findFirst({ + where: { + id: parseInt(courseId, 10), + purchasedBy: { + some: { + userId, + }, + }, + }, + }); + + if (purchasedCourse) { + return true; + } + + // If not directly purchased, check if user has access through extra courses logic + const purchasedCourses = await db.course.findMany({ where: { - id: parseInt(collectionId, 10), - courses: { + purchasedBy: { some: { - course: { - purchasedBy: { - some: { - userId, - }, - }, - }, + userId, }, }, }, }); - return userCollection !== null; + const allCourses = await db.course.findMany(); + const extraCourses = getExtraCourses(purchasedCourses, allCourses); + + // Check if the requested course is in the extra courses + const hasAccess = extraCourses.some( + (course) => course.id === parseInt(courseId, 10), + ); + + return hasAccess; } export async function GET( request: NextRequest, - { params }: { params: { collectionId: string } }, + { params }: { params: { collectionId: string; courseId: string } }, ) { try { const user = JSON.parse(request.headers.get('g') || ''); + if (!user) { return NextResponse.json({ message: 'User not found' }, { status: 401 }); } - const { collectionId } = params; + const { collectionId, courseId } = params; const userHasCollectionAccess = await checkUserCollectionAccess( user.id, collectionId, + courseId, ); if (!userHasCollectionAccess) { return NextResponse.json( @@ -48,6 +73,14 @@ export async function GET( parentId: parseInt(collectionId, 10), }, }); + + if (!collectionData) { + return NextResponse.json( + { message: 'Collection not found' }, + { status: 404 }, + ); + } + return NextResponse.json({ message: 'Collection Data fetched successfully', data: collectionData, diff --git a/src/app/api/mobile/courses/[courseId]/route.ts b/src/app/api/mobile/courses/[courseId]/route.ts index 795f69f27..4a5d6aa6a 100644 --- a/src/app/api/mobile/courses/[courseId]/route.ts +++ b/src/app/api/mobile/courses/[courseId]/route.ts @@ -1,19 +1,44 @@ import db from '@/db'; import { NextResponse, NextRequest } from 'next/server'; +import { getExtraCourses } from '../route'; async function checkUserCourseAccess(userId: string, courseId: string) { - const userCourse = await db.course.findFirst({ + // First check if user has directly purchased the course + const purchasedCourse = await db.course.findFirst({ where: { + id: parseInt(courseId, 10), purchasedBy: { some: { userId, }, }, - id: parseInt(courseId, 10), }, }); - return userCourse !== null; + if (purchasedCourse) { + return true; + } + + // If not directly purchased, check if user has access through the extra courses logic + const purchasedCourses = await db.course.findMany({ + where: { + purchasedBy: { + some: { + userId, + }, + }, + }, + }); + + const allCourses = await db.course.findMany(); + const extraCourses = getExtraCourses(purchasedCourses, allCourses); + + // Check if the requested course is in the extra courses + const hasAccess = extraCourses.some( + (course) => course.id === parseInt(courseId, 10), + ); + + return hasAccess; } export async function GET( @@ -21,9 +46,15 @@ export async function GET( { params }: { params: { courseId: string } }, ) { try { - const user: { id: string } = JSON.parse(request.headers.get('g') || ''); + const user: { id: string; email: string } = JSON.parse( + request.headers.get('g') || '', + ); const { courseId } = params; + if (!user) { + return NextResponse.json({ message: 'User Not Found' }, { status: 400 }); + } + const userCourseAccess = await checkUserCourseAccess(user.id, courseId); if (!userCourseAccess) { return NextResponse.json( @@ -31,21 +62,28 @@ export async function GET( { status: 403 }, ); } - const folderContents = await db.content.findMany({ + + const courseData = await db.content.findMany({ where: { id: parseInt(courseId, 10), - type: 'folder', }, }); + if (!courseData) { + return NextResponse.json( + { message: 'Course not found' }, + { status: 404 }, + ); + } + return NextResponse.json({ - message: 'Courses Data fetched successfully', - data: folderContents, + message: 'Course data fetched successfully', + data: courseData, }); } catch (error) { - console.log(error); + console.error('Error fetching course:', error); return NextResponse.json( - { message: 'Error fetching user courses', error }, + { message: 'Error fetching course data', error }, { status: 500 }, ); } diff --git a/src/app/api/mobile/courses/route.ts b/src/app/api/mobile/courses/route.ts index c9e922f53..e712f2d1b 100644 --- a/src/app/api/mobile/courses/route.ts +++ b/src/app/api/mobile/courses/route.ts @@ -1,13 +1,77 @@ -import db from '@/db'; import { NextResponse, NextRequest } from 'next/server'; +import db from '@/db'; +import { Course } from '@/store/atoms'; + +const COHORT_3_PARENT_COURSES = [8, 9, 10, 11, 12]; + +export function getExtraCourses( + currentCourses: Course[], + allCourses: Course[], +): Course[] { + const hasCohort2 = currentCourses + .map((x) => x.id.toString()) + .find((x) => ['1', '2', '3'].includes(x.toString())); + + const hasCohort3 = currentCourses.find((x) => + COHORT_3_PARENT_COURSES.map((x) => x.toString()).includes(x.id.toString()), + ); + + let initialCourses: Course[] = []; + + if (hasCohort2) { + initialCourses = [...allCourses.filter((x) => x.openToEveryone)]; + } else if (hasCohort3) { + initialCourses = [...allCourses.filter((x) => x.id === 7 || x.id === 4)]; + } + + if (!hasCohort3) return initialCourses; + + const userCourses = [...initialCourses]; + + let hasWebDev = false; + let hasDevOps = false; + let hasWeb3 = false; + + if (currentCourses.find((x) => x.id === 8)) { + hasWebDev = hasDevOps = hasWeb3 = true; + } + if (currentCourses.find((x) => x.id === 9)) { + hasWebDev = hasDevOps = true; + } + if (currentCourses.find((x) => x.id === 10)) { + hasWeb3 = true; + } + if (currentCourses.find((x) => x.id === 11)) { + hasWebDev = true; + } + if (currentCourses.find((x) => x.id === 12)) { + hasDevOps = true; + } + + // Add specific courses based on user's access + if (hasWebDev) { + userCourses.push(allCourses.find((x) => x.id === 14)!); + } + if (hasDevOps) { + userCourses.push(allCourses.find((x) => x.id === 15)!); + } + if (hasWeb3) { + userCourses.push(allCourses.find((x) => x.id === 13)!); + userCourses.push(allCourses.find((x) => x.id === 20)!); + } + + return userCourses; +} export async function GET(req: NextRequest) { try { const user = JSON.parse(req.headers.get('g') || ''); + if (!user) { return NextResponse.json({ message: 'User Not Found' }, { status: 400 }); } - const userCourses = await db.course.findMany({ + + const purchasedCourses = await db.course.findMany({ where: { purchasedBy: { some: { @@ -19,12 +83,26 @@ export async function GET(req: NextRequest) { }, }); + const allCourses = await db.course.findMany(); + + const extraCourses = getExtraCourses(purchasedCourses, allCourses); + + // Combine and filter out parent courses + const userCourses = [...purchasedCourses, ...extraCourses].filter( + (course) => !COHORT_3_PARENT_COURSES.includes(course.id), + ); + + // Remove duplicates based on course ID + const uniqueUserCourses = Array.from( + new Map(userCourses.map((course) => [course.id, course])).values(), + ); + return NextResponse.json({ message: 'User courses fetched successfully', - data: userCourses, + data: uniqueUserCourses, }); } catch (error) { - console.log(error); + console.error('Error fetching user courses:', error); return NextResponse.json( { message: 'Error fetching user courses', error }, { status: 500 },