Skip to content

Commit

Permalink
add field to show the total number of payments
Browse files Browse the repository at this point in the history
  • Loading branch information
Vyshnav001 committed Oct 11, 2024
1 parent 6f5f9e8 commit bacacce
Showing 1 changed file with 62 additions and 56 deletions.
118 changes: 62 additions & 56 deletions src/components/common/searchable-infinite-scroll-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect, useRef, useState, useCallback } from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Input } from "@/components/ui/input";
import { Loader2, Search } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import axios from "axios";
import debounce from "lodash.debounce";

Expand All @@ -18,15 +19,14 @@ interface TableData {
amount: number;
}

export function SearchableInfiniteScrollTable() {
export function SearchableInfiniteScrollTable({totalPayments}: {totalPayments: number}) {
const [data, setData] = useState<TableData[]>([]);
const [filteredData, setFilteredData] = useState<TableData[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [page, setPage] = useState(1);
const [searchTerm, setSearchTerm] = useState("");
const [hasMoreData, setHasMoreData] = useState(true);
const loaderRef = useRef<HTMLDivElement>(null);
const observerRef = useRef<IntersectionObserver | null>(null);

const getPaymentDetails = async (page: number, query: string) => {
if (isLoading || !hasMoreData) return;
Expand All @@ -37,19 +37,18 @@ export function SearchableInfiniteScrollTable() {
`/api/users/payment?page=${page}&search=${encodeURIComponent(query)}`
);
const users = response.data.users;

if (users.length === 0) {
setHasMoreData(false); // No more data to load
setHasMoreData(false);
}

setData((prevData) => {
const newData = [...prevData, ...users];
// Remove duplicates
const uniqueData = Array.from(
new Map(newData.map((item) => [item.razorpayPaymentId, item])).values()
);
return uniqueData;
});

setPage((prevPage) => prevPage + 1);
} catch (error) {
console.error("Error fetching payment details:", error);
Expand All @@ -58,20 +57,22 @@ export function SearchableInfiniteScrollTable() {
}
};

const loadMoreData = () => {
const loadMoreData = useCallback(() => {
if (searchTerm === "") {
getPaymentDetails(page, "");
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [page, searchTerm]);

const fetchSearchResults = useCallback(async (query: string) => {
setPage(1); // Reset page number
setHasMoreData(true); // Reset hasMoreData
setPage(1);
setHasMoreData(true);
try {
const response = await axios.get(`/api/users/payment?page=1&search=${encodeURIComponent(query)}`);
const users = response.data.users;
setData(users); // Set new data from search
setFilteredData(users); // Set filtered data to the same as new data
const total = response.data.total;
setData(users);
setFilteredData(users);
} catch (error) {
console.error("Error fetching payment details:", error);
}
Expand All @@ -81,20 +82,19 @@ export function SearchableInfiniteScrollTable() {
const debouncedFetch = useCallback(
debounce((query: string) => {
fetchSearchResults(query);
}, 500),
[]
}, 300),
[fetchSearchResults]
);

const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
setSearchTerm(value);
debouncedFetch(value); // Use debounced fetch function
debouncedFetch(value);
};

useEffect(() => {
loadMoreData(); // Initial load
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
loadMoreData();
}, [loadMoreData]);

useEffect(() => {
const observer = new IntersectionObserver(
Expand All @@ -115,55 +115,61 @@ export function SearchableInfiniteScrollTable() {
// eslint-disable-next-line react-hooks/exhaustive-deps
observer.unobserve(loaderRef.current);
}
observer.disconnect();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading]);
}, [isLoading, loadMoreData]);

return (
<div className="container mx-auto py-10">
<div className="mb-4 relative">
<Input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleSearch}
className="pl-10"
/>
<Search
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
size={20}
/>
<div className="flex justify-between items-center mb-4">
<Badge variant="secondary" className="text-lg">
Total Payments: {totalPayments}
</Badge>
<div className="relative w-64">
<Input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleSearch}
className="pl-10"
aria-label="Search payments"
/>
<Search
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
size={20}
/>
</div>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
<TableHead>USN</TableHead>
<TableHead>Payment ID</TableHead>
<TableHead>Contact Number</TableHead>
<TableHead>Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{(searchTerm ? filteredData : data).map((item, index) => (
<TableRow key={index}>
<TableCell>{item.user.name}</TableCell>
<TableCell>{item.user.email}</TableCell>
<TableCell>{item.usn}</TableCell>
<TableCell>{item.razorpayPaymentId}</TableCell>
<TableCell>{item.contactNumber}</TableCell>
<TableCell>{item.amount.toFixed(2)}</TableCell>
<div className="overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
<TableHead>USN</TableHead>
<TableHead>Payment ID</TableHead>
<TableHead>Contact Number</TableHead>
<TableHead>Amount</TableHead>
</TableRow>
))}
</TableBody>
</Table>
</TableHeader>
<TableBody>
{(searchTerm ? filteredData : data).map((item, index) => (
<TableRow key={item.razorpayPaymentId}>
<TableCell>{item.user.name}</TableCell>
<TableCell>{item.user.email}</TableCell>
<TableCell>{item.usn}</TableCell>
<TableCell>{item.razorpayPaymentId}</TableCell>
<TableCell>{item.contactNumber}</TableCell>
<TableCell>{item.amount.toFixed(2)}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
{searchTerm === "" && hasMoreData && (
<div ref={loaderRef} className="flex justify-center py-4">
{isLoading && <Loader2 className="h-6 w-6 animate-spin" />}
</div>
)}
</div>
);
}
}

0 comments on commit bacacce

Please sign in to comment.