From 962b9708bff0c3fb5bbdbd3d1f47a20ba3bbe81e Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Mon, 19 Jan 2026 13:03:54 +0700 Subject: [PATCH] fix:page query, polda query --- components/landing/CategorySatker.tsx | 2 +- components/landing/RegionalNews.tsx | 2 +- components/main/detail/list-news.tsx | 251 ++++++++++++++++++++++---- services/article.ts | 39 ++-- 4 files changed, 238 insertions(+), 56 deletions(-) diff --git a/components/landing/CategorySatker.tsx b/components/landing/CategorySatker.tsx index ca3fd01..97db9a6 100644 --- a/components/landing/CategorySatker.tsx +++ b/components/landing/CategorySatker.tsx @@ -320,7 +320,7 @@ export default function CategorySatker(props: { {SatkerAll.map((item: any, index: any) => (
diff --git a/components/landing/RegionalNews.tsx b/components/landing/RegionalNews.tsx index 83cd2b6..f60716e 100644 --- a/components/landing/RegionalNews.tsx +++ b/components/landing/RegionalNews.tsx @@ -318,7 +318,7 @@ export default function RegionalNews(props: { {listPoldaAll.map((item: any, index: any) => (
diff --git a/components/main/detail/list-news.tsx b/components/main/detail/list-news.tsx index b578d0f..23ee6f5 100644 --- a/components/main/detail/list-news.tsx +++ b/components/main/detail/list-news.tsx @@ -37,6 +37,7 @@ import { import { convertDateFormatNoTimeV2, formatMonthString, + getUnixTimestamp, htmlToString, textEllipsis, } from "@/utils/global"; @@ -50,6 +51,7 @@ import { close, loading } from "@/config/swal"; import { format } from "date-fns"; import { getCategoryById } from "@/services/master-categories"; import AsyncSelect from "react-select/async"; +import { data } from "autoprefixer"; const months = [ "Jan", @@ -79,7 +81,7 @@ export default function ListNews() { const categoryIds = searchParams.get("category_id"); const [categories, setCategories] = useState([]); const [searchValue, setSearchValue] = useState( - searchParams.get("search") || "" + searchParams.get("search") || "", ); const [categorySearch, setCategorySearch] = useState(""); const [selectedCategoryId, setSelectedCategoryId] = useState([]); @@ -88,9 +90,14 @@ export default function ListNews() { const [year, setYear] = useState(today.getFullYear()); const [selectedMonth, setSelectedMonth] = useState( - searchParams.get("month") ? Number(searchParams.get("month")) - 1 : null + searchParams.get("month") ? Number(searchParams.get("month")) - 1 : null, ); const [selectedDate, setSelectedDate] = useState(null); + const [poldaCategId, setPoldaCategId] = useState(0); + const isPoldaPage = pathname.includes("/news/polda/"); + const [poldaCategoryOption, setPoldaCategoryOption] = useState( + null, + ); const handleMonthClick = (monthIndex: number) => { setSelectedMonth(monthIndex); @@ -98,17 +105,68 @@ export default function ListNews() { }; 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 (isPoldaPage) getPoldaCategId(); + }, [params, isPoldaPage]); + + const getPoldaCategId = async () => { + const poldaNow = category as string; + console.log("poldanow", poldaNow.split("-").join(" ")); + const dataNow = await getCategory(poldaNow.split("-").join(" ")); + console.log("datanow", dataNow); + if (dataNow?.length > 0) { + const poldaObj = dataNow[0]; + + setPoldaCategId(poldaObj.id); + + const option = setupCategory([poldaObj])[0]; // <-- wajib array + setPoldaCategoryOption(option); + + // pastikan masuk ke selectedCategoryId (kalau belum ada) + setSelectedCategoryId((prev: any[]) => { + const already = prev.some((x) => x.id === option.id); + if (already) return prev; + return [option, ...prev]; + }); + } + }; + + useEffect(() => { + const search = searchParams.get("search") || ""; + const category = searchParams.get("category_id") || ""; + const month = searchParams.get("month"); + const yearQ = searchParams.get("year"); + const pageQ = searchParams.get("page"); + + // sync UI state dari URL + setSearchValue(search); + + if (pageQ) setPage(Number(pageQ)); + else setPage(1); + + if (yearQ) setYear(Number(yearQ)); + + if (month && yearQ) { + const m = Number(month) - 1; + setSelectedMonth(m); + setSelectedDate(new Date(Number(yearQ), m, 1)); + } else { + setSelectedMonth(null); + setSelectedDate(null); } if (category && category !== "") { getCategoryFromQueries(category.split(",")); + } else { + setSelectedCategoryId([]); + getArticle({ + title: search, + category: [], + month: month ? Number(month) : null, + year: yearQ ? Number(yearQ) : null, + page: pageQ ? Number(pageQ) : 1, + }); } - }, [searchParams]); + }, [searchParams, poldaCategId]); const getCategoryFromQueries = async (category: string[]) => { const temp = []; @@ -121,41 +179,88 @@ export default function ListNews() { const setup = setupCategory(temp); setSelectedCategoryId(setup); - getArticle({ category: setup }); + + const search = searchParams.get("search") || ""; + const month = searchParams.get("month"); + const yearQ = searchParams.get("year"); + const pageQ = searchParams.get("page"); + + getArticle({ + title: search, + category: setup, + month: month ? Number(month) : null, + year: yearQ ? Number(yearQ) : null, + page: pageQ ? Number(pageQ) : 1, + }); }; - useEffect(() => { - getArticle(); - }, [page, searchParams]); + // useEffect(() => { + // getArticle(); + // }, [page, searchParams]); - async function getArticle(props?: { title?: string; category?: any }) { + async function getArticle(props?: { + title?: string; + category?: any[]; + month?: number | null; + year?: number | null; + page?: number; + }) { loading(); - // topRef.current?.scrollIntoView({ behavior: "smooth" }); + + const usedPage = props?.page || page; + const usedSearch = props?.title ?? searchValue ?? ""; + + // 1) ambil kategori dari props atau state + const baseCategories = + props?.category && props.category.length > 0 + ? props.category + : selectedCategoryId; + + // 2) kalau halaman polda, pastikan poldaCategId selalu ikut + let finalCategories = baseCategories; + + if (isPoldaPage && poldaCategId) { + const hasPolda = baseCategories.some((x: any) => x.id === poldaCategId); + + if (!hasPolda) { + // polda wajib selalu ada + finalCategories = [ + ...(poldaCategoryOption ? [poldaCategoryOption] : []), + ...baseCategories, + ]; + } + } + + const usedCategoryIds = + finalCategories.length > 0 + ? finalCategories.map((val: any) => val.id).join(",") + : ""; + + const usedMonth = + props?.month ?? (selectedDate ? selectedDate.getMonth() + 1 : null); + + const usedYear = + props?.year ?? (selectedDate ? selectedDate.getFullYear() : null); + const req = { - page: page, - search: props?.title || searchValue || "", + page: usedPage, + search: usedSearch, limit: "9", 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(",") - : "", + categorySlug: pathname.includes("satker") ? String(category) : "", + categoryIds: usedCategoryIds, startDate: - selectedDate && selectedMonth !== null - ? convertDateFormatNoTimeV2(new Date(year, selectedMonth, 1)) + usedMonth && usedYear + ? convertDateFormatNoTimeV2(new Date(usedYear, usedMonth - 1, 1)) : "", endDate: - selectedDate && selectedMonth !== null - ? convertDateFormatNoTimeV2(new Date(year, selectedMonth + 1, 0)) + usedMonth && usedYear + ? convertDateFormatNoTimeV2(new Date(usedYear, usedMonth, 0)) : "", }; + const response = await getListArticle(req); setArticle(response?.data?.data); setTotalPage(response?.data?.meta?.totalPage); @@ -170,6 +275,7 @@ export default function ListNews() { // title: debouncedValue, limit: !search || search === "" ? "5" : "", title: search ? search : "", + timeStamp: getUnixTimestamp(), }); if (res?.data?.data) { setCategories(res?.data?.data); @@ -205,9 +311,28 @@ export default function ListNews() { } }, 1500); }, - [] + [], ); + const updateQuery = (newParams: Record) => { + const params = new URLSearchParams(searchParams.toString()); + + Object.entries(newParams).forEach(([key, value]) => { + if ( + value === undefined || + value === null || + value === "" || + (Array.isArray(value) && value.length === 0) + ) { + params.delete(key); + } else { + params.set(key, String(value)); + } + }); + + router.push(`${pathname}?${params.toString()}`); + }; + return (
@@ -225,7 +350,7 @@ export default function ListNews() { className="w-full lg:w-[300px]" classNames={{ inputWrapper: "bg-white hover:!bg-gray-100 border-1 rounded-md", - input: "text-sm !text-black", + input: "text-sm !text-black outline-none", }} // onKeyDown={(event) => { // if (event.key === "Enter") { @@ -251,7 +376,30 @@ export default function ListNews() { menu: () => "z-50", }} value={selectedCategoryId} - onChange={setSelectedCategoryId} + onChange={(val: any) => { + const nextValue = val || []; + + // kalau bukan halaman polda, normal + if (!pathname.includes("/news/polda/")) { + setSelectedCategoryId(nextValue); + return; + } + + // halaman polda: kategori polda harus tetap ada + if (poldaCategoryOption) { + const hasPolda = nextValue.some( + (x: any) => x.id === poldaCategoryOption.id, + ); + + if (!hasPolda) { + // user mencoba hapus kategori polda -> balikin lagi + setSelectedCategoryId([poldaCategoryOption, ...nextValue]); + return; + } + } + + setSelectedCategoryId(nextValue); + }} /> - */} + {/* */}
@@ -372,7 +541,7 @@ export default function ListNews() { ))}
- */} + { + setPage(p); + updateQuery({ page: p }); + }} + classNames={{ + item: "w-fit px-3", + cursor: "w-fit px-3", + }} />
diff --git a/services/article.ts b/services/article.ts index cbd667c..c8e9736 100644 --- a/services/article.ts +++ b/services/article.ts @@ -38,7 +38,7 @@ export async function getListArticle(props: PaginationRequest) { }&category=${categorySlug || ""}&isBanner=${isBanner || ""}&categoryIds=${ categoryIds || "" }&createdByIds=${createdByIds || ""}&isPolda=${isPolda || ""}`, - headers + headers, ); } @@ -68,7 +68,7 @@ export async function getListArticleAdminPage(props: PaginationRequest) { sort || "asc" }&category=${categorySlug || ""}&isBanner=${isBanner || ""}&categoryIds=${ categoryIds || "" - }&createdByIds=${createdByIds || ""}&timeStamp=${timeStamp || ""}` + }&createdByIds=${createdByIds || ""}&timeStamp=${timeStamp || ""}`, ); } @@ -90,7 +90,7 @@ export async function getTopArticles(props: PaginationRequest) { endDate || "" }&category=${category || ""}&sortBy=view_count&sort=desc&timeStamp=${ timeStamp || "" - }` + }`, ); } @@ -133,7 +133,7 @@ export async function getRecapArticleData(data: any) { }; return await httpGet( `/articles?page=${data.page}&userLevelId=${data.id}&startDate=${data.startDate}&endDate=${data.endDate}&startTime=${data.startTime}&endTime=${data.endTime}`, - headers + headers, ); } @@ -157,7 +157,7 @@ export async function getArticleByCategory(timeStamp: number) { Authorization: `Bearer ${token}`, }; return await httpGetInterceptor( - `/article-categories?limit=1000&timeStamp=${timeStamp}` + `/article-categories?limit=1000&timeStamp=${timeStamp}`, ); } export async function getCategoryPagination(data: any) { @@ -167,7 +167,7 @@ export async function getCategoryPagination(data: any) { }; return await httpGetInterceptor( - `/article-categories?limit=${data?.limit}&page=${data?.page}&title=${data?.search}&timeStamp=${data.timeStamp}` + `/article-categories?limit=${data?.limit}&page=${data?.page}&title=${data?.search}&timeStamp=${data.timeStamp}`, ); } @@ -207,7 +207,7 @@ export async function getUserLevelDataStat( startTime: string, endTime: string, levelType: string, - levelId?: number + levelId?: number, ) { // const headers = { // "content-type": "application/json", @@ -216,7 +216,7 @@ export async function getUserLevelDataStat( return await httpGetInterceptor( `/articles/statistic/user-levels?startDate=${startDate}&endDate=${endDate}&startTime=${startTime}&endTime=${endTime}&levelType=${levelType}&userLevelId=${ levelId || "" - }&timeStamp=${timeStamp}` + }&timeStamp=${timeStamp}`, ); } @@ -227,13 +227,13 @@ export async function getStatisticForMaps(startDate: string, endDate: string) { }; return await httpGet( `/activity-logs/visitors-by-region-stats?startDate=${startDate}&endDate=${endDate}`, - headers + headers, ); } export async function getStatisticVisitorsBrowser( startDate: string, - endDate: string + endDate: string, ) { const headers = { "content-type": "application/json", @@ -241,7 +241,7 @@ export async function getStatisticVisitorsBrowser( }; return await httpGet( `/activity-logs/visitors-by-browser-stats?startDate=${startDate}&endDate=${endDate}`, - headers + headers, ); } export async function getStatisticMonthly(year: string, timeStamp: number) { @@ -250,7 +250,7 @@ export async function getStatisticMonthly(year: string, timeStamp: number) { Authorization: `Bearer ${token}`, }; return await httpGetInterceptor( - `/articles/statistic/monthly?year=${year}&timeStamp=${timeStamp}` + `/articles/statistic/monthly?year=${year}&timeStamp=${timeStamp}`, ); } export async function getStatisticVisitorsMonthly(year: string) { @@ -260,7 +260,7 @@ export async function getStatisticVisitorsMonthly(year: string) { }; return await httpGet( `/activity-logs/visitors-monthly-stats?year=${year}`, - headers + headers, ); } export async function getStatisticUsersMonthly(year: string) { @@ -270,12 +270,12 @@ export async function getStatisticUsersMonthly(year: string) { }; return await httpGet( `/articles/statistic/monthly-per-user-level?year=${year}`, - headers + headers, ); } export async function getStatisticMonthlyFeedback( year: string, - timeStamp: number + timeStamp: number, ) { const headers = { "content-type": "application/json", @@ -283,7 +283,7 @@ export async function getStatisticMonthlyFeedback( }; return await httpGet( `/feedbacks/statistic/monthly?year=${year}&timeStamp=${timeStamp}`, - headers + headers, ); } export async function getStatisticSummary(timeStamp: number) { @@ -292,7 +292,7 @@ export async function getStatisticSummary(timeStamp: number) { Authorization: `Bearer ${token}`, }; return await httpGetInterceptor( - `/articles/statistic/summary?timeStamp=${timeStamp}` + `/articles/statistic/summary?timeStamp=${timeStamp}`, ); } @@ -320,12 +320,13 @@ export async function updateIsBannerArticle(id: number, status: boolean) { export async function getArticleByCategoryLanding(props: { limit: string; title: string; + timeStamp?: number; }) { const headers = { "content-type": "application/json", }; return await httpGet( - `/article-categories?limit=${props.limit}&title=${props.title}`, - headers + `/article-categories?limit=${props.limit}&title=${props.title}&timeStamp=${props?.timeStamp}`, + headers, ); }