feat: implement debounced input search functionality and clean up TableList component
This commit is contained in:
parent
af41495643
commit
06387116f7
|
|
@ -10,11 +10,10 @@ import {
|
|||
SortingState,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button, Label, Table } from "flowbite-react";
|
||||
import { HiChevronLeft, HiChevronRight, HiPlus } from "react-icons/hi";
|
||||
import { useLocal } from "@/lib/utils/use-local";
|
||||
import { debouncedHandler } from "@/lib/utils/debounceHandler";
|
||||
import { FaSort, FaSortDown, FaSortUp } from "react-icons/fa6";
|
||||
import Link from "next/link";
|
||||
import { init_column } from "./lib/column";
|
||||
|
|
@ -196,7 +195,6 @@ export const TableList = <T extends object>({
|
|||
{"Loading..."}
|
||||
</>
|
||||
);
|
||||
console.log(local.fieldResultFilter);
|
||||
if (typeof onCount === "function") {
|
||||
const params = await events("onload-param", {
|
||||
take: 1,
|
||||
|
|
@ -273,6 +271,8 @@ export const TableList = <T extends object>({
|
|||
sort: local.sort,
|
||||
take,
|
||||
paging: local.paging,
|
||||
...local.filter,
|
||||
...local.fieldResultFilter,
|
||||
});
|
||||
if (!autoPagination) {
|
||||
res = paginateArray(res, take, local.paging);
|
||||
|
|
@ -360,6 +360,7 @@ export const TableList = <T extends object>({
|
|||
paging: 1,
|
||||
search: local.search,
|
||||
...local.filter,
|
||||
...local.fieldResultFilter,
|
||||
});
|
||||
const res = await onCount(params);
|
||||
local.count = res;
|
||||
|
|
@ -383,6 +384,8 @@ export const TableList = <T extends object>({
|
|||
sort: local.sort,
|
||||
take,
|
||||
paging: 1,
|
||||
...local.filter,
|
||||
...local.fieldResultFilter,
|
||||
});
|
||||
if (!autoPagination) {
|
||||
res = paginateArray(res, take, 1);
|
||||
|
|
@ -552,12 +555,6 @@ export const TableList = <T extends object>({
|
|||
onStateChange: setState,
|
||||
debugTable: state.pagination.pageIndex > 2,
|
||||
}));
|
||||
const handleSearch = useCallback(
|
||||
debouncedHandler(() => {
|
||||
local.refresh();
|
||||
}, 1000),
|
||||
[]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className="tbl-wrapper flex flex-grow flex-col">
|
||||
|
|
@ -586,7 +583,7 @@ export const TableList = <T extends object>({
|
|||
|
||||
<div className="ml-auto flex items-center flex-row gap-x-1">
|
||||
<div className="tbl-search hidden items-center sm:mb-0 sm:flex sm:divide-x sm:divide-gray-100">
|
||||
<form
|
||||
<div
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
await local.reload();
|
||||
|
|
@ -597,19 +594,19 @@ export const TableList = <T extends object>({
|
|||
</Label>
|
||||
<div className="relative lg:w-56">
|
||||
<InputSearch
|
||||
// className="bg-white search text-xs "
|
||||
id="users-search"
|
||||
delay={1000}
|
||||
name="users-search"
|
||||
placeholder={`Search`}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
local.search = value;
|
||||
local.render();
|
||||
handleSearch();
|
||||
local.refresh();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{mode === "table" && filter && local?.fieldFilter?.length ? (
|
||||
<div className="flex flex-row items-center">
|
||||
|
|
|
|||
|
|
@ -1,39 +1,48 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { HiSearch } from "react-icons/hi";
|
||||
import debounce from "lodash.debounce";
|
||||
|
||||
interface InputSearchProps extends React.ComponentProps<"input"> {
|
||||
delay?: number;
|
||||
}
|
||||
|
||||
const InputSearch = React.forwardRef<HTMLInputElement, InputSearchProps>(
|
||||
({ className, type, onChange, delay = 100, ...props }, ref) => {
|
||||
const debouncedLoadOptions = React.useMemo(
|
||||
() =>
|
||||
debounce((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (onChange) onChange(event);
|
||||
}, delay),
|
||||
[delay, onChange]
|
||||
);
|
||||
|
||||
const InputSearch = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
React.ComponentProps<"input">
|
||||
>(({ className, type, ...props }, ref) => {
|
||||
return (
|
||||
<div className="flex flex-row relative">
|
||||
<HiSearch
|
||||
className={cx(
|
||||
"absolute",
|
||||
css`
|
||||
top: 50%;
|
||||
left: 17px;
|
||||
transform: translate(-50%, -50%);
|
||||
`
|
||||
)}
|
||||
/>
|
||||
<HiSearch className="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-500" />
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"px-3 py-2 flex h-9 w-full rounded-md border border-gray-300 border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"px-3 py-2 flex h-9 w-full rounded-md border border-gray-300 bg-transparent text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className,
|
||||
css`
|
||||
padding-left: 30px;
|
||||
`
|
||||
"pl-10"
|
||||
)}
|
||||
ref={ref}
|
||||
onChange={debouncedLoadOptions}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter" && onChange) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault(); // Mencegah submit form default jika ada
|
||||
onChange(event as any); // Panggil `onChange` langsung saat Enter ditekan
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
InputSearch.displayName = "Input";
|
||||
}
|
||||
);
|
||||
|
||||
InputSearch.displayName = "InputSearch";
|
||||
|
||||
export { InputSearch };
|
||||
|
|
|
|||
Loading…
Reference in New Issue