Commit e45b44cb by Arjun Jhukal

updated the multiple filter logic and integrated filter at transaction

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