feat: enhance news API schema with author and categories details,
desc: update dashboard to display author names, and improve pagination button styles
This commit is contained in:
parent
b61235a3b5
commit
d3dc3b5016
@ -2,19 +2,26 @@ import { z } from 'zod'
|
||||
|
||||
import { HttpServer, type THttpServer } from '~/libs/http-server'
|
||||
|
||||
const authorSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
profile_picture: z.string(),
|
||||
})
|
||||
|
||||
const categoriesCodeSchema = z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
code: z.string(),
|
||||
}),
|
||||
)
|
||||
const newsSchema = z.object({
|
||||
data: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
content: z.string(),
|
||||
categories: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
code: z.string(),
|
||||
}),
|
||||
),
|
||||
categories: categoriesCodeSchema,
|
||||
tags: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
@ -29,15 +36,14 @@ const newsSchema = z.object({
|
||||
live_at: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
author: z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
profile_picture: z.string(),
|
||||
}),
|
||||
author: authorSchema,
|
||||
}),
|
||||
),
|
||||
})
|
||||
|
||||
export type TAuthor = z.infer<typeof authorSchema>
|
||||
export type TCategories = z.infer<typeof categoriesCodeSchema>
|
||||
|
||||
export const getNews = async (parameters: THttpServer) => {
|
||||
try {
|
||||
const { data } = await HttpServer(parameters).get(`/api/news`)
|
||||
|
||||
36
app/app.css
36
app/app.css
@ -37,3 +37,39 @@ nav[aria-label='pagination'] {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
/* Style untuk tombol aktif (current) */
|
||||
.dt-paging-button.current {
|
||||
background-color: #2e2f7c !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Style tombol aktif, kecuali jika disabled */
|
||||
div.dt-container .dt-paging .dt-paging-button.current:not(.disabled),
|
||||
div.dt-container .dt-paging .dt-paging-button.current:not(.disabled):hover {
|
||||
color: white !important;
|
||||
background-color: #2e2f7c !important;
|
||||
min-width: 24px;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
|
||||
/* Style tombol disabled */
|
||||
div.dt-container .dt-paging .dt-paging-button.disabled {
|
||||
background-color: transparent !important;
|
||||
color: #ccc !important;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none; /* Agar tidak bisa diklik */
|
||||
}
|
||||
|
||||
/* Menghindari hover effect untuk tombol yang disabled */
|
||||
div.dt-container .dt-paging .dt-paging-button:not(.disabled):hover {
|
||||
background-color: #2e2f7c !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Style default tombol */
|
||||
div.dt-container .dt-paging .dt-paging-button {
|
||||
min-width: 24px;
|
||||
padding: 3px 6px;
|
||||
background-color: transparent !important;
|
||||
color: #2e2f7c !important;
|
||||
}
|
||||
|
||||
@ -3,8 +3,7 @@ import DataTable from 'datatables.net-react'
|
||||
import React from 'react'
|
||||
|
||||
export type UiTableProperties = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data: any[]
|
||||
data: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
columns: ConfigColumns[]
|
||||
slots?: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
options?: Config
|
||||
|
||||
@ -95,67 +95,6 @@ export const BERITA: TNews = {
|
||||
],
|
||||
}
|
||||
|
||||
export const KAJIAN: TNews = {
|
||||
title: 'KAJIAN',
|
||||
description: DUMMY_DESCRIPTION,
|
||||
items: [
|
||||
{
|
||||
title: 'Travelling as a way of self-discovery and progress ',
|
||||
content:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
|
||||
featured: '/images/news-2.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
slug: 'travelling-as-a-way-of-self-discovery-and-progress ',
|
||||
},
|
||||
{
|
||||
title: 'Travelling as a way of self-discovery and progress ',
|
||||
content:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
|
||||
featured: '/images/news-2.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
slug: 'travelling-as-a-way-of-self-discovery-and-progress ',
|
||||
},
|
||||
{
|
||||
title: 'Travelling as a way of self-discovery and progress ',
|
||||
content:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
|
||||
featured: '/images/news-2.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
slug: 'travelling-as-a-way-of-self-discovery-and-progress ',
|
||||
},
|
||||
{
|
||||
title: 'Travelling as a way of self-discovery and progress ',
|
||||
content:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
|
||||
featured: 'https://placehold.co/600x400.png',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
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.',
|
||||
featured: '/images/news-3.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
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.',
|
||||
featured: '/images/news-4.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
slug: 'helping-a-local-business-reinvent-itself',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const BANNER: TBanner[] = [
|
||||
{
|
||||
id: 1,
|
||||
|
||||
@ -2,11 +2,11 @@ import DT from 'datatables.net-dt'
|
||||
import DataTable from 'datatables.net-react'
|
||||
import { Link, useRouteLoaderData } from 'react-router'
|
||||
|
||||
import type { TAuthor, TCategories } from '~/apis/admin/get-news'
|
||||
import { Button } from '~/components/ui/button'
|
||||
import { UiTable } from '~/components/ui/table'
|
||||
import { TitleDashboard } from '~/components/ui/title-dashboard'
|
||||
import type { loader } from '~/routes/_admin.lg-admin._dashboard.contents'
|
||||
import type { TCategory } from '~/types/news'
|
||||
import { formatDate } from '~/utils/formatter'
|
||||
|
||||
export const ContentsPage = () => {
|
||||
@ -19,8 +19,8 @@ export const ContentsPage = () => {
|
||||
const dataTable = newsData
|
||||
const dataColumns = [
|
||||
{ title: 'No', data: 'id' },
|
||||
{ title: 'Tanggal Konten', data: 'created_at' },
|
||||
{ title: 'Nama Penulis', data: 'author_id' },
|
||||
{ title: 'Tanggal Konten', data: 'live_at' },
|
||||
{ title: 'Nama Penulis', data: 'author' },
|
||||
{ title: 'Judul', data: 'title' },
|
||||
{ title: 'Kategori', data: 'categories' },
|
||||
{
|
||||
@ -34,18 +34,17 @@ export const ContentsPage = () => {
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
data: 'id',
|
||||
data: 'slug',
|
||||
},
|
||||
]
|
||||
const dataSlot = {
|
||||
1: (value: string) => {
|
||||
return formatDate(value)
|
||||
},
|
||||
|
||||
4: (value: TCategory[]) => {
|
||||
return value.map((item: { name: string }) => {
|
||||
return `${item.name}`
|
||||
})
|
||||
2: (value: TAuthor) => `${value.name}`,
|
||||
4: (value: TCategories) => {
|
||||
const categories = value.map((item) => item.name).join(', ')
|
||||
return `${categories}`
|
||||
},
|
||||
6: (value: string | number) => {
|
||||
return (
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DUMMY_DESCRIPTION } from '~/data/contents'
|
||||
import type { TNews, TNewsDetail } from '~/types/news'
|
||||
import type { TNewsDetail } from '~/types/news'
|
||||
|
||||
export const CONTENT: TNewsDetail = {
|
||||
title: 'Hotman Paris Membuka Perpustakaan di tengah Diskotik',
|
||||
@ -38,35 +37,3 @@ export const CONTENT: TNewsDetail = {
|
||||
categories: [],
|
||||
tags: ['Category', 'Popular', 'Trending', 'Latest'],
|
||||
}
|
||||
|
||||
export const BERITA: TNews = {
|
||||
title: 'BERITA',
|
||||
description: DUMMY_DESCRIPTION,
|
||||
items: [
|
||||
{
|
||||
title: 'Travelling as a way of self-discovery and progress',
|
||||
content:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
|
||||
featured: '/images/news-2.jpg',
|
||||
tags: ['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.',
|
||||
featured: '/images/news-3.jpg',
|
||||
tags: ['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.',
|
||||
featured: '/images/news-4.jpg',
|
||||
tags: ['Hukum Property'],
|
||||
isPremium: true,
|
||||
slug: 'helping-a-local-business-reinvent-itself',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ export const NewsDetailPage = () => {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<IconsSocial className="flex-row-reverse" />
|
||||
<IconsSocial className="flex-row" />
|
||||
</div>
|
||||
{/* end next planing create component for this section */}
|
||||
<div className="w-full bg-amber-200">
|
||||
@ -50,7 +50,7 @@ export const NewsDetailPage = () => {
|
||||
{htmlParse(content)}
|
||||
</article>
|
||||
</div>
|
||||
<div className="items-end justify-between border-b-3 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">
|
||||
<p className="mb-2">Share this post</p>
|
||||
<IconsSocial className="a" />
|
||||
@ -66,18 +66,6 @@ export const NewsDetailPage = () => {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 flex items-center gap-2 align-middle">
|
||||
<img
|
||||
src={'https://placehold.co/50x50.png'}
|
||||
alt={title}
|
||||
className="h-12 w-12 rounded-full"
|
||||
/>
|
||||
<div>
|
||||
<h4 className="text-md">{author}</h4>
|
||||
<p className="text-sm">Job title, Company name</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
|
||||
@ -18,41 +18,3 @@ export type TNewsDetail = {
|
||||
isPremium?: boolean
|
||||
categories?: Array<string>
|
||||
}
|
||||
|
||||
export type TTag = {
|
||||
id: string
|
||||
code: string
|
||||
name: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export type TCategory = {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export type Author = {
|
||||
id: string
|
||||
name: string
|
||||
profile_picture: string
|
||||
}
|
||||
|
||||
export type TKontents = {
|
||||
id: string
|
||||
title: string
|
||||
content: string
|
||||
featured_image: string
|
||||
tags: TTag[]
|
||||
categories: TCategory[]
|
||||
is_premium: boolean
|
||||
slug: string
|
||||
author_id: string
|
||||
live_at: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
author: Author
|
||||
}
|
||||
|
||||
@ -12,7 +12,10 @@ type TGetPremiumAttribute = {
|
||||
|
||||
export const getPremiumAttribute = (parameters: TGetPremiumAttribute) => {
|
||||
const { isPremium, slug, onClick, userData } = parameters
|
||||
if (isPremium && (!userData || userData?.subscribe_plan_code === 'basic')) {
|
||||
if (
|
||||
isPremium &&
|
||||
(!userData || userData?.subscribe.subscribe_plan.code === 'basic')
|
||||
) {
|
||||
return {
|
||||
onClick,
|
||||
to: '',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user