feat:approval
This commit is contained in:
parent
33fcdd670c
commit
e4dd1da844
|
|
@ -18,13 +18,22 @@ import {
|
|||
deleteArticleFiles,
|
||||
getArticleByCategory,
|
||||
getArticleById,
|
||||
submitApproval,
|
||||
updateArticle,
|
||||
uploadArticleFile,
|
||||
uploadArticleThumbnail,
|
||||
} from "@/service/article";
|
||||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
import { Chip } from "@heroui/react";
|
||||
import {
|
||||
Chip,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
useDisclosure,
|
||||
} from "@heroui/react";
|
||||
import GenerateSingleArticleForm from "./generate-ai-single-form";
|
||||
import { htmlToString } from "@/utils/global";
|
||||
import { close, error, loading } from "@/config/swal";
|
||||
|
|
@ -112,6 +121,10 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
null
|
||||
);
|
||||
const [thumbnailValidation, setThumbnailValidation] = useState("");
|
||||
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
||||
const [approvalStatus, setApprovalStatus] = useState<number>(2);
|
||||
const [approvalMessage, setApprovalMessage] = useState("");
|
||||
const [detailData, setDetailData] = useState<any>();
|
||||
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
onDrop: (acceptedFiles) => {
|
||||
|
|
@ -151,6 +164,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
loading();
|
||||
const res = await getArticleById(id);
|
||||
const data = res.data?.data;
|
||||
setDetailData(data);
|
||||
setValue("title", data?.title);
|
||||
setValue("slug", data?.slug);
|
||||
setValue("description", data?.htmlDescription);
|
||||
|
|
@ -161,15 +175,14 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
|
||||
setupInitCategory(data?.categories);
|
||||
close();
|
||||
console.log("Data Aritcle", data?.files);
|
||||
}
|
||||
|
||||
const setupInitCategory = (data: any) => {
|
||||
const temp: CategoryType[] = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
for (let i = 0; i < data?.length; i++) {
|
||||
const datas = listCategory.filter((a) => a.id == data[i].id);
|
||||
if (datas[0]) {
|
||||
temp.push(datas[0]); // Hanya tambahkan jika datas[0] ada
|
||||
temp.push(datas[0]);
|
||||
}
|
||||
}
|
||||
setValue("category", temp as [CategoryType, ...CategoryType[]]);
|
||||
|
|
@ -373,6 +386,49 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
}
|
||||
};
|
||||
|
||||
const approval = async () => {
|
||||
loading();
|
||||
const req = {
|
||||
articleId: Number(id),
|
||||
message: approvalMessage,
|
||||
statusId: approvalStatus,
|
||||
};
|
||||
const res = await submitApproval(req);
|
||||
|
||||
if (res?.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
initState();
|
||||
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "OK",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const doApproval = () => {
|
||||
MySwal.fire({
|
||||
title: "Submit Data?",
|
||||
text: "",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Submit",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
approval();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex flex-col lg:flex-row gap-8 text-black"
|
||||
|
|
@ -767,6 +823,30 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
)}
|
||||
</div>
|
||||
<div className="flex flex-row justify-end gap-3">
|
||||
{isDetail && detailData?.statusId === 1 && (
|
||||
<Button
|
||||
color="primary"
|
||||
type="button"
|
||||
onPress={() => {
|
||||
setApprovalStatus(2);
|
||||
onOpen();
|
||||
}}
|
||||
>
|
||||
Setujui
|
||||
</Button>
|
||||
)}
|
||||
{isDetail && detailData?.statusId === 1 && (
|
||||
<Button
|
||||
color="danger"
|
||||
type="button"
|
||||
onPress={() => {
|
||||
setApprovalStatus(3);
|
||||
onOpen();
|
||||
}}
|
||||
>
|
||||
Tolak
|
||||
</Button>
|
||||
)}
|
||||
{!isDetail && (
|
||||
<Button color="primary" type="submit">
|
||||
Publish
|
||||
|
|
@ -783,6 +863,57 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
<ModalContent>
|
||||
{(onClose) => (
|
||||
<>
|
||||
<ModalHeader className="flex flex-col">Approval</ModalHeader>
|
||||
<ModalBody>
|
||||
<p className="text-sm">
|
||||
Status :
|
||||
<span
|
||||
className={
|
||||
approvalStatus === 3 ? "text-primary" : "text-danger"
|
||||
}
|
||||
>
|
||||
{" "}
|
||||
{approvalStatus === 3 ? "Disetujui" : "Ditolak"}
|
||||
</span>
|
||||
</p>
|
||||
<Textarea
|
||||
labelPlacement="outside"
|
||||
label="Pesan "
|
||||
placeholder="Masukkan pesan"
|
||||
variant="bordered"
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
value={approvalMessage}
|
||||
onValueChange={setApprovalMessage}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="primary" onPress={doApproval}>
|
||||
Submit
|
||||
</Button>
|
||||
<Button
|
||||
color="danger"
|
||||
variant="light"
|
||||
onPress={() => {
|
||||
setApprovalMessage("");
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -104,10 +104,10 @@ export default function ENewsPolri() {
|
|||
</div>
|
||||
</div>
|
||||
<Link
|
||||
className="flex items-center gap-2 text-[#DD8306] mt-3"
|
||||
className="flex items-center gap-2 text-[#bb3523] mt-3"
|
||||
href="/e-majalah-polri/daftar-majalah"
|
||||
>
|
||||
Lihat Semua <ChevronRightIcon color="[#DD8306]" />
|
||||
Lihat Semua <ChevronRightIcon color="[#bb3523]" />
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,12 @@ export default function HeaderNews() {
|
|||
}, []);
|
||||
|
||||
async function getArticle() {
|
||||
const req = { page: 1, search: "", limit: "10", sort: "desc" };
|
||||
const req = {
|
||||
page: 1,
|
||||
search: "",
|
||||
limit: "10",
|
||||
sort: "desc",
|
||||
};
|
||||
const response = await getListArticle(req);
|
||||
setArticle(response?.data?.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ const columns = [
|
|||
{ name: "Kategori", uid: "category" },
|
||||
{ name: "Tanggal Unggah", uid: "createdAt" },
|
||||
{ name: "Kreator", uid: "createdByName" },
|
||||
// { name: "Status", uid: "isPublish" },
|
||||
{ name: "Aksi", uid: "actions" },
|
||||
];
|
||||
|
||||
|
|
@ -89,7 +90,6 @@ export default function ArticleTable() {
|
|||
}
|
||||
|
||||
async function initState() {
|
||||
console.log("seeecle", Array.from(selectedCategories));
|
||||
const req = {
|
||||
limit: showData,
|
||||
page: page,
|
||||
|
|
@ -98,6 +98,8 @@ export default function ArticleTable() {
|
|||
startDateValue.startDate === null ? "" : startDateValue.startDate,
|
||||
endDate: startDateValue.endDate === null ? "" : startDateValue.endDate,
|
||||
category: Array.from(selectedCategories).join(","),
|
||||
sort: "desc",
|
||||
sortBy: "created_at",
|
||||
};
|
||||
const res = await getListArticle(req);
|
||||
getTableNumber(parseInt(showData), res.data?.data);
|
||||
|
|
@ -148,25 +150,21 @@ export default function ArticleTable() {
|
|||
const renderCell = useCallback(
|
||||
(article: any, columnKey: Key) => {
|
||||
const cellValue = article[columnKey as keyof any];
|
||||
const statusColorMap: Record<string, ChipProps["color"]> = {
|
||||
active: "primary",
|
||||
cancel: "danger",
|
||||
pending: "success",
|
||||
};
|
||||
|
||||
switch (columnKey) {
|
||||
case "status":
|
||||
case "isPublish":
|
||||
return (
|
||||
<Chip
|
||||
className="capitalize "
|
||||
color={statusColorMap[article.status]}
|
||||
size="lg"
|
||||
variant="flat"
|
||||
>
|
||||
<div className="flex flex-row items-center gap-2 justify-center">
|
||||
{article.status}
|
||||
</div>
|
||||
</Chip>
|
||||
// <Chip
|
||||
// className="capitalize "
|
||||
// color={statusColorMap[article.status]}
|
||||
// size="lg"
|
||||
// variant="flat"
|
||||
// >
|
||||
// <div className="flex flex-row items-center gap-2 justify-center">
|
||||
// {article.status}
|
||||
// </div>
|
||||
// </Chip>
|
||||
<p>{article.isPublish ? "Publish" : "Draft"}</p>
|
||||
);
|
||||
case "createdAt":
|
||||
return <p>{convertDateFormat(article.createdAt)}</p>;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export function loading(msg?: any) {
|
|||
timerProgressBar: true,
|
||||
didOpen: () => {
|
||||
MySwal.showLoading();
|
||||
timerInterval = setInterval(() => { }, 100);
|
||||
timerInterval = setInterval(() => {}, 100);
|
||||
},
|
||||
willClose: () => {
|
||||
clearInterval(timerInterval);
|
||||
|
|
@ -37,6 +37,10 @@ export function error(msg?: any) {
|
|||
icon: "error",
|
||||
title: "Failed...",
|
||||
text: msg || "Unknown Error",
|
||||
customClass: {
|
||||
popup: "custom-popup",
|
||||
confirmButton: "custom-button",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -91,5 +95,3 @@ export function successToast(title: string, text: string) {
|
|||
text: text,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export async function getArticleByCategory() {
|
|||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpGet(`/article-categories?limit=50`, headers);
|
||||
return await httpGet(`/article-categories?limit=200`, headers);
|
||||
}
|
||||
export async function getCategoryPagination(data: any) {
|
||||
const headers = {
|
||||
|
|
@ -139,3 +139,15 @@ export async function getStatisticSummary() {
|
|||
};
|
||||
return await httpGet(`/articles/statistic/summary`, headers);
|
||||
}
|
||||
|
||||
export async function submitApproval(data: {
|
||||
articleId: number;
|
||||
message: string;
|
||||
statusId: number;
|
||||
}) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpPost(`/article-approvals`, headers, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,3 +96,11 @@ main {
|
|||
.komdigi-styling #gpr-kominfo-widget-body {
|
||||
height: 67vh !important;
|
||||
}
|
||||
|
||||
.custom-popup {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.custom-button {
|
||||
color: black !important;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue