fix:filter use query urt

This commit is contained in:
Rama Priyanto 2026-01-29 19:00:18 +07:00
parent 1df9197c5b
commit 4c807a7fee
3 changed files with 155 additions and 48 deletions

View File

@ -110,18 +110,15 @@ export default function ListNews() {
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
const option = setupCategory([poldaObj])[0];
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;
@ -137,7 +134,6 @@ export default function ListNews() {
const yearQ = searchParams.get("year");
const pageQ = searchParams.get("page");
// sync UI state dari URL
setSearchValue(search);
if (pageQ) setPage(Number(pageQ));
@ -210,20 +206,17 @@ export default function ListNews() {
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,
@ -380,20 +373,17 @@ export default function ListNews() {
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;
}

View File

@ -61,6 +61,7 @@ import { parseDate } from "@internationalized/date";
import { listMasterUsers } from "@/services/master-user";
import ReactSelect from "react-select";
import makeAnimated from "react-select/animated";
import { useRouter, useSearchParams } from "next/navigation";
const columns = [
{ name: "No", uid: "no" },
@ -100,11 +101,14 @@ export default function ArticleTable() {
const animatedComponents = makeAnimated();
const roleId = getCookiesDecrypt("urie");
const [page, setPage] = useState(1);
const router = useRouter();
const searchParams = useSearchParams();
const [page, setPage] = useState(Number(searchParams.get("page")) || 1);
const [totalPage, setTotalPage] = useState(1);
const [article, setArticle] = useState<any[]>([]);
const [showData, setShowData] = useState("10");
const [search, setSearch] = useState("");
const [showData, setShowData] = useState(searchParams.get("limit") || "10");
const [search, setSearch] = useState(searchParams.get("search") || "");
const [categories, setCategories] = useState<any>([]);
const [users, setUsers] = useState<any>([]);
const [selectedCategories, setSelectedCategories] = useState<any>([]);
@ -116,36 +120,92 @@ export default function ArticleTable() {
const [selectedArticles, setSelectedArticles] = useState<any>(new Set([]));
// const [articleDate, setArticleDate] = useState<any>({
// startDate: parseDate(
// convertDateFormatNoTimeV2(
// new Date(new Date().setDate(new Date().getDate() - 7)),
// ),
// ),
// endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
// });
const [articleDate, setArticleDate] = useState<any>({
startDate: parseDate(
convertDateFormatNoTimeV2(
new Date(new Date().setDate(new Date().getDate() - 7))
)
),
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
startDate: searchParams.get("startDate")
? parseDate(searchParams.get("startDate")!)
: null,
endDate: searchParams.get("endDate")
? parseDate(searchParams.get("endDate")!)
: null,
});
useEffect(() => {
initState();
}, [page, showData]);
useEffect(() => {
if (page == 1) {
initState();
} else {
setPage(1);
}
}, [selectedCategories, selectedUsers, articleDate, startDateValue]);
useEffect(() => {
getCategories();
getUsers();
}, []);
useEffect(() => {
initState();
}, [searchParams]);
const updateQuery = (params: Record<string, any>) => {
const current = new URLSearchParams(searchParams.toString());
Object.entries(params).forEach(([key, value]) => {
if (
value === undefined ||
value === null ||
value === "" ||
(Array.isArray(value) && value.length === 0)
) {
current.delete(key);
} else {
current.set(key, String(value));
}
});
current.set("timeStamp", String(getUnixTimestamp()));
router.push(`?${current.toString()}`);
};
const setupList = (data: any, type: string) => {
const temp = [];
const categoryIds = searchParams.get("categoryIds") || "";
const createdByIds = searchParams.get("createdByIds") || "";
let tempCateg: number[] = [];
let tempCreated: number[] = [];
const selectedCat: any[] = [];
const selectedUsr: any[] = [];
if (categoryIds && categoryIds !== "") {
tempCateg = categoryIds
.split(",")
.map((id) => Number(id))
.filter((id) => !isNaN(id));
}
if (createdByIds && createdByIds !== "") {
tempCreated = createdByIds
.split(",")
.map((id) => Number(id))
.filter((id) => !isNaN(id));
}
if (data) {
for (const element of data) {
if (type === "category" && tempCateg.includes(element.id)) {
selectedCat.push({
id: element.id,
label: element.title,
value: element.id,
});
}
if (type === "users" && tempCreated.includes(element.id)) {
selectedUsr.push({
id: element.id,
label: element.fullname,
value: element.id,
});
}
temp.push({
id: element.id,
label: element.title || element.fullname,
@ -154,10 +214,12 @@ export default function ArticleTable() {
}
if (type === "users") {
setUsers(temp);
setSelectedUsers(selectedUsr);
}
if (type === "category") {
setCategories(temp);
setSelectedCategories(selectedCat);
}
}
};
@ -208,16 +270,16 @@ export default function ArticleTable() {
async function initState() {
loading();
const req = {
limit: showData,
page: page,
search: search,
startDate: getDate(articleDate.startDate),
endDate: getDate(articleDate.endDate),
categoryIds: getIds(selectedCategories),
createdByIds: getIds(selectedUsers),
limit: searchParams.get("limit") || showData,
page: Number(searchParams.get("page")) || "",
search: searchParams.get("search") || "",
startDate: searchParams.get("startDate") || "",
endDate: searchParams.get("endDate") || "",
categoryIds: searchParams.get("categoryIds") || "",
createdByIds: searchParams.get("createdByIds") || "",
sort: "desc",
sortBy: "created_at",
timeStamp: getUnixTimestamp(),
timeStamp: searchParams.get("timeStamp") || getUnixTimestamp(),
};
const res = await getListArticleAdminPage(req);
await getTableNumber(parseInt(showData), res.data?.data);
@ -467,7 +529,7 @@ export default function ArticleTable() {
return cellValue;
}
},
[article, page, selectedArticles]
[article, page, selectedArticles],
);
let typingTimer: NodeJS.Timeout;
@ -487,6 +549,19 @@ export default function ArticleTable() {
initState();
}
const handleApplyFilter = () => {
setPage(1);
updateQuery({
page: 1,
limit: showData,
search,
categoryIds: getIds(selectedCategories),
createdByIds: getIds(selectedUsers),
startDate: getDate(articleDate.startDate),
endDate: getDate(articleDate.endDate),
});
};
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
@ -507,16 +582,17 @@ export default function ArticleTable() {
aria-label="Search"
classNames={{
inputWrapper: "bg-default-100",
input: "text-sm",
input: "text-sm outline-none",
}}
labelPlacement="outside"
startContent={
<SearchIcon className="text-base text-default-400 pointer-events-none flex-shrink-0" />
}
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
onKeyUp={handleKeyUp}
onKeyDown={handleKeyDown}
// onKeyUp={handleKeyUp}
// onKeyDown={handleKeyDown}
/>
</div>
<div className="flex flex-col gap-1 w-full lg:w-[72px]">
@ -554,6 +630,7 @@ export default function ArticleTable() {
isClearable={true}
isSearchable={true}
isMulti={true}
value={selectedCategories}
placeholder="Kategori..."
name="sub-module"
options={categories}
@ -564,7 +641,7 @@ export default function ArticleTable() {
<p className="font-semibold text-sm">Author</p>
<ReactSelect
className="basic-single text-black z-40"
className="basic-single text-black z-30"
classNames={{
control: (state: any) =>
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
@ -572,6 +649,7 @@ export default function ArticleTable() {
classNamePrefix="select"
onChange={setSelectedUsers}
closeMenuOnSelect={false}
value={selectedUsers}
components={animatedComponents}
isClearable={true}
isSearchable={true}
@ -666,6 +744,42 @@ export default function ArticleTable() {
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-1 ">
<p className="font-semibold text-sm">Filter</p>
<div className="flex flex-row gap-1">
<Button
color="primary"
className="h-[42px] w-full"
onPress={handleApplyFilter}
>
Cari
</Button>
<Button
variant="bordered"
className="w-full"
color="warning"
onPress={() => {
setSearch("");
setSelectedCategories([]);
setSelectedUsers([]);
setArticleDate({ startDate: null, endDate: null });
setPage(1);
setShowData("10");
updateQuery({
page: 1,
limit: "10",
search: "",
categoryIds: [],
createdByIds: [],
startDate: "",
endDate: "",
});
}}
>
Reset
</Button>
</div>
</div>
</div>
<Table
aria-label="micro issue table"
@ -717,7 +831,10 @@ export default function ArticleTable() {
}}
page={page}
total={totalPage}
onChange={(page) => setPage(page)}
onChange={(p) => {
setPage(p);
updateQuery({ page: p });
}}
/>
</div>
</div>

View File

@ -43,7 +43,7 @@ export async function getListArticle(props: PaginationRequest) {
);
}
export async function getListArticleAdminPage(props: PaginationRequest) {
export async function getListArticleAdminPage(props: any) {
const {
page,
limit,