From 1b4ff4c3e7909b489638ef70433a6a71d9ab60ce Mon Sep 17 00:00:00 2001 From: Ardeman Date: Mon, 3 Mar 2025 08:59:06 +0800 Subject: [PATCH] feat: refactor user handling in news components and add premium attribute logic --- app/apis/news/get-user.ts | 6 ++++-- app/components/ui/carousel-hero.tsx | 5 +++++ app/components/ui/carousel-section.tsx | 5 +++++ app/components/ui/category-section.tsx | 5 +++++ app/utils/{render.ts => render.tsx} | 7 +++++-- 5 files changed, 24 insertions(+), 4 deletions(-) rename app/utils/{render.ts => render.tsx} (63%) diff --git a/app/apis/news/get-user.ts b/app/apis/news/get-user.ts index 858c943..060d820 100644 --- a/app/apis/news/get-user.ts +++ b/app/apis/news/get-user.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { HttpServer, type THttpServer } from '~/libs/http-server' -const playerSchema = z.object({ +const userSchema = z.object({ data: z.object({ id: z.string(), email: z.string(), @@ -12,10 +12,12 @@ const playerSchema = z.object({ }), }) +export type TUser = z.infer + export const getUser = async (parameters: THttpServer) => { try { const { data } = await HttpServer(parameters).get(`/api/user/profile`) - return playerSchema.parse(data) + return userSchema.parse(data) } catch (error) { // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject return Promise.reject(error) diff --git a/app/components/ui/carousel-hero.tsx b/app/components/ui/carousel-hero.tsx index 2715f16..7ab2966 100644 --- a/app/components/ui/carousel-hero.tsx +++ b/app/components/ui/carousel-hero.tsx @@ -1,14 +1,18 @@ import useEmblaCarousel from 'embla-carousel-react' import { useCallback, useEffect, useState } from 'react' +import { useRouteLoaderData } from 'react-router' import { Button } from '~/components/ui/button' import { CarouselButton } from '~/components/ui/button-slide' import { useNewsContext } from '~/contexts/news' +import type { loader } from '~/routes/_layout' import type { TNews } from '~/types/news' import { getPremiumAttribute } from '~/utils/render' export const CarouselHero = (properties: TNews) => { const { setIsSuccessOpen } = useNewsContext() + const loaderData = useRouteLoaderData('routes/_layout') + const userData = loaderData?.userData const { title, description, items } = properties const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false }) @@ -93,6 +97,7 @@ export const CarouselHero = (properties: TNews) => { isPremium, slug, onClick: () => setIsSuccessOpen('warning'), + userData, })} > View More diff --git a/app/components/ui/carousel-section.tsx b/app/components/ui/carousel-section.tsx index 364fe95..8173721 100644 --- a/app/components/ui/carousel-section.tsx +++ b/app/components/ui/carousel-section.tsx @@ -1,14 +1,18 @@ import useEmblaCarousel from 'embla-carousel-react' import { useCallback, useEffect, useState } from 'react' +import { useRouteLoaderData } from 'react-router' import { Button } from '~/components/ui/button' import { CarouselButton } from '~/components/ui/button-slide' import { useNewsContext } from '~/contexts/news' +import type { loader } from '~/routes/_layout' import type { TNews } from '~/types/news' import { getPremiumAttribute } from '~/utils/render' export const CarouselSection = (properties: TNews) => { const { setIsSuccessOpen } = useNewsContext() + const loaderData = useRouteLoaderData('routes/_layout') + const userData = loaderData?.userData const { title, description, items } = properties const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false, @@ -115,6 +119,7 @@ export const CarouselSection = (properties: TNews) => { isPremium, slug, onClick: () => setIsSuccessOpen('warning'), + userData, })} className="mb-5" > diff --git a/app/components/ui/category-section.tsx b/app/components/ui/category-section.tsx index 89eb6ba..2586bb4 100644 --- a/app/components/ui/category-section.tsx +++ b/app/components/ui/category-section.tsx @@ -1,14 +1,18 @@ +import { useRouteLoaderData } from 'react-router' import { twMerge } from 'tailwind-merge' import { CarouselNextIcon } from '~/components/icons/carousel-next' import { CarouselPreviousIcon } from '~/components/icons/carousel-previous' import { Button } from '~/components/ui/button' import { useNewsContext } from '~/contexts/news' +import type { loader } from '~/routes/_layout' import type { TNews } from '~/types/news' import { getPremiumAttribute } from '~/utils/render' export const CategorySection = (properties: TNews) => { const { setIsSuccessOpen } = useNewsContext() + const loaderData = useRouteLoaderData('routes/_layout') + const userData = loaderData?.userData const { title, description, items } = properties @@ -86,6 +90,7 @@ export const CategorySection = (properties: TNews) => { isPremium, slug, onClick: () => setIsSuccessOpen('warning'), + userData, })} className="mb-5" > diff --git a/app/utils/render.ts b/app/utils/render.tsx similarity index 63% rename from app/utils/render.ts rename to app/utils/render.tsx index bae2c03..6989a95 100644 --- a/app/utils/render.ts +++ b/app/utils/render.tsx @@ -1,15 +1,18 @@ import type { MouseEventHandler } from 'react' import { Link } from 'react-router' +import type { TUser } from '~/apis/news/get-user' + type TGetPremiumAttribute = { isPremium?: boolean slug: string onClick: MouseEventHandler + userData?: TUser['data'] } export const getPremiumAttribute = (parameters: TGetPremiumAttribute) => { - const { isPremium, slug, onClick } = parameters - if (isPremium) { + const { isPremium, slug, onClick, userData } = parameters + if (isPremium && (!userData || userData?.subscribe_plan_code === 'basic')) { return { onClick, to: '',