diff --git a/actions/auth-actions.ts b/actions/auth-actions.ts
index 3cbfc27..91b4eb9 100644
--- a/actions/auth-actions.ts
+++ b/actions/auth-actions.ts
@@ -116,6 +116,7 @@ export async function signup(_actionState: ActionState, formData: FormData) {
id_card: parsedData.data.id_card,
dob: new Date(parsedData.data.dob),
role: "USER",
+ accNo: parsedData.data.accNo,
phoneNumber: NUMBER_WITH_COUNTRY_CODE,
},
});
diff --git a/actions/payment.ts b/actions/payment.ts
index 0625397..ce00069 100644
--- a/actions/payment.ts
+++ b/actions/payment.ts
@@ -9,24 +9,28 @@ import { redirect } from "next/navigation";
import { addDevicesToGroup } from "./omada-actions";
export async function createPayment(data: PaymentType) {
- console.log("data", data);
- const payment = await prisma.payment.create({
- data: {
- amount: data.amount,
- numberOfMonths: data.numberOfMonths,
- paid: data.paid,
- userId: data.userId,
- devices: {
- connect: data.deviceIds.map((id) => {
- return {
- id,
- };
- }),
+ try {
+ console.log("data", data);
+ const payment = await prisma.payment.create({
+ data: {
+ amount: data.amount,
+ numberOfMonths: data.numberOfMonths,
+ paid: data.paid,
+ userId: data.userId,
+ devices: {
+ connect: data.deviceIds.map((id) => {
+ return {
+ id,
+ };
+ }),
+ },
},
- },
- });
- revalidatePath("/devices");
- return payment;
+ });
+ return { success: true, paymentId: payment.id };
+ } catch (error) {
+ console.error("Error creating payment:", error);
+ return { success: false, error: "Failed to create payment" };
+ }
}
type VerifyPaymentType = {
diff --git a/actions/user-actions.ts b/actions/user-actions.ts
index bb91bd4..2afbc25 100644
--- a/actions/user-actions.ts
+++ b/actions/user-actions.ts
@@ -26,7 +26,7 @@ export async function VerifyUser(userId: string) {
verified: true,
},
});
- await CreateClient({
+ const ninjaClient = await CreateClient({
group_settings_id: "",
address1: "",
city: user.atoll?.name || "",
diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx
index 2c2cc74..556aff6 100644
--- a/app/(auth)/login/page.tsx
+++ b/app/(auth)/login/page.tsx
@@ -13,7 +13,7 @@ export default async function LoginPage() {
return redirect("/devices");
}
return (
-
+
diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx
index 315300e..a377acd 100644
--- a/app/(auth)/signup/page.tsx
+++ b/app/(auth)/signup/page.tsx
@@ -29,8 +29,8 @@ export default async function SignupPage({
});
return (
-
-
+
+
);
diff --git a/app/(dashboard)/user-payments/page.tsx b/app/(dashboard)/user-payments/page.tsx
index b603714..e689978 100644
--- a/app/(dashboard)/user-payments/page.tsx
+++ b/app/(dashboard)/user-payments/page.tsx
@@ -1,8 +1,20 @@
+import { UsersPaymentsTable } from "@/components/admin/user-payments-table";
import { AdminAuthGuard } from "@/lib/auth-guard";
-import React from "react";
+import React, { Suspense } from "react";
-export default async function UserPayments() {
+export default async function UserPayments({
+ searchParams,
+}: {
+ searchParams: Promise<{
+ query: string;
+ page: number;
+ sortBy: string;
+ status: string;
+ }>;
+}) {
await AdminAuthGuard();
+ const query = (await searchParams)?.query || "";
+
return (
@@ -10,6 +22,9 @@ export default async function UserPayments() {
User Payments
+
+
+
);
}
diff --git a/app/layout.tsx b/app/layout.tsx
index ccefdb5..5c26fe4 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -25,7 +25,7 @@ export default function RootLayout({
}>) {
return (
-
+
diff --git a/components/admin/admin-devices-table.tsx b/components/admin/admin-devices-table.tsx
new file mode 100644
index 0000000..0262e29
--- /dev/null
+++ b/components/admin/admin-devices-table.tsx
@@ -0,0 +1,187 @@
+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 BlockDeviceDialog from "../block-device-dialog";
+import ClickableRow from "../clickable-row";
+import DeviceCard from "../device-card";
+import Pagination from "../pagination";
+
+export async function AdminDevicesTable({
+ searchParams,
+ parentalControl,
+}: {
+ searchParams: Promise<{
+ query: string;
+ page: number;
+ sortBy: string;
+ }>;
+ parentalControl?: boolean;
+}) {
+ const session = await auth.api.getSession({
+ headers: await headers()
+ })
+ const isAdmin = session?.user.role === "ADMIN"
+ const query = (await searchParams)?.query || "";
+ const page = (await searchParams)?.page;
+ const sortBy = (await searchParams)?.sortBy || "asc";
+ const totalDevices = await prisma.device.count({
+ where: {
+ OR: [
+ {
+ name: {
+ contains: query || "",
+ mode: "insensitive",
+ },
+ },
+ {
+ mac: {
+ contains: query || "",
+ mode: "insensitive",
+ },
+ },
+ ],
+ },
+ });
+
+ const totalPages = Math.ceil(totalDevices / 10);
+ const limit = 10;
+ const offset = (Number(page) - 1) * limit || 0;
+
+ const devices = await prisma.device.findMany({
+ where: {
+ OR: [
+ {
+ name: {
+ contains: query || "",
+ mode: "insensitive",
+ },
+ },
+ {
+ mac: {
+ contains: query || "",
+ mode: "insensitive",
+ },
+ },
+ ],
+ },
+
+ skip: offset,
+ take: limit,
+ orderBy: {
+ name: `${sortBy}` as "asc" | "desc",
+ },
+ });
+
+ return (
+
+ {devices.length === 0 ? (
+
+
No devices yet.
+
+ ) : (
+ <>
+
+
+ Table of all devices.
+
+
+ Device Name
+ MAC Address
+ isActive
+ blocked
+ blockedBy
+ expiryDate
+
+
+
+ {devices.map((device) => (
+
+
+
+
+ {device.name}
+
+
+ Active until{" "}
+ {new Date().toLocaleDateString("en-US", {
+ month: "short",
+ day: "2-digit",
+ year: "numeric",
+ })}
+
+ {device.blocked && (
+
+
Comment:
+
+ blocked because he was watching youtube
+
+
+ )}
+
+
+
+ {device.mac}
+
+ {device.isActive ? "Active" : "Inactive"}
+
+
+ {device.blocked ? "Blocked" : "Not Blocked"}
+
+
+ {device.blockedBy ? device.blockedBy : "Not Blocked"}
+
+
+ {new Date().toLocaleDateString("en-US", {
+ month: "short",
+ day: "2-digit",
+ year: "numeric",
+ })}
+
+
+
+
+
+ ))}
+
+
+
+
+ {query.length > 0 && (
+
+ Showing {devices.length} locations for "{query}
+ "
+
+ )}
+
+
+ {totalDevices} devices
+
+
+
+
+
+
+
+ {devices.map((device) => (
+
+ ))}
+
+ >
+ )}
+
+ );
+}
diff --git a/components/admin/user-payments-table.tsx b/components/admin/user-payments-table.tsx
new file mode 100644
index 0000000..9219835
--- /dev/null
+++ b/components/admin/user-payments-table.tsx
@@ -0,0 +1,222 @@
+import Pagination from "@/components/pagination";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import {
+ Table,
+ TableBody,
+ TableCaption,
+ TableCell,
+ TableFooter,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import prisma from "@/lib/db";
+import Link from "next/link";
+
+export async function UsersPaymentsTable({
+ searchParams,
+}: {
+ searchParams: Promise<{
+ query: string;
+ page: number;
+ sortBy: string;
+ status: string;
+ }>;
+}) {
+ const query = (await searchParams)?.query || "";
+ const page = (await searchParams)?.page;
+ const sortBy = (await searchParams)?.sortBy || "asc";
+ const totalPayments = await prisma.payment.count({
+ where: {
+ OR: [
+ {
+ user: {
+ name: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ phoneNumber: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ address: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ id_card: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ ],
+ },
+ });
+
+ const totalPages = Math.ceil(totalPayments / 10);
+ const limit = 10;
+ const offset = (Number(page) - 1) * limit || 0;
+
+ const payments = await prisma.payment.findMany({
+ where: {
+ OR: [
+ {
+ user: {
+ name: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ phoneNumber: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ address: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ {
+ user: {
+ id_card: {
+ contains: query || "",
+ mode: "insensitive",
+ }
+ },
+ },
+ ],
+ },
+ include: {
+ user: true,
+ devices: true,
+ },
+ skip: offset,
+ take: limit,
+ orderBy: {
+ id: `${sortBy}` as "asc" | "desc",
+ },
+ });
+
+ // const users = await prisma.user.findMany({
+ // where: {
+ // role: "USER",
+ // },
+ // include: {
+ // atoll: true,
+ // island: true,
+ // },
+ // });
+ return (
+
+ {payments.length === 0 ? (
+
+
No Users yet.
+
+ ) : (
+ <>
+
+ Table of all users.
+
+
+ Name
+ ID Card
+ Atoll
+ Island
+ House Name
+ Status
+ Dob
+ Phone Number
+ Action
+
+
+
+ {payments.map((payment) => (
+
+ {payment.user.name}
+ {payment.user.id_card}
+ {payment.user?.name}
+ {payment.user?.name}
+ {payment.id}
+
+
+ {payment.paid ? (
+
+ Verified
+
+ ) : (
+
+ Unverified
+
+ )}
+
+
+ {new Date(payment.paidAt ?? "").toLocaleDateString("en-US", {
+ month: "short",
+ day: "2-digit",
+ year: "numeric",
+ })}
+
+
+ {payment.id}
+
+
+
+
+
+
+ ))}
+
+
+
+
+ {query.length > 0 && (
+
+ Showing {payments.length} locations for "{query}
+ "
+
+ )}
+
+
+ {totalPayments} payments
+
+
+
+
+
+ >
+ )}
+
+ );
+}
diff --git a/components/auth/application-layout.tsx b/components/auth/application-layout.tsx
index 137fa65..cc38a95 100644
--- a/components/auth/application-layout.tsx
+++ b/components/auth/application-layout.tsx
@@ -37,7 +37,7 @@ export async function ApplicationLayout({
{session?.user.role === "ADMIN" && (
-
+
Welcome back {session?.user.name}
)}
diff --git a/components/auth/signup-form.tsx b/components/auth/signup-form.tsx
index 6e20497..355df34 100644
--- a/components/auth/signup-form.tsx
+++ b/components/auth/signup-form.tsx
@@ -48,7 +48,7 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
return (