diff --git a/app/(admin)/admin/article/page.tsx b/app/(admin)/admin/article/page.tsx index 3306b6c..abefe5a 100644 --- a/app/(admin)/admin/article/page.tsx +++ b/app/(admin)/admin/article/page.tsx @@ -15,6 +15,7 @@ export default function BasicPage() { )); - 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)); + } } }; @@ -617,43 +743,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 @@ -662,45 +879,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 24f05d1..d499d6e 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,12 +38,15 @@ import { Popover, PopoverContent, PopoverTrigger, + Tab, + Tabs, useDisclosure, } from "@heroui/react"; import GenerateSingleArticleForm from "./generate-ai-single-form"; import { convertDateFormatNoTime, getUnixTimestamp, + formatMonthString, htmlToString, } from "@/utils/global"; import { close, error, loading } from "@/config/swal"; @@ -51,6 +56,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( () => { @@ -109,6 +115,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(); @@ -120,6 +140,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(""); @@ -138,20 +160,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: [] }, @@ -185,7 +227,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(); } @@ -362,12 +411,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", @@ -563,14 +649,6 @@ export default function EditArticleForm(props: { isDetail: boolean }) { control={control} name="description" render={({ field: { onChange, value } }) => - // - // isDetail ? ( ) : ( @@ -586,66 +664,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

) @@ -657,15 +836,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} @@ -739,7 +925,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { variant="bordered" size="sm" color="danger" - onClick={() => setThumbnail("")} + onPress={() => setThumbnail("")} > @@ -758,7 +944,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { variant="bordered" size="sm" color="danger" - onClick={() => setThumbnailImg([])} + onPress={() => setThumbnailImg([])} > diff --git a/components/form/magazine/create-magazine-form.tsx b/components/form/magazine/create-magazine-form.tsx index 6575916..9c510e6 100644 --- a/components/form/magazine/create-magazine-form.tsx +++ b/components/form/magazine/create-magazine-form.tsx @@ -81,6 +81,9 @@ const createArticleSchema = z.object({ }), }) ), + category: z.array(categorySchema).nonempty({ + message: "Kategori harus memiliki setidaknya satu item", + }), }); export default function NewCreateMagazineForm() { @@ -90,6 +93,30 @@ export default function NewCreateMagazineForm() { const editor = useRef(null); const [files, setFiles] = useState([]); const [thumbnailImg, setThumbnailImg] = useState([]); + const [listCategory, setListCategory] = useState([]); + + useEffect(() => { + fetchCategory(); + }, []); + + const fetchCategory = async () => { + const res = await getArticleByCategory(); + if (res?.data?.data) { + setupCategory(res?.data?.data); + } + }; + + const setupCategory = (data: any) => { + const temp = []; + for (const element of data) { + temp.push({ + id: element.id, + label: element.title, + value: element.id, + }); + } + setListCategory(temp); + }; const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { @@ -153,6 +180,8 @@ export default function NewCreateMagazineForm() { typeId: 1, slug: values.slug, statusId: 1, + categoryIds: values.category.map((a) => a.id).join(","), + // description: htmlToString(removeImgTags(values.description)), description: values.description, // rows: values.rows, @@ -385,6 +414,37 @@ export default function NewCreateMagazineForm() { {errors?.slug && (

{errors.slug?.message}

)} + +

Kategori

+ ( + + "!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500", + }} + classNamePrefix="select" + onChange={onChange} + closeMenuOnSelect={false} + components={animatedComponents} + isClearable={true} + isSearchable={true} + isMulti={true} + placeholder="Kategori..." + name="sub-module" + options={listCategory} + /> + )} + /> + {errors?.category && ( +

+ {errors.category?.message} +

+ )} +

Thumbnail

