feat: enhance news detail page with subscription prompt and content restriction for basic users
This commit is contained in:
parent
c7195b7428
commit
cc5331284b
@ -1,16 +1,20 @@
|
|||||||
import htmlParse from 'html-react-parser'
|
import htmlParse from 'html-react-parser'
|
||||||
import { useReadingTime } from 'react-hook-reading-time'
|
import { useReadingTime } from 'react-hook-reading-time'
|
||||||
import { useRouteLoaderData } from 'react-router'
|
import { useRouteLoaderData } from 'react-router'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
import { Button } from '~/components/ui/button'
|
||||||
import { Card } from '~/components/ui/card'
|
import { Card } from '~/components/ui/card'
|
||||||
import { CarouselSection } from '~/components/ui/carousel-section'
|
import { CarouselSection } from '~/components/ui/carousel-section'
|
||||||
import { NewsAuthor } from '~/components/ui/news-author'
|
import { NewsAuthor } from '~/components/ui/news-author'
|
||||||
import { SocialShareButtons } from '~/components/ui/social-share'
|
import { SocialShareButtons } from '~/components/ui/social-share'
|
||||||
import { Tags } from '~/components/ui/tags'
|
import { Tags } from '~/components/ui/tags'
|
||||||
|
import { useNewsContext } from '~/contexts/news'
|
||||||
import type { loader } from '~/routes/_news.detail.$slug'
|
import type { loader } from '~/routes/_news.detail.$slug'
|
||||||
import type { TNews } from '~/types/news'
|
import type { TNews } from '~/types/news'
|
||||||
|
|
||||||
export const NewsDetailPage = () => {
|
export const NewsDetailPage = () => {
|
||||||
|
const { setIsSuccessOpen } = useNewsContext()
|
||||||
const loaderData = useRouteLoaderData<typeof loader>(
|
const loaderData = useRouteLoaderData<typeof loader>(
|
||||||
'routes/_news.detail.$slug',
|
'routes/_news.detail.$slug',
|
||||||
)
|
)
|
||||||
@ -22,6 +26,7 @@ export const NewsDetailPage = () => {
|
|||||||
const currentUrl = globalThis.location
|
const currentUrl = globalThis.location
|
||||||
const { title, content, featured_image, author, live_at, tags } =
|
const { title, content, featured_image, author, live_at, tags } =
|
||||||
loaderData?.newsDetailData || {}
|
loaderData?.newsDetailData || {}
|
||||||
|
const { shouldSubscribe } = loaderData || {}
|
||||||
|
|
||||||
const { text } = useReadingTime(content || '')
|
const { text } = useReadingTime(content || '')
|
||||||
|
|
||||||
@ -51,10 +56,23 @@ export const NewsDetailPage = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 flex items-center justify-center">
|
<div className="mt-8 flex flex-col items-center justify-center gap-y-4">
|
||||||
<article className="prose prose-headings:my-0.5 prose-p:my-0.5">
|
<article
|
||||||
|
className={twMerge(
|
||||||
|
'prose prose-headings:my-0.5 prose-p:my-0.5',
|
||||||
|
shouldSubscribe ? 'line-clamp-5' : '',
|
||||||
|
)}
|
||||||
|
>
|
||||||
{content && htmlParse(content)}
|
{content && htmlParse(content)}
|
||||||
</article>
|
</article>
|
||||||
|
{shouldSubscribe && (
|
||||||
|
<Button
|
||||||
|
onClick={() => setIsSuccessOpen('warning')}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
Read More
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="items-end justify-between border-b-gray-300 py-4 sm:flex">
|
<div className="items-end justify-between border-b-gray-300 py-4 sm:flex">
|
||||||
<div className="flex flex-col max-sm:mb-3">
|
<div className="flex flex-col max-sm:mb-3">
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { isRouteErrorResponse, redirect } from 'react-router'
|
import { isRouteErrorResponse } from 'react-router'
|
||||||
|
import { stripHtml } from 'string-strip-html'
|
||||||
|
|
||||||
import { getCategories } from '~/apis/common/get-categories'
|
import { getCategories } from '~/apis/common/get-categories'
|
||||||
import { getNews } from '~/apis/common/get-news'
|
import { getNews } from '~/apis/common/get-news'
|
||||||
@ -12,17 +13,21 @@ import type { Route } from './+types/_news.detail.$slug'
|
|||||||
|
|
||||||
export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
||||||
const { userToken: accessToken } = await handleCookie(request)
|
const { userToken: accessToken } = await handleCookie(request)
|
||||||
if (!accessToken) {
|
let userData
|
||||||
return redirect('/')
|
if (accessToken) {
|
||||||
|
const { data } = await getUser({ accessToken })
|
||||||
|
userData = data
|
||||||
}
|
}
|
||||||
const { data: userData } = await getUser({ accessToken })
|
|
||||||
const { slug } = params
|
const { slug } = params
|
||||||
const { data: newsDetailData } = await getNewsBySlug({ slug, accessToken })
|
let { data: newsDetailData } = await getNewsBySlug({ slug, accessToken })
|
||||||
if (
|
const shouldSubscribe =
|
||||||
userData.subscribe.subscribe_plan.code === 'basic' &&
|
(!accessToken || userData?.subscribe?.subscribe_plan?.code === 'basic') &&
|
||||||
newsDetailData.is_premium
|
newsDetailData?.is_premium
|
||||||
) {
|
newsDetailData = {
|
||||||
return redirect('/')
|
...newsDetailData,
|
||||||
|
content: shouldSubscribe
|
||||||
|
? stripHtml(newsDetailData.content).result.slice(0, 600)
|
||||||
|
: newsDetailData.content,
|
||||||
}
|
}
|
||||||
const { data: categoriesData } = await getCategories()
|
const { data: categoriesData } = await getCategories()
|
||||||
const beritaCode = 'berita'
|
const beritaCode = 'berita'
|
||||||
@ -36,12 +41,12 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
|||||||
newsDetailData,
|
newsDetailData,
|
||||||
beritaCategory,
|
beritaCategory,
|
||||||
beritaNews,
|
beritaNews,
|
||||||
|
shouldSubscribe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const meta = ({ data }: Route.MetaArgs) => {
|
export const meta = ({ data }: Route.MetaArgs) => {
|
||||||
if (data) {
|
const { newsDetailData } = data || {}
|
||||||
const { newsDetailData } = data
|
|
||||||
const metaTitle = APP.title
|
const metaTitle = APP.title
|
||||||
const title = `${newsDetailData?.title} - ${metaTitle}`
|
const title = `${newsDetailData?.title} - ${metaTitle}`
|
||||||
|
|
||||||
@ -51,7 +56,6 @@ export const meta = ({ data }: Route.MetaArgs) => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
|
export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
|
||||||
let message = 'Oops!'
|
let message = 'Oops!'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user