diff --git a/app/(admin)/admin/comment/review/[id]/page.tsx b/app/(admin)/admin/comment/review/[id]/page.tsx index 65fadc3..62adf39 100644 --- a/app/(admin)/admin/comment/review/[id]/page.tsx +++ b/app/(admin)/admin/comment/review/[id]/page.tsx @@ -54,7 +54,6 @@ export default function ReviewComment() { setDetailData(res?.data?.data); const resArticle = await getArticleById(res?.data?.data?.articleId); setDetailArticle(resArticle?.data?.data); - console.log("iddd", res?.data?.data); close(); }; @@ -115,7 +114,7 @@ export default function ReviewComment() { return (
-
+

Artikel

{ @@ -112,6 +115,20 @@ const createArticleSchema = z.object({ }), }); +const renderPreview = (file: File) => { + if (file.type === "application/pdf") { + return ; + } else if ( + file.type === + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" || + file.type === "application/msword" + ) { + return ; + } else { + return "File"; + } +}; + export default function CreateArticleForm() { const { isOpen, onOpen, onOpenChange } = useDisclosure(); const userLevel = Cookies.get("ulne"); @@ -124,11 +141,16 @@ export default function CreateArticleForm() { const [listCategory, setListCategory] = useState([]); const [tag, setTag] = useState(""); const [thumbnailImg, setThumbnailImg] = useState([]); + const [thumbnailDocumentImg, setThumbnailDocumentImg] = useState([]); + const [documentFiles, setDocumentFiles] = useState([]); const [selectedMainImage, setSelectedMainImage] = useState( null ); const [thumbnailValidation, setThumbnailValidation] = useState(""); + const [thumbnailDocumentValidation, setThumbnailDocumentValidation] = + useState(""); const [filesValidation, setFileValidation] = useState(""); + const [documentValidation, setDocumentValidation] = useState(""); const [diseData, setDiseData] = useState(); const [selectedWritingType, setSelectedWritingType] = useState("single"); const [status, setStatus] = useState<"publish" | "draft" | "scheduled">( @@ -139,17 +161,37 @@ export default function CreateArticleForm() { const [startDateValue, setStartDateValue] = useState(null); + const [selectedFileType, setSelectedFileType] = useState("image"); + const { getRootProps, getInputProps } = useDropzone({ + accept: + selectedFileType === "image" + ? { + "image/*": [], + } + : { + "application/pdf": [], + "application/msword": [], + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + [], + "application/vnd.ms-powerpoint": [], + "application/vnd.openxmlformats-officedocument.presentationml.presentation": + [], + }, onDrop: (acceptedFiles) => { - setFiles((prevFiles) => [ - ...prevFiles, - ...acceptedFiles.map((file) => Object.assign(file)), - ]); + if (selectedFileType === "image") { + setFiles((prevFiles) => [ + ...prevFiles, + ...acceptedFiles.map((file) => Object.assign(file)), + ]); + } else { + setDocumentFiles((prevFiles) => [ + ...prevFiles, + ...acceptedFiles.map((file) => Object.assign(file)), + ]); + } }, multiple: true, - accept: { - "image/*": [], - }, }); const formOptions = { @@ -193,17 +235,33 @@ export default function CreateArticleForm() { }; const onSubmit = async (values: z.infer) => { - if ((thumbnailImg.length < 1 && !selectedMainImage) || files.length < 1) { + if ( + (selectedFileType === "image" && + ((thumbnailImg.length < 1 && !selectedMainImage) || + files.length < 1)) || + (selectedFileType === "document" && + (documentFiles.length < 1 || thumbnailDocumentImg.length < 1)) + ) { if (files.length < 1) { setFileValidation("Required"); } else { setFileValidation(""); } + if (documentFiles.length < 1) { + setDocumentValidation("Required"); + } else { + setDocumentValidation(""); + } if (thumbnailImg.length < 1 && !selectedMainImage) { setThumbnailValidation("Required"); } else { setThumbnailValidation(""); } + if (thumbnailDocumentImg.length < 1) { + setThumbnailDocumentValidation("Required"); + } else { + setThumbnailDocumentValidation(""); + } } else { setThumbnailValidation(""); setFileValidation(""); @@ -293,9 +351,9 @@ export default function CreateArticleForm() { }; const save = async (values: z.infer) => { + // const userLevelStatus = await getUserLevelApprovalStatus(); loading(); - const userLevelStatus = await getUserLevelApprovalStatus(); const formData = { title: values.title, typeId: 1, @@ -311,6 +369,8 @@ export default function CreateArticleForm() { isPublish: status === "publish", }; + console.log("formData", formData); + const response = await createArticle(formData); if (response?.error) { @@ -319,31 +379,51 @@ export default function CreateArticleForm() { } const articleId = response?.data?.data?.id; - if (files?.length > 0) { + if (files?.length > 0 || documentFiles.length > 0) { const formFiles = new FormData(); - for (const element of files) { - formFiles.append("file", element); - const resFile = await uploadArticleFile(articleId, formFiles); + if (selectedFileType === "image") { + for (const element of files) { + formFiles.append("file", element); + const resFile = await uploadArticleFile(articleId, formFiles); + } + } + + if (selectedFileType === "document") { + for (const element of documentFiles) { + formFiles.append("file", element); + const resFile = await uploadArticleFile(articleId, formFiles); + } } } - if (thumbnailImg?.length > 0 || files?.length > 0) { - if (thumbnailImg?.length > 0) { - const formFiles = new FormData(); - - formFiles.append("files", thumbnailImg[0]); - const resFile = await uploadArticleThumbnail(articleId, formFiles); - } else { - const formFiles = new FormData(); - - if (selectedMainImage) { - formFiles.append("files", files[selectedMainImage - 1]); + if (selectedFileType === "image") { + if (thumbnailImg?.length > 0 || files?.length > 0) { + if (thumbnailImg?.length > 0) { + const formFiles = new FormData(); + formFiles.append("files", thumbnailImg[0]); const resFile = await uploadArticleThumbnail(articleId, formFiles); + } else { + const formFiles = new FormData(); + + if (selectedMainImage) { + formFiles.append("files", files[selectedMainImage - 1]); + + const resFile = await uploadArticleThumbnail(articleId, formFiles); + } } } } + if (selectedFileType === "document") { + if (thumbnailDocumentImg?.length > 0) { + const formFiles = new FormData(); + + formFiles.append("files", thumbnailDocumentImg[0]); + const resFile = await uploadArticleThumbnail(articleId, formFiles); + } + } + if (status === "scheduled") { const request = { id: articleId, @@ -406,10 +486,18 @@ export default function CreateArticleForm() { } }; - const handleRemoveFile = (file: FileWithPreview) => { - const uploadedFiles = files; - const filtered = uploadedFiles.filter((i) => i.name !== file.name); - setFiles([...filtered]); + const handleRemoveFile = (file: FileWithPreview | File, type: string) => { + if (type === "image") { + const uploadedFiles = files; + const filtered = uploadedFiles.filter((i) => i.name !== file.name); + setFiles([...filtered]); + } + + if (type === "document") { + const uploadedFiles = documentFiles; + const filtered = uploadedFiles.filter((i) => i.name !== file.name); + setDocumentFiles([...filtered]); + } }; const fileList = files.map((file, index) => ( @@ -444,17 +532,55 @@ export default function CreateArticleForm() {
)); - const handleFileChange = (event: React.ChangeEvent) => { + const documentList = documentFiles.map((file, index) => ( +
+
+
{renderPreview(file)}
+
+
{file.name}
+
+ {Math.round(file.size / 100) / 10 > 1000 ? ( + <>{(Math.round(file.size / 100) / 10000).toFixed(1)} + ) : ( + <>{(Math.round(file.size / 100) / 10).toFixed(1)} + )} + {" kb"} +
+
+
+ + +
+ )); + + const handleFileChange = ( + event: React.ChangeEvent, + type: string + ) => { const selectedFiles = event.target.files; if (selectedFiles) { - setThumbnailImg(Array.from(selectedFiles)); + if (type === "image") { + setThumbnailImg(Array.from(selectedFiles)); + } + if (type === "document") { + setThumbnailDocumentImg(Array.from(selectedFiles)); + } } }; @@ -612,43 +738,134 @@ export default function CreateArticleForm() { )}

File Media

- -
- -
- -

- Tarik file disini atau klik untuk upload. -

-
- ( Upload file dengan format .jpg, .jpeg, atau .png. Ukuran - maksimal 100mb.) -
-
-
- {files.length ? ( + { + setSelectedFileType(String(e)); + }} + > + -
{fileList}
-
- +
+ +
+ +

+ Tarik file disini atau klik untuk upload. +

+
+ ( Upload file dengan format .jpg, .jpeg, atau .png. Ukuran + maksimal 100mb.) +
+
+ {files.length ? ( + +
{fileList}
+
+ +
+
+ ) : null} - ) : null} - - {filesValidation !== "" && files.length < 1 && ( -

Upload File Media

- )} + {filesValidation !== "" && files.length < 1 && ( +

Upload File Media

+ )} + + + +
+ +
+ +

+ Tarik file disini atau klik untuk upload. +

+
+ ( Upload file dengan format .pdf, atau .docx. Ukuran + maksimal 100mb.) +
+
+
+ {documentFiles.length ? ( + +
{documentList}
+
+ +
+
+ ) : null} +
+ {documentValidation !== "" && documentFiles.length < 1 && ( +

Upload Document

+ )} +
+

Thubmnail

- {selectedMainImage && files.length >= selectedMainImage ? ( + {selectedFileType === "image" ? ( + selectedMainImage && files.length >= selectedMainImage ? ( +
+ thumbnail + +
+ ) : thumbnailImg.length > 0 ? ( +
+ thumbnail + +
+ ) : ( + <> + handleFileChange(e, "image")} + /> + {thumbnailValidation !== "" && ( +

+ Upload thumbnail atau pilih dari File Media +

+ )} + + ) + ) : thumbnailDocumentImg.length > 0 ? (
thumbnail @@ -657,45 +874,23 @@ export default function CreateArticleForm() { variant="bordered" size="sm" color="danger" - onClick={() => setSelectedMainImage(null)} - > - - -
- ) : thumbnailImg.length > 0 ? ( -
- thumbnail -
) : ( <> - {/* {" "} */} handleFileChange(e, "document")} /> - {thumbnailValidation !== "" && ( -

- Upload thumbnail atau pilih dari File Media -

+ {thumbnailDocumentValidation !== "" && ( +

Upload thumbnail

)} )} diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index 61b7349..0b9316a 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -26,6 +26,8 @@ import { import ReactSelect from "react-select"; import makeAnimated from "react-select/animated"; import { + Accordion, + AccordionItem, Calendar, Chip, Modal, @@ -36,10 +38,16 @@ import { Popover, PopoverContent, PopoverTrigger, + Tab, + Tabs, useDisclosure, } from "@heroui/react"; import GenerateSingleArticleForm from "./generate-ai-single-form"; -import { convertDateFormatNoTime, htmlToString } from "@/utils/global"; +import { + convertDateFormatNoTime, + formatMonthString, + htmlToString, +} from "@/utils/global"; import { close, error, loading } from "@/config/swal"; import { useParams, useRouter } from "next/navigation"; import { fromJSON, list } from "postcss"; @@ -47,6 +55,7 @@ import GetSeoScore from "./get-seo-score-form"; import Link from "next/link"; import { stringify } from "querystring"; import Cookies from "js-cookie"; +import { PdfIcon, WordIcon } from "@/components/icons/globals"; const ViewEditor = dynamic( () => { @@ -105,6 +114,20 @@ interface DiseData { additionalKeywords: string; } +const renderPreview = (file: File) => { + if (file.type === "application/pdf") { + return ; + } else if ( + file.type === + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" || + file.type === "application/msword" + ) { + return ; + } else { + return "File"; + } +}; + export default function EditArticleForm(props: { isDetail: boolean }) { const { isDetail } = props; const params = useParams(); @@ -116,6 +139,8 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const router = useRouter(); const editor = useRef(null); const [files, setFiles] = useState([]); + const [documentFiles, setDocumentFiles] = useState([]); + const [useAi, setUseAI] = useState(false); const [listCategory, setListCategory] = useState([]); const [tag, setTag] = useState(""); @@ -134,20 +159,40 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const [detailData, setDetailData] = useState(); const [startDateValue, setStartDateValue] = useState(null); const [timeValue, setTimeValue] = useState("00:00"); + const [documentValidation, setDocumentValidation] = useState(""); + const [filesValidation, setFileValidation] = useState(""); + const [selectedFileType, setSelectedFileType] = useState("image"); const { getRootProps, getInputProps } = useDropzone({ + accept: + selectedFileType === "image" + ? { + "image/*": [], + } + : { + "application/pdf": [], + "application/msword": [], + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + [], + "application/vnd.ms-powerpoint": [], + "application/vnd.openxmlformats-officedocument.presentationml.presentation": + [], + }, onDrop: (acceptedFiles) => { - setFiles((prevFiles) => [ - ...prevFiles, - ...acceptedFiles.map((file) => Object.assign(file)), - ]); + if (selectedFileType === "image") { + setFiles((prevFiles) => [ + ...prevFiles, + ...acceptedFiles.map((file) => Object.assign(file)), + ]); + } else { + setDocumentFiles((prevFiles) => [ + ...prevFiles, + ...acceptedFiles.map((file) => Object.assign(file)), + ]); + } }, multiple: true, - accept: { - "image/*": [], - }, }); - const formOptions = { resolver: zodResolver(createArticleSchema), defaultValues: { title: "", description: "", category: [], tags: [] }, @@ -181,7 +226,14 @@ export default function EditArticleForm(props: { isDetail: boolean }) { setThumbnail(data?.thumbnailUrl); setDiseId(data?.aiArticleId); setDetailFiles(data?.files); - + if ( + data.files[0].file_name.split(".")[1].includes("doc") || + data.files[0].file_name.split(".")[1].includes("pdf") + ) { + setSelectedFileType("document"); + } else { + setSelectedFileType("image"); + } setupInitCategory(data?.categories); close(); } @@ -358,12 +410,19 @@ export default function EditArticleForm(props: { isDetail: boolean }) { } }; - const handleRemoveFile = (file: FileWithPreview) => { - const uploadedFiles = files; - const filtered = uploadedFiles.filter((i) => i.name !== file.name); - setFiles([...filtered]); - }; + const handleRemoveFile = (file: FileWithPreview | File, type: string) => { + if (type === "image") { + const uploadedFiles = files; + const filtered = uploadedFiles.filter((i) => i.name !== file.name); + setFiles([...filtered]); + } + if (type === "document") { + const uploadedFiles = documentFiles; + const filtered = uploadedFiles.filter((i) => i.name !== file.name); + setDocumentFiles([...filtered]); + } + }; const fileList = files.map((file) => (
handleRemoveFile(file)} + onPress={() => handleRemoveFile(file, "image")} >
)); + const documentList = documentFiles.map((file, index) => ( +
+
+
{renderPreview(file)}
+
+
{file.name}
+
+ {Math.round(file.size / 100) / 10 > 1000 ? ( + <>{(Math.round(file.size / 100) / 10000).toFixed(1)} + ) : ( + <>{(Math.round(file.size / 100) / 10).toFixed(1)} + )} + {" kb"} +
+
+
+ + +
+ )); + const handleDeleteFile = (id: number) => { MySwal.fire({ title: "Hapus File", @@ -559,14 +648,6 @@ export default function EditArticleForm(props: { isDetail: boolean }) { control={control} name="description" render={({ field: { onChange, value } }) => - // - // isDetail ? ( ) : ( @@ -582,66 +663,167 @@ export default function EditArticleForm(props: { isDetail: boolean }) {

File Media

{!isDetail && ( - -
- -
- -

- Tarik file disini atau klik untuk upload. -

-
- ( Upload file dengan format .jpg, .jpeg, atau .png. Ukuran - maksimal 100mb.) -
-
-
- {files.length ? ( + { + setSelectedFileType(String(e)); + }} + > + -
{fileList}
-
- {/*
- -
- +
+ +
+ +

+ Tarik file disini atau klik untuk upload. +

+
+ ( Upload file dengan format .jpg, .jpeg, atau .png. Ukuran + maksimal 100mb.) +
-
*/}
+ {files.length ? ( + +
{fileList}
+
+ +
+
+ ) : null} - ) : null} - + {filesValidation !== "" && files.length < 1 && ( +

Upload File Media

+ )} + + + +
+ +
+ +

+ Tarik file disini atau klik untuk upload. +

+
+ ( Upload file dengan format .pdf, atau .docx. Ukuran + maksimal 100mb.) +
+
+
+ {documentFiles.length ? ( + +
{documentList}
+
+ +
+
+ ) : null} +
+ {documentValidation !== "" && documentFiles.length < 1 && ( +

Upload Document

+ )} +
+ )} {isDetail ? ( detailfiles.length > 0 ? ( - <> -
- main -
- - +
+
+
Nama File
+
+ {file?.file_name} +
+
+
+
Ukuran File
+
+ {Math.round(file?.size / 100) / 10 > 1000 ? ( + <> + {(Math.round(file?.size / 100) / 10000).toFixed( + 1 + )} + + ) : ( + <> + {(Math.round(file?.size / 100) / 10).toFixed(1)} + + )} + {" kb"} +
+
+ +
+
+ Tanggal Publish +
+
+ {formatMonthString(file?.created_at)} +
+
+
+ + + + + + )) + ) : ( + <> +
+ main +
+
+ {detailfiles?.map((file: any, index: number) => ( + setMainImage(index)} + className="cursor-pointer" + > + {`image-${index}`} + + ))} +
+ + ) ) : (

Belum Ada File

) @@ -653,15 +835,22 @@ export default function EditArticleForm(props: { isDetail: boolean }) { className=" flex justify-between border px-3.5 py-3 rounded-md" >
-
- {`image-${index}`} -
+ {selectedFileType === "image" ? ( +
+ {`image-${index}`} +
+ ) : file.file_name.split(".")[1].includes("pdf") ? ( + + ) : ( + + )} +
{file?.file_name} @@ -735,7 +924,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { variant="bordered" size="sm" color="danger" - onClick={() => setThumbnail("")} + onPress={() => setThumbnail("")} > @@ -754,7 +943,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { variant="bordered" size="sm" color="danger" - onClick={() => setThumbnailImg([])} + onPress={() => setThumbnailImg([])} > diff --git a/components/form/login.tsx b/components/form/login.tsx index bd1735d..ccef5fa 100644 --- a/components/form/login.tsx +++ b/components/form/login.tsx @@ -69,90 +69,90 @@ export default function Login() { error("Username & Password Wajib Diisi !"); } else { // login dengan otp - const response = await emailValidation(data); - if (response?.error) { - error("Username / Password Tidak Sesuai"); - return false; - } - - if (response?.data?.messages[0] === "Continue to setup email") { - setFirstLogin(true); - } else { - setNeedOtp(true); - } - - // login tanpa otp - // loading(); - // const response = await postSignIn(data); + // const response = await emailValidation(data); // if (response?.error) { // error("Username / Password Tidak Sesuai"); - // } else { - // const profile = await getProfile(response?.data?.data?.access_token); - // const dateTime: any = new Date(); - - // const newTime: any = dateTime.getTime() + 10 * 60 * 1000; - - // Cookies.set("access_token", response?.data?.data?.access_token, { - // expires: 1, - // }); - // Cookies.set("refresh_token", response?.data?.data?.refresh_token, { - // expires: 1, - // }); - // Cookies.set("time_refresh", newTime, { - // expires: 1, - // }); - // Cookies.set("is_first_login", "true", { - // secure: true, - // sameSite: "strict", - // }); - // const resActivity = await saveActivity( - // { - // activityTypeId: 1, - // url: "https://kontenhumas.com/auth", - // userId: profile?.data?.data?.id, - // }, - // accessData?.id_token - // ); - // Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, { - // expires: 1, - // }); - // Cookies.set("uie", profile?.data?.data?.id, { - // expires: 1, - // }); - // Cookies.set("ufne", profile?.data?.data?.fullname, { - // expires: 1, - // }); - // Cookies.set("ulie", profile?.data?.data?.userLevelGroup, { - // expires: 1, - // }); - // Cookies.set("username", profile?.data?.data?.username, { - // expires: 1, - // }); - // Cookies.set("urie", profile?.data?.data?.roleId, { - // expires: 1, - // }); - // Cookies.set("roleName", profile?.data?.data?.roleName, { - // expires: 1, - // }); - // Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, { - // expires: 1, - // }); - // Cookies.set("ulne", profile?.data?.data?.userLevelId, { - // expires: 1, - // }); - // Cookies.set("urce", profile?.data?.data?.roleCode, { - // expires: 1, - // }); - // Cookies.set("email", profile?.data?.data?.email, { - // expires: 1, - // }); - // router.push("/admin/dashboard"); - // Cookies.set("status", "login", { - // expires: 1, - // }); - - // close(); + // return false; // } + + // if (response?.data?.messages[0] === "Continue to setup email") { + // setFirstLogin(true); + // } else { + // setNeedOtp(true); + // } + + // login tanpa otp + loading(); + const response = await postSignIn(data); + if (response?.error) { + error("Username / Password Tidak Sesuai"); + } else { + const profile = await getProfile(response?.data?.data?.access_token); + const dateTime: any = new Date(); + + const newTime: any = dateTime.getTime() + 10 * 60 * 1000; + + Cookies.set("access_token", response?.data?.data?.access_token, { + expires: 1, + }); + Cookies.set("refresh_token", response?.data?.data?.refresh_token, { + expires: 1, + }); + Cookies.set("time_refresh", newTime, { + expires: 1, + }); + Cookies.set("is_first_login", "true", { + secure: true, + sameSite: "strict", + }); + const resActivity = await saveActivity( + { + activityTypeId: 1, + url: "https://kontenhumas.com/auth", + userId: profile?.data?.data?.id, + }, + accessData?.id_token + ); + Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, { + expires: 1, + }); + Cookies.set("uie", profile?.data?.data?.id, { + expires: 1, + }); + Cookies.set("ufne", profile?.data?.data?.fullname, { + expires: 1, + }); + Cookies.set("ulie", profile?.data?.data?.userLevelGroup, { + expires: 1, + }); + Cookies.set("username", profile?.data?.data?.username, { + expires: 1, + }); + Cookies.set("urie", profile?.data?.data?.roleId, { + expires: 1, + }); + Cookies.set("roleName", profile?.data?.data?.roleName, { + expires: 1, + }); + Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, { + expires: 1, + }); + Cookies.set("ulne", profile?.data?.data?.userLevelId, { + expires: 1, + }); + Cookies.set("urce", profile?.data?.data?.roleCode, { + expires: 1, + }); + Cookies.set("email", profile?.data?.data?.email, { + expires: 1, + }); + router.push("/admin/dashboard"); + Cookies.set("status", "login", { + expires: 1, + }); + + close(); + } } }; diff --git a/components/landing/HeaderNews.tsx b/components/landing/HeaderNews.tsx index e2fb6b0..f8ce4b1 100644 --- a/components/landing/HeaderNews.tsx +++ b/components/landing/HeaderNews.tsx @@ -5,6 +5,7 @@ import { CardFooter, CircularProgress, ScrollShadow, + Skeleton, } from "@heroui/react"; import { ChevronLeftIcon, ChevronRightIcon, EyeIcon } from "../icons"; import { Swiper, SwiperSlide, useSwiper } from "swiper/react"; @@ -82,7 +83,7 @@ export default function HeaderNews() {
- {banner ? ( + {banner.length > 0 ? ( ) : ( - + +
+ )}
@@ -159,51 +162,57 @@ export default function HeaderNews() { Hot Topik

- {hotNews?.map((data: any, index: number) => ( -
- {/* headernews */} -
- - {textEllipsis(data.title, 40)} - - - {textEllipsis(data.title, 66)} - -
-

- {convertDateFormat(data.createdAt)} WIB -

-

- - {data.viewCount === null ? 0 : data.viewCount} -

+ {hotNews.length > 0 ? ( + hotNews.map((data: any, index: number) => ( +
+
+ + {textEllipsis(data.title, 40)} + + + {textEllipsis(data.title, 66)} + +
+

+ {convertDateFormat(data.createdAt)} WIB +

+

+ + {data.viewCount === null ? 0 : data.viewCount} +

+
+ )) + ) : ( +
+ +
+ + +
+ + +
+ + +
+
- ))} + )}
- +
-
- {banner ? ( +
+ {banner.length > 0 ? ( - {banner?.map((newsItem: any, index: number) => ( + {banner.map((newsItem: any, index: number) => ( ) : ( - + +
+ )}
@@ -315,25 +326,42 @@ export default function HeaderNews() {
- {article?.map((list: any, index: number) => ( -
- -

{list?.title}

- -
-

- {convertDateFormat(list?.createdAt)} WIB -

-

- - {list?.viewCount === null ? 0 : list?.viewCount} -

+ {article.length > 0 ? ( + article.map((list: any, index: number) => ( +
+ +

{list?.title}

+ +
+

+ {convertDateFormat(list?.createdAt)} WIB +

+

+ + {list?.viewCount === null ? 0 : list?.viewCount} +

+
+ )) + ) : ( +
+ +
+ + +
+ + +
+ + +
+
- ))} + )}
- {article && ( + {article.length > 0 ? (
+ ) : ( +
+

Loading...

+
)}
{ + setHasMounted(true); + }, []); + + // Render + if (!hasMounted) return null; return (
state.locale); const setLanguage = storedLanguage((state) => state.setLocale); @@ -88,6 +89,22 @@ export default function NavbarHumas(props: { size: string }) { }); }; + let typingTimer: NodeJS.Timeout; + const doneTypingInterval = 1500; + + const handleKeyUp = () => { + clearTimeout(typingTimer); + typingTimer = setTimeout(doneTyping, doneTypingInterval); + }; + + const handleKeyDown = () => { + clearTimeout(typingTimer); + }; + + async function doneTyping() { + router.push(`/news/all?search=${search}`); + } + const searchInput = ( setSearch(e.target.value)} + onKeyUp={handleKeyUp} + onKeyDown={handleKeyDown} startContent={ } diff --git a/components/main/detail/e-magazine-detail.tsx b/components/main/detail/e-magazine-detail.tsx index ea8dbb2..c02db8c 100644 --- a/components/main/detail/e-magazine-detail.tsx +++ b/components/main/detail/e-magazine-detail.tsx @@ -114,13 +114,13 @@ export default function EMagazineDetail() { {file?.fileName}
-
+
Deskripsi
{file?.description == "" ? "-" : file?.description}
-
+
Ukuran File
{Math.round(file?.size / 100) / 10 > 1000 ? ( @@ -134,7 +134,7 @@ export default function EMagazineDetail() {
-
+
Tanggal Publish
{formatMonthString(file?.createdAt)} diff --git a/components/main/detail/list-news.tsx b/components/main/detail/list-news.tsx index b31870d..d2a7411 100644 --- a/components/main/detail/list-news.tsx +++ b/components/main/detail/list-news.tsx @@ -1,31 +1,68 @@ "use client"; import { + Autocomplete, + AutocompleteItem, BreadcrumbItem, Breadcrumbs, Button, + DatePicker, Image, Input, + Listbox, + ListboxItem, Pagination, + Popover, + PopoverContent, + PopoverTrigger, + Select, + SelectItem, } from "@heroui/react"; import { CalendarIcon, Calender, + ChevronLeftIcon, ChevronRightIcon, ClockIcon, EyeFilledIcon, SearchIcon, + TimesIcon, UserIcon, } from "../../icons"; import Link from "next/link"; import { useEffect, useRef, useState } from "react"; -import { getListArticle } from "@/services/article"; -import { formatMonthString, htmlToString, textEllipsis } from "@/utils/global"; +import { + getArticleByCategoryLanding, + getListArticle, +} from "@/services/article"; +import { + convertDateFormatNoTimeV2, + formatMonthString, + htmlToString, + textEllipsis, +} from "@/utils/global"; import { useParams, usePathname, useRouter, useSearchParams, } from "next/navigation"; +import { close, loading } from "@/config/swal"; +import { format } from "date-fns"; + +const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", +]; export default function ListNews() { const [article, setArticle] = useState([]); @@ -37,35 +74,97 @@ export default function ListNews() { const params = useParams(); const category = params?.name; const searchParams = useSearchParams(); - const search = searchParams.get("search"); + const categoryIds = searchParams.get("category_id"); + const [categories, setCategories] = useState([]); + const [search, setSearch] = useState(searchParams.get("search") || ""); const [searchValue, setSearchValue] = useState(search || ""); + const [categorySearch, setCategorySearch] = useState(""); + const [debouncedValue, setDebouncedValue] = useState(""); + const [selectedCategoryId, setSelectedCategoryId] = useState(); + + const today = new Date(); + const [year, setYear] = useState(today.getFullYear()); + + const [selectedMonth, setSelectedMonth] = useState( + searchParams.get("month") ? Number(searchParams.get("month")) - 1 : null + ); + const [selectedDate, setSelectedDate] = useState(null); + + const handleMonthClick = (monthIndex: number) => { + setSelectedMonth(monthIndex); + setSelectedDate(new Date(year, monthIndex, 1)); + }; + + useEffect(() => { + setSearch(searchParams.get("search") || ""); + setSearchValue(searchParams.get("search") || ""); + console.log( + "ini", + searchParams.get("month") ? Number(searchParams.get("month")) : null + ); + setSelectedMonth( + searchParams.get("month") ? Number(searchParams.get("month")) : null + ); + }, [searchParams]); useEffect(() => { getArticle(); - }, [page, category]); + }, [page, category, search, searchParams]); + + useEffect(() => { + getCategory(); + }, [debouncedValue]); + + const getCategory = async () => { + const res = await getArticleByCategoryLanding({ + limit: debouncedValue === "" ? "5" : "", + title: debouncedValue, + }); + if (res?.data?.data) { + setCategories(res?.data?.data); + } + }; async function getArticle() { - // loading(); - topRef.current?.scrollIntoView({ behavior: "smooth" }); + loading(); + // topRef.current?.scrollIntoView({ behavior: "smooth" }); const req = { page: page, search: searchValue || "", limit: "9", - // isPublish: pathname.includes("polda") ? false : true, isPublish: true, sort: "desc", categorySlug: pathname.includes("polda") || pathname.includes("satker") ? String(category) : "", + categoryIds: categoryIds ? categoryIds : "", + startDate: selectedMonth + ? convertDateFormatNoTimeV2(new Date(year, selectedMonth, 1)) + : "", + endDate: selectedMonth + ? convertDateFormatNoTimeV2(new Date(year, selectedMonth + 1, 0)) + : "", }; const response = await getListArticle(req); setArticle(response?.data?.data); setTotalPage(response?.data?.meta?.totalPage); - // close(); + close(); } + useEffect(() => { + const timeout = setTimeout(() => { + setDebouncedValue(categorySearch); + }, 1500); + + return () => clearTimeout(timeout); + }, [categorySearch]); + + const onInputChange = (value: string) => { + setCategorySearch(value); + }; + return (
@@ -76,38 +175,109 @@ export default function ListNews() {

Berita

-
+
{ - if (event.key === "Enter") { - router.push(pathname + `?search=${searchValue}`); - getArticle(); - } - }} + // onKeyDown={(event) => { + // if (event.key === "Enter") { + // router.push(pathname + `?search=${searchValue}`); + // getArticle(); + // } + // }} labelPlacement="outside" - placeholder="Search..." - value={searchValue || ""} + placeholder="Judul..." + value={searchValue} onValueChange={setSearchValue} - endContent={ - - } type="search" /> +
+ setSelectedCategoryId(e)} + inputProps={{ classNames: { inputWrapper: "border-1" } }} + > + {categories.length > 0 && + categories.map((category: any) => ( + + {category.title} + + ))} + +
+
+ + +
-

{formatMonthString(news?.updatedAt)}

+

{formatMonthString(news?.createdAt)}

-

{`${new Date(news?.updatedAt) +

{`${new Date(news?.createdAt) .getHours() .toString() - .padStart(2, "0")}:${new Date(news?.updatedAt) + .padStart(2, "0")}:${new Date(news?.createdAt) .getMinutes() .toString() .padStart(2, "0")}`}

diff --git a/components/main/detail/new-detail.tsx b/components/main/detail/new-detail.tsx index aec025a..a359c82 100644 --- a/components/main/detail/new-detail.tsx +++ b/components/main/detail/new-detail.tsx @@ -24,13 +24,12 @@ export default function NewsDetailPage(props: { datas: any }) { const [articles, setArticles] = useState([]); useEffect(() => { - // initFetch(); getArticles(); sendActivity(); }, []); async function getArticles() { - const req = { page: 1, search: "", limit: "50" }; + const req = { page: 1, search: "", limit: "50", isPublish: true }; const response = await getListArticle(req); setArticles(response?.data?.data); } @@ -70,7 +69,7 @@ export default function NewsDetailPage(props: { datas: any }) {
- +
diff --git a/components/page/detail-news.tsx b/components/page/detail-news.tsx index 4056688..1408a41 100644 --- a/components/page/detail-news.tsx +++ b/components/page/detail-news.tsx @@ -25,7 +25,7 @@ import { useEffect, useState } from "react"; import { image } from "@heroui/theme"; import Cookies from "js-cookie"; import { saveActivity } from "@/services/activity-log"; -import { Image } from "@heroui/react"; +import { Accordion, AccordionItem, Image } from "@heroui/react"; const token = Cookies.get("access_token"); const uid = Cookies.get("uie"); @@ -153,35 +153,101 @@ export default function DetailNews(props: { data: any; listArticle: any }) {

- {data?.files?.length > 0 && ( + {data.files[0].file_name.split(".")[1].includes("doc") || + data.files[0].file_name.split(".")[1].includes("pdf") ? ( Main Image + ) : ( + data?.files?.length > 0 && ( + Main Image + ) )}
- {data?.files?.length > 0 && ( -
- {data?.files?.map((file: any, index: number) => ( - setImageNow(index)} - className="cursor-pointer" - > - NextUI hero Image - - ))} -
- )} + {data?.files?.length > 0 && + (data.files[0].file_name.split(".")[1].includes("doc") || + data.files[0].file_name.split(".")[1].includes("pdf") ? ( + data.files?.map((file: any, index: number) => ( + + + {`File ${index + 1}`} +

+ } + > +
+
+
Nama File
+
+ {file?.file_name} +
+
+
+
Ukuran File
+
+ {Math.round(file?.size / 100) / 10 > 1000 ? ( + <>{(Math.round(file?.size / 100) / 10000).toFixed(1)} + ) : ( + <>{(Math.round(file?.size / 100) / 10).toFixed(1)} + )} + {" kb"} +
+
+ +
+
Tanggal Publish
+
+ {formatMonthString(file?.created_at)} +
+
+
+ + + +
+
+ )) + ) : ( +
+ {data?.files?.map((file: any, index: number) => ( + setImageNow(index)} + className="cursor-pointer" + > + NextUI hero Image + + ))} +
+ ))}
([]); useEffect(() => { async function getArticle() { - const req = { page: 1, search: "", limit: "10" }; + console.log("categories", categories); + const idString = categories.map((item: any) => item.id).join(","); + const req = { + page: 1, + search: "", + limit: "10", + isPublish: true, + categoryIds: idString, + }; const response = await getListArticle(req); setArticle(response?.data?.data); } diff --git a/components/page/sidebar-detail.tsx b/components/page/sidebar-detail.tsx index 913e806..15580c6 100644 --- a/components/page/sidebar-detail.tsx +++ b/components/page/sidebar-detail.tsx @@ -8,22 +8,38 @@ import "swiper/css/effect-fade"; import "swiper/css/pagination"; import Link from "next/link"; import { getListArticle } from "@/services/article"; -import { Card, CardFooter } from "@heroui/react"; +import { Card, CardFooter, Skeleton } from "@heroui/react"; import { convertDateFormat, textEllipsis } from "@/utils/global"; import Image from "next/image"; export default function SidebarDetail() { + const [articleMabes, setArticleMabes] = useState([]); const [article, setArticle] = useState([]); useEffect(() => { - async function getArticle() { - const req = { page: 1, search: "", limit: "10" }; - - const response = await getListArticle(req); - setArticle(response?.data?.data); - } getArticle(); + getArticleMabes(); }, []); + + async function getArticle() { + const req = { page: 1, search: "", limit: "10", isPublish: true }; + + const response = await getListArticle(req); + setArticle(response?.data?.data); + } + + async function getArticleMabes() { + const req = { + page: 1, + search: "", + limit: "10", + isPublish: true, + category: "586", + }; + + const response = await getListArticle(req); + setArticleMabes(response?.data?.data); + } return (
@@ -33,49 +49,57 @@ export default function SidebarDetail() {
- - {article?.map((newsItem: any) => ( - -
- headernews -
- -

- {textEllipsis(newsItem.title, 45)} + {articleMabes?.length < 1 ? ( + +

+ + ) : ( + + {articleMabes?.map((newsItem: any) => ( + +
+ headernews +
+ +

+ {textEllipsis(newsItem.title, 45)} +

+ +

+ {convertDateFormat(newsItem.createdAt)} WIB

- -

- {convertDateFormat(newsItem.createdAt)} WIB -

+
-
- - ))} - + + ))} + + )}
@@ -85,49 +109,57 @@ export default function SidebarDetail() {
- - {article?.map((newsItem: any) => ( - -
- headernews -
- -

- {textEllipsis(newsItem.title, 45)} + {article?.length < 1 ? ( + +

+ + ) : ( + + {article?.map((newsItem: any) => ( + +
+ headernews +
+ +

+ {textEllipsis(newsItem.title, 45)} +

+ +

+ {convertDateFormat(newsItem.createdAt)} WIB

- -

- {convertDateFormat(newsItem.createdAt)} WIB -

+
-
- - ))} - + + ))} + + )}
diff --git a/components/table/comment/comment-table.tsx b/components/table/comment/comment-table.tsx index d839d55..2305e86 100644 --- a/components/table/comment/comment-table.tsx +++ b/components/table/comment/comment-table.tsx @@ -142,7 +142,10 @@ export default function CommentTable() { }; const openArticle = async (id: number) => { + loading(); const res = await getArticleById(id); + close(); + if (res?.error) { MySwal.fire({ title: "Artikel tidak ditemukan atau telah dihapus", diff --git a/components/table/tabel-emajalah-polri.tsx b/components/table/tabel-emajalah-polri.tsx index c2319f9..55793dc 100644 --- a/components/table/tabel-emajalah-polri.tsx +++ b/components/table/tabel-emajalah-polri.tsx @@ -116,9 +116,9 @@ export default function ListEnewsPolri() { -
+ {/*

Tanggal Publikasi

- {/* setStartDateValue(e)} inputClassName="z-50 w-full text-sm bg-white border-1 border-gray-200 px-2 py-[6px] rounded-xl h-[40px] text-black" - /> */} -
+ /> +
*/}
( - + {item.title} diff --git a/services/article.ts b/services/article.ts index 4264e1f..fdc5342 100644 --- a/services/article.ts +++ b/services/article.ts @@ -34,7 +34,7 @@ export async function getListArticle(props: PaginationRequest) { }&title=${search}&startDate=${startDate || ""}&endDate=${ endDate || "" }&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${ - sort || "asc" + sort || "desc" }&category=${categorySlug || ""}&isBanner=${isBanner || ""}&categoryIds=${ categoryIds || "" }&createdByIds=${createdByIds || ""}`, @@ -222,3 +222,16 @@ export async function updateIsBannerArticle(id: number, status: boolean) { const pathUrl = `/articles/banner/${id}?isBanner=${status}`; return await httpPut(pathUrl, headers); } + +export async function getArticleByCategoryLanding(props: { + limit: string; + title: string; +}) { + const headers = { + "content-type": "application/json", + }; + return await httpGet( + `/article-categories?limit=${props.limit}&title=${props.title}`, + headers + ); +}