diff --git a/app/apis/admin/get-news.ts b/app/apis/admin/get-news.ts index aa860aa..eecfd14 100644 --- a/app/apis/admin/get-news.ts +++ b/app/apis/admin/get-news.ts @@ -1,5 +1,6 @@ import { z } from 'zod' +import { categorySchema } from '~/apis/common/get-categories' import { HttpServer, type THttpServer } from '~/libs/http-server' const authorSchema = z.object({ @@ -7,47 +8,37 @@ const authorSchema = z.object({ 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( + id: z.string(), + title: z.string(), + content: z.string(), + categories: z.array(categorySchema), + tags: z.array( z.object({ id: z.string(), - title: z.string(), - content: z.string(), - categories: categoriesCodeSchema, - tags: z.array( - z.object({ - id: z.string(), - name: z.string(), - code: z.string(), - }), - ), - is_premium: z.boolean(), - slug: z.string(), - featured_image: z.string(), - author_id: z.string(), - live_at: z.string(), - created_at: z.string(), - updated_at: z.string(), - author: authorSchema, + name: z.string(), + code: z.string(), }), ), + is_premium: z.boolean(), + slug: z.string(), + featured_image: z.string(), + author_id: z.string(), + live_at: z.string(), + created_at: z.string(), + updated_at: z.string(), + author: authorSchema, +}) +const dataSchema = z.object({ + data: z.array(newsSchema), }) -export type TAuthor = z.infer -export type TCategories = z.infer +export type TNewsSchema = z.infer export const getNews = async (parameters: THttpServer) => { try { const { data } = await HttpServer(parameters).get(`/api/news`) - return newsSchema.parse(data) + return dataSchema.parse(data) } catch (error) { // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject return Promise.reject(error) diff --git a/app/apis/common/get-categories.ts b/app/apis/common/get-categories.ts index e1cab30..fd4cca1 100644 --- a/app/apis/common/get-categories.ts +++ b/app/apis/common/get-categories.ts @@ -2,22 +2,22 @@ import { z } from 'zod' import { HttpServer, type THttpServer } from '~/libs/http-server' -const categorySchema = z.object({ - data: z.array( - z.object({ - id: z.string(), - code: z.string(), - name: z.string(), - }), - ), +export const categorySchema = z.object({ + id: z.string(), + name: z.string(), + code: z.string(), +}) +const categoriesSchema = z.object({ + data: z.array(categorySchema), }) export type TCategorySchema = z.infer +export type TCategoriesSchema = z.infer export const getCategories = async (parameters?: THttpServer) => { try { const { data } = await HttpServer(parameters).get(`/api/category`) - return categorySchema.parse(data) + return categoriesSchema.parse(data) } catch (error) { // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject return Promise.reject(error) diff --git a/app/apis/common/get-tags.ts b/app/apis/common/get-tags.ts index bf6c36b..ea61719 100644 --- a/app/apis/common/get-tags.ts +++ b/app/apis/common/get-tags.ts @@ -3,13 +3,12 @@ import { z } from 'zod' import { HttpServer, type THttpServer } from '~/libs/http-server' const tagSchema = z.object({ - data: z.array( - z.object({ - id: z.string(), - code: z.string(), - name: z.string(), - }), - ), + id: z.string(), + code: z.string(), + name: z.string(), +}) +const tagsSchema = z.object({ + data: z.array(tagSchema), }) export type TTagSchema = z.infer @@ -17,7 +16,7 @@ export type TTagSchema = z.infer export const getTags = async (parameters?: THttpServer) => { try { const { data } = await HttpServer(parameters).get(`/api/tag`) - return tagSchema.parse(data) + return tagsSchema.parse(data) } catch (error) { // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject return Promise.reject(error) diff --git a/app/layouts/news/header-menu-mobile.tsx b/app/layouts/news/header-menu-mobile.tsx index e4674e9..faa2453 100644 --- a/app/layouts/news/header-menu-mobile.tsx +++ b/app/layouts/news/header-menu-mobile.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Link, useFetcher, useRouteLoaderData } from 'react-router' -import type { TCategorySchema } from '~/apis/common/get-categories' +import type { TCategoriesSchema } from '~/apis/common/get-categories' import { CloseIcon } from '~/components/icons/close' import { MenuIcon } from '~/components/icons/menu' import { Button } from '~/components/ui/button' @@ -10,7 +10,7 @@ import { HeaderSearch } from '~/layouts/news/header-search' import type { loader } from '~/routes/_layout' type THeaderMenuMobile = { - menu?: TCategorySchema['data'] + menu?: TCategoriesSchema['data'] } export default function HeaderMenuMobile(properties: THeaderMenuMobile) { diff --git a/app/pages/dashboard-contents/data.ts b/app/pages/dashboard-contents/data.ts deleted file mode 100644 index 93a4c2c..0000000 --- a/app/pages/dashboard-contents/data.ts +++ /dev/null @@ -1,102 +0,0 @@ -type TContents = { - id: number - createdAt: string - author: string - title: string - tags: string - category: string - status: string -} - -export const CONTENTS: TContents[] = [ - { - id: 1, - createdAt: '24/10/2024', - author: 'John Doe', - title: 'Introduction to TypeScript', - tags: 'Normal', - category: 'Education', - status: 'Published', - }, - { - id: 2, - createdAt: '24/10/2024', - author: 'Jane Smith', - title: 'Advanced React Patterns', - tags: 'Normal', - category: 'Development', - status: 'Draft', - }, - { - id: 3, - createdAt: '24/10/2024', - author: 'Alice Johnson', - title: 'Understanding Redux', - tags: 'Normal', - category: 'Development', - status: 'Published', - }, - { - id: 4, - createdAt: '24/10/2024', - author: 'Bob Brown', - title: 'CSS Grid Layout', - tags: 'Premium', - category: 'Design', - status: 'Published', - }, - { - id: 5, - createdAt: '24/10/2024', - author: 'Charlie Davis', - title: 'Node.js Best Practices', - tags: 'Premium', - category: 'Development', - status: 'Published', - }, - { - id: 6, - createdAt: '24/10/2024', - author: 'Diana Evans', - title: 'GraphQL for Beginners', - tags: 'Premium', - category: 'Development', - status: 'Draft', - }, - { - id: 7, - createdAt: '24/10/2024', - author: 'Evan Harris', - title: 'Building RESTful APIs', - tags: 'Premium', - category: 'Development', - status: 'Published', - }, - { - id: 8, - createdAt: '24/10/2024', - author: 'Fiona Green', - title: 'Introduction to Docker', - tags: 'Normal', - category: 'DevOps', - status: 'Published', - }, - { - id: 9, - createdAt: '24/10/2024', - author: 'George King', - title: 'Microservices Architecture', - tags: 'Normal', - category: 'Development', - status: 'Draft', - }, - { - id: 10, - createdAt: '24/10/2024', - author: 'Hannah Lee', - title: 'Kubernetes Essentials', - tags: 'Normal', - category: 'DevOps', - status: 'Published', - }, -] diff --git a/app/pages/dashboard-contents/index.tsx b/app/pages/dashboard-contents/index.tsx index 5bc737f..5434bc3 100644 --- a/app/pages/dashboard-contents/index.tsx +++ b/app/pages/dashboard-contents/index.tsx @@ -2,7 +2,9 @@ import DT from 'datatables.net-dt' import DataTable from 'datatables.net-react' import { Link, useRouteLoaderData } from 'react-router' -import type { TCategories } from '~/apis/admin/get-news' +import type { TNewsSchema } from '~/apis/admin/get-news' +import type { TCategorySchema } from '~/apis/common/get-categories' +import type { TTagSchema } from '~/apis/common/get-tags' import { Button } from '~/components/ui/button' import { UiTable } from '~/components/ui/table' import { TitleDashboard } from '~/components/ui/title-dashboard' @@ -20,28 +22,31 @@ export const ContentsPage = () => { const dataColumns = [ { title: 'No', - data: undefined, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - render: function (data: any, type: any, row: any, meta: any) { + render: ( + data: unknown, + type: unknown, + row: unknown, + meta: { row: number }, + ) => { return meta.row + 1 }, }, - { title: 'Tanggal Konten', data: 'live_at' }, + { + title: 'Tanggal Konten', + data: 'live_at', + }, { title: 'Nama Penulis', - - data: 'author', }, { title: 'Judul', data: 'title' }, - { title: 'Kategori', data: 'categories' }, { - title: 'Tags', + title: 'Kategori', + data: 'categories', + }, + { title: 'Tag', data: 'tags' }, + { + title: 'Premium', data: 'is_premium', - render: (value: string) => { - return value - ? `Premium` - : `Normal` - }, }, { title: 'Action', @@ -49,28 +54,35 @@ export const ContentsPage = () => { }, ] const dataSlot = { - 1: (value: string) => { - return formatDate(value) - }, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - 2: (value: any, type: any, data: any) => - `${value.name}
ID: ${data.id.slice(0, 12)}`, - 4: (value: TCategories) => { - const categories = value.map((item) => item.name).join(', ') - return `${categories}` - }, - 6: (value: string | number) => { - return ( - - ) - }, + 1: (value: string) => formatDate(value), + 2: (_value: unknown, _type: unknown, data: TNewsSchema) => ( +
+
{data.author.name}
+
ID: {data.id.slice(0, 8)}
+
+ ), + 4: (value: TCategorySchema[]) => value.map((item) => item.name).join(', '), + 5: (value: TTagSchema[]) => value.map((item) => item.name).join(', '), + 6: (value: string) => + value ? ( +
+ Premium +
+ ) : ( +
+ Normal +
+ ), + 7: (value: string) => ( + + ), } const dataOptions = { paging: true, diff --git a/app/utils/formatter.ts b/app/utils/formatter.ts index 0d4bba3..db00613 100644 --- a/app/utils/formatter.ts +++ b/app/utils/formatter.ts @@ -3,9 +3,9 @@ export const formatNumberWithPeriods = (number: number) => { } export const formatDate = (isoDate: string): string => { const date = new Date(isoDate) - const day = date.getDate().toString().padStart(2, '0') - const month = (date.getMonth() + 1).toString().padStart(2, '0') // Month is zero-based - const year = date.getFullYear() - - return `${day}/${month}/${year}` + return new Intl.DateTimeFormat('id-ID', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + }).format(date) }