From 9ad1887f88ad6c1512687cb7b5cb3a7fe9feb802 Mon Sep 17 00:00:00 2001 From: i701 Date: Wed, 24 Sep 2025 19:33:48 +0500 Subject: [PATCH] =?UTF-8?q?refactor:=20add=20animations=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(dashboard)/devices/[deviceId]/page.tsx | 13 +- components/clickable-row.tsx | 179 +++---- components/device-card.tsx | 196 ++++---- components/devices-table.tsx | 211 ++++---- components/devices-to-pay.tsx | 30 +- components/payments-table.tsx | 514 ++++++++++---------- components/topups-table.tsx | 386 +++++++-------- components/ui/app-sidebar.tsx | 402 +++++++-------- components/wallet-transactions-table.tsx | 4 +- components/welcome-banner.tsx | 52 +- 10 files changed, 994 insertions(+), 993 deletions(-) diff --git a/app/(dashboard)/devices/[deviceId]/page.tsx b/app/(dashboard)/devices/[deviceId]/page.tsx index 4058770..d57f4f7 100644 --- a/app/(dashboard)/devices/[deviceId]/page.tsx +++ b/app/(dashboard)/devices/[deviceId]/page.tsx @@ -27,11 +27,16 @@ export default async function DeviceDetails({
-

+

{device?.name}

- {device?.mac} -

+ + {device?.mac} + +

Device active until{" "} {new Date(device?.expiry_date || "").toLocaleDateString("en-US", { month: "short", @@ -40,7 +45,7 @@ export default async function DeviceDetails({ })}

-
+
{device?.expiry_date && new Date() < new Date(device.expiry_date) && (

ACTIVE diff --git a/components/clickable-row.tsx b/components/clickable-row.tsx index 243e2e9..88bbfe6 100644 --- a/components/clickable-row.tsx +++ b/components/clickable-row.tsx @@ -9,96 +9,99 @@ import { cn } from "@/lib/utils"; import AddDevicesToCartButton from "./add-devices-to-cart-button"; import BlockDeviceDialog from "./block-device-dialog"; export default function ClickableRow({ - device, - parentalControl, - admin = false, + device, + parentalControl, + admin = false, + idx, }: { - device: Device; - parentalControl?: boolean; - admin?: boolean; + device: Device; + parentalControl?: boolean; + admin?: boolean; + idx?: number; }) { - const [devices, setDeviceCart] = useAtom(deviceCartAtom); + const [devices, setDeviceCart] = useAtom(deviceCartAtom); - return ( - { - if (device.blocked) return; - if (device.is_active === true) return; - if (device.has_a_pending_payment === true) return; - if (parentalControl === true) return; - setDeviceCart((prev) => - devices.some((d) => d.id === device.id) - ? prev.filter((d) => d.id !== device.id) - : [...prev, device], - ); - }} - > - -

- e.stopPropagation()} - > - {device.name} - - {device.is_active ? ( -
- Active until{" "} - - {new Date(device.expiry_date || "").toLocaleDateString( - "en-US", - { - month: "short", - day: "2-digit", - year: "numeric", - }, - )} - -
- ) : ( -

Device Inactive

- )} - {device.has_a_pending_payment && ( - - - Payment Pending{" "} - - - - )} + return ( + { + if (device.blocked) return; + if (device.is_active === true) return; + if (device.has_a_pending_payment === true) return; + if (parentalControl === true) return; + setDeviceCart((prev) => + devices.some((d) => d.id === device.id) + ? prev.filter((d) => d.id !== device.id) + : [...prev, device], + ); + }} + > + +
+ e.stopPropagation()} + > + {device.name} + + {device.is_active ? ( +
+ Active until{" "} + + {new Date(device.expiry_date || "").toLocaleDateString( + "en-US", + { + month: "short", + day: "2-digit", + year: "numeric", + }, + )} + +
+ ) : ( +

Device Inactive

+ )} + {device.has_a_pending_payment && ( + + + Payment Pending{" "} + + + + )} - {device.blocked_by === "ADMIN" && device.blocked && ( -
- Comment -

{device?.reason_for_blocking}

-
- )} -
-
- {device.mac} - {device?.vendor} - - {!parentalControl ? ( - - ) : ( - - )} - -
- ); + {device.blocked_by === "ADMIN" && device.blocked && ( +
+ Comment +

{device?.reason_for_blocking}

+
+ )} +
+ + {device.mac} + {device?.vendor} + + {!parentalControl ? ( + + ) : ( + + )} + + + ); } diff --git a/components/device-card.tsx b/components/device-card.tsx index ce0b8a1..6ec0428 100644 --- a/components/device-card.tsx +++ b/components/device-card.tsx @@ -10,108 +10,108 @@ import BlockDeviceDialog from "./block-device-dialog"; import { Badge } from "./ui/badge"; export default function DeviceCard({ - device, - parentalControl, - isAdmin, + device, + parentalControl, + isAdmin, }: { - device: Device; - parentalControl?: boolean; - isAdmin?: boolean; + device: Device; + parentalControl?: boolean; + isAdmin?: boolean; }) { - const [devices, setDeviceCart] = useAtom(deviceCartAtom); + const [devices, setDeviceCart] = useAtom(deviceCartAtom); - const isChecked = devices.some((d) => d.id === device.id); + const isChecked = devices.some((d) => d.id === device.id); - return ( - // biome-ignore lint/a11y/noStaticElementInteractions: -
{}} - onClick={() => { - if (device.blocked) return; - if (device.is_active === true) return; - if (device.has_a_pending_payment === true) return; - if (parentalControl === true) return; - setDeviceCart((prev) => - devices.some((d) => d.id === device.id) - ? prev.filter((d) => d.id !== device.id) - : [...prev, device], - ); - }} - className="w-full" - > -
-
-
- - {device.name} - - - {device.mac} - - - {device.vendor} - -
+ return ( + // biome-ignore lint/a11y/noStaticElementInteractions: +
{}} + onClick={() => { + if (device.blocked) return; + if (device.is_active === true) return; + if (device.has_a_pending_payment === true) return; + if (parentalControl === true) return; + setDeviceCart((prev) => + devices.some((d) => d.id === device.id) + ? prev.filter((d) => d.id !== device.id) + : [...prev, device], + ); + }} + className="w-full" + > +
+
+
+ + {device.name} + + + {device.mac} + + + {device.vendor} + +
- {device.is_active ? ( -
- Active until{" "} - - {new Date(device.expiry_date || "").toLocaleDateString( - "en-US", - { - month: "short", - day: "2-digit", - year: "numeric", - }, - )} - -
- ) : ( -

Device Inactive

- )} - {device.has_a_pending_payment && ( - - - Payment Pending{" "} - - - - )} + {device.is_active ? ( +
+ Active until{" "} + + {new Date(device.expiry_date || "").toLocaleDateString( + "en-US", + { + month: "short", + day: "2-digit", + year: "numeric", + }, + )} + +
+ ) : ( +

Device Inactive

+ )} + {device.has_a_pending_payment && ( + + + Payment Pending{" "} + + + + )} - {device.blocked && device.blocked_by === "ADMIN" && ( -
- Blocked by admin -

{device?.reason_for_blocking}

-
- )} -
-
- {!parentalControl ? ( - - ) : ( - - )} -
-
-
- ); + {device.blocked && device.blocked_by === "ADMIN" && ( +
+ Blocked by admin +

{device?.reason_for_blocking}

+
+ )} +
+
+ {!parentalControl ? ( + + ) : ( + + )} +
+
+
+ ); } diff --git a/components/devices-table.tsx b/components/devices-table.tsx index 3bc65d1..ba797ef 100644 --- a/components/devices-table.tsx +++ b/components/devices-table.tsx @@ -2,13 +2,13 @@ import { redirect } from "next/navigation"; import { getServerSession } from "next-auth"; import { authOptions } from "@/app/auth"; import { - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow, + Table, + TableBody, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, } from "@/components/ui/table"; import { getDevices } from "@/queries/devices"; import { tryCatch } from "@/utils/tryCatch"; @@ -18,107 +18,108 @@ import DeviceCard from "./device-card"; import Pagination from "./pagination"; export async function DevicesTable({ - searchParams, - parentalControl, - additionalFilters = {}, + searchParams, + parentalControl, + additionalFilters = {}, }: { - searchParams: Promise<{ - [key: string]: unknown; - }>; - parentalControl?: boolean; - additionalFilters?: Record; + searchParams: Promise<{ + [key: string]: unknown; + }>; + parentalControl?: boolean; + additionalFilters?: Record; }) { - const resolvedParams = await searchParams; - const session = await getServerSession(authOptions); - const isAdmin = session?.user?.is_admin; + const resolvedParams = await searchParams; + const session = await getServerSession(authOptions); + const isAdmin = session?.user?.is_admin; - const page = Number.parseInt(resolvedParams.page as string) || 1; - const limit = 10; - const offset = (page - 1) * limit; + const page = Number.parseInt(resolvedParams.page as string) || 1; + const limit = 10; + const offset = (page - 1) * limit; - // Build params object for getDevices - const apiParams: Record = {}; - for (const [key, value] of Object.entries(resolvedParams)) { - if (value !== undefined && value !== "") { - apiParams[key] = typeof value === "number" ? value : String(value); - } - } + // Build params object for getDevices + const apiParams: Record = {}; + for (const [key, value] of Object.entries(resolvedParams)) { + if (value !== undefined && value !== "") { + apiParams[key] = typeof value === "number" ? value : String(value); + } + } - for (const [key, value] of Object.entries(additionalFilters)) { - if (value !== undefined && value !== "") { - apiParams[key] = typeof value === "number" ? value : String(value); - } - } - apiParams.limit = limit; - apiParams.offset = offset; - const [error, devices] = await tryCatch(getDevices(apiParams)); - if (error) { - if (error.message === "UNAUTHORIZED") { - redirect("/auth/signin"); - } else { - return ; - } - } - const { meta, data } = devices; - return ( -
- {data?.length === 0 ? ( -
-

{parentalControl ? "No active devices" : "No devices."}

-
- ) : ( - <> -
- - - - Device Name - MAC Address - Vendor - # - - - - {data?.map((device) => ( - - ))} - - - - - {meta?.total === 1 ? ( -

Total {meta?.total} device.

- ) : ( -

- Total {meta?.total} devices. -

- )} -
-
-
-
-
-
- {data?.map((device) => ( - - ))} -
- - - )} -
- ); + for (const [key, value] of Object.entries(additionalFilters)) { + if (value !== undefined && value !== "") { + apiParams[key] = typeof value === "number" ? value : String(value); + } + } + apiParams.limit = limit; + apiParams.offset = offset; + const [error, devices] = await tryCatch(getDevices(apiParams)); + if (error) { + if (error.message === "UNAUTHORIZED") { + redirect("/auth/signin"); + } else { + return ; + } + } + const { meta, data } = devices; + return ( +
+ {data?.length === 0 ? ( +
+

{parentalControl ? "No active devices" : "No devices."}

+
+ ) : ( + <> +
+ + + + Device Name + MAC Address + Vendor + # + + + + {data?.map((device, idx) => ( + + ))} + + + + + {meta?.total === 1 ? ( +

Total {meta?.total} device.

+ ) : ( +

+ Total {meta?.total} devices. +

+ )} +
+
+
+
+
+
+ {data?.map((device) => ( + + ))} +
+ + + )} +
+ ); } diff --git a/components/devices-to-pay.tsx b/components/devices-to-pay.tsx index 592438a..05a4f7f 100644 --- a/components/devices-to-pay.tsx +++ b/components/devices-to-pay.tsx @@ -126,6 +126,7 @@ export default function DevicesToPay({ type="submit" variant={"secondary"} size={"lg"} + className="w-full" > {isPending ? "Processing payment..." @@ -145,7 +146,7 @@ export default function DevicesToPay({ disabled={isPending || disabled} type="submit" size={"lg"} - className="mb-4" + className="mb-4 w-full" > {isPending ? "Processing payment..." : "I have paid"} {isPending ? ( @@ -162,10 +163,8 @@ export default function DevicesToPay({ - - Payment created - - + Payment created + {new Date(payment?.created_at ?? "").toLocaleDateString( "en-US", { @@ -180,31 +179,22 @@ export default function DevicesToPay({ - - Total Devices - - + Total Devices + {devices?.length} - - Duration - - + Duration + {payment?.number_of_months} Months - - Total Due - - + Total Due + {payment?.amount?.toFixed(2)} diff --git a/components/payments-table.tsx b/components/payments-table.tsx index 4ddcc71..1f59f2a 100644 --- a/components/payments-table.tsx +++ b/components/payments-table.tsx @@ -3,13 +3,13 @@ import Link from "next/link"; import { redirect } from "next/navigation"; import { getPayments } from "@/actions/payment"; import { - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow, + Table, + TableBody, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, } from "@/components/ui/table"; import type { Payment } from "@/lib/backend-types"; import { cn } from "@/lib/utils"; @@ -20,265 +20,265 @@ import { Button } from "./ui/button"; import { Separator } from "./ui/separator"; export async function PaymentsTable({ - searchParams, + searchParams, }: { - searchParams: Promise<{ - [key: string]: unknown; - }>; + searchParams: Promise<{ + [key: string]: unknown; + }>; }) { - const resolvedParams = await searchParams; - const page = Number.parseInt(resolvedParams.page as string) || 1; - const limit = 10; - const offset = (page - 1) * limit; - const apiParams: Record = {}; - for (const [key, value] of Object.entries(resolvedParams)) { - if (value !== undefined && value !== "") { - apiParams[key] = typeof value === "number" ? value : String(value); - } - } - apiParams.limit = limit; - apiParams.offset = offset; - const [error, payments] = await tryCatch(getPayments(apiParams)); + const resolvedParams = await searchParams; + const page = Number.parseInt(resolvedParams.page as string) || 1; + const limit = 10; + const offset = (page - 1) * limit; + const apiParams: Record = {}; + for (const [key, value] of Object.entries(resolvedParams)) { + if (value !== undefined && value !== "") { + apiParams[key] = typeof value === "number" ? value : String(value); + } + } + apiParams.limit = limit; + apiParams.offset = offset; + const [error, payments] = await tryCatch(getPayments(apiParams)); - if (error) { - if (error.message.includes("Unauthorized")) { - redirect("/auth/signin"); - } else { - return
{JSON.stringify(error, null, 2)}
; - } - } - const { data, meta } = payments; - return ( -
- {data?.length === 0 ? ( -
-

No Payments.

-
- ) : ( - <> -
- - - - Details - Duration - Status - Amount - - - - {payments?.data?.map((payment) => ( - - -
-
- - - {new Date(payment.created_at).toLocaleDateString( - "en-US", - { - month: "short", - day: "2-digit", - year: "numeric", - minute: "2-digit", - hour: "2-digit", - timeZone: "Indian/Maldives", // Force consistent timezone - }, - )} - -
+ if (error) { + if (error.message.includes("Unauthorized")) { + redirect("/auth/signin"); + } else { + return
{JSON.stringify(error, null, 2)}
; + } + } + const { data, meta } = payments; + return ( +
+ {data?.length === 0 ? ( +
+

No Payments.

+
+ ) : ( + <> +
+
+ + + Details + Duration + Status + Amount + + + + {payments?.data?.map((payment) => ( + + +
+
+ + + {new Date(payment.created_at).toLocaleDateString( + "en-US", + { + month: "short", + day: "2-digit", + year: "numeric", + minute: "2-digit", + hour: "2-digit", + timeZone: "Indian/Maldives", // Force consistent timezone + }, + )} + +
-
- - - -
-
-

Devices

-
    - {payment.devices.map((device) => ( -
  1. - {device.name} -
  2. - ))} -
-
-
-
+
+ + + +
+
+

Devices

+
    + {payment.devices.map((device) => ( +
  1. + {device.name} +
  2. + ))} +
+
+ + - - {payment.number_of_months} Months - - - - {payment.paid ? ( - - {payment.status} - - ) : payment.is_expired ? ( - Expired - ) : ( - {payment.status} - )} - - - - - {payment.amount.toFixed(2)} - - MVR - -
- ))} -
- - - - {meta?.total === 1 ? ( -

- Total {meta?.total} payment. -

- ) : ( -

- Total {meta?.total} payments. -

- )}{" "} -
-
-
-
- -
-
- {data.map((payment) => ( - - ))} -
- - )} -
- ); + + {payment.number_of_months} Months + + + + {payment.paid ? ( + + {payment.status} + + ) : payment.is_expired ? ( + Expired + ) : ( + {payment.status} + )} + + + + + {payment.amount.toFixed(2)} + + MVR + + + ))} + + + + + {meta?.total === 1 ? ( +

+ Total {meta?.total} payment. +

+ ) : ( +

+ Total {meta?.total} payments. +

+ )}{" "} +
+
+
+ + +
+
+ {data.map((payment) => ( + + ))} +
+ + )} +
+ ); } export function MobilePaymentDetails({ - payment, - isAdmin = false, + payment, + isAdmin = false, }: { - payment: Payment; - isAdmin?: boolean; + payment: Payment; + isAdmin?: boolean; }) { - return ( -
-
- - - {new Date(payment.created_at).toLocaleDateString("en-US", { - month: "short", - day: "2-digit", - year: "numeric", - minute: "2-digit", - hour: "2-digit", - timeZone: "Indian/Maldives", // Force consistent timezone - })} - -
+ return ( +
+
+ + + {new Date(payment.created_at).toLocaleDateString("en-US", { + month: "short", + day: "2-digit", + year: "numeric", + minute: "2-digit", + hour: "2-digit", + timeZone: "Indian/Maldives", // Force consistent timezone + })} + +
-
- - - -
-
-

Devices

-
    - {payment.devices.map((device) => ( -
  1. - {device.name} -
  2. - ))} -
-
- -

Duration

- - {payment.number_of_months} Months - - -

Amount

-
- - {payment.amount.toFixed(2)} MVR - - - {payment.paid ? ( - - {payment.status} - - ) : payment.is_expired ? ( - Expired - ) : ( - {payment.status} - )} - - {isAdmin && ( -
- {payment?.user?.name} - - {payment?.user?.id_card} - -
- )} -
-
-
-
- ); +
+ + + +
+
+

Devices

+
    + {payment.devices.map((device) => ( +
  1. + {device.name} +
  2. + ))} +
+
+ +

Duration

+ + {payment.number_of_months} Months + + +

Amount

+
+ + {payment.amount.toFixed(2)} MVR + + + {payment.paid ? ( + + {payment.status} + + ) : payment.is_expired ? ( + Expired + ) : ( + {payment.status} + )} + + {isAdmin && ( +
+ {payment?.user?.name} + + {payment?.user?.id_card} + +
+ )} +
+
+
+
+ ); } diff --git a/components/topups-table.tsx b/components/topups-table.tsx index bfe0711..1c4d9a6 100644 --- a/components/topups-table.tsx +++ b/components/topups-table.tsx @@ -3,13 +3,13 @@ import Link from "next/link"; import { redirect } from "next/navigation"; import { getTopups } from "@/actions/payment"; import { - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow, + Table, + TableBody, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, } from "@/components/ui/table"; import type { Topup } from "@/lib/backend-types"; import { cn } from "@/lib/utils"; @@ -19,199 +19,201 @@ import { Badge } from "./ui/badge"; import { Button } from "./ui/button"; export async function TopupsTable({ - searchParams, + searchParams, }: { - searchParams: Promise<{ - [key: string]: unknown; - }>; + searchParams: Promise<{ + [key: string]: unknown; + }>; }) { - const resolvedParams = await searchParams; - const page = Number.parseInt(resolvedParams.page as string) || 1; - const limit = 10; - const offset = (page - 1) * limit; - // Build params object - const apiParams: Record = {}; - for (const [key, value] of Object.entries(resolvedParams)) { - if (value !== undefined && value !== "") { - apiParams[key] = typeof value === "number" ? value : String(value); - } - } - apiParams.limit = limit; - apiParams.offset = offset; - const [error, topups] = await tryCatch(getTopups(apiParams)); + const resolvedParams = await searchParams; + const page = Number.parseInt(resolvedParams.page as string) || 1; + const limit = 10; + const offset = (page - 1) * limit; + // Build params object + const apiParams: Record = {}; + for (const [key, value] of Object.entries(resolvedParams)) { + if (value !== undefined && value !== "") { + apiParams[key] = typeof value === "number" ? value : String(value); + } + } + apiParams.limit = limit; + apiParams.offset = offset; + const [error, topups] = await tryCatch(getTopups(apiParams)); - if (error) { - if (error.message.includes("Unauthorized")) { - redirect("/auth/signin"); - } else { - return
{JSON.stringify(error, null, 2)}
; - } - } - const { data, meta } = topups; - return ( -
- {data?.length === 0 ? ( -
-

No topups.

-
- ) : ( - <> -
- - - - Details - Status - Amount - - - - {topups?.data?.map((topup) => ( - - -
-
- - - {new Date(topup.created_at).toLocaleDateString( - "en-US", - { - month: "short", - day: "2-digit", - year: "numeric", - minute: "2-digit", - hour: "2-digit", - }, - )} - -
+ if (error) { + if (error.message.includes("Unauthorized")) { + redirect("/auth/signin"); + } else { + return
{JSON.stringify(error, null, 2)}
; + } + } + const { data, meta } = topups; + return ( +
+ {data?.length === 0 ? ( +
+

No topups.

+
+ ) : ( + <> +
+
+ + + Details + Status + Amount + + + + {topups?.data?.map((topup) => ( + + +
+
+ + + {new Date(topup.created_at).toLocaleDateString( + "en-US", + { + month: "short", + day: "2-digit", + year: "numeric", + minute: "2-digit", + hour: "2-digit", + }, + )} + +
-
- - - -
-
-
+
+ + + +
+ + - - - {topup.paid ? ( - - {topup.status} - - ) : topup.is_expired ? ( - Expired - ) : ( - {topup.status} - )} - - - - - {topup.amount.toFixed(2)} - - MVR - -
- ))} -
- - - - {meta?.total === 1 ? ( -

Total {meta?.total} topup.

- ) : ( -

Total {meta?.total} topups.

- )} -
-
-
-
-
-
- {data.map((topup) => ( - - ))} -
- - - )} -
- ); + + + {topup.paid ? ( + + {topup.status} + + ) : topup.is_expired ? ( + Expired + ) : ( + {topup.status} + )} + + + + + {topup.amount.toFixed(2)} + + MVR + + + ))} + + + + + {meta?.total === 1 ? ( +

Total {meta?.total} topup.

+ ) : ( +

Total {meta?.total} topups.

+ )} +
+
+
+ +
+
+ {data.map((topup) => ( + + ))} +
+ + + )} +
+ ); } function MobileTopupDetails({ topup }: { topup: Topup }) { - return ( -
-
- - - {new Date(topup.created_at).toLocaleDateString("en-US", { - month: "short", - day: "2-digit", - year: "numeric", - })} - -
+ return ( +
+
+ + + {new Date(topup.created_at).toLocaleDateString("en-US", { + month: "short", + day: "2-digit", + year: "numeric", + })} + +
-
- - - -
+
+ + + +
-
-
-

Amount

- - {topup.amount.toFixed(2)} MVR - -
- - {topup.paid ? ( - - {topup.status} - - ) : topup.is_expired ? ( - Expired - ) : ( - {topup.status} - )} - -
-
- ); +
+
+

Amount

+ + {topup.amount.toFixed(2)} MVR + +
+ + {topup.paid ? ( + + {topup.status} + + ) : topup.is_expired ? ( + Expired + ) : ( + {topup.status} + )} + +
+
+ ); } diff --git a/components/ui/app-sidebar.tsx b/components/ui/app-sidebar.tsx index 92816dc..2631065 100644 --- a/components/ui/app-sidebar.tsx +++ b/components/ui/app-sidebar.tsx @@ -1,226 +1,226 @@ import { - BadgePlus, - Calculator, - ChevronRight, - Coins, - CreditCard, - Handshake, - MonitorSpeaker, - Smartphone, - UsersRound, - Wallet2Icon, + BadgePlus, + Calculator, + ChevronRight, + Coins, + CreditCard, + Handshake, + MonitorSpeaker, + Smartphone, + UsersRound, + Wallet2Icon, } from "lucide-react"; import Link from "next/link"; import { getServerSession } from "next-auth"; import { authOptions } from "@/app/auth"; import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, + Collapsible, + CollapsibleContent, + CollapsibleTrigger, } from "@/components/ui/collapsible"; import { - Sidebar, - SidebarContent, - SidebarGroup, - SidebarGroupContent, - SidebarGroupLabel, - SidebarHeader, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, - SidebarRail, + Sidebar, + SidebarContent, + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarRail, } from "@/components/ui/sidebar"; type Permission = { - id: number; - name: string; + id: number; + name: string; }; type Categories = { - id: string; - children: ( - | { - title: string; - link: string; - perm_identifier: string; - icon: React.JSX.Element; - } - | { - title: string; - link: string; - icon: React.JSX.Element; - perm_identifier?: undefined; - } - )[]; + id: string; + children: ( + | { + title: string; + link: string; + perm_identifier: string; + icon: React.JSX.Element; + } + | { + title: string; + link: string; + icon: React.JSX.Element; + perm_identifier?: undefined; + } + )[]; }[]; export async function AppSidebar({ - ...props + ...props }: React.ComponentProps) { - const categories = [ - { - id: "MENU", - url: "#", - children: [ - { - title: "Devices", - link: "/devices?page=1", - perm_identifier: "device", - icon: , - }, - { - title: "Parental Control", - link: "/parental-control?page=1", - icon: , - perm_identifier: "device", - }, - { - title: "Subscriptions", - link: "/payments?page=1", - icon: , - perm_identifier: "payment", - }, - { - title: "Top Ups", - link: "/top-ups?page=1", - icon: , - perm_identifier: "topup", - }, - { - title: "Transaction History", - link: "/wallet", - icon: , - perm_identifier: "wallet transaction", - }, - { - title: "Agreements", - link: "/agreements", - icon: , - perm_identifier: "device", - }, - ], - }, - { - id: "ADMIN CONTROL", - url: "#", - children: [ - { - title: "Users", - link: "/users", - icon: , - perm_identifier: "device", - }, - { - title: "User Devices", - link: "/user-devices", - icon: , - perm_identifier: "device", - }, - { - title: "User Payments", - link: "/user-payments", - icon: , - perm_identifier: "payment", - }, - { - title: "User Topups", - link: "/user-topups", - icon: , - perm_identifier: "topup", - }, - { - title: "Price Calculator", - link: "/price-calculator", - icon: , - perm_identifier: "device", - }, - ], - }, - ]; + const categories = [ + { + id: "MENU", + url: "#", + children: [ + { + title: "Devices", + link: "/devices?page=1", + perm_identifier: "device", + icon: , + }, + { + title: "Parental Control", + link: "/parental-control?page=1", + icon: , + perm_identifier: "device", + }, + { + title: "Subscriptions", + link: "/payments?page=1", + icon: , + perm_identifier: "payment", + }, + { + title: "Top Ups", + link: "/top-ups?page=1", + icon: , + perm_identifier: "topup", + }, + { + title: "Transaction History", + link: "/wallet", + icon: , + perm_identifier: "wallet transaction", + }, + { + title: "Agreements", + link: "/agreements", + icon: , + perm_identifier: "device", + }, + ], + }, + { + id: "ADMIN CONTROL", + url: "#", + children: [ + { + title: "Users", + link: "/users", + icon: , + perm_identifier: "device", + }, + { + title: "User Devices", + link: "/user-devices", + icon: , + perm_identifier: "device", + }, + { + title: "User Payments", + link: "/user-payments", + icon: , + perm_identifier: "payment", + }, + { + title: "User Topups", + link: "/user-topups", + icon: , + perm_identifier: "topup", + }, + { + title: "Price Calculator", + link: "/price-calculator", + icon: , + perm_identifier: "device", + }, + ], + }, + ]; - const session = await getServerSession(authOptions); + const session = await getServerSession(authOptions); - let CATEGORIES: Categories; - if (session?.user?.is_admin) { - CATEGORIES = categories; - } else { - // Filter out ADMIN CONTROL category for non-admin users - const nonAdminCategories = categories.filter( - (category) => category.id !== "ADMIN CONTROL", - ); + let CATEGORIES: Categories; + if (session?.user?.is_admin) { + CATEGORIES = categories; + } else { + // Filter out ADMIN CONTROL category for non-admin users + const nonAdminCategories = categories.filter( + (category) => category.id !== "ADMIN CONTROL", + ); - const filteredCategories = nonAdminCategories.map((category) => { - const filteredChildren = category.children.filter((child) => { - const permIdentifier = child.perm_identifier; - return session?.user?.user_permissions?.some( - (permission: Permission) => { - const permissionParts = permission.name.split(" "); - const modelNameFromPermission = permissionParts.slice(2).join(" "); - return modelNameFromPermission === permIdentifier; - }, - ); - }); + const filteredCategories = nonAdminCategories.map((category) => { + const filteredChildren = category.children.filter((child) => { + const permIdentifier = child.perm_identifier; + return session?.user?.user_permissions?.some( + (permission: Permission) => { + const permissionParts = permission.name.split(" "); + const modelNameFromPermission = permissionParts.slice(2).join(" "); + return modelNameFromPermission === permIdentifier; + }, + ); + }); - return { ...category, children: filteredChildren }; - }); + return { ...category, children: filteredChildren }; + }); - CATEGORIES = filteredCategories.filter( - (category) => category.children.length > 0, - ); - } + CATEGORIES = filteredCategories.filter( + (category) => category.children.length > 0, + ); + } - return ( - - -

- Sar Link Portal -

-
- - {CATEGORIES.map((item) => { - return ( - - - - - {item.id}{" "} - - - - - - - {item.children.map((item) => ( - - - - {item.icon} - - {item.title} - - - - - ))} - - - - - - ); - })} - - -
- ); + return ( + + +

+ Sar Link Portal +

+
+ + {CATEGORIES.map((item) => { + return ( + + + + + {item.id}{" "} + + + + + + + {item.children.map((item) => ( + + + + {item.icon} + + {item.title} + + + + + ))} + + + + + + ); + })} + + +
+ ); } diff --git a/components/wallet-transactions-table.tsx b/components/wallet-transactions-table.tsx index e686dba..a5687a9 100644 --- a/components/wallet-transactions-table.tsx +++ b/components/wallet-transactions-table.tsx @@ -66,7 +66,7 @@ export async function WalletTransactionsTable({ ) : (
-
+
Total Debit @@ -95,7 +95,7 @@ export async function WalletTransactionsTable({ {transactions?.data?.map((trx) => ( { - const timer = setTimeout(() => { - setIsVisible(false); - }, 4000); + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + }, 4000); - return () => clearTimeout(timer); - }, []); + return () => clearTimeout(timer); + }, []); - return ( - - {isVisible && ( - - Welcome,{" "} -

- {firstName} {lastName} -

-
- )} -
- ); + return ( + + {isVisible && ( + + Welcome,{" "} +

+ {firstName} {lastName} +

+
+ )} +
+ ); }