From 52085ea25e4343d8f50ac58eca83b1d3fd001c19 Mon Sep 17 00:00:00 2001 From: "fredy.siswanto" Date: Sat, 15 Mar 2025 01:00:32 +0700 Subject: [PATCH] feat: implement subscription update API and enhance news detail loader with user subscription checks --- app/apis/admin/update-subscribe.ts | 36 ++++++++++++++++++++++++++++++ app/routes/_news.detail.$slug.tsx | 32 ++++++++++++++++++-------- app/routes/actions.subscribe.ts | 8 +++++++ 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 app/apis/admin/update-subscribe.ts diff --git a/app/apis/admin/update-subscribe.ts b/app/apis/admin/update-subscribe.ts new file mode 100644 index 0000000..83872fe --- /dev/null +++ b/app/apis/admin/update-subscribe.ts @@ -0,0 +1,36 @@ +import { z } from 'zod' + +import { HttpServer, type THttpServer } from '~/libs/http-server' +import type { TSubscribePlanSchema } from '~/pages/form-subscribe-plan' + +const subscribePlanResponseSchema = z.object({ + data: z.object({ + Message: z.string(), + }), +}) + +type TSubscribeSchema = Pick +type TParameters = { + payload: { subscribe_plan: TSubscribeSchema } +} & THttpServer + +export const updateSubscribeRequest = async (parameters: TParameters) => { + const { payload, ...restParameters } = parameters + const { id } = payload.subscribe_plan + try { + const transformedPayload = { + status: 1, + subscribe_plan_id: id, + } + const { data } = await HttpServer(restParameters).patch( + `/api/subscribe/update`, + transformedPayload, + ) + console.log(data) // eslint-disable-line no-console + + return subscribePlanResponseSchema.parse(data) + } catch (error) { + // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject + return Promise.reject(error) + } +} diff --git a/app/routes/_news.detail.$slug.tsx b/app/routes/_news.detail.$slug.tsx index 6b5fd4a..3d0ead4 100644 --- a/app/routes/_news.detail.$slug.tsx +++ b/app/routes/_news.detail.$slug.tsx @@ -1,8 +1,9 @@ -import { isRouteErrorResponse } from 'react-router' +import { isRouteErrorResponse, redirect } from 'react-router' import { getCategories } from '~/apis/common/get-categories' import { getNews } from '~/apis/common/get-news' import { getNewsBySlug } from '~/apis/common/get-news-by-slug' +import { getUser } from '~/apis/news/get-user' import { APP } from '~/configs/meta' import { handleCookie } from '~/libs/cookies' import { NewsDetailPage } from '~/pages/news-detail' @@ -11,6 +12,10 @@ import type { Route } from './+types/_news.detail.$slug' export const loader = async ({ request, params }: Route.LoaderArgs) => { const { userToken: accessToken } = await handleCookie(request) + if (!accessToken) { + return redirect('/') + } + const { data: userData } = await getUser({ accessToken }) const { slug } = params const { data: newsDetailData } = await getNewsBySlug({ slug, accessToken }) const { data: categoriesData } = await getCategories() @@ -21,6 +26,13 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => { let { data: beritaNews } = await getNews({ categories: [beritaCode] }) beritaNews = beritaNews.filter((news) => new Date(news.live_at) <= new Date()) + if ( + userData.subscribe.subscribe_plan.code === 'basic' && + newsDetailData.is_premium + ) { + return redirect('/') + } + return { newsDetailData, beritaCategory, @@ -29,15 +41,17 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => { } export const meta = ({ data }: Route.MetaArgs) => { - const { newsDetailData } = data - const metaTitle = APP.title - const title = `${newsDetailData.title} - ${metaTitle}` + if (data) { + const { newsDetailData } = data + const metaTitle = APP.title + const title = `${newsDetailData?.title} - ${metaTitle}` - return [ - { - title, - }, - ] + return [ + { + title, + }, + ] + } } export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => { diff --git a/app/routes/actions.subscribe.ts b/app/routes/actions.subscribe.ts index e27badf..355c1e4 100644 --- a/app/routes/actions.subscribe.ts +++ b/app/routes/actions.subscribe.ts @@ -3,6 +3,7 @@ import { data } from 'react-router' import { getValidatedFormData } from 'remix-hook-form' import { XiorError } from 'xior' +import { updateSubscribeRequest } from '~/apis/admin/update-subscribe' import { getUser } from '~/apis/news/get-user' import { subscribeSchema, @@ -32,6 +33,13 @@ export const action = async ({ request }: Route.ActionArgs) => { // TODO: implement subscribe console.log('payload', payload) // eslint-disable-line no-console + // TODO: will run after payment success + const { data: updateSubscribeData } = await updateSubscribeRequest({ + payload, + accessToken, + }) + console.log(updateSubscribeData) // eslint-disable-line no-console + const { data: userData } = await getUser({ accessToken }) return data(