mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-02-22 18:01:59 +00:00
- Introduced wallet payment option in verifyPayment function to allow users to pay using their wallet balance. - Added new BlockDeviceDialog component for managing device blocking and unblocking actions. - Updated DeviceCard component to display device status and integrate blocking functionality. - Refactored DevicesTable to utilize DeviceCard for better UI representation of devices. - Implemented Wallet component to manage wallet balance and top-up functionality. - Enhanced API routes and Prisma schema to support wallet transactions and device blocking reasons. - Improved overall user experience with responsive design adjustments and new UI elements. These changes improve user control over payments and device management, enhancing the overall functionality of the application.
190 lines
4.5 KiB
TypeScript
190 lines
4.5 KiB
TypeScript
import {
|
|
Table,
|
|
TableBody,
|
|
TableCaption,
|
|
TableCell,
|
|
TableFooter,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import { auth } from "@/lib/auth";
|
|
import prisma from "@/lib/db";
|
|
import { headers } from "next/headers";
|
|
import Link from "next/link";
|
|
import AddDevicesToCartButton from "./add-devices-to-cart-button";
|
|
import BlockDeviceButton from "./block-device-dialog";
|
|
import DeviceCard from "./device-card";
|
|
import Pagination from "./pagination";
|
|
|
|
export async function DevicesTable({
|
|
searchParams,
|
|
parentalControl
|
|
}: {
|
|
searchParams: Promise<{
|
|
query: string;
|
|
page: number;
|
|
sortBy: string;
|
|
}>;
|
|
parentalControl?: boolean;
|
|
}) {
|
|
const session = await auth.api.getSession({
|
|
headers: await headers()
|
|
})
|
|
const query = (await searchParams)?.query || "";
|
|
const page = (await searchParams)?.page;
|
|
const sortBy = (await searchParams)?.sortBy || "asc";
|
|
const totalDevices = await prisma.device.count({
|
|
where: {
|
|
userId: session?.session.userId,
|
|
OR: [
|
|
{
|
|
name: {
|
|
contains: query || "",
|
|
mode: "insensitive",
|
|
},
|
|
},
|
|
{
|
|
mac: {
|
|
contains: query || "",
|
|
mode: "insensitive",
|
|
},
|
|
},
|
|
],
|
|
NOT: {
|
|
payment: {
|
|
paid: false
|
|
}
|
|
},
|
|
isActive: parentalControl ? parentalControl : undefined,
|
|
blocked: parentalControl !== undefined ? undefined : false,
|
|
},
|
|
});
|
|
|
|
const totalPages = Math.ceil(totalDevices / 10);
|
|
const limit = 10;
|
|
const offset = (Number(page) - 1) * limit || 0;
|
|
|
|
const devices = await prisma.device.findMany({
|
|
where: {
|
|
userId: session?.session.userId,
|
|
OR: [
|
|
{
|
|
name: {
|
|
contains: query || "",
|
|
mode: "insensitive",
|
|
},
|
|
},
|
|
{
|
|
mac: {
|
|
contains: query || "",
|
|
mode: "insensitive",
|
|
},
|
|
},
|
|
],
|
|
NOT: {
|
|
payment: {
|
|
paid: false
|
|
}
|
|
},
|
|
isActive: parentalControl,
|
|
blocked: parentalControl !== undefined ? undefined : false,
|
|
|
|
},
|
|
|
|
skip: offset,
|
|
take: limit,
|
|
orderBy: {
|
|
name: `${sortBy}` as "asc" | "desc",
|
|
},
|
|
});
|
|
|
|
return (
|
|
<div>
|
|
{devices.length === 0 ? (
|
|
<div className="h-[calc(100svh-400px)] flex flex-col items-center justify-center my-4">
|
|
<h3>No devices yet.</h3>
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="hidden sm:block">
|
|
<Table className="overflow-scroll">
|
|
<TableCaption>Table of all devices.</TableCaption>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>Device Name</TableHead>
|
|
<TableHead>MAC Address</TableHead>
|
|
<TableHead>Actions</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody className="overflow-scroll">
|
|
{devices.map((device) => (
|
|
<TableRow key={device.id}>
|
|
<TableCell>
|
|
<div className="flex flex-col items-start">
|
|
<Link
|
|
className="font-medium hover:underline"
|
|
href={`/devices/${device.id}`}
|
|
>
|
|
{device.name}
|
|
</Link>
|
|
<span className="text-muted-foreground">
|
|
Active until{" "}
|
|
{new Date().toLocaleDateString("en-US", {
|
|
month: "short",
|
|
day: "2-digit",
|
|
year: "numeric",
|
|
})}
|
|
</span>
|
|
{parentalControl && (
|
|
<div className="p-2 rounded border my-2">
|
|
<span>Comment: </span>
|
|
<p className="text-neutral-500">
|
|
blocked because he was watching youtube
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
</TableCell>
|
|
<TableCell className="font-medium">{device.mac}</TableCell>
|
|
<TableCell>
|
|
{!parentalControl ? (
|
|
<AddDevicesToCartButton device={device} />
|
|
) : (
|
|
<BlockDeviceButton device={device} />
|
|
)}
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
<TableFooter>
|
|
<TableRow>
|
|
<TableCell colSpan={2}>
|
|
{query.length > 0 && (
|
|
<p className="text-sm text-muted-foreground">
|
|
Showing {devices.length} locations for "{query}
|
|
"
|
|
</p>
|
|
)}
|
|
</TableCell>
|
|
<TableCell className="text-muted-foreground">
|
|
{totalDevices} devices
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableFooter>
|
|
</Table>
|
|
<Pagination totalPages={totalPages} currentPage={page} />
|
|
</div>
|
|
<div className="sm:hidden my-4">
|
|
{devices.map((device) => (
|
|
<DeviceCard parentalControl={parentalControl} key={device.id} device={device} />
|
|
))}
|
|
</div>
|
|
</>
|
|
|
|
)}
|
|
</div>
|
|
);
|
|
}
|