feat: implement createNews API and integrate with content creation flow
This commit is contained in:
parent
894698c5d6
commit
414806734d
39
app/apis/admin/create-news.ts
Normal file
39
app/apis/admin/create-news.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
import { HttpServer } from '~/libs/http-server'
|
||||||
|
import type { TContentSchema } from '~/pages/contents-create'
|
||||||
|
|
||||||
|
const newsResponseSchema = z.object({
|
||||||
|
data: z.object({
|
||||||
|
Message: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
type TParameter = {
|
||||||
|
accessToken: string
|
||||||
|
payload: TContentSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createNewsRequest = async (parameters: TParameter) => {
|
||||||
|
const { accessToken, payload } = parameters
|
||||||
|
try {
|
||||||
|
const { categories, tags, ...restPayload } = payload
|
||||||
|
const transformedPayload = {
|
||||||
|
...restPayload,
|
||||||
|
categories: categories.map((category) => category?.code),
|
||||||
|
tags: tags?.map((tag) => tag?.code),
|
||||||
|
live_at: new Date(payload?.live_at).toISOString(),
|
||||||
|
}
|
||||||
|
if (transformedPayload.tags?.length === 0) {
|
||||||
|
delete transformedPayload.tags
|
||||||
|
}
|
||||||
|
const { data } = await HttpServer({ accessToken }).post(
|
||||||
|
'/api/news/create',
|
||||||
|
transformedPayload,
|
||||||
|
)
|
||||||
|
return newsResponseSchema.parse(data)
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line unicorn/no-useless-promise-resolve-reject
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -84,6 +84,7 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
|
|||||||
types: ['heading', 'paragraph'],
|
types: ['heading', 'paragraph'],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
immediatelyRender: false,
|
||||||
content: watchContent,
|
content: watchContent,
|
||||||
onUpdate: ({ editor }) => {
|
onUpdate: ({ editor }) => {
|
||||||
setValue(name, editor.getHTML() as any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
setValue(name, editor.getHTML() as any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { DevTool } from '@hookform/devtools'
|
import { DevTool } from '@hookform/devtools'
|
||||||
import { zodResolver } from '@hookform/resolvers/zod'
|
import { zodResolver } from '@hookform/resolvers/zod'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useFetcher, useRouteLoaderData } from 'react-router'
|
import { useFetcher, useNavigate, useRouteLoaderData } from 'react-router'
|
||||||
import { RemixFormProvider, useRemixForm } from 'remix-hook-form'
|
import { RemixFormProvider, useRemixForm } from 'remix-hook-form'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
@ -27,16 +27,18 @@ export const contentSchema = z.object({
|
|||||||
.refine((data) => !!data, {
|
.refine((data) => !!data, {
|
||||||
message: 'Please select a category',
|
message: 'Please select a category',
|
||||||
}),
|
}),
|
||||||
tags: z.array(
|
tags: z
|
||||||
z
|
.array(
|
||||||
.object({
|
z
|
||||||
id: z.string(),
|
.object({
|
||||||
code: z.string(),
|
id: z.string(),
|
||||||
name: z.string(),
|
code: z.string(),
|
||||||
})
|
name: z.string(),
|
||||||
.optional()
|
})
|
||||||
.nullable(),
|
.optional()
|
||||||
),
|
.nullable(),
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
title: z.string().min(1, {
|
title: z.string().min(1, {
|
||||||
message: 'Judul is required',
|
message: 'Judul is required',
|
||||||
}),
|
}),
|
||||||
@ -54,6 +56,7 @@ export type TContentSchema = z.infer<typeof contentSchema>
|
|||||||
|
|
||||||
export const CreateContentsPage = () => {
|
export const CreateContentsPage = () => {
|
||||||
const fetcher = useFetcher()
|
const fetcher = useFetcher()
|
||||||
|
const navigate = useNavigate()
|
||||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin')
|
const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin')
|
||||||
const categories = loaderData?.categoriesData
|
const categories = loaderData?.categoriesData
|
||||||
const tags = loaderData?.tagsData
|
const tags = loaderData?.tagsData
|
||||||
@ -77,6 +80,7 @@ export const CreateContentsPage = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
navigate('/lg-admin/contents')
|
||||||
setDisabled(true)
|
setDisabled(true)
|
||||||
setError(undefined)
|
setError(undefined)
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { data } from 'react-router'
|
|||||||
import { getValidatedFormData } from 'remix-hook-form'
|
import { getValidatedFormData } from 'remix-hook-form'
|
||||||
import { XiorError } from 'xior'
|
import { XiorError } from 'xior'
|
||||||
|
|
||||||
|
import { createNewsRequest } from '~/apis/admin/create-news'
|
||||||
import { handleCookie } from '~/libs/cookies'
|
import { handleCookie } from '~/libs/cookies'
|
||||||
import { contentSchema, type TContentSchema } from '~/pages/contents-create'
|
import { contentSchema, type TContentSchema } from '~/pages/contents-create'
|
||||||
|
|
||||||
@ -25,17 +26,15 @@ export const action = async ({ request }: Route.ActionArgs) => {
|
|||||||
return data({ success: false, errors, defaultValues }, { status: 400 })
|
return data({ success: false, errors, defaultValues }, { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement subscribe
|
const { data: newsData } = await createNewsRequest({
|
||||||
console.log('payload', payload) // eslint-disable-line no-console
|
accessToken: staffToken,
|
||||||
console.log('staffToken', staffToken) // eslint-disable-line no-console
|
payload,
|
||||||
|
})
|
||||||
// const { data: userData } = await getUser({
|
|
||||||
// accessToken: userToken,
|
|
||||||
// })
|
|
||||||
|
|
||||||
return data(
|
return data(
|
||||||
{
|
{
|
||||||
success: true,
|
success: true,
|
||||||
|
newsData,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user