{thumbnailImg.length > 0 ? ( diff --git a/components/landing/HeaderNews.tsx b/components/landing/HeaderNews.tsx index 59374a8..9570169 100644 --- a/components/landing/HeaderNews.tsx +++ b/components/landing/HeaderNews.tsx @@ -6,6 +6,7 @@ import { CircularProgress, Image, ScrollShadow, + Skeleton, } from "@heroui/react"; import { ChevronLeftIcon, ChevronRightIcon, EyeIcon } from "../icons"; import { Swiper, SwiperSlide, useSwiper } from "swiper/react"; @@ -81,7 +82,7 @@ export default function HeaderNews() {
- {hotNews ? ( + {banner.length > 0 ? ( ) : ( - + +
+ )}
@@ -156,51 +159,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} +

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

- {" "} - {textEllipsis(list.title, 120)} -

- -
-

- {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; const [hasMounted, setHasMounted] = useState(false); diff --git a/components/layout/navbar/NavbarHumas.tsx b/components/layout/navbar/NavbarHumas.tsx index d70649d..9721871 100644 --- a/components/layout/navbar/NavbarHumas.tsx +++ b/components/layout/navbar/NavbarHumas.tsx @@ -64,6 +64,7 @@ export default function NavbarHumas(props: { size: string }) { const token = Cookies.get("access_token"); const isAuthenticated = Cookies.get("is_authenticated"); const [isScrolled, setIsScrolled] = useState(false); + const [search, setSearch] = useState(""); const language = storedLanguage((state) => 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/dashboard/dashboard-container.tsx b/components/main/dashboard/dashboard-container.tsx index ec432d3..e1c6114 100644 --- a/components/main/dashboard/dashboard-container.tsx +++ b/components/main/dashboard/dashboard-container.tsx @@ -90,6 +90,15 @@ export default function DashboardContainer() { endDate: parseDate(convertDateFormatNoTimeV2(new Date())), }); + const [topContentDate, setTopContentDate] = useState({ + startDate: parseDate( + convertDateFormatNoTimeV2( + new Date(new Date().setDate(new Date().getDate() - 7)) + ) + ), + endDate: parseDate(convertDateFormatNoTimeV2(new Date())), + }); + const [typeDate, setTypeDate] = useState("monthly"); const [summary, setSummary] = useState(); @@ -124,7 +133,17 @@ export default function DashboardContainer() { useEffect(() => { fetchTopPages(); - }, [topPagespage]); + }, [topPagespage, topContentDate]); + + const getDate = (data: any) => { + if (data === null) { + return ""; + } else { + return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${ + data.day < 10 ? `0${data.day}` : data.day + }`; + } + }; async function fetchTopPages() { const req = { @@ -134,6 +153,8 @@ export default function DashboardContainer() { sort: "desc", isPublish: true, timeStamp: getUnixTimestamp(), + startDate: getDate(topContentDate.startDate), + endDate: getDate(topContentDate.endDate), }; const res = await getTopArticles(req); setTopPages(getTableNumber(10, res.data?.data)); @@ -143,6 +164,7 @@ export default function DashboardContainer() { useEffect(() => { fetchPostCount(); }, [postContentDate]); + async function fetchPostCount() { const getDate = (data: any) => { return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${ @@ -334,7 +356,8 @@ export default function DashboardContainer() {

Recent Article

- + + {/* */} @@ -367,6 +390,8 @@ export default function DashboardContainer() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} @@ -435,14 +460,6 @@ export default function DashboardContainer() { Mingguan
- {/* setStartDateValue(e)} - inputClassName="z-50 w-full text-xs lg:text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300" - /> */}

Top Pages

+
+ + + + {convertDateFormatNoTime(topContentDate.startDate)} + + + + + setTopContentDate({ + startDate: e, + endDate: topContentDate.endDate, + }) + } + maxValue={topContentDate.endDate} + /> + + + - + + + + {convertDateFormatNoTime(topContentDate.endDate)} + + + + + setTopContentDate({ + startDate: topContentDate.startDate, + endDate: e, + }) + } + minValue={topContentDate.startDate} + /> + + +
No
Title
Visits
+ {(!topPages || topPages?.length < 1) && ( +
+ Tidak ada Data +
+ )} {topPages?.map((list) => (
{list?.no}
@@ -488,21 +557,25 @@ export default function DashboardContainer() {
{list?.viewCount}
))} -
- setTopPagesPage(page)} - /> -
+ {topPages?.length > 0 && ( +
+ setTopPagesPage(page)} + /> +
+ )}
diff --git a/components/main/detail/e-magazine-detail.tsx b/components/main/detail/e-magazine-detail.tsx index f71f1bf..3ece1ea 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 b580793..b578d0f 100644 --- a/components/main/detail/list-news.tsx +++ b/components/main/detail/list-news.tsx @@ -1,25 +1,45 @@ "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 { useCallback, useEffect, useRef, useState } from "react"; +import { + getArticleByCategoryLanding, + getListArticle, +} from "@/services/article"; +import { + convertDateFormatNoTimeV2, + formatMonthString, + htmlToString, + textEllipsis, +} from "@/utils/global"; import { useParams, usePathname, @@ -27,6 +47,24 @@ import { useSearchParams, } from "next/navigation"; import { close, loading } from "@/config/swal"; +import { format } from "date-fns"; +import { getCategoryById } from "@/services/master-categories"; +import AsyncSelect from "react-select/async"; + +const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", +]; export default function ListNews() { const [article, setArticle] = useState([]); @@ -38,28 +76,85 @@ export default function ListNews() { const params = useParams(); const category = params?.name; const searchParams = useSearchParams(); - const search = searchParams.get("search"); - const [searchValue, setSearchValue] = useState(search || ""); + const categoryIds = searchParams.get("category_id"); + const [categories, setCategories] = useState([]); + const [searchValue, setSearchValue] = useState( + searchParams.get("search") || "" + ); + const [categorySearch, setCategorySearch] = 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(() => { + const search = searchParams.get("search"); + const category = searchParams.get("category_id"); + if (searchParams.get("search")) { + setSearchValue(String(searchParams.get("search"))); + getArticle({ title: String(search) }); + } + + if (category && category !== "") { + getCategoryFromQueries(category.split(",")); + } + }, [searchParams]); + + const getCategoryFromQueries = async (category: string[]) => { + const temp = []; + for (const element of category) { + const res = await getCategoryById(Number(element)); + if (res?.data?.data) { + temp.push(res?.data?.data); + } + } + + const setup = setupCategory(temp); + setSelectedCategoryId(setup); + getArticle({ category: setup }); + }; useEffect(() => { getArticle(); - }, [page, category]); + }, [page, searchParams]); - async function getArticle() { + async function getArticle(props?: { title?: string; category?: any }) { loading(); - topRef.current?.scrollIntoView({ behavior: "smooth" }); - + // topRef.current?.scrollIntoView({ behavior: "smooth" }); const req = { page: page, - search: searchValue || "", + search: props?.title || searchValue || "", limit: "9", - // isPublish: pathname.includes("polda") ? false : true, isPublish: true, sort: "desc", categorySlug: pathname.includes("polda") || pathname.includes("satker") ? String(category) : "", + categoryIds: props?.category + ? props.category.map((val: any) => val.id).join(",") + : selectedCategoryId.length > 0 + ? selectedCategoryId.map((val: any) => val.id).join(",") + : "", + + startDate: + selectedDate && selectedMonth !== null + ? convertDateFormatNoTimeV2(new Date(year, selectedMonth, 1)) + : "", + endDate: + selectedDate && selectedMonth !== null + ? convertDateFormatNoTimeV2(new Date(year, selectedMonth + 1, 0)) + : "", }; const response = await getListArticle(req); setArticle(response?.data?.data); @@ -67,6 +162,52 @@ export default function ListNews() { close(); } + const debounceTimeout = useRef(null); + + const getCategory = async (search?: string) => { + const res = await getArticleByCategoryLanding({ + // limit: debouncedValue === "" ? "5" : "", + // title: debouncedValue, + limit: !search || search === "" ? "5" : "", + title: search ? search : "", + }); + if (res?.data?.data) { + setCategories(res?.data?.data); + return res?.data?.data; + } + return []; + }; + + const setupCategory = (data: any) => { + const temp = []; + for (const element of data) { + temp.push({ + id: element.id, + label: element.title, + value: element.id, + }); + } + return temp; + }; + + const loadOptions = useCallback( + (inputValue: string, callback: (options: any) => void) => { + if (debounceTimeout.current) { + clearTimeout(debounceTimeout.current); + } + + debounceTimeout.current = setTimeout(async () => { + try { + const data = await getCategory(inputValue); + callback(setupCategory(data)); + } catch (error) { + callback([]); + } + }, 1500); + }, + [] + ); + return (
@@ -77,92 +218,172 @@ export default function ListNews() {

Berita

-
- { - if (event.key === "Enter") { - router.push(pathname + `?search=${searchValue}`); - getArticle(); - } - }} - labelPlacement="outside" - placeholder="Search..." - value={searchValue || ""} - onValueChange={setSearchValue} - endContent={ - - } - type="search" - /> -
-
- {article?.map((news: any) => ( - +
+ { + // if (event.key === "Enter") { + // router.push(pathname + `?search=${searchValue}`); + // getArticle(); + // } + // }} + labelPlacement="outside" + placeholder="Judul..." + value={searchValue} + onValueChange={setSearchValue} + type="search" + /> + + "border border-gray-300 border-1 rounded-xl min-w-[300px] max-w-[600px]", + menu: () => "z-50", + }} + value={selectedCategoryId} + onChange={setSelectedCategoryId} + /> +
+ + + + {" "} + {selectedDate + ? format(selectedDate, "MMMM yyyy") + : "Pilih Bulan"} + + + +
+ + {year} + +
+ +
+ {months.map((month, idx) => ( + + ))} +
+
+
{" "} + {selectedDate && ( + setSelectedDate(null)} + > + + + )} +
+
-
- + Cari + + {/* */} +
+ {article?.length < 1 || !article ? ( +
Tidak ada Data
+ ) : ( + <> +
+ {article?.map((news: any) => ( + +
+ thumbnail +
+
+
{news?.title}
+
+
+ +

{formatMonthString(news?.createdAt)}

+
+
+ +

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

+
+
+ +

{news?.createdByName}

+
+
+
+ {textEllipsis(htmlToString(news?.description), 165)} +
+
+ + ))} +
+
+ +
+ + )}
); diff --git a/components/main/detail/new-detail.tsx b/components/main/detail/new-detail.tsx index 46e8986..cb3c941 100644 --- a/components/main/detail/new-detail.tsx +++ b/components/main/detail/new-detail.tsx @@ -24,7 +24,6 @@ export default function NewsDetailPage(props: { datas: any }) { const [articles, setArticles] = useState([]); useEffect(() => { - // initFetch(); getArticles(); sendActivity(); }, []); @@ -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 8be8c04..ee74b16 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"); @@ -157,35 +157,102 @@ 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" - > - Sub 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.file_alt} + {/* {`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 + + ))} +
+ ))}
TAGS

{data?.categories?.map((category: any) => ( - + @@ -205,17 +276,20 @@ export default function DetailNews(props: { data: any; listArticle: any }) { ))}
- {data?.tags?.split(",").map((tag: any) => ( - - - - ))} + {data?.tags?.split(",").map( + (tag: any) => + tag !== "" && ( + + + + ) + )}
diff --git a/components/page/related-news.tsx b/components/page/related-news.tsx index 497a35b..976485d 100644 --- a/components/page/related-news.tsx +++ b/components/page/related-news.tsx @@ -12,13 +12,22 @@ import "swiper/css/navigation"; import Link from "next/link"; import { convertDateFormat, textEllipsis } from "@/utils/global"; -export default function RelatedNews() { +export default function RelatedNews(props: { categories: any }) { + const { categories } = props; const [article, setArticle] = useState([]); useEffect(() => { async function getArticle() { - const req = { page: 1, search: "", limit: "10", isPublish: true }; + 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); } @@ -63,8 +72,8 @@ export default function RelatedNews() { ); }} > - {article?.map((newsItem: any) => ( - + {article?.map((newsItem: any, index: number) => ( + ([]); - const [article, setArticle] = useState([]); + const [articlePolda, setArticlePolda] = useState([]); useEffect(() => { - getArticle(); getArticleMabes(); + getArticlePolda(); }, []); - 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: "1906", + category: "586", }; const response = await getListArticle(req); setArticleMabes(response?.data?.data); } + + async function getArticlePolda() { + const req = { + page: 1, + search: "", + limit: "10", + isPublish: true, + isPolda: true, + }; + + const response = await getListArticle(req); + setArticlePolda(response?.data?.data); + } + return (
@@ -49,49 +56,57 @@ export default function SidebarDetail() {
- - {articleMabes?.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 -

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

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

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

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

+ +

+ {convertDateFormat(newsItem.createdAt)} WIB

- -

- {convertDateFormat(newsItem.createdAt)} WIB -

+
-
- - ))} - + + ))} + + )}
diff --git a/components/table/article-table.tsx b/components/table/article-table.tsx index 3208481..6b7df31 100644 --- a/components/table/article-table.tsx +++ b/components/table/article-table.tsx @@ -328,7 +328,7 @@ export default function ArticleTable() { - + copyUrlArticle(article.id, article.slug)} @@ -671,6 +671,8 @@ export default function ArticleTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/comment/comment-table.tsx b/components/table/comment/comment-table.tsx index ae12d5a..5c36341 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", @@ -340,6 +343,8 @@ export default function CommentTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/disestages/transcript-draft-table.tsx b/components/table/disestages/transcript-draft-table.tsx index f5f7ee4..a4c90c7 100644 --- a/components/table/disestages/transcript-draft-table.tsx +++ b/components/table/disestages/transcript-draft-table.tsx @@ -179,6 +179,8 @@ export default function TranscriptDraftTable(props: { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/magazine/magazine-table.tsx b/components/table/magazine/magazine-table.tsx index 91d3fdb..17333bb 100644 --- a/components/table/magazine/magazine-table.tsx +++ b/components/table/magazine/magazine-table.tsx @@ -341,6 +341,8 @@ export default function MagazineTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/master-categories/categories-table.tsx b/components/table/master-categories/categories-table.tsx index 5977258..3c10406 100644 --- a/components/table/master-categories/categories-table.tsx +++ b/components/table/master-categories/categories-table.tsx @@ -285,7 +285,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { - + openModal(category.id, true)} @@ -468,6 +468,8 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/master-role-table.tsx b/components/table/master-role-table.tsx index c2a7c50..e942e14 100644 --- a/components/table/master-role-table.tsx +++ b/components/table/master-role-table.tsx @@ -250,6 +250,8 @@ export default function MasterRoleTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/master-user-table.tsx b/components/table/master-user-table.tsx index 672c67e..238a698 100644 --- a/components/table/master-user-table.tsx +++ b/components/table/master-user-table.tsx @@ -308,6 +308,8 @@ export default function MasterUserTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/master/master-user-level/master-user-level-table.tsx b/components/table/master/master-user-level/master-user-level-table.tsx index a508d17..337fc3c 100644 --- a/components/table/master/master-user-level/master-user-level-table.tsx +++ b/components/table/master/master-user-level/master-user-level-table.tsx @@ -381,6 +381,8 @@ export default function MasterUserLevelTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/static-page-table.tsx b/components/table/static-page-table.tsx index 52ab16e..3f8bb03 100644 --- a/components/table/static-page-table.tsx +++ b/components/table/static-page-table.tsx @@ -290,6 +290,8 @@ export default function StaticPageTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} diff --git a/components/table/suggestions/suggestions-table.tsx b/components/table/suggestions/suggestions-table.tsx index 4964f15..88a8195 100644 --- a/components/table/suggestions/suggestions-table.tsx +++ b/components/table/suggestions/suggestions-table.tsx @@ -665,6 +665,8 @@ export default function SuggestionsTable() { classNames={{ base: "bg-transparent", wrapper: "bg-transparent", + item: "w-fit px-3", + cursor: "w-fit px-3", }} page={page} total={totalPage} 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 6127724..f6c4a6d 100644 --- a/services/article.ts +++ b/services/article.ts @@ -24,21 +24,21 @@ export async function getListArticle(props: PaginationRequest) { isBanner, categoryIds, createdByIds, - timeStamp, + isPolda, } = props; const headers = { "content-type": "application/json", }; return await httpGet( - `/articles/public?sort=desc&sortBy=created_at&limit=${limit}&page=${page}&isPublish=${ + `/articles/public?limit=${limit}&page=${page}&isPublish=${ isPublish === undefined ? "" : isPublish }&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 || ""}&timeStamp=${timeStamp || ""}`, + }&createdByIds=${createdByIds || ""}&isPolda=${isPolda || ""}`, headers ); } @@ -241,32 +241,15 @@ export async function updateIsBannerArticle(id: number, status: boolean) { return await httpPut(pathUrl, headers); } -export async function httpGetHumas(pathUrl: any, headers: any) { - const response = await axiosInterceptorInstanceHumas - .get(pathUrl, { headers }) - .catch(function (error: any) { - console.log(error); - return error.response; - }); - console.log("Response base svc : ", response); - if (response?.status == 200 || response?.status == 201) { - return { - error: false, - message: "success", - data: response?.data, - }; - } else { - return { - error: true, - message: response?.data?.message || response?.data || null, - data: null, - }; - } -} - -export async function getArticleByIdHumas(id: any) { +export async function getArticleByCategoryLanding(props: { + limit: string; + title: string; +}) { const headers = { "content-type": "application/json", }; - return await httpGetHumas(`/articles/${id}`, headers); + return await httpGet( + `/article-categories?limit=${props.limit}&title=${props.title}`, + headers + ); } diff --git a/types/globals.tsx b/types/globals.tsx index 2a315df..a9e1597 100644 --- a/types/globals.tsx +++ b/types/globals.tsx @@ -69,5 +69,5 @@ export type PaginationRequest = { isBanner?: boolean; categoryIds?: string; createdByIds?: string; - timeStamp?: number; + isPolda?: boolean; };