feat: 콘텐츠 승인 요청 작업
This commit is contained in:
@@ -67,6 +67,15 @@ export class ContentsApiService implements ContentsService {
|
||||
`${ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS}/${contsSn}/${contsVer}`,
|
||||
);
|
||||
}
|
||||
|
||||
public async requestApprove(
|
||||
contsSn: number,
|
||||
contsVer: number,
|
||||
): Promise<void> {
|
||||
await client.put(
|
||||
`${ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS}/${contsSn}/${contsVer}/approveRequest`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ContentsApi = new ContentsApiService();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export { ContentsApi } from "./api/contents-service";
|
||||
export {
|
||||
CONTENTS_APPROVAL_STATUS,
|
||||
CONTENTS_APPROVE_STATUS,
|
||||
contentsFormSchema,
|
||||
type Contents,
|
||||
type ContentsParams,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export const CONTENTS_APPROVAL_STATUS = {
|
||||
export const CONTENTS_APPROVE_STATUS = {
|
||||
DRAFT: "01",
|
||||
REQUESTED: "02",
|
||||
APPROVED: "99",
|
||||
} as const;
|
||||
|
||||
export type ContentsApprovalStatus =
|
||||
(typeof CONTENTS_APPROVAL_STATUS)[keyof typeof CONTENTS_APPROVAL_STATUS];
|
||||
export type ContentsApproveStatus =
|
||||
(typeof CONTENTS_APPROVE_STATUS)[keyof typeof CONTENTS_APPROVE_STATUS];
|
||||
|
||||
export interface ContentsParams extends PageableParams {
|
||||
contsTtl?: string;
|
||||
@@ -19,7 +19,7 @@ export interface ContentsParams extends PageableParams {
|
||||
export interface ContentsVersionParams extends PageableParams {
|
||||
contsSn?: number;
|
||||
contsCn?: string;
|
||||
aprvCd?: string;
|
||||
aprvCd?: ContentsApproveStatus;
|
||||
cclCd?: string;
|
||||
koglCd?: string;
|
||||
tag?: string;
|
||||
@@ -54,7 +54,11 @@ export const contentsDetailSchema = z.object({
|
||||
contsTtl: z.string(),
|
||||
contsCn: z.string(),
|
||||
contsRmrk: z.string().nullish(),
|
||||
aprvCd: z.string(),
|
||||
aprvCd: z.enum([
|
||||
CONTENTS_APPROVE_STATUS.DRAFT,
|
||||
CONTENTS_APPROVE_STATUS.REQUESTED,
|
||||
CONTENTS_APPROVE_STATUS.APPROVED,
|
||||
]),
|
||||
cclCd: z.string().nullish(),
|
||||
koglCd: z.string().nullish(),
|
||||
tag: z.string().nullish(),
|
||||
@@ -91,4 +95,5 @@ export interface ContentsService {
|
||||
data: ContentsFormData,
|
||||
): Promise<void>;
|
||||
deleteContents(contsSn: number, contsVer: number): Promise<void>;
|
||||
requestApprove(contsSn: number, contsVer: number): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import {
|
||||
CONTENTS_APPROVAL_STATUS,
|
||||
CONTENTS_APPROVE_STATUS,
|
||||
ContentsApi,
|
||||
contentsFormSchema,
|
||||
type ContentsFormData,
|
||||
@@ -19,9 +20,13 @@ import {
|
||||
SelectValue,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
Button,
|
||||
} from "@common/components/ui";
|
||||
|
||||
function ModifyPage({ sequential }: { sequential: string }) {
|
||||
const contsSn = Number(sequential);
|
||||
|
||||
const { confirm } = useConfirm();
|
||||
const queryClient = useQueryClient();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
@@ -31,7 +36,7 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
>({});
|
||||
|
||||
const { data: contentsVersionList } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, sequential],
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
queryFn: () =>
|
||||
ContentsApi.getContentsVersionList({
|
||||
contsSn: contsSn,
|
||||
@@ -51,14 +56,14 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, sequential],
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: updateContents } = useMutation({
|
||||
mutationFn: (data: ContentsFormData) =>
|
||||
ContentsApi.updateContents(contsSn, contentsDetail?.contsVer ?? 0, data),
|
||||
ContentsApi.updateContents(contsSn, contentsVersion, data),
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.");
|
||||
},
|
||||
@@ -69,7 +74,17 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
onSuccess: () => {
|
||||
alert("삭제되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, sequential],
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: requestApprove } = useMutation({
|
||||
mutationFn: () => ContentsApi.requestApprove(contsSn, contentsVersion),
|
||||
onSuccess: () => {
|
||||
alert("승인 요청이 완료되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contentsVersion],
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -79,9 +94,18 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
values: contentsDetail,
|
||||
});
|
||||
|
||||
const contsSn = Number(sequential);
|
||||
const isDraftContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.DRAFT;
|
||||
const isRequestedContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.REQUESTED;
|
||||
const isApprovedContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVAL_STATUS.APPROVED;
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.APPROVED;
|
||||
|
||||
const onRequestApprove = async () => {
|
||||
const message =
|
||||
"승인 요청하면 더이상 내용을 수정할 수 없습니다.\n요청하시겠습니까?";
|
||||
if (await confirm(message)) requestApprove();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!contentsVersionList?.content?.length) return;
|
||||
@@ -89,11 +113,7 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
const latestContent = contentsVersionList?.content[0];
|
||||
if (!latestContent) return;
|
||||
|
||||
if (latestContent?.contsVer > 1) {
|
||||
setDisabledFields({
|
||||
contsTtl: true,
|
||||
});
|
||||
}
|
||||
if (latestContent?.contsVer > 1) setDisabledFields({ contsTtl: true });
|
||||
setContentsVersion(latestContent?.contsVer ?? 0);
|
||||
}, [contentsVersionList?.content]);
|
||||
|
||||
@@ -101,7 +121,7 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
<div className="card card-border !mb-0 !mt-6">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">템플릿 수정</h3>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Select
|
||||
value={contentsVersion.toString()}
|
||||
onValueChange={(value) => {
|
||||
@@ -122,6 +142,15 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{isDraftContents && (
|
||||
<Button onClick={onRequestApprove}>승인요청</Button>
|
||||
)}
|
||||
{isRequestedContents && (
|
||||
<>
|
||||
<Button>승인</Button>
|
||||
<Button color="gray">반려</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<ContentsForm
|
||||
|
||||
@@ -24,7 +24,9 @@ function ConfirmDialog({
|
||||
<Dialog open={isOpen ?? isGlobalOpen} onOpenChange={onCancel}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<div className="py-10">
|
||||
<p className="text-center text-[1.4rem] text-foreground">{message}</p>
|
||||
<p className="whitespace-pre-line text-center text-[1.4rem] text-foreground">
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<DialogClose asChild>
|
||||
|
||||
Reference in New Issue
Block a user