diff --git a/actions/omada-actions.ts b/actions/omada-actions.ts index ae7ccbd..8f02359 100644 --- a/actions/omada-actions.ts +++ b/actions/omada-actions.ts @@ -112,8 +112,14 @@ export async function addDevicesToGroup({ export async function blockDevice({ macAddress, type, - reason -}: { macAddress: string; type: "block" | "unblock", reason?: string }) { + reason, + blockedBy = "PARENT", +}: { + macAddress: string; + type: "block" | "unblock"; + reason?: string; + blockedBy?: "ADMIN" | "PARENT"; +}) { console.log("hello world asdasd"); if (!macAddress) { throw new Error("macAddress is a required parameter"); @@ -147,6 +153,7 @@ export async function blockDevice({ data: { reasonForBlocking: type === "block" ? reason : "", blocked: type === "block", + blockedBy: blockedBy, }, }); revalidatePath("/parental-control"); diff --git a/actions/payment.ts b/actions/payment.ts index e3402c9..0625397 100644 --- a/actions/payment.ts +++ b/actions/payment.ts @@ -3,6 +3,7 @@ import prisma from "@/lib/db"; import type { PaymentType } from "@/lib/types"; import { formatMacAddress } from "@/lib/utils"; +import type { Prisma } from "@prisma/client"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { addDevicesToGroup } from "./omada-actions"; @@ -38,13 +39,11 @@ type VerifyPaymentType = { type?: "TRANSFER" | "WALLET"; }; -type PaymentWithDevices = { - id: string; - devices: Array<{ - name: string; - mac: string; - }>; -}; +type PaymentWithDevices = Prisma.PaymentGetPayload<{ + include: { + devices: true; + }; +}>; class InsufficientFundsError extends Error { constructor() { @@ -67,6 +66,8 @@ async function processWalletPayment( throw new InsufficientFundsError(); } + const expiryDate = new Date(); + expiryDate.setMonth(expiryDate.getMonth() + payment.numberOfMonths); await prisma.$transaction([ prisma.payment.update({ where: { id: payment.id }, @@ -76,7 +77,7 @@ async function processWalletPayment( devices: { updateMany: { where: { paymentId: payment.id }, - data: { isActive: true }, + data: { isActive: true, expiryDate: expiryDate }, }, }, }, @@ -107,7 +108,7 @@ async function verifyExternalPayment( data: VerifyPaymentType, payment: PaymentWithDevices | null, ): Promise { - console.log('payment verify data ->', data) + console.log("payment verify data ->", data); const response = await fetch( "https://verifypaymentsapi.baraveli.dev/verify-payment", { @@ -118,12 +119,14 @@ async function verifyExternalPayment( ); const json = await response.json(); - console.log(json) + console.log(json); if (!payment) { throw new Error("Payment verification failed or payment not found"); } if (json.success) { + const expiryDate = new Date(); + expiryDate.setMonth(expiryDate.getMonth() + payment.numberOfMonths); await prisma.payment.update({ where: { id: payment.id }, data: { @@ -132,7 +135,7 @@ async function verifyExternalPayment( devices: { updateMany: { where: { paymentId: payment.id }, - data: { isActive: true }, + data: { isActive: true, expiryDate: expiryDate }, }, }, }, diff --git a/app/(dashboard)/parental-control/page.tsx b/app/(dashboard)/parental-control/page.tsx index bd17ab9..e83b3dd 100644 --- a/app/(dashboard)/parental-control/page.tsx +++ b/app/(dashboard)/parental-control/page.tsx @@ -2,9 +2,6 @@ import { DevicesTable } from "@/components/devices-table"; import Search from "@/components/search"; import { Suspense } from "react"; - - - export default async function ParentalControl({ searchParams, }: { @@ -19,9 +16,7 @@ export default async function ParentalControl({ return (
-

- Parental Control -

+

Parental Control

-
- +
); diff --git a/app/(dashboard)/user-devices/page.tsx b/app/(dashboard)/user-devices/page.tsx index 9ba1b6b..a9dbb98 100644 --- a/app/(dashboard)/user-devices/page.tsx +++ b/app/(dashboard)/user-devices/page.tsx @@ -1,4 +1,21 @@ -export default async function UserDevcies() { +import { DevicesTable } from "@/components/devices-table"; +import Search from "@/components/search"; +import { Suspense } from "react"; + + + + +export default async function UserDevices({ + searchParams, +}: { + searchParams: Promise<{ + query: string; + page: number; + sortBy: string; + status: string; + }>; +}) { + const query = (await searchParams)?.query || ""; return (
@@ -6,6 +23,17 @@ export default async function UserDevcies() { User Devices
+ +
+ + +
+ + +
); } diff --git a/bun.lockb b/bun.lockb index e7e7f80..9ded7a1 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/auth/application-layout.tsx b/components/auth/application-layout.tsx index 46a68f9..137fa65 100644 --- a/components/auth/application-layout.tsx +++ b/components/auth/application-layout.tsx @@ -36,6 +36,11 @@ export async function ApplicationLayout({
+ {session?.user.role === "ADMIN" && ( + + Welcome back {session?.user.name} + + )}
diff --git a/components/block-device-dialog.tsx b/components/block-device-dialog.tsx index 0ced481..71db266 100644 --- a/components/block-device-dialog.tsx +++ b/components/block-device-dialog.tsx @@ -1,7 +1,7 @@ -"use client" +"use client"; -import { blockDevice } from "@/actions/omada-actions" -import { Button } from "@/components/ui/button" +import { blockDevice } from "@/actions/omada-actions"; +import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, @@ -9,127 +9,174 @@ import { DialogHeader, DialogTitle, DialogTrigger, -} from "@/components/ui/dialog" -import { Label } from "@/components/ui/label" -import { cn } from "@/lib/utils" -import { zodResolver } from "@hookform/resolvers/zod" -import type { Device, } from "@prisma/client" -import { OctagonX } from "lucide-react" -import { useState } from "react" -import { type SubmitHandler, useForm } from "react-hook-form" -import { toast } from "sonner" -import { z } from "zod" -import { Textarea } from "./ui/textarea" -import { TextShimmer } from "./ui/text-shimmer" - - +} from "@/components/ui/dialog"; +import { Label } from "@/components/ui/label"; +import { cn } from "@/lib/utils"; +import { zodResolver } from "@hookform/resolvers/zod"; +import type { Device } from "@prisma/client"; +import { OctagonX } from "lucide-react"; +import { useState } from "react"; +import { type SubmitHandler, useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; +import { TextShimmer } from "./ui/text-shimmer"; +import { Textarea } from "./ui/textarea"; const validationSchema = z.object({ reasonForBlocking: z.string().min(5, { message: "Reason is required" }), -}) +}); -export default function BlockDeviceDialog({ device, type }: { device: Device, type: "block" | "unblock" }) { - const [disabled, setDisabled] = useState(false) - const [open, setOpen] = useState(false) +export default function BlockDeviceDialog({ + device, + type, + admin, +}: { device: Device; type: "block" | "unblock"; admin?: boolean }) { + const [disabled, setDisabled] = useState(false); + const [open, setOpen] = useState(false); const { register, handleSubmit, formState: { errors }, } = useForm>({ resolver: zodResolver(validationSchema), - }) + }); const onSubmit: SubmitHandler> = (data) => { - setDisabled(true) - console.log(data) - toast.promise(blockDevice({ - macAddress: device.mac, - type: type, - reason: data.reasonForBlocking, - // reason: data.reasonForBlocking, - }), { - loading: "Blocking...", - success: () => { - setDisabled(false) - setOpen((prev) => !prev) - return "Blocked!" + setDisabled(true); + console.log(data); + toast.promise( + blockDevice({ + macAddress: device.mac, + type: type, + reason: data.reasonForBlocking, + blockedBy: "ADMIN", + // reason: data.reasonForBlocking, + }), + { + loading: "Blocking...", + success: () => { + setDisabled(false); + setOpen((prev) => !prev); + return "Blocked!"; + }, + error: (error) => { + setDisabled(false); + return error || "Something went wrong"; + }, }, - error: (error) => { - setDisabled(false) - return error || "Something went wrong" - }, - }) - setDisabled(false) - - } + ); + setDisabled(false); + }; return (
{device.blocked ? ( - - ) : ( - - - - - - - - Please provide a reason for blocking this device. - - -
-
-
- -