feat: 콘텐츠 승인 로직 작업
This commit is contained in:
@@ -76,6 +76,15 @@ export class ContentsApiService implements ContentsService {
|
||||
`${ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS}/${contsSn}/${contsVer}/approveRequest`,
|
||||
);
|
||||
}
|
||||
|
||||
public async approveContents(
|
||||
contsSn: number,
|
||||
contsVer: number,
|
||||
): Promise<void> {
|
||||
await client.put(
|
||||
`${ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS}/${contsSn}/${contsVer}/approve`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ContentsApi = new ContentsApiService();
|
||||
|
||||
@@ -96,4 +96,5 @@ export interface ContentsService {
|
||||
): Promise<void>;
|
||||
deleteContents(contsSn: number, contsVer: number): Promise<void>;
|
||||
requestApprove(contsSn: number, contsVer: number): Promise<void>;
|
||||
approveContents(contsSn: number, contsVer: number): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ const Editor = ({ ...props }: IAllProps) => {
|
||||
}}
|
||||
init={{
|
||||
...baseConfig.init,
|
||||
disabled: props.disabled,
|
||||
images_upload_handler: imagesUploadHandler,
|
||||
file_picker_callback: filePickerCallback,
|
||||
}}
|
||||
|
||||
@@ -27,7 +27,8 @@ const Editor = dynamic(
|
||||
interface ContentsFormProps {
|
||||
form: UseFormReturn<ContentsFormData>;
|
||||
contsSn?: number;
|
||||
disabledFields?: Partial<Record<keyof ContentsFormData, boolean>>;
|
||||
isEditable?: boolean;
|
||||
isContsTtlDisabled?: boolean;
|
||||
handleSave: (data: ContentsFormData) => Promise<void>;
|
||||
handleDelete?: () => Promise<void>;
|
||||
}
|
||||
@@ -35,7 +36,8 @@ interface ContentsFormProps {
|
||||
function ContentsForm({
|
||||
form,
|
||||
contsSn,
|
||||
disabledFields,
|
||||
isEditable,
|
||||
isContsTtlDisabled,
|
||||
...props
|
||||
}: ContentsFormProps) {
|
||||
const { data: cclCode } = useQuery({
|
||||
@@ -71,7 +73,7 @@ function ContentsForm({
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="콘텐츠 제목을 입력하십시오."
|
||||
disabled={disabledFields?.contsTtl}
|
||||
disabled={!isEditable || isContsTtlDisabled}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
@@ -91,6 +93,7 @@ function ContentsForm({
|
||||
<Editor
|
||||
value={field.value ?? ""}
|
||||
onEditorChange={field.onChange}
|
||||
disabled={!isEditable}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
@@ -112,6 +115,7 @@ function ContentsForm({
|
||||
name="cclCd"
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
disabled={!isEditable}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="" id="ccl-none" />
|
||||
@@ -162,6 +166,7 @@ function ContentsForm({
|
||||
name="koglCd"
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
disabled={!isEditable}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="" id="koglNone" />
|
||||
@@ -214,6 +219,7 @@ function ContentsForm({
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="태그를 입력하십시오."
|
||||
disabled={!isEditable}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
@@ -235,6 +241,7 @@ function ContentsForm({
|
||||
name="useYn"
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
disabled={!isEditable}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
|
||||
@@ -24,16 +24,12 @@ import {
|
||||
} 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);
|
||||
|
||||
const [contentsVersion, setContentsVersion] = useState(0);
|
||||
const [disabledFields, setDisabledFields] = useState<
|
||||
Partial<Record<keyof ContentsFormData, boolean>>
|
||||
>({});
|
||||
const contsSn = Number(sequential);
|
||||
const [contsVer, setContsVer] = useState(0);
|
||||
|
||||
const { data: contentsVersionList } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
@@ -46,14 +42,15 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
});
|
||||
|
||||
const { data: contentsDetail } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contentsVersion],
|
||||
queryFn: () => ContentsApi.getLatestContentsInfo(contsSn, contentsVersion),
|
||||
enabled: !!contentsVersion,
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsVer],
|
||||
queryFn: () => ContentsApi.getLatestContentsInfo(contsSn, contsVer),
|
||||
enabled: !!contsVer,
|
||||
});
|
||||
|
||||
const { mutateAsync: createContents } = useMutation({
|
||||
mutationFn: (data: ContentsFormData) => ContentsApi.createContents(data),
|
||||
onSuccess: () => {
|
||||
setContsVer(0);
|
||||
alert("수정되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
@@ -63,15 +60,16 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
|
||||
const { mutateAsync: updateContents } = useMutation({
|
||||
mutationFn: (data: ContentsFormData) =>
|
||||
ContentsApi.updateContents(contsSn, contentsVersion, data),
|
||||
ContentsApi.updateContents(contsSn, contsVer, data),
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: deleteContents } = useMutation({
|
||||
mutationFn: () => ContentsApi.deleteContents(contsSn, contentsVersion),
|
||||
mutationFn: () => ContentsApi.deleteContents(contsSn, contsVer),
|
||||
onSuccess: () => {
|
||||
setContsVer(0);
|
||||
alert("삭제되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
@@ -80,11 +78,21 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
});
|
||||
|
||||
const { mutateAsync: requestApprove } = useMutation({
|
||||
mutationFn: () => ContentsApi.requestApprove(contsSn, contentsVersion),
|
||||
mutationFn: () => ContentsApi.requestApprove(contsSn, contsVer),
|
||||
onSuccess: () => {
|
||||
alert("승인 요청이 완료되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contentsVersion],
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: approveContents } = useMutation({
|
||||
mutationFn: () => ContentsApi.approveContents(contsSn, contsVer),
|
||||
onSuccess: () => {
|
||||
alert("승인되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS],
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -94,12 +102,9 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
values: contentsDetail,
|
||||
});
|
||||
|
||||
const isDraftContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.DRAFT;
|
||||
const isRequestedContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.REQUESTED;
|
||||
const isApprovedContents =
|
||||
contentsDetail?.aprvCd === CONTENTS_APPROVE_STATUS.APPROVED;
|
||||
const approveStatus = contentsDetail?.aprvCd;
|
||||
const isContsTtlDisabled =
|
||||
(contentsVersionList?.content?.[0]?.contsVer ?? 0) > 1;
|
||||
|
||||
const onRequestApprove = async () => {
|
||||
const message =
|
||||
@@ -107,14 +112,19 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
if (await confirm(message)) requestApprove();
|
||||
};
|
||||
|
||||
const onApprove = async () => {
|
||||
const message = "승인하시겠습니까?";
|
||||
if (await confirm(message)) approveContents();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (contsVer) return;
|
||||
if (!contentsVersionList?.content?.length) return;
|
||||
|
||||
const latestContent = contentsVersionList?.content[0];
|
||||
if (!latestContent) return;
|
||||
|
||||
if (latestContent?.contsVer > 1) setDisabledFields({ contsTtl: true });
|
||||
setContentsVersion(latestContent?.contsVer ?? 0);
|
||||
setContsVer(latestContent?.contsVer ?? 0);
|
||||
}, [contentsVersionList?.content]);
|
||||
|
||||
return (
|
||||
@@ -123,9 +133,9 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
<h3 className="text-2xl font-medium text-label">템플릿 수정</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<Select
|
||||
value={contentsVersion.toString()}
|
||||
value={contsVer.toString()}
|
||||
onValueChange={(value) => {
|
||||
setContentsVersion(Number(value));
|
||||
setContsVer(Number(value));
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-[28rem]">
|
||||
@@ -142,12 +152,12 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{isDraftContents && (
|
||||
{approveStatus === CONTENTS_APPROVE_STATUS.DRAFT && (
|
||||
<Button onClick={onRequestApprove}>승인요청</Button>
|
||||
)}
|
||||
{isRequestedContents && (
|
||||
{approveStatus === CONTENTS_APPROVE_STATUS.REQUESTED && (
|
||||
<>
|
||||
<Button>승인</Button>
|
||||
<Button onClick={onApprove}>승인</Button>
|
||||
<Button color="gray">반려</Button>
|
||||
</>
|
||||
)}
|
||||
@@ -156,8 +166,13 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
<ContentsForm
|
||||
form={form}
|
||||
contsSn={contsSn}
|
||||
disabledFields={disabledFields}
|
||||
handleSave={isApprovedContents ? createContents : updateContents}
|
||||
isEditable={approveStatus !== CONTENTS_APPROVE_STATUS.REQUESTED}
|
||||
isContsTtlDisabled={isContsTtlDisabled}
|
||||
handleSave={
|
||||
approveStatus === CONTENTS_APPROVE_STATUS.APPROVED
|
||||
? createContents
|
||||
: updateContents
|
||||
}
|
||||
handleDelete={deleteContents}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user