diff --git a/ui/.eslintrc.json b/ui/.eslintrc.json
deleted file mode 100644
index 0e81f9b..0000000
--- a/ui/.eslintrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "next/core-web-vitals"
-}
\ No newline at end of file
diff --git a/ui/.gitignore b/ui/.gitignore
deleted file mode 100644
index fd3dbb5..0000000
--- a/ui/.gitignore
+++ /dev/null
@@ -1,36 +0,0 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
-/node_modules
-/.pnp
-.pnp.js
-.yarn/install-state.gz
-
-# testing
-/coverage
-
-# next.js
-/.next/
-/out/
-
-# production
-/build
-
-# misc
-.DS_Store
-*.pem
-
-# debug
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# local env files
-.env*.local
-
-# vercel
-.vercel
-
-# typescript
-*.tsbuildinfo
-next-env.d.ts
diff --git a/ui/README.md b/ui/README.md
deleted file mode 100644
index c403366..0000000
--- a/ui/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
-
-## Getting Started
-
-First, run the development server:
-
-```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
-```
-
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
-
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
-
-This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
-
-## Learn More
-
-To learn more about Next.js, take a look at the following resources:
-
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
-
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
-
-## Deploy on Vercel
-
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
-
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/ui/app/api/overview/get-all/route.ts b/ui/app/api/overview/get-all/route.ts
deleted file mode 100644
index 857ab7c..0000000
--- a/ui/app/api/overview/get-all/route.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export async function GET(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/overview/get-all`
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/password/forget-request/route.ts b/ui/app/api/password/forget-request/route.ts
deleted file mode 100644
index a6a637c..0000000
--- a/ui/app/api/password/forget-request/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/password/forget-request`;
-
- const { email } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- email
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/password/reset/route.ts b/ui/app/api/password/reset/route.ts
deleted file mode 100644
index c46bc1e..0000000
--- a/ui/app/api/password/reset/route.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/password/reset`;
-
- const { email, old_password, new_password } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- email,
- old_password,
- new_password
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/delete-all/route.ts b/ui/app/api/session/delete-all/route.ts
deleted file mode 100644
index a9aaf64..0000000
--- a/ui/app/api/session/delete-all/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/delete-all`;
-
- const { uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/delete/route.ts b/ui/app/api/session/delete/route.ts
deleted file mode 100644
index 4719363..0000000
--- a/ui/app/api/session/delete/route.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/delete`;
-
- const { session_id, uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- session_id,
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/get-all-from-uid/route.ts b/ui/app/api/session/get-all-from-uid/route.ts
deleted file mode 100644
index 14ab980..0000000
--- a/ui/app/api/session/get-all-from-uid/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/get-all-from-uid`;
-
- const { uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/get-all/route.ts b/ui/app/api/session/get-all/route.ts
deleted file mode 100644
index 0ab2143..0000000
--- a/ui/app/api/session/get-all/route.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export async function GET(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/get-all`;
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/revoke-all/route.ts b/ui/app/api/session/revoke-all/route.ts
deleted file mode 100644
index abcf0a3..0000000
--- a/ui/app/api/session/revoke-all/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/revoke-all`;
-
- const { uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/session/revoke/route.ts b/ui/app/api/session/revoke/route.ts
deleted file mode 100644
index ef7d565..0000000
--- a/ui/app/api/session/revoke/route.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/session/revoke`;
-
- const { session_id, uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- session_id,
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/delete/route.ts b/ui/app/api/user/delete/route.ts
deleted file mode 100644
index 7e6a948..0000000
--- a/ui/app/api/user/delete/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/delete`;
-
- const { email } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- cache: 'no-cache',
- body: JSON.stringify({
- email
- }),
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/get-all/route.ts b/ui/app/api/user/get-all/route.ts
deleted file mode 100644
index f4015f1..0000000
--- a/ui/app/api/user/get-all/route.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export async function GET(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/get-all`
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/get-from-uid/route.ts b/ui/app/api/user/get-from-uid/route.ts
deleted file mode 100644
index aa89af8..0000000
--- a/ui/app/api/user/get-from-uid/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/get-from-id`;
-
- const { uid } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- uid
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/get-recent/route.ts b/ui/app/api/user/get-recent/route.ts
deleted file mode 100644
index 18b0387..0000000
--- a/ui/app/api/user/get-recent/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/get-recent`;
-
- const { limit } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- cache: 'no-cache',
- body: JSON.stringify({
- limit
- }),
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/toggle-active-status/route.ts b/ui/app/api/user/toggle-active-status/route.ts
deleted file mode 100644
index b74f9f1..0000000
--- a/ui/app/api/user/toggle-active-status/route.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/toggle-account-active-status`;
-
- const { email, is_active } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- email,
- is_active
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/update-role/route.ts b/ui/app/api/user/update-role/route.ts
deleted file mode 100644
index 34376e7..0000000
--- a/ui/app/api/user/update-role/route.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/update-role`;
-
- const { email, role } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- email,
- role
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/api/user/update/route.ts b/ui/app/api/user/update/route.ts
deleted file mode 100644
index bab208a..0000000
--- a/ui/app/api/user/update/route.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export async function POST(req: Request) {
- const endPoint: (string | undefined) = `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/update`;
-
- const { name, email } = await req.json();
-
- if (endPoint) {
- try {
- const res = await fetch(endPoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json', // Set the appropriate content type for your request
- 'x-api-key': process.env.X_API_KEY!,
- },
- body: JSON.stringify({
- name,
- email
- }),
- cache: 'no-cache',
- });
- const data = await res.json();
- return Response.json({ data })
- } catch (error) {
- console.error('Error during request:', error);
- }
- }
-}
\ No newline at end of file
diff --git a/ui/app/favicon.ico b/ui/app/favicon.ico
deleted file mode 100644
index 1e4d4cc..0000000
Binary files a/ui/app/favicon.ico and /dev/null differ
diff --git a/ui/app/globals.css b/ui/app/globals.css
deleted file mode 100644
index 523b3dd..0000000
--- a/ui/app/globals.css
+++ /dev/null
@@ -1,57 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-@layer base {
- :root {
- --background: 222.2 50% 4.9%;
- --foreground: 210 40% 98%;
- --card: 222.2 84% 4.9%;
- --card-foreground: 210 40% 98%;
- --popover: 222.2 84% 4.9%;
- --popover-foreground: 210 40% 98%;
- --primary: 217.2 91.2% 59.8%;
- --primary-foreground: 222.2 47.4% 11.2%;
- --secondary: 217.2 32.6% 17.5%;
- --secondary-foreground: 210 40% 98%;
- --muted: 217.2 32.6% 17.5%;
- --muted-foreground: 215 20.2% 65.1%;
- --accent: 217.2 32.6% 17.5%;
- --accent-foreground: 210 40% 98%;
- --destructive: 0 94% 30.6%;
- --destructive-foreground: 210 40% 98%;
- --border: 217.2 32.6% 17.5%;
- --input: 217.2 32.6% 17.5%;
- --ring: 224.3 76.3% 48%;
- --radius: 0.5rem;
-
- --chart-1-1: 221.2 83.2% 53.3%;
- --chart-2-1: 212 95% 68%;
- --chart-3-1: 216 92% 60%;
- --chart-4-1: 210 98% 78%;
- --chart-5-1: 212 97% 87%;
-
- --chart-1-2: 359 2% 90%;
- --chart-2-2: 240 1% 74%;
- --chart-3-2: 240 1% 58%;
- --chart-4-2: 240 1% 42%;
- --chart-5-2: 240 2% 26%;
-
- --chart-1-3: 139 65% 20%;
- --chart-2-3: 140 74% 44%;
- --chart-3-3: 142 88% 28%;
- --chart-4-3: 137 55% 15%;
- --chart-5-3: 141 40% 9%;
- }
-}
-
-
-@layer base {
- * {
- @apply border-border overflow-x-clip;
- }
-
- body {
- @apply bg-background text-foreground;
- }
-}
\ No newline at end of file
diff --git a/ui/app/layout.tsx b/ui/app/layout.tsx
deleted file mode 100644
index 96536cb..0000000
--- a/ui/app/layout.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { Metadata } from "next";
-import { Poppins } from "next/font/google";
-import "./globals.css";
-import { TooltipProvider } from "@/components/ui/tooltip";
-import Navbar from "@/components/shared/Navbar";
-import { Toaster } from "@/components/ui/toaster";
-import Sidebar from "@/components/shared/Sidebar/Sidebar";
-import { AppPages } from "@/constants/appconstants";
-
-const poppins = Poppins({
- weight: '400',
- subsets: ['latin'],
- display: 'swap',
-})
-
-export const metadata: Metadata = {
- title: "FlexAuth Dashboard",
- description: "Your own flexible, blazingly fast 🦀, and secure in-house authentication system.",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: React.ReactNode;
-}>) {
- return (
-
-
-
-
-
-
-
-
-
- TooltipProvider>
-
-
-
- );
-}
diff --git a/ui/app/page.tsx b/ui/app/page.tsx
deleted file mode 100644
index fc8ddaa..0000000
--- a/ui/app/page.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-"use client";
-import React from 'react'
-import Overview from '@/components/Overview/Overview';
-
-const OverviewPage = () => {
- return (
-
-
-
- )
-}
-
-export default OverviewPage
\ No newline at end of file
diff --git a/ui/app/sessions/page.tsx b/ui/app/sessions/page.tsx
deleted file mode 100644
index c59020e..0000000
--- a/ui/app/sessions/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-"use client"
-
-import SessionTableAll from '@/components/session/SessionTableAll'
-import React from 'react'
-
-const Sessions = () => {
- return (
-
-
-
- )
-}
-
-export default Sessions
\ No newline at end of file
diff --git a/ui/app/users/[userID]/page.tsx b/ui/app/users/[userID]/page.tsx
deleted file mode 100644
index a24c4a2..0000000
--- a/ui/app/users/[userID]/page.tsx
+++ /dev/null
@@ -1,540 +0,0 @@
-"use client";
-import React, { useCallback, useEffect } from "react";
-import { Loader } from "@/components/custom/Loader";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { IUser } from "@/interfaces/IUser";
-import {
- AlertDialog,
- AlertDialogCancel,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogTitle,
- AlertDialogTrigger,
-} from "@/components/ui/alert-dialog";
-import { Input } from "@/components/ui/input";
-import { useRouter } from "next/navigation";
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu";
-import { IoMdMore } from "react-icons/io";
-import { toast } from "@/components/ui/use-toast";
-import { Badge } from "@/components/ui/badge";
-import { GoClockFill } from "react-icons/go";
-import { TiTick } from "react-icons/ti";
-import { IoIosWarning } from "react-icons/io";
-import { format } from "date-fns";
-import SessionTableUser from "@/components/session/SessionTableUser";
-import PasswordInput from "@/components/ui/passwordInput";
-import { FaRegCopy } from "react-icons/fa";
-import useCopy from "@/hooks/useCopy";
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
-
-const UserDetails = ({ params }: any) => {
- const { userID } = params;
- const [loading, setLoading] = React.useState(true);
- const [user, setUser] = React.useState(null);
- const [role, setRole] = React.useState("");
- const [name, setName] = React.useState("");
- const [oldPassword, setOldPassword] = React.useState("");
- const [newPassword, setNewPassword] = React.useState("");
- const [confirmNewPassword, setConfirmNewPassword] = React.useState("");
- const router = useRouter();
- const { copyHandler } = useCopy();
-
- // function to update is_active
- const updateUserActive = async (is_active: boolean) => {
- try {
- setLoading(true);
- await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/toggle-active-status`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email: user?.email,
- is_active: is_active,
- }),
- }
- );
- await getUser();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- const getUser = useCallback(async () => {
- try {
- setLoading(true);
- const res = await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/get-from-uid`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- uid: userID,
- }),
- }
- );
- const { data } = await res.json();
- setUser(data);
- setRole(data?.role || "");
- setName(data?.name || "");
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- }, [userID]);
-
- // delete user function
- const deleteUser = async (email: string) => {
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/delete`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email,
- }),
- });
- router.push("/");
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // reset password function
- const resetPassword = async (
- email: string,
- old_password: string,
- new_password: string
- ) => {
- if (
- old_password === "" ||
- new_password === "" ||
- confirmNewPassword === ""
- ) {
- toast({
- title: "Error",
- description: "Fill all the fields correctly.",
- variant: "destructive",
- });
- return;
- } else {
- if (new_password !== confirmNewPassword) {
- toast({
- title: "Error",
- description: "New and Confirm New Passwords do not match.",
- variant: "destructive",
- });
- return;
- }
- }
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/password/reset`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email,
- old_password,
- new_password,
- }),
- });
- } catch (error) {
- console.error("Error during POST request:", error);
- } finally {
- setOldPassword("");
- setNewPassword("");
- setConfirmNewPassword("");
- }
- setLoading(false);
- };
-
- // forget password request function
- const forgetPassword = async (email: string) => {
- try {
- setLoading(true);
- await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/password/forget-request`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email,
- }),
- }
- );
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // edit user function
- const editUser = async (email: string, name: string, role: string) => {
- if (name === "" || role === "") {
- toast({
- title: "Error",
- description: "Fill all the fields correctly.",
- variant: "destructive",
- });
- return;
- }
- try {
- setLoading(true);
- if (role !== user?.role) {
- await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update-role`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email: user?.email,
- role,
- }),
- }
- );
- }
- if (name !== user?.name) {
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- email,
- name,
- }),
- });
- }
- await getUser();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- useEffect(() => {
- getUser();
- }, [getUser]);
-
- return (
-
-
- {loading ? (
-
-
-
- ) : (
-
-
-
-
-
-
{user?.name}
-
-
- {user?.uid}
-
-
-
-
-
-
-
- Copy UID
-
-
-
-
-
-
-
-
-
-
-
-
-
Email
-
{user?.email}
-
-
-
-
- Email Verification
-
-
- {user?.email_verified ? : }
-
- {user?.email_verified ? "Verified" : "Pending"}
-
-
-
-
Account Status
-
- {user?.is_active ? : }
-
- {user?.is_active ? "Active" : "Suspended"}
-
-
-
-
Created At
-
- {format(
- new Date(parseInt(user?.created_at.$date.$numberLong!)),
- "PP - p"
- )}
-
-
-
-
Updated At
-
- {format(
- new Date(parseInt(user?.updated_at.$date.$numberLong!)),
- "PP - p"
- )}
-
-
-
-
-
-
-
- )}
-
-
- );
-};
-
-export default UserDetails;
diff --git a/ui/app/users/page.tsx b/ui/app/users/page.tsx
deleted file mode 100644
index 9de8c91..0000000
--- a/ui/app/users/page.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-"use client"
-import React from 'react'
-import Users from '@/components/Users/Users'
-
-const UsersPage = () => {
- return (
-
- )
-}
-
-export default UsersPage
\ No newline at end of file
diff --git a/ui/components.json b/ui/components.json
deleted file mode 100644
index 15f2b02..0000000
--- a/ui/components.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "$schema": "https://ui.shadcn.com/schema.json",
- "style": "default",
- "rsc": true,
- "tsx": true,
- "tailwind": {
- "config": "tailwind.config.ts",
- "css": "app/globals.css",
- "baseColor": "slate",
- "cssVariables": true,
- "prefix": ""
- },
- "aliases": {
- "components": "@/components",
- "utils": "@/lib/utils"
- }
-}
\ No newline at end of file
diff --git a/ui/components/Overview/Overview.tsx b/ui/components/Overview/Overview.tsx
deleted file mode 100644
index ce83078..0000000
--- a/ui/components/Overview/Overview.tsx
+++ /dev/null
@@ -1,469 +0,0 @@
-/* eslint-disable react-hooks/rules-of-hooks */
-"use client";
-import React, { useEffect, useState } from 'react'
-import { Loader } from '../custom/Loader';
-import { IOverview } from '@/interfaces/IOverview';
-import { DonutChartStats } from '../custom/DonutChartForStats';
-import { ChartConfig } from '../ui/chart';
-import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
-import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
-import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
-import { FaUsersSlash } from 'react-icons/fa';
-import { ChartPie } from '../custom/PieChart';
-import { IUser } from '@/interfaces/IUser';
-import { ColumnDef } from '@tanstack/react-table';
-import { LuArrowUpRight } from 'react-icons/lu';
-import { useRouter } from 'next/navigation';
-import { Badge } from '../ui/badge';
-import { TiTick } from 'react-icons/ti';
-import { GoClockFill } from 'react-icons/go';
-import { IoIosWarning, IoMdMore } from 'react-icons/io';
-import { format } from 'date-fns';
-import { toast } from '../ui/use-toast';
-import { Input } from '../ui/input';
-import { Button } from '../ui/button';
-import { DataTable } from '../ui/data-table';
-
-const Overview = () => {
- const [overview, setOverview] = useState(null)
- const [recentUsers, setRecentUsers] = useState([])
- const [loading, setLoading] = useState(true)
-
- const userChartData = [
- { name: "active", count: overview?.active_user_count, fill: "var(--color-active)" },
- { name: "inactive", count: overview?.inactive_user_count, fill: "var(--color-inactive)" },
- ]
-
- const userChartConfig = {
- user: {
- label: "Users",
- },
- active: {
- label: "Active",
- color: "hsl(var(--chart-1-1))",
- },
- inactive: {
- label: "Inactive",
- color: "hsl(var(--chart-2-1))",
- },
- } satisfies ChartConfig
-
- const sessionChartData = [
- { name: "active", count: overview?.active_session_count, fill: "var(--color-active)" },
- { name: "revoked", count: overview?.revoked_session_count, fill: "var(--color-revoked)" },
- ]
-
- const sessionChartConfig = {
- session: {
- label: "Sessions",
- },
- active: {
- label: "Active",
- color: "hsl(var(--chart-1-1))",
- },
- revoked: {
- label: "Revoked",
- color: "hsl(var(--chart-2-2))",
- },
- } satisfies ChartConfig
-
-
- // Define an interface for the device counts
- interface CountObject {
- [key: string]: number;
- }
-
- // Initialize the device counts object with the correct type
- const deviceCounts: CountObject = (overview ?? {
- device_types: [],
- }).device_types.reduce((acc, device) => {
- const sanitizedKey = device.replace(/\s+/g, ''); // Remove whitespace from the key
- acc[sanitizedKey] = (acc[sanitizedKey] || 0) + 1;
- return acc;
- }, {} as CountObject);
-
- // Count occurrences in the browsers array
- const browserCounts: CountObject = (overview ?? {
- browser_types: [],
- }).browser_types.reduce((acc, browser) => {
- const sanitizedKey = browser.replace(/\s+/g, ''); // Remove whitespace from the key
- acc[sanitizedKey] = (acc[sanitizedKey] || 0) + 1;
- return acc;
- }, {} as CountObject);
-
- // Count occurrences in the OS types array
- const osTypeCounts: CountObject = (overview ?? {
- os_types: [],
- }).os_types.reduce((acc, os) => {
- const sanitizedKey = os.replace(/\s+/g, ''); // Remove whitespace from the key
- acc[sanitizedKey] = (acc[sanitizedKey] || 0) + 1;
- return acc;
- }, {} as CountObject);
-
-
- // Define a function to generate colors dynamically
- const generateColor = (index: number, themeNo: number) => {
- return `hsl(var(--chart-${index + 1}-${themeNo}))`;
- };
-
- // Generic function to generate chart configuration
- const generateChartConfig = (counts: CountObject, themeNo: number) => {
- const config: { [key: string]: { label: string; color: string } } = {};
- const types = Object.keys(counts);
-
-
- types.forEach((type, index) => {
- config[type] = {
- label: type,
- color: generateColor(index, themeNo),
- };
- });
-
- return config;
- };
-
- const sessionDeviceChartData = Object.keys(deviceCounts).map(device => ({
- name: device,
- count: deviceCounts[device] || 0,
- fill: `var(--color-${device})`
- }));
-
- const sessionBrowserChartData = Object.keys(browserCounts).map(browser => ({
- name: browser,
- count: browserCounts[browser] || 0,
- fill: `var(--color-${browser})`
- }));
-
- const sessionOsTypeChartData = Object.keys(osTypeCounts).map(os => ({
- name: os,
- count: osTypeCounts[os] || 0,
- fill: `var(--color-${os})`
- }));
-
- const sessionDeviceChartConfig = generateChartConfig(deviceCounts, 2);
-
- const sessionBrowserChartConfig = generateChartConfig(browserCounts, 1);
-
- const sessionOSChartConfig = generateChartConfig(osTypeCounts, 2);
-
- // delete user function
- const deleteUser = async (email: string) => {
- try {
- setLoading(true)
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/delete`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email
- }),
- });
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- const router = useRouter();
-
- const columns: ColumnDef[] = [
- {
- accessorKey: "name",
- header: "Name",
- cell: ({ row }) => {
- const user = row.original;
- return (
- router.push(`/users/${user.uid}`)}>
-
{user.name}
-
-
-
-
- );
- }
- },
- {
- accessorKey: "email",
- header: "Email",
- },
- {
- accessorKey: "role",
- header: "Role",
- },
- {
- accessorKey: "email_verified",
- header: "Email Verification",
- cell: ({ row }) => {
- return (
-
- {row.original?.email_verified ? : }
-
- {row.original?.email_verified ? "Verified" : "Pending"}
-
- )
- },
- },
- {
- accessorKey: "is_active",
- header: "Account Status",
- cell: ({ row }) => {
- return (
-
- {row.original?.is_active ? : }
-
- {row.original?.is_active ? "Active" : "Suspended"}
-
- )
- },
- },
- {
- accessorKey: "created_at",
- header: "Created At",
- cell: ({ row }) => {
- return (
-
- {format(
- new Date(parseInt(row.original?.created_at.$date.$numberLong!)),
- "PP - p"
- )}
-
- )
- },
- },
- {
- accessorKey: "updated_at",
- header: "Action",
- cell: ({ row }) => {
- const user = row.original;
- const [name, setName] = useState(user.name);
- const [role, setRole] = useState(user.role)
- // edit user function
- const editUser = async (email: string, name: string, role: string) => {
- if (name === "" || role === "") {
- toast({
- title: "Error",
- description: "Fill all the fields correctly.",
- variant: "destructive"
- });
- return;
- };
- try {
- setLoading(true)
- if (role !== user?.role) {
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update-role`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email: user?.email,
- role
- }),
- });
- }
- if (name !== user?.name) {
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email,
- name
- }),
- });
- }
- await getRecentUsers()
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- return (
-
- )
- },
- },
- ];
-
-
- const getOverview = async () => {
- try {
- setLoading(true)
- const res = await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/overview/get-all`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- cache: 'no-cache',
- });
- const { data } = await res.json();
- setOverview(data);
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- const getRecentUsers = async () => {
- try {
- setLoading(true)
- const res = await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/get-recent`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ limit: 5 }),
- cache: 'no-cache',
- });
- const { data } = await res.json();
- setRecentUsers(data);
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- const fetchAllData = async () => {
- await Promise.all([getOverview(), getRecentUsers()])
- }
-
- useEffect(() => {
- fetchAllData()
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [])
-
- return (
-
- {
- loading ?
-
-
-
- :
-
-
-
-
-
- Blocked Users
-
-
-
-
- {overview?.blocked_user_count}
-
-
-
-
-
-
-
-
-
-
Recent Users
-
-
-
- }
-
- )
-}
-
-export default Overview
\ No newline at end of file
diff --git a/ui/components/Users/Users.tsx b/ui/components/Users/Users.tsx
deleted file mode 100644
index f128549..0000000
--- a/ui/components/Users/Users.tsx
+++ /dev/null
@@ -1,274 +0,0 @@
-/* eslint-disable react-hooks/rules-of-hooks */
-"use client";
-
-import { IUser } from '@/interfaces/IUser';
-import { ColumnDef } from '@tanstack/react-table';
-import { useRouter } from 'next/navigation';
-import React, { useEffect, useState } from 'react'
-import { LuArrowUpRight } from 'react-icons/lu';
-import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
-import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
-import { Button } from '@/components/ui/button';
-import { IoIosWarning, IoMdMore } from 'react-icons/io';
-import { Input } from '@/components/ui/input';
-import { Loader } from '@/components/custom/Loader';
-import { DataTable } from '@/components/ui/data-table';
-import { toast } from '@/components/ui/use-toast';
-import { Badge } from '../ui/badge';
-import { TiTick } from 'react-icons/ti';
-import { GoClockFill } from 'react-icons/go';
-import { format } from 'date-fns';
-
-
-const Users = () => {
- const [users, setUsers] = useState([] as IUser[])
- const [loading, setLoading] = useState(true)
- const router = useRouter();
-
- const getAllUsers = async () => {
- try {
- setLoading(true)
- const res = await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/get-all`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- cache: 'no-cache',
- });
- const { data } = await res.json();
- setUsers(data);
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- // delete user function
- const deleteUser = async (email: string) => {
- try {
- setLoading(true)
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/delete`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email
- }),
- });
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
-
- const columns: ColumnDef[] = [
- {
- accessorKey: "name",
- header: "Name",
- cell: ({ row }) => {
- const user = row.original;
- return (
- router.push(`/users/${user.uid}`)}>
-
{user.name}
-
-
-
-
- );
- }
- },
- {
- accessorKey: "email",
- header: "Email",
- },
- {
- accessorKey: "role",
- header: "Role",
- },
- {
- accessorKey: "email_verified",
- header: "Email Verification",
- cell: ({ row }) => {
- return (
-
- {row.original?.email_verified ? : }
-
- {row.original?.email_verified ? "Verified" : "Pending"}
-
- )
- },
- },
- {
- accessorKey: "is_active",
- header: "Account Status",
- cell: ({ row }) => {
- return (
-
- {row.original?.is_active ? : }
-
- {row.original?.is_active ? "Active" : "Suspended"}
-
- )
- },
- },
- {
- accessorKey: "created_at",
- header: "Created At",
- cell: ({ row }) => {
- return (
-
- {format(
- new Date(parseInt(row.original?.created_at.$date.$numberLong!)),
- "PP - p"
- )}
-
- )
- },
- },
- {
- accessorKey: "updated_at",
- header: "Action",
- cell: ({ row }) => {
- const user = row.original;
- const [name, setName] = useState(user.name);
- const [role, setRole] = useState(user.role)
- // edit user function
- const editUser = async (email: string, name: string, role: string) => {
- if (name === "" || role === "") {
- toast({
- title: "Error",
- description: "Fill all the fields correctly.",
- variant: "destructive"
- });
- return;
- };
- try {
- setLoading(true)
- if (role !== user?.role) {
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update-role`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email: user?.email,
- role
- }),
- });
- }
- if (name !== user?.name) {
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/user/update`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email,
- name
- }),
- });
- }
- await getAllUsers()
- } catch (error) {
- console.error('Error during POST request:', error);
- }
- setLoading(false)
- }
-
- return (
-
- )
- },
- },
- ];
-
- useEffect(() => {
- getAllUsers()
- }, [])
- return (
-
- {
- loading ?
-
-
-
- :
-
-
- }
-
- )
-}
-
-export default Users
\ No newline at end of file
diff --git a/ui/components/custom/BarChart.tsx b/ui/components/custom/BarChart.tsx
deleted file mode 100644
index 0183e02..0000000
--- a/ui/components/custom/BarChart.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-"use client"
-
-import { Bar, BarChart, CartesianGrid, Rectangle, XAxis } from "recharts"
-
-import {
- Card,
- CardContent,
- CardHeader,
- CardTitle,
-} from "@/components/ui/card"
-import {
- ChartConfig,
- ChartContainer,
- ChartTooltip,
- ChartTooltipContent,
-} from "@/components/ui/chart"
-
-interface ChartPieProps {
- title: string;
- chartData: any;
- key: string;
- chartConfig: ChartConfig;
-}
-
-export function ChartBar({ title, chartData, key, chartConfig }: ChartPieProps) {
- return (
-
-
- {title}
-
-
-
-
-
-
- String(chartData[value]?.name)
- }
- />
- }
- />
- {
- return (
-
- )
- }}
- />
-
-
-
-
- )
-}
diff --git a/ui/components/custom/DonutChartForStats.tsx b/ui/components/custom/DonutChartForStats.tsx
deleted file mode 100644
index 176598b..0000000
--- a/ui/components/custom/DonutChartForStats.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { Label, Pie, PieChart } from "recharts"
-
-import {
- Card,
- CardContent,
- CardHeader,
- CardTitle,
-} from "@/components/ui/card"
-import {
- ChartConfig,
- ChartContainer,
- ChartTooltip,
- ChartTooltipContent,
-} from "@/components/ui/chart"
-import { FaClock, FaUsersSlash } from "react-icons/fa"
-
-interface DonutChartProps {
- title: string;
- chartData: any;
- key: string;
- chartConfig: ChartConfig;
-}
-
-export function DonutChartStats({ title, chartData, chartConfig, key }: DonutChartProps) {
- const totalCount = React.useMemo(() => {
- return chartData.reduce((acc: any, curr: { count: any }) => acc + curr.count, 0)
- }, [chartData])
-
- return (
-
-
- {title}
-
-
-
- {totalCount === 0 ?
-
-
-
- {totalCount}
-
-
- :
- }
- />
-
-
- }
-
-
-
- )
-}
diff --git a/ui/components/custom/Loader.tsx b/ui/components/custom/Loader.tsx
deleted file mode 100644
index a1d0dcf..0000000
--- a/ui/components/custom/Loader.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-export const Loader = ({ size = '1.25em' }) => {
- return (
-
-
- Loading...
-
-
- );
-};
diff --git a/ui/components/custom/PieChart.tsx b/ui/components/custom/PieChart.tsx
deleted file mode 100644
index 3dd4b9f..0000000
--- a/ui/components/custom/PieChart.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-"use client"
-
-import { Label, Pie, PieChart, Sector } from "recharts"
-import {
- Card,
- CardContent,
- CardHeader,
- CardTitle,
-} from "../ui/card"
-import {
- ChartConfig,
- ChartContainer,
- ChartStyle,
- ChartTooltip,
- ChartTooltipContent,
-} from "../ui/chart"
-import React from "react";
-import { PieSectorDataItem } from "recharts/types/polar/Pie";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
-
-
-interface ChartPieProps {
- title: string;
- chartData: any;
- key: string;
- chartConfig: ChartConfig;
-}
-
-export function ChartPie({ title, chartData, chartConfig, key }: ChartPieProps) {
- const id = "pie-interactive"
- const [active, setActive] = React.useState(chartData[0]?.name)
- const activeIndex = React.useMemo(() => {
- const index = (chartData as []).findIndex((item: any) => item.name === active);
- return index === -1 ? 0 : index;
- }, [active, chartData]);
-
- const options = React.useMemo(() => chartData.map((item: any) => item.name), [chartData])
-
- return (
-
-
-
-
- {title}
-
- {(chartData as []).length > 0 && }
-
-
-
- {(chartData as []).length > 0 ?
- }
- />
- (
-
-
-
-
- )}
- >
-
- :
-
-
- No Data to show
-
-
- }
-
-
-
- )
-}
\ No newline at end of file
diff --git a/ui/components/session/SessionTableAll.tsx b/ui/components/session/SessionTableAll.tsx
deleted file mode 100644
index 8ea5132..0000000
--- a/ui/components/session/SessionTableAll.tsx
+++ /dev/null
@@ -1,293 +0,0 @@
-/* eslint-disable @next/next/no-img-element */
-import { ISession } from "@/interfaces/ISession";
-import {
- AlertDialog,
- AlertDialogTrigger,
- AlertDialogContent,
- AlertDialogTitle,
- AlertDialogDescription,
- AlertDialogCancel,
-} from "@/components/ui/alert-dialog";
-import {
- DropdownMenu,
- DropdownMenuTrigger,
- DropdownMenuContent,
- DropdownMenuItem,
-} from "@/components/ui/dropdown-menu";
-import { ColumnDef } from "@tanstack/react-table";
-import { Loader } from "lucide-react";
-import React, { useCallback, useEffect } from "react";
-import { IoMdMore } from "react-icons/io";
-import { AlertDialogHeader, AlertDialogFooter } from "../ui/alert-dialog";
-import { Button } from "../ui/button";
-import { DataTable } from "../ui/data-table";
-import { addDays, format } from "date-fns";
-
-const SessionTableAll: React.FC = () => {
- const [loading, setLoading] = React.useState(false);
- const [sessions, setSessions] = React.useState([]);
-
- // fetch all sessions
- const fetchAllSessions = useCallback(async () => {
- try {
- setLoading(true);
- const res = await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/get-all`,
- {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- cache: "no-cache",
- }
- );
- const { data } = await res.json();
- setSessions(data);
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- }, []);
-
- // revoke session function
- const revokeSession = async (session_id: string, uid: string) => {
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/revoke`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- session_id,
- uid,
- }),
- });
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // delete session function
- const deleteSession = async (session_id: string, uid: string) => {
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/delete`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- session_id,
- uid,
- }),
- });
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- useEffect(() => {
- fetchAllSessions();
- }, [fetchAllSessions]);
-
- const sessionColumns: ColumnDef[] = [
- {
- accessorKey: "user_agent",
- header: "User Agent",
- cell: ({ row }) => {
- const session = row.original;
- return (
- // render device type and browser name with logo
-
-
-
- {session.device === "smartphone" &&
- (
-
- )}
- {session.device === "pc" &&
- (
-
- )}
-
-
-
{session?.device === "smartphone" ? "Smartphone" : session?.device === "pc" ? "Desktop" : ""} ({session.vendor})
-
{session?.os} - Version {session.os_version}
-
- {session?.browser.includes("Chrome") && (
-
- )}
- {session?.browser.includes("Mozilla") && (
-
- )}
- {session?.browser.includes("Safari") && (
-
- )}
-
{session?.browser} - Version: {session?.browser_version}
-
-
-
-
-
- );
- },
- },
- {
- accessorKey: "updated_at",
- header: "Updated At",
- cell: ({ row }) => {
- return (
-
- {
- format(
- parseInt(row.original.updated_at.$date.$numberLong)
- , "PP - p"
- )
- }
-
- );
- },
- },
- {
- accessorKey: "created_at",
- header: "Expires At",
- cell: ({ row }) => {
- return (
-
- {
- format(addDays(
- parseInt(row.original.created_at.$date.$numberLong)
- , 45), "PP - p")
- }
-
- );
- },
- },
- {
- accessorKey: "is_revoked",
- header: "Revoked",
- cell: ({ row }) => {
- return (
-
- {row.original.is_revoked ? "Yes" : "No"}
-
- );
- },
- },
- {
- accessorKey: "action",
- header: "Action",
- cell: ({ row }) => {
- const session = row.original;
- return (
-
-
-
-
-
-
- {!row.original.is_revoked && (
-
-
-
- Revoke
-
-
-
-
- Are you absolutely sure?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
- )}
-
-
-
- Delete
-
-
-
-
- Are you absolutely sure?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
-
-
-
- );
- },
- },
- ];
-
- return (
-
- );
-};
-
-export default SessionTableAll;
diff --git a/ui/components/session/SessionTableUser.tsx b/ui/components/session/SessionTableUser.tsx
deleted file mode 100644
index b0a0f28..0000000
--- a/ui/components/session/SessionTableUser.tsx
+++ /dev/null
@@ -1,431 +0,0 @@
-/* eslint-disable @next/next/no-img-element */
-import { ISession } from "@/interfaces/ISession";
-import {
- AlertDialog,
- AlertDialogTrigger,
- AlertDialogContent,
- AlertDialogTitle,
- AlertDialogDescription,
- AlertDialogCancel,
-} from "@/components/ui/alert-dialog";
-import {
- DropdownMenu,
- DropdownMenuTrigger,
- DropdownMenuContent,
- DropdownMenuItem,
-} from "@/components/ui/dropdown-menu";
-import { ColumnDef } from "@tanstack/react-table";
-import { Loader } from "lucide-react";
-import React, { useCallback, useEffect } from "react";
-import { IoMdMore } from "react-icons/io";
-import { AlertDialogHeader, AlertDialogFooter } from "../ui/alert-dialog";
-import { Button } from "../ui/button";
-import { Card, CardHeader, CardTitle, CardContent } from "../ui/card";
-import { DataTable } from "../ui/data-table";
-import UAParser from "ua-parser-js";
-import { addDays, format } from "date-fns";
-
-interface SessionTableProps {
- userID: string;
-}
-
-const SessionTable: React.FC = ({ userID }) => {
- const [loading, setLoading] = React.useState(false);
- const [sessions, setSessions] = React.useState([]);
-
- // fetch all sessions
- const fetchAllSessions = useCallback(async () => {
- try {
- setLoading(true);
- const res = await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/get-all-from-uid`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- uid: userID,
- }),
- cache: "no-cache",
- }
- );
- const { data } = await res.json();
- setSessions(data);
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- }, [userID]);
-
- // revoke session function
- const revokeSession = async (session_id: string) => {
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/revoke`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- session_id,
- uid: userID,
- }),
- });
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // delete session function
- const deleteSession = async (session_id: string) => {
- try {
- setLoading(true);
- await fetch(`${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/delete`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- session_id,
- uid: userID,
- }),
- });
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // delete all sessions function
- const deleteAllSessions = async () => {
- try {
- setLoading(true);
- await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/delete-all`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- uid: userID,
- }),
- }
- );
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- // revoke all sessions function
- const revokeAllSessions = async () => {
- try {
- setLoading(true);
- await fetch(
- `${process.env.NEXT_PUBLIC_ENDPOINT}/api/session/revoke-all`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- uid: userID,
- }),
- }
- );
- await fetchAllSessions();
- } catch (error) {
- console.error("Error during POST request:", error);
- }
- setLoading(false);
- };
-
- useEffect(() => {
- fetchAllSessions();
- }, [fetchAllSessions]);
-
- const parser = new UAParser("user-agent");
-
- const sessionColumns: ColumnDef[] = [
- {
- accessorKey: "user_agent",
- header: "User Agent",
- cell: ({ row }) => {
- const session = row.original;
-
- return (
- // render device type and browser name with logo
-
-
-
- {session.device === "smartphone" &&
- (
-
- )}
- {session.device === "pc" &&
- (
-
- )}
-
-
-
{session?.device === "smartphone" ? "Smartphone" : session?.device === "pc" ? "Desktop" : ""} ({session.vendor})
-
{session?.os} - Version {session.os_version}
-
- {session?.browser.includes("Chrome") && (
-
- )}
- {session?.browser.includes("Mozilla") && (
-
- )}
- {session?.browser.includes("Safari") && (
-
- )}
-
{session?.browser} - Version: {session?.browser_version}
-
-
-
-
-
- );
- },
- },
- {
- accessorKey: "updated_at",
- header: "Updated At",
- cell: ({ row }) => {
- return (
-
- {
- format(
- parseInt(row.original.updated_at.$date.$numberLong)
- , "PP - p"
- )
- }
-
- );
- },
- },
- {
- accessorKey: "created_at",
- header: "Expires At",
- cell: ({ row }) => {
- return (
-
- {
- format(addDays(
- parseInt(row.original.created_at.$date.$numberLong)
- , 45), "PP - p")
- }
-
- );
- },
- },
- {
- accessorKey: "is_revoked",
- header: "Revoked",
- cell: ({ row }) => {
- return (
-
- {row.original.is_revoked ? "Yes" : "No"}
-
- );
- },
- },
- {
- accessorKey: "action",
- header: "Action",
- cell: ({ row }) => {
- const session = row.original;
- return (
-
-
-
-
-
-
- {!row.original.is_revoked && (
-
-
-
- Revoke
-
-
-
-
- Are you absolutely sure?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
- )}
-
-
-
- Delete
-
-
-
-
- Are you absolutely sure?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
-
-
-
- );
- },
- },
- ];
-
- return (
-
-
-
- Sessions
-
-
-
-
-
-
-
-
- Revoke All
-
-
-
-
- Want to revoke all the sessions?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
-
-
-
- Delete All
-
-
-
-
- Want to delete all the sessions?
-
-
- This action cannot be undone.
-
-
-
- Cancel
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default SessionTable;
diff --git a/ui/components/shared/Navbar.tsx b/ui/components/shared/Navbar.tsx
deleted file mode 100644
index d3ebdf8..0000000
--- a/ui/components/shared/Navbar.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/* eslint-disable @next/next/no-img-element */
-"use client";
-
-import React from "react";
-import { usePathname, useRouter } from "next/navigation";
-import { AiOutlineArrowLeft } from "react-icons/ai";
-import { Button } from "../ui/button";
-
-const Navbar = () => {
- const path = usePathname();
- const router = useRouter();
-
- const returnPageName = () => {
- if (path.includes("/") && (!path.includes("/user/") && !path.includes("/user"))) {
- return (
-
- Overview
-
- )
- }
- if (path.includes("/user") && (!path.includes("/user/"))) {
- return (
-
- Users
-
- )
- }
- if (path.includes("/user/")) {
- return (
-
-
- User Details
-
- )
- }
- }
-
- return (
-
-
-
-
router.push("/")}
- />
-
FlexAuth
-
-
- {returnPageName()}
-
-
-
- );
-};
-
-export default Navbar;
diff --git a/ui/components/shared/Sidebar/Sidebar.tsx b/ui/components/shared/Sidebar/Sidebar.tsx
deleted file mode 100644
index 3313774..0000000
--- a/ui/components/shared/Sidebar/Sidebar.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-"use client";
-
-import React from 'react'
-import { usePathname, useRouter } from 'next/navigation';
-import SidebarItem from './SidebarItem';
-
-export interface IPages {
- name: string;
- icon?: any;
- link: string;
- showOnSidebar?: boolean;
-}
-
-interface Props {
- items: IPages[]
-}
-
-const Sidebar: React.FC = ({ items }) => {
- const path = usePathname();
- const router = useRouter();
-
- return (
-
-
- {items.map((item) => (
-
- ))}
-
-
-
-
© 2024 FlexAuth • All rights reserved
-
-
- )
-}
-
-export default Sidebar
\ No newline at end of file
diff --git a/ui/components/shared/Sidebar/SidebarItem.tsx b/ui/components/shared/Sidebar/SidebarItem.tsx
deleted file mode 100644
index 7b03fa0..0000000
--- a/ui/components/shared/Sidebar/SidebarItem.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react'
-import { IPages } from './Sidebar'
-import Image from 'next/image'
-
-interface Props {
- item: IPages
- path: string
- router: any
-}
-
-const SidebarItem: React.FC = ({ item, path, router }) => {
- const handleClickSidebarItems = (item: IPages) => {
- router.push(item.link)
- }
-
- const handleHighlight = (item: IPages) => {
- if (path.includes("/user/")) {
- return (item.link === "/user")
- }
- if (path.includes("/users/")) {
- return (item.link === "/users")
- }
- return (path === item.link);
- }
-
- return (
- <>
- {item.showOnSidebar && (
-
-
{ handleClickSidebarItems(item) }}>
-
- {typeof item.icon === "string" ?
: item.icon}
-
-
-
-
- )}
- >
- )
-}
-
-export default SidebarItem
\ No newline at end of file
diff --git a/ui/components/ui/alert-dialog.tsx b/ui/components/ui/alert-dialog.tsx
deleted file mode 100644
index 25e7b47..0000000
--- a/ui/components/ui/alert-dialog.tsx
+++ /dev/null
@@ -1,141 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
-
-import { cn } from "@/lib/utils"
-import { buttonVariants } from "@/components/ui/button"
-
-const AlertDialog = AlertDialogPrimitive.Root
-
-const AlertDialogTrigger = AlertDialogPrimitive.Trigger
-
-const AlertDialogPortal = AlertDialogPrimitive.Portal
-
-const AlertDialogOverlay = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
-
-const AlertDialogContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-
-))
-AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
-
-const AlertDialogHeader = ({
- className,
- ...props
-}: React.HTMLAttributes) => (
-
-)
-AlertDialogHeader.displayName = "AlertDialogHeader"
-
-const AlertDialogFooter = ({
- className,
- ...props
-}: React.HTMLAttributes) => (
-
-)
-AlertDialogFooter.displayName = "AlertDialogFooter"
-
-const AlertDialogTitle = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
-
-const AlertDialogDescription = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogDescription.displayName =
- AlertDialogPrimitive.Description.displayName
-
-const AlertDialogAction = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
-
-const AlertDialogCancel = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
-
-export {
- AlertDialog,
- AlertDialogPortal,
- AlertDialogOverlay,
- AlertDialogTrigger,
- AlertDialogContent,
- AlertDialogHeader,
- AlertDialogFooter,
- AlertDialogTitle,
- AlertDialogDescription,
- AlertDialogAction,
- AlertDialogCancel,
-}
diff --git a/ui/components/ui/badge.tsx b/ui/components/ui/badge.tsx
deleted file mode 100644
index ecc423c..0000000
--- a/ui/components/ui/badge.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const badgeVariants = cva(
- "inline-flex items-center border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
- {
- variants: {
- variant: {
- default:
- "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
- secondary:
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
- destructive:
- "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
- outline: "text-foreground",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-export interface BadgeProps
- extends React.HTMLAttributes,
- VariantProps { }
-
-function Badge({ className, variant, ...props }: BadgeProps) {
- return (
-
- )
-}
-
-export { Badge, badgeVariants }
diff --git a/ui/components/ui/button.tsx b/ui/components/ui/button.tsx
deleted file mode 100644
index 0ba4277..0000000
--- a/ui/components/ui/button.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const buttonVariants = cva(
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
- destructive:
- "bg-destructive text-destructive-foreground hover:bg-destructive/90",
- outline:
- "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
- secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default: "h-10 px-4 py-2",
- sm: "h-9 rounded-md px-3",
- lg: "h-11 rounded-md px-8",
- icon: "h-10 w-10",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
-
-export interface ButtonProps
- extends React.ButtonHTMLAttributes,
- VariantProps {
- asChild?: boolean
-}
-
-const Button = React.forwardRef(
- ({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
- return (
-
- )
- }
-)
-Button.displayName = "Button"
-
-export { Button, buttonVariants }
diff --git a/ui/components/ui/card.tsx b/ui/components/ui/card.tsx
deleted file mode 100644
index afa13ec..0000000
--- a/ui/components/ui/card.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import * as React from "react"
-
-import { cn } from "@/lib/utils"
-
-const Card = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-Card.displayName = "Card"
-
-const CardHeader = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardHeader.displayName = "CardHeader"
-
-const CardTitle = React.forwardRef<
- HTMLParagraphElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardTitle.displayName = "CardTitle"
-
-const CardDescription = React.forwardRef<
- HTMLParagraphElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardDescription.displayName = "CardDescription"
-
-const CardContent = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardContent.displayName = "CardContent"
-
-const CardFooter = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardFooter.displayName = "CardFooter"
-
-export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/ui/components/ui/chart.tsx b/ui/components/ui/chart.tsx
deleted file mode 100644
index 75b26b9..0000000
--- a/ui/components/ui/chart.tsx
+++ /dev/null
@@ -1,366 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as RechartsPrimitive from "recharts"
-
-import { cn } from "@/lib/utils"
-
-// Format: { THEME_NAME: CSS_SELECTOR }
-const THEMES = { light: "", dark: ".dark" } as const
-
-export type ChartConfig = {
- [k in string]: {
- label?: React.ReactNode
- icon?: React.ComponentType
- } & (
- | { color?: string; theme?: never }
- | { color?: never; theme: Record }
- )
-}
-
-type ChartContextProps = {
- config: ChartConfig
-}
-
-const ChartContext = React.createContext(null)
-
-function useChart() {
- const context = React.useContext(ChartContext)
-
- if (!context) {
- throw new Error("useChart must be used within a ")
- }
-
- return context
-}
-
-const ChartContainer = React.forwardRef<
- HTMLDivElement,
- React.ComponentProps<"div"> & {
- config: ChartConfig
- children: React.ComponentProps<
- typeof RechartsPrimitive.ResponsiveContainer
- >["children"]
- }
->(({ id, className, children, config, ...props }, ref) => {
- const uniqueId = React.useId()
- const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
-
- return (
-
-
-
-
- {children}
-
-
-
- )
-})
-ChartContainer.displayName = "Chart"
-
-const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
- const colorConfig = Object.entries(config).filter(
- ([_, config]) => config.theme || config.color
- )
-
- if (!colorConfig.length) {
- return null
- }
-
- return (
-