Commit e45b44cb by Arjun Jhukal

updated the multiple filter logic and integrated filter at transaction

parent 59a2480e
......@@ -20,6 +20,7 @@ interface SelectFieldProps {
options: Option[];
error?: boolean;
touched?: boolean;
placeholder?: string;
}
export default function SelectField({
......@@ -32,6 +33,7 @@ export default function SelectField({
options,
error,
touched,
placeholder
}: SelectFieldProps) {
const theme = useThemeContext();
return (
......@@ -47,7 +49,7 @@ export default function SelectField({
onBlur={onBlur}
className="w-full border text-[14px] border-gray-300 rounded-lg px-3 py-2 focus:border-primary outline-0"
>
<option value="">Select the Type of Game</option>
<option value="">{placeholder || "-- choose any one --"}</option>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.name}
......
// // import { Button, IconButton, InputAdornment, OutlinedInput, useMediaQuery } from "@mui/material";
// // import SelectField from "../atom/SelectField";
// // import { DocumentDownload, SearchNormal } from "@wandersonalwes/iconsax-react";
// // interface TableHeaderProps {
// // search: string;
// // setSearch?: (value: string) => void;
// // filterMethod?: string;
// // setFilterMethod?: (value: string) => void;
// // onDownloadCSV: () => void;
// // }
// // export default function TableHeader({
// // search,
// // setSearch,
// // filterMethod,
// // setFilterMethod,
// // onDownloadCSV,
// // }: TableHeaderProps) {
// // const downMD = useMediaQuery((theme) => theme.breakpoints.down('md'));
// // return (
// // <div className="table__header p-4 mb-4 flex justify-between">
// // <div className="inpute__field relative">
// // <OutlinedInput
// // placeholder="Search keywords..."
// // name="search"
// // id="search"
// // value={search}
// // onChange={(e) => setSearch && setSearch(e.target.value)}
// // startAdornment={
// // <InputAdornment position="start">
// // <IconButton edge="start">
// // <SearchNormal size={20} />
// // </IconButton>
// // </InputAdornment>
// // }
// // />
// // </div>
// // {filterMethod ? <div className="header-right flex justify-end items-center gap-2">
// // <SelectField
// // name="search"
// // value={filterMethod}
// // onChange={(e) => setFilterMethod && setFilterMethod(e.target.value)}
// // options={[
// // { value: "all", name: "All Method" },
// // { value: "crypto", name: "Crypto" },
// // { value: "paypal", name: "USD/Paypal" },
// // ]}
// // />
// // </div> : ""}
// // <Button
// // startIcon={
// // !downMD && <DocumentDownload size={16} />
// // }
// // onClick={onDownloadCSV} sx={{
// // borderRadius: "8px",
// // border: "1px solid var(--Gray, #E0E0E3)",
// // padding: "8px 16px",
// // color: "#0E0E11",
// // maxWidth: "fit-content",
// // }}>{downMD ? <DocumentDownload size={16} /> : "Download CSV"}</Button>
// // </div>
// // );
// // }
// import { Button, IconButton, InputAdornment, OutlinedInput, useMediaQuery } from "@mui/material";
// import SelectField from "../atom/SelectField";
// import { DocumentDownload, SearchNormal } from "@wandersonalwes/iconsax-react";
// interface FilterOption {
// value: string;
// label: string;
// }
// interface TableHeaderProps {
// search: string;
// setSearch?: (value: string) => void;
// filterMethod?: string;
// setFilterMethod?: (value: string) => void;
// filterOptions?: FilterOption[];
// onDownloadCSV: () => void;
// }
......@@ -15,11 +86,13 @@
// setSearch,
// filterMethod,
// setFilterMethod,
// filterOptions,
// onDownloadCSV,
// }: TableHeaderProps) {
// const downMD = useMediaQuery((theme) => theme.breakpoints.down('md'));
// const downMD = useMediaQuery((theme: any) => theme.breakpoints.down('md'));
// return (
// <div className="table__header p-4 mb-4 flex justify-between">
// <div className="table__header p-4 mb-4 flex justify-between items-center gap-4">
// <div className="inpute__field relative">
// <OutlinedInput
// placeholder="Search keywords..."
......@@ -36,33 +109,37 @@
// }
// />
// </div>
// {filterMethod ? <div className="header-right flex justify-end items-center gap-2">
// <SelectField
// name="search"
// value={filterMethod}
// onChange={(e) => setFilterMethod && setFilterMethod(e.target.value)}
// options={[
// { value: "all", name: "All Method" },
// { value: "crypto", name: "Crypto" },
// { value: "paypal", name: "USD/Paypal" },
// ]}
// />
// </div> : ""}
// <Button
// startIcon={
// !downMD && <DocumentDownload size={16} />
// }
// onClick={onDownloadCSV} sx={{
// borderRadius: "8px",
// border: "1px solid var(--Gray, #E0E0E3)",
// padding: "8px 16px",
// color: "#0E0E11",
// maxWidth: "fit-content",
// }}>{downMD ? <DocumentDownload size={16} /> : "Download CSV"}</Button>
// <div className="header-right flex justify-end items-center gap-2">
// {filterOptions && (
// <SelectField
// name="filter"
// value={filterMethod || ""}
// onChange={(e) => setFilterMethod && setFilterMethod(e.target.value)}
// options={filterOptions.map(option => ({
// value: option.value,
// name: option.label
// }))}
// />
// )}
// {onDownloadCSV ? <Button
// startIcon={!downMD && <DocumentDownload size={16} />}
// onClick={onDownloadCSV}
// sx={{
// borderRadius: "8px",
// border: "1px solid var(--Gray, #E0E0E3)",
// padding: "8px 16px",
// color: "#0E0E11",
// maxWidth: "fit-content",
// }}
// >
// {downMD ? <DocumentDownload size={16} /> : "Download CSV"}
// </Button> : ""}
// </div>
// </div>
// );
// }
import { Button, IconButton, InputAdornment, OutlinedInput, useMediaQuery } from "@mui/material";
import SelectField from "../atom/SelectField";
import { DocumentDownload, SearchNormal } from "@wandersonalwes/iconsax-react";
......@@ -75,8 +152,13 @@ interface FilterOption {
interface TableHeaderProps {
search: string;
setSearch?: (value: string) => void;
// Single filter support
filterMethod?: string;
setFilterMethod?: (value: string) => void;
// Multiple filters support
filters?: { value: string; setValue: (value: string) => void; options: FilterOption[], placeholder?: string }[];
filterOptions?: FilterOption[];
onDownloadCSV: () => void;
}
......@@ -86,13 +168,16 @@ export default function TableHeader({
setSearch,
filterMethod,
setFilterMethod,
filterOptions,
filters,
onDownloadCSV,
filterOptions,
}: TableHeaderProps) {
const downMD = useMediaQuery((theme: any) => theme.breakpoints.down('md'));
return (
<div className="table__header p-4 mb-4 flex justify-between items-center gap-4">
<div className="table__header p-4 mb-4 flex flex-wrap justify-between items-center gap-4">
{/* Search Field */}
<div className="inpute__field relative">
<OutlinedInput
placeholder="Search keywords..."
......@@ -110,20 +195,33 @@ export default function TableHeader({
/>
</div>
<div className="header-right flex justify-end items-center gap-2">
{filterMethod && filterOptions && (
{/* Filters */}
<div className="header-right flex flex-wrap justify-end items-center gap-2">
{/* Multi-filter mode */}
{filters?.map((f, idx) => (
<SelectField
key={idx}
name={`filter-${idx}`}
value={f.value}
onChange={(e) => f.setValue && f.setValue(e.target.value)}
options={f.options.map(opt => ({ value: opt.value, name: opt.label }))}
placeholder={f.placeholder && f.placeholder}
/>
))}
{/* Legacy single filter mode */}
{filterOptions && filterMethod !== undefined && setFilterMethod && (
<SelectField
name="filter"
value={filterMethod}
onChange={(e) => setFilterMethod && setFilterMethod(e.target.value)}
options={filterOptions.map(option => ({
value: option.value,
name: option.label
}))}
onChange={(e) => setFilterMethod(e.target.value)}
options={filterOptions.map(opt => ({ value: opt.value, name: opt.label }))}
/>
)}
{onDownloadCSV ? <Button
{/* Download Button */}
<Button
startIcon={!downMD && <DocumentDownload size={16} />}
onClick={onDownloadCSV}
sx={{
......@@ -135,8 +233,8 @@ export default function TableHeader({
}}
>
{downMD ? <DocumentDownload size={16} /> : "Download CSV"}
</Button> : ""}
</Button>
</div>
</div>
);
}
\ No newline at end of file
}
......@@ -5,6 +5,8 @@ import { User, Lock, ArrowUp, ArrowDown } from '@wandersonalwes/iconsax-react';
import React, { useMemo } from 'react';
import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, ColumnDef } from '@tanstack/react-table';
import { Pagination, Box } from '@mui/material';
import { TransactionStatusProps } from '../transaction/TransactionTable';
import { StatusOptions } from '@/types/config';
interface Activity {
id: number;
......@@ -168,11 +170,12 @@ export default function Activities() {
const [search, setSearch] = React.useState("");
const [page, setPage] = React.useState(1);
const [status, setStatus] = React.useState<TransactionStatusProps | undefined>();
const [pageSize, setPageSize] = React.useState(10);
const [activityType, setActivityType] = React.useState("all");
const [sorting, setSorting] = React.useState<any>([]);
// Filter data based on search and activity type
const filteredData = useMemo(() => {
return activities.filter(activity => {
const matchesSearch = search === "" ||
......@@ -308,18 +311,17 @@ export default function Activities() {
const totalPages = Math.ceil(filteredData.length / pageSize);
return (
<div className="border-gray border-solid border-[1px] rounded-[8px] lg:rounded-[16px]">
<TableHeader
search={search}
setSearch={setSearch}
filterMethod={activityType}
setFilterMethod={(value) => {
setActivityType(value);
setPage(1);
}}
filterOptions={activityTypes}
filters={[
{ value: activityType, setValue: setActivityType, options: activityTypes, placeholder: "Filter by type" },
{ value: status || "", setValue: (value) => setStatus(value as TransactionStatusProps), options: StatusOptions, placeholder: "Filter by status" }
]}
onDownloadCSV={() => { }}
/>
......
......@@ -2,6 +2,7 @@
import TableHeader from '@/components/molecules/TableHeader';
import CustomTable from '@/components/organism/Table';
import { useGetAllTransactionQuery } from '@/services/transaction';
import { StatusOptions } from '@/types/config';
import { SingleDepositProps } from '@/types/transaction';
import { formatDateTime } from '@/utils/formatDateTime';
import { getInitials } from '@/utils/getInitials';
......@@ -16,12 +17,14 @@ import {
import { ArrowDown, ArrowUp } from '@wandersonalwes/iconsax-react';
import React, { useMemo, useState } from 'react';
export type TransactionStatusProps = "success" | "failed" | "pending";
export default function TransactionTable({ user_id, game_id, search, setSearch }: { user_id?: string; game_id?: number, search: string, setSearch?: (newvalue: string) => void }) {
const [sorting, setSorting] = useState<{ id: string; desc: boolean }[]>([]);
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [rowSelection, setRowSelection] = useState({});
const [status, setStatus] = React.useState<TransactionStatusProps | undefined>();
const queryArgs = useMemo(
() => ({
page,
......@@ -29,8 +32,9 @@ export default function TransactionTable({ user_id, game_id, search, setSearch }
search: search || "",
game_id,
user_id,
status
}),
[page, pageSize, search, game_id, user_id]
[page, pageSize, search, game_id, user_id, status]
);
const { data, isLoading: loadingTransaction } = useGetAllTransactionQuery(queryArgs);
......@@ -149,7 +153,14 @@ export default function TransactionTable({ user_id, game_id, search, setSearch }
return (
<div className="border-gray border-solid border-[1px] rounded-[8px] lg:rounded-[16px]">
<TableHeader search={search} setSearch={setSearch && setSearch} onDownloadCSV={() => { }} />
<TableHeader
search={search}
setSearch={setSearch && setSearch}
onDownloadCSV={() => { }}
filters={[
{ value: status || "", setValue: (value) => setStatus(value as TransactionStatusProps), options: StatusOptions, placeholder: "Filter by status" }
]}
/>
<>
<CustomTable
......
......@@ -2,6 +2,7 @@ import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./baseQuery";
import { DepositListProps, DepositProps, DepositResponseProps, DepositUrlProps } from "@/types/transaction";
import { QueryParams } from "@/types/config";
import { TransactionStatusProps } from "@/components/pages/dashboard/adminDashboard/transaction/TransactionTable";
export const transactionApi = createApi({
reducerPath: "transactionApi",
......@@ -52,14 +53,15 @@ export const transactionApi = createApi({
},
providesTags: ["Withdrawl"]
}),
getAllTransaction: builder.query<DepositListProps, QueryParams & { user_id?: string | number; game_id?: string | number }>({
query: ({ search, page, per_page, user_id, game_id }) => {
getAllTransaction: builder.query<DepositListProps, QueryParams & { status?: TransactionStatusProps; user_id?: string | number; game_id?: string | number }>({
query: ({ search, page, per_page, user_id, game_id, status }) => {
const params = new URLSearchParams();
if (search) params.append('search', search);
if (page) params.append('page', page.toString());
if (per_page) params.append('page_size', per_page.toString());
if (user_id) params.append('user', user_id.toString());
if (game_id) params.append('game', game_id.toString());
if (status) params.append('status', status.toString());
const queryString = params.toString();
return {
url: `/api/admin/transactions${queryString ? `?${queryString}` : ''}`,
......
......@@ -38,4 +38,10 @@ export interface QueryParams {
per_page?: number;
search?: string;
status?: string;
}
\ No newline at end of file
}
export const StatusOptions = [
{ label: "Success", value: "success" },
{ label: "Pending", value: "pending" },
{ label: "Failed", value: "failed" },
]
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment