From e73949295d402dbd69e032918dfb1b5ee7155aa6 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Thu, 20 Feb 2025 07:01:36 +0800 Subject: [PATCH] feat: refactor news components and add news detail layout --- app/components/ui/banner.tsx | 2 +- app/components/ui/button.tsx | 61 ++++---- app/components/ui/carousel.tsx | 238 +++++++++++------------------- app/components/ui/newsletter.tsx | 2 +- app/pages/news-detail/data.ts | 11 ++ app/pages/news-detail/index.tsx | 17 +++ app/pages/news/data.ts | 21 ++- app/pages/news/index.tsx | 2 +- app/pages/news/newsletter.tsx | 3 - app/routes/_layout.news.$slug.tsx | 7 + app/routes/_layout.news.tsx | 7 +- app/types/news.ts | 17 ++- 12 files changed, 179 insertions(+), 209 deletions(-) create mode 100644 app/pages/news-detail/data.ts create mode 100644 app/pages/news-detail/index.tsx delete mode 100644 app/pages/news/newsletter.tsx create mode 100644 app/routes/_layout.news.$slug.tsx diff --git a/app/components/ui/banner.tsx b/app/components/ui/banner.tsx index 3770a44..a20d0eb 100644 --- a/app/components/ui/banner.tsx +++ b/app/components/ui/banner.tsx @@ -2,7 +2,7 @@ import { Link } from 'react-router' import { APP } from '~/data/meta' -export default function Banner() { +export const Banner = () => { return (
diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx index bf4976f..56026c0 100644 --- a/app/components/ui/button.tsx +++ b/app/components/ui/button.tsx @@ -1,10 +1,5 @@ import { cva, type VariantProps } from 'class-variance-authority' -import type { - ButtonHTMLAttributes, - HTMLAttributes, - MouseEventHandler, - ReactNode, -} from 'react' +import type { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react' import { twMerge } from 'tailwind-merge' const buttonVariants = cva( @@ -16,14 +11,6 @@ const buttonVariants = cva( newsPrimaryOutline: 'border-[3px] border-white text-white text-lg', newsSecondary: 'border-[3px] border-[#2E2F7C] text-[#2E2F7C] text-lg', icon: '', - // destructive: - // 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', - // outline: - // 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', - // secondary: - // 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', - // ghost: 'hover:bg-accent hover:text-accent-foreground', - // link: 'text-primary underline-offset-4 hover:underline', }, size: { default: 'h-[50px] w-[150px]', @@ -40,34 +27,38 @@ const buttonVariants = cva( }, ) -type TProperties = { - type?: ButtonHTMLAttributes['type'] - onClick?: MouseEventHandler - className?: HTMLAttributes['className'] - disabled?: boolean +type ButtonBaseProperties = { children: ReactNode variant?: VariantProps['variant'] size?: VariantProps['size'] + className?: string } -export const Button = (properties: TProperties) => { - const { - type = 'button', - onClick, - className, - disabled, - children, - variant, - size, - } = properties +type PolymorphicReference = + ComponentPropsWithoutRef['ref'] + +type ButtonProperties = ButtonBaseProperties & { + as?: C + ref?: PolymorphicReference +} & Omit, keyof ButtonBaseProperties> + +export const Button = ({ + as, + children, + variant, + size, + className, + ...properties +}: ButtonProperties) => { + const Component = as || 'button' + const classes = twMerge(buttonVariants({ variant, size, className })) + return ( - + ) } diff --git a/app/components/ui/carousel.tsx b/app/components/ui/carousel.tsx index 87d3880..47ddb14 100644 --- a/app/components/ui/carousel.tsx +++ b/app/components/ui/carousel.tsx @@ -1,3 +1,4 @@ +import { Link } from 'react-router' import { twMerge } from 'tailwind-merge' import { CarouselNextIcon } from '~/components/icons/carousel-next' @@ -9,159 +10,96 @@ import { Button } from './button' export const Carousel = (properties: TNews) => { const { title, description, items, type } = properties return ( - <> - {/*
-
-
-

{title}

-

- {description} -

-
-
- - -
+
+
+
+

+ {title} +

+

+ {description} +

-
- {items.map(({ image, title, content }, index) => ( -
- {title} -
-
-

- {title} -

-

{content}

-
- -
-
- ))} -
-
*/} -
-
-
-

- {title} -

-

- {description} -

-
- -
- - -
-
-
- {items.map(({ image, title, content, tag }, index) => ( -
- {title} -
-
- {tag?.map((item) => ( - - {item} - - ))} -
- -
-

- {title} -

-

- {content} -

-
- -
-
- ))} +
+ +
- +
+ {items.map(({ featured, title, content, tag, slug }, index) => ( +
+ {title} +
+
+ {tag?.map((item) => ( + + {item} + + ))} +
+ +
+

+ {title} +

+

+ {content} +

+
+ +
+
+ ))} +
+
) } diff --git a/app/components/ui/newsletter.tsx b/app/components/ui/newsletter.tsx index 1c4f212..a21793b 100644 --- a/app/components/ui/newsletter.tsx +++ b/app/components/ui/newsletter.tsx @@ -1,7 +1,7 @@ import { Button } from '~/components/ui/button' import { APP } from '~/data/meta' -export const UiNewsLetter = () => { +export const Newsletter = () => { return ( <>
diff --git a/app/pages/news-detail/data.ts b/app/pages/news-detail/data.ts new file mode 100644 index 0000000..17291a7 --- /dev/null +++ b/app/pages/news-detail/data.ts @@ -0,0 +1,11 @@ +import type { TNewsDetail } from '~/types/news' + +export const CONTENT: TNewsDetail = { + title: 'Hotman Paris Membuka Perpustakaan di tengah Diskotik', + content: + 'Pengacara Kondang, Hotman Paris Hutapea, membuka sebuah perpustakaan baru di dalam diskotik nya yang berlokasi di daerah Jakarta Pusat, Hotman berkata Perpustakaan ini dibuka dengan harapan untuk meningkatkan gairah membaca masyarakat Indonesia, namun sayangnya..', + featured: '/images/news-1.jpg', + slug: 'hotman-paris-membuka-perpustakaan-di-tengah-diskotik', + author: 'John Doe', + date: new Date(), +} diff --git a/app/pages/news-detail/index.tsx b/app/pages/news-detail/index.tsx new file mode 100644 index 0000000..b1e0fa3 --- /dev/null +++ b/app/pages/news-detail/index.tsx @@ -0,0 +1,17 @@ +import { Card } from '~/components/ui/card' + +import { CONTENT } from './data' + +export const NewsDetailPage = () => { + const { title } = CONTENT + return ( +
+ +

+ {title} +

+ News Detail +
+
+ ) +} diff --git a/app/pages/news/data.ts b/app/pages/news/data.ts index 63d4ec2..9888613 100644 --- a/app/pages/news/data.ts +++ b/app/pages/news/data.ts @@ -9,7 +9,8 @@ export const SPOTLIGHT: TNews = { title: 'Hotman Paris Membuka Perpustakaan di tengah Diskotik', content: 'Pengacara Kondang, Hotman Paris Hutapea, membuka sebuah perpustakaan baru di dalam diskotik nya yang berlokasi di daerah Jakarta Pusat, Hotman berkata Perpustakaan ini dibuka dengan harapan untuk meningkatkan gairah membaca masyarakat Indonesia, namun sayangnya..', - image: '/images/news-1.jpg', + featured: '/images/news-1.jpg', + slug: 'hotman-paris-membuka-perpustakaan-di-tengah-diskotik', }, ], } @@ -23,22 +24,25 @@ export const BERITA: TNews = { title: 'Travelling as a way of self-discovery and progress', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-2.jpg', + featured: '/images/news-2.jpg', tag: ['Hukum Property'], + slug: 'travelling-as-a-way-of-self-discovery-and-progress', }, { title: 'How does writing influence your personal brand?', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-3.jpg', + featured: '/images/news-3.jpg', tag: ['Hukum'], + slug: 'how-does-writing-influence-your-personal-brand', }, { title: 'Helping a local business reinvent itself', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-4.jpg', + featured: '/images/news-4.jpg', tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'helping-a-local-business-reinvent-itself', }, ], } @@ -52,22 +56,25 @@ export const KAJIAN: TNews = { title: 'Travelling as a way of self-discovery and progress', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-2.jpg', + featured: '/images/news-2.jpg', tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'travelling-as-a-way-of-self-discovery-and-progress', }, { title: 'How does writing influence your personal brand?', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-3.jpg', + featured: '/images/news-3.jpg', tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'how-does-writing-influence-your-personal-brand', }, { title: 'Helping a local business reinvent itself', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-4.jpg', + featured: '/images/news-4.jpg', tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'helping-a-local-business-reinvent-itself', }, ], } diff --git a/app/pages/news/index.tsx b/app/pages/news/index.tsx index 04c8dee..2528b4c 100644 --- a/app/pages/news/index.tsx +++ b/app/pages/news/index.tsx @@ -1,8 +1,8 @@ import { Card } from '~/components/ui/card' import { Carousel } from '~/components/ui/carousel' +import { Newsletter } from '~/components/ui/newsletter' import { BERITA, KAJIAN, SPOTLIGHT } from './data' -import { Newsletter } from './newsletter' export const NewsPage = () => { return ( diff --git a/app/pages/news/newsletter.tsx b/app/pages/news/newsletter.tsx deleted file mode 100644 index 53057e9..0000000 --- a/app/pages/news/newsletter.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Newsletter = () => { - return
Newsletter
-} diff --git a/app/routes/_layout.news.$slug.tsx b/app/routes/_layout.news.$slug.tsx new file mode 100644 index 0000000..93d567b --- /dev/null +++ b/app/routes/_layout.news.$slug.tsx @@ -0,0 +1,7 @@ +import { NewsDetailPage } from '~/pages/news-detail' + +const NewsDetailLayout = () => { + return +} + +export default NewsDetailLayout diff --git a/app/routes/_layout.news.tsx b/app/routes/_layout.news.tsx index 7c02deb..1977241 100644 --- a/app/routes/_layout.news.tsx +++ b/app/routes/_layout.news.tsx @@ -1,5 +1,6 @@ import { Outlet } from 'react-router' +import { Banner } from '~/components/ui/banner' import { FooterLinks } from '~/layouts/footer-links' import { FooterNewsletter } from '~/layouts/footer-newsletter' import { HeaderMenu } from '~/layouts/header-menu' @@ -13,11 +14,7 @@ const NewsLayout = () => {
- banner +
diff --git a/app/types/news.ts b/app/types/news.ts index df00bd8..fdd854b 100644 --- a/app/types/news.ts +++ b/app/types/news.ts @@ -2,10 +2,15 @@ export type TNews = { title: string description: string type: 'hero' | 'grid' - items: { - title: string - content: string - image: string - tag?: Array - }[] + items: Pick[] +} + +export type TNewsDetail = { + title: string + content: string + featured: string + author: string + date: Date + slug: string + tag?: Array }