diff --git a/server/src/module/opensource/opensource.routes.ts b/server/src/module/opensource/opensource.routes.ts index 0fe379c8d..4de5a3854 100644 --- a/server/src/module/opensource/opensource.routes.ts +++ b/server/src/module/opensource/opensource.routes.ts @@ -1,5 +1,9 @@ +<<<<<<< HEAD +import { Router } from "express"; +======= import { Router } from "express"; import { prisma } from "../../database/db.js"; +>>>>>>> upstream/main import { OpensourceController } from "./opensource.controller.js"; import { authMiddleware } from "../../middleware/auth.middleware.js"; import { requireRole } from "../../middleware/role.middleware.js"; @@ -21,6 +25,8 @@ opensourceRouter.get("/languages", (req, res, next) => controller.getLanguages(r // Get GSoC organizations opensourceRouter.get("/gsoc/orgs", (req, res, next) => controller.getGsocOrgs(req, res, next)); +<<<<<<< HEAD +======= // ─── Student Progress Tracking ───────────────────────────────── // NOTE: must be before /:id to avoid route conflicts @@ -39,6 +45,7 @@ opensourceRouter.patch( ); // ─── Repo Requests (Student-authenticated) ───────────────────── +>>>>>>> upstream/main // NOTE: these must be registered BEFORE /:id to avoid route conflicts opensourceRouter.post("/requests", authMiddleware, requireRole("STUDENT"), (req, res, next) => diff --git a/server/src/module/opensource/opensource.service.ts b/server/src/module/opensource/opensource.service.ts index 27ff7603c..9fca8dffd 100644 --- a/server/src/module/opensource/opensource.service.ts +++ b/server/src/module/opensource/opensource.service.ts @@ -78,23 +78,25 @@ export class OpensourceService { if (language) where["language"] = { equals: language, mode: "insensitive" }; if (difficulty) where["difficulty"] = difficulty; if (domain) where["domain"] = domain; - const trimmedSearch = search?.trim(); - if (trimmedSearch) { - // Prisma's scalar-list filters can't do case-insensitive substring match - // on array elements, so resolve tag matches via a raw ILIKE-on-unnest - // subquery and merge the matching ids into the OR clause. +const trimmedSearch = search?.trim(); + +if (trimmedSearch) { + // Prisma's scalar-list filters can't do case-insensitive substring match + // on array elements, so resolve tag matches via a raw ILIKE-on-unnest + // subquery and merge the matching ids into the OR clause. const tagMatches = await prisma.$queryRaw>` SELECT id FROM "opensourceRepo" WHERE EXISTS ( SELECT 1 FROM unnest(tags) AS t WHERE t ILIKE ${`%${trimmedSearch}%`} ) `; + const tagMatchIds = tagMatches.map((r) => r.id); - where["OR"] = [ - { name: { contains: trimmedSearch, mode: "insensitive" } }, - { owner: { contains: trimmedSearch, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - { language: { contains: search, mode: "insensitive" } }, +where["OR"] = [ + { name: { contains: trimmedSearch, mode: "insensitive" } }, + { owner: { contains: trimmedSearch, mode: "insensitive" } }, + { description: { contains: trimmedSearch, mode: "insensitive" } }, + { language: { contains: trimmedSearch, mode: "insensitive" } }, ...(tagMatchIds.length > 0 ? [{ id: { in: tagMatchIds } }] : []), ]; } @@ -162,10 +164,12 @@ export class OpensourceService { const skip = (page - 1) * limit; const where: any = {}; - if (search) { + const trimmedSearch = search?.trim(); + + if (trimmedSearch) { where.OR = [ - { name: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, + { name: { contains: trimmedSearch, mode: "insensitive" } }, + { description: { contains: trimmedSearch, mode: "insensitive" } }, ]; } if (category) {