feat: enhance payment retrieval with flexible query parameters and add dynamic filters to payments page
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 2m18s

This commit is contained in:
2025-07-05 20:39:28 +05:00
parent 5bc8366003
commit fa0d088f7f
4 changed files with 62 additions and 22 deletions

View File

@ -90,10 +90,19 @@ export async function getPayment({ id }: { id: string }) {
return data;
}
export async function getPayments() {
type GetPaymentProps = {
[key: string]: string | number | undefined; // Allow additional properties for flexibility
};
export async function getPayments(params: GetPaymentProps) {
// Build query string from all defined params
const query = Object.entries(params)
.filter(([_, value]) => value !== undefined && value !== "")
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join("&");
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/payment/`,
`${process.env.SARLINK_API_BASE_URL}/api/billing/payment/?${query}`,
{
method: "GET",
headers: {

View File

@ -1,4 +1,5 @@
import { Suspense } from "react";
import DynamicFilter from "@/components/generic-filter";
import { PaymentsTable } from "@/components/payments-table";
import Search from "@/components/search";
@ -8,8 +9,6 @@ export default async function Payments({
searchParams: Promise<{
query: string;
page: number;
sortBy: string;
status: string;
}>;
}) {
const query = (await searchParams)?.query || "";
@ -23,7 +22,37 @@ export default async function Payments({
id="user-filters"
className=" pb-4 gap-4 flex sm:flex-row flex-col items-start justify-start"
>
<Search />
<DynamicFilter
inputs={[
{
label: "Payment",
name: "paid",
type: "radio-group",
options: [
{
label: "All",
value: "",
},
{
label: "Paid",
value: "true",
},
{
label: "Unpaid",
value: "false",
},
],
},
{
label: "Number of months",
name: "number_of_months",
type: "dual-range-slider",
min: 1,
max: 12,
step: 1,
},
]}
/>{" "}
</div>
<Suspense key={query} fallback={"loading...."}>
<PaymentsTable searchParams={searchParams} />

View File

@ -22,7 +22,6 @@ export async function DevicesTable({
searchParams,
parentalControl,
additionalFilters = {},
}: {
searchParams: Promise<{
[key: string]: unknown;

View File

@ -24,13 +24,17 @@ export async function PaymentsTable({
searchParams,
}: {
searchParams: Promise<{
query: string;
page: number;
sortBy: string;
[key: string]: unknown;
}>;
}) {
const query = (await searchParams)?.query || "";
const [error, payments] = await tryCatch(getPayments());
const resolvedParams = await searchParams;
const apiParams: Record<string, string | number | undefined> = {};
for (const [key, value] of Object.entries(resolvedParams)) {
if (value !== undefined && value !== "") {
apiParams[key] = typeof value === "number" ? value : String(value);
}
}
const [error, payments] = await tryCatch(getPayments(apiParams));
if (error) {
if (error.message.includes("Unauthorized")) {
@ -134,18 +138,17 @@ export async function PaymentsTable({
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={2}>
{query.length > 0 && (
<p className="text-sm text-muted-foreground">
Showing {payments?.data?.length} payments for &quot;
{query}
&quot;
<TableCell colSpan={3} className="text-muted-foreground">
{meta?.total === 1 ? (
<p className="text-center">
Total {meta?.total} payment.
</p>
)}
</TableCell>
<TableCell className="text-muted-foreground">
{meta.total} payments
</TableCell>
) : (
<p className="text-center">
Total {meta?.total} payments.
</p>
)} </TableCell>
</TableRow>
</TableFooter>
</Table>