From 5cebd200c441a182c81481abcff6e096efb02481 Mon Sep 17 00:00:00 2001 From: Rafi Arrafif Date: Mon, 30 Mar 2026 19:03:37 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=94=20feat:=20support=20user=20collect?= =?UTF-8?q?ion=20check=20on=20hero=20banner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../getActiveHeroBanner.controller.ts | 17 ++++++----- .../GET/findAllActiveHeroBanner.repository.ts | 13 ++++++++- .../schemas/getActiveHeroBanner.schema.ts | 8 ++++++ .../services/getActiveHeroBanner.service.ts | 28 +++++++++++-------- 4 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 src/modules/heroBanner/schemas/getActiveHeroBanner.schema.ts diff --git a/src/modules/heroBanner/controllers/getActiveHeroBanner.controller.ts b/src/modules/heroBanner/controllers/getActiveHeroBanner.controller.ts index 65c454d..a988150 100644 --- a/src/modules/heroBanner/controllers/getActiveHeroBanner.controller.ts +++ b/src/modules/heroBanner/controllers/getActiveHeroBanner.controller.ts @@ -1,17 +1,16 @@ -import { Context } from "elysia"; +import { Context, Static } from "elysia"; import { mainErrorHandler } from "../../../helpers/error/handler"; import { returnReadResponse } from "../../../helpers/callback/httpResponse"; import { getActiveHeroBannerService } from "../services/getActiveHeroBanner.service"; +import { getActiveHeroBannerSchema } from "../schemas/getActiveHeroBanner.schema"; -export const getActiveHeroBannerController = async (ctx: Context) => { +export const getActiveHeroBannerController = async (ctx: { + set: Context["set"]; + header: Static; +}) => { try { - const response = await getActiveHeroBannerService(); - return returnReadResponse( - ctx.set, - 200, - "Active hero banners fetched successfully", - response, - ); + const response = await getActiveHeroBannerService({ cookie: ctx.header?.cookie }); + return returnReadResponse(ctx.set, 200, "Active hero banners fetched successfully", response); } catch (error) { return mainErrorHandler(ctx.set, error); } diff --git a/src/modules/heroBanner/repositories/GET/findAllActiveHeroBanner.repository.ts b/src/modules/heroBanner/repositories/GET/findAllActiveHeroBanner.repository.ts index 9afe52a..cb6cfb9 100644 --- a/src/modules/heroBanner/repositories/GET/findAllActiveHeroBanner.repository.ts +++ b/src/modules/heroBanner/repositories/GET/findAllActiveHeroBanner.repository.ts @@ -1,7 +1,7 @@ import { AppError } from "../../../../helpers/error/instances/app"; import { prisma } from "../../../../utils/databases/prisma/connection"; -export const findAllActiveHeroBannerRepository = async () => { +export const findAllActiveHeroBannerRepository = async (userId?: string) => { try { return await prisma.heroBanner.findMany({ where: { @@ -36,6 +36,17 @@ export const findAllActiveHeroBannerRepository = async () => { name: true, }, }, + _count: { + select: { + inCollections: { + where: { + collection: { + ownerId: userId, + }, + }, + }, + }, + }, }, }, }, diff --git a/src/modules/heroBanner/schemas/getActiveHeroBanner.schema.ts b/src/modules/heroBanner/schemas/getActiveHeroBanner.schema.ts new file mode 100644 index 0000000..aee2319 --- /dev/null +++ b/src/modules/heroBanner/schemas/getActiveHeroBanner.schema.ts @@ -0,0 +1,8 @@ +import { t } from "elysia"; +import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema"; + +export const getActiveHeroBannerSchema = { + headers: t.Object({ + cookie: t.Optional(t.String()), + }), +} satisfies AppRouteSchema; diff --git a/src/modules/heroBanner/services/getActiveHeroBanner.service.ts b/src/modules/heroBanner/services/getActiveHeroBanner.service.ts index e10d115..047d57a 100644 --- a/src/modules/heroBanner/services/getActiveHeroBanner.service.ts +++ b/src/modules/heroBanner/services/getActiveHeroBanner.service.ts @@ -1,22 +1,25 @@ -import { redisKey } from "../../../config/redis/key"; import { AppError } from "../../../helpers/error/instances/app"; import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; -import { redis } from "../../../utils/databases/redis/connection"; +import { tokenValidationService } from "../../auth/services/http/tokenValidation.service"; import { findSystemPreferenceService } from "../../systemPreference/services/internal/findSystemPreference.service"; import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository"; -export const getActiveHeroBannerService = async () => { +export const getActiveHeroBannerService = async ({ cookie }: { cookie?: string }) => { try { + const userId = cookie ? (await tokenValidationService(cookie)).user.id : undefined; + // Check if Hero Banner is enabled in system preferences const isHeroBannerEnabled = await findSystemPreferenceService("HERO_BANNER_ENABLED", "boolean"); if (!isHeroBannerEnabled) throw new AppError(403, "Hero Banner is disabled"); - // Try to get active banners from Redis cache - const cachedBanners = await redis.get(`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`); - if (cachedBanners) return JSON.parse(cachedBanners); + // Don’t implement caching just yet; implement collection caching first, then implement banner caching. + // Please note that currently, a database query is still required to check the collections. + // // Try to get active banners from Redis cache + // const cachedBanners = await redis.get(`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`); + // if (cachedBanners) return JSON.parse(cachedBanners); // If not in cache, fetch from database and cache the result - const activeBanners = await findAllActiveHeroBannerRepository(); + const activeBanners = await findAllActiveHeroBannerRepository(userId); const constructedBanners = activeBanners.map((banner) => ({ id: banner.media.id, title: banner.media.title, @@ -27,11 +30,14 @@ export const getActiveHeroBannerService = async () => { slug: genre.slug, name: genre.name, })), + isInCollection: banner.media._count.inCollections > 0, })); - await redis.set( - `${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`, - JSON.stringify(constructedBanners), - ); + + // await redis.set( + // `${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`, + // JSON.stringify(constructedBanners), + // ); + return constructedBanners; } catch (error) { ErrorForwarder(error);