From 745f8d8fada76f2d1732ddd961cb1618c5b078a3 Mon Sep 17 00:00:00 2001 From: i701 Date: Wed, 1 Jan 2025 23:48:56 +0500 Subject: [PATCH] Enhance device management and user experience features - Updated `package.json` to include the latest version of `@radix-ui/react-separator` and added `moment` for date handling. - Modified `blockDevice` function in `omada-actions.ts` to include a `blockedBy` parameter, allowing differentiation between admin and parent actions. - Refactored `payment.ts` to include expiry date handling for devices during payment processing. - Improved `DevicesTable` and `ClickableRow` components to support admin functionalities and enhance device interaction. - Updated `BlockDeviceDialog` to accept an `admin` prop, allowing for tailored blocking actions based on user role. - Enhanced UI components for better consistency and responsiveness across the dashboard. These changes improve the overall functionality and maintainability of the application, providing a better user experience in device management. --- actions/omada-actions.ts | 11 +- actions/payment.ts | 25 +- app/(dashboard)/parental-control/page.tsx | 13 +- app/(dashboard)/user-devices/page.tsx | 30 ++- bun.lockb | Bin 293679 -> 294028 bytes components/auth/application-layout.tsx | 5 + components/block-device-dialog.tsx | 247 +++++++++++------- components/clickable-row.tsx | 8 +- components/device-card.tsx | 6 +- components/devices-table.tsx | 18 +- components/payments-table.tsx | 208 ++++++++++----- components/wallet.tsx | 4 +- package.json | 3 +- .../20250101160105_add/migration.sql | 5 + prisma/migrations/migration_lock.toml | 2 +- prisma/schema.prisma | 6 + 16 files changed, 378 insertions(+), 213 deletions(-) create mode 100644 prisma/migrations/20250101160105_add/migration.sql 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 e7e7f80ec8ddda0a853fbf0164924dc4b29bf76f..9ded7a1c9086a28b527bded3b07dbc8a56210f82 100755 GIT binary patch delta 30650 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 oMCSNme9r78!Fr>w@P1ymR$MJF5J&%+%3Ffht<8 delta 30630 zcmeIbcYIY<`u2Sa2Xl~sAP_>RDgq**8!$k`MvdTDAdZMZLPwC^VggcvbT+sM7@E>l zq^Y3@0;19p1f__IWdt2Yv5Yb^==;6)UK<00zR&M{p69RE^U0NK-PgKTFMFMxeR3wB zFR|*MC8j6V=+Sq{x$m#~=+pNf*%o~7rQ3d-zW#4#+T0#~t^AIDZSq&w{B^;ILIJ&= zozbCE=%ra}hSj;+S$%cOw9~@^fvW?7?8t~fpaeXi-{AW48;yP~_Sh(=^%SYiT&ik#s!*ZXDA&;xiUcpu+x@Khbuhny4Al?ZUi|ZLP!^*rLRqo)QRD zg?kOGH9Wm5{qcSSG6I3Ou~lmKKK;6+_Zb*?-tp{i zJs^mU6TOgoZRM)P~wqn(Kraj|% z_s$qTMCvcbv%B?4A2cYVYhW3(5sdysQ)@oJ%O<~bvZ-m0nK`w-q~zt=Zr6Wv_sPw&0!v zYYoWgo-yoxY!#eFyn3u9tksYr{{{s1k%8t|cQRDXHm>#xx?zoH?}L@F_FAunRh@fF zRLbg2wi<}_#H#p3u$tk(#o#e;33wjOkY4sxuNj?bhV+@FSE-#~`M0NZ`TbWInjk;oPq$=ce?mY7Z-tfN3$Xg9@&?b&!`48Ig;hW^8($ADid`1gz+4T>ui_?8 zp9E_g8VRe}y%bZ@^_VaFYorgAuU$Eg4pYZnRtmRtAS?aRR&%)_|^IrfItw zn9+Ag#(+RzK*qp+eTHNN47w^Z4px3cVO6}B)vIpvDmD?mHj9Yw7JCjYaL^PUwcShD zwclfd2K0P9qc*wDYDXfC0zUBEl*vfAltO}$L%c%7j+s{yI z_k~NVD=L$by6UrcJjVgf=xgJ$y6yBj(r@1p8@nA=wp}y24DQYf`h1etFTU+p+qakC zUjhGluuA(C|0?j7J>JY&1FPCgU=8Sky>5RyaivPMnvJHuAC%rdy-S~rz-{}yG@0n? zl0B2Wrmx%YU1R(`Ybdtjr@=SCNzN0cs@3R#RT=9=Qi4{0v16Ve@mPw&sM>%tInnhAG1A$welXoXaClJy$7IseEk` bqki;ipV*vR!&|{ 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 + {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. - - -
-
-
- -