diff --git a/apps/api/src/util/package.ts b/apps/api/src/util/package.ts index ba5ca96a..82dad612 100644 --- a/apps/api/src/util/package.ts +++ b/apps/api/src/util/package.ts @@ -1 +1,2 @@ -export const LIB_VERSION = "1.1.0";export const LIB_LICENSE = undefined; +export const LIB_VERSION = '1.1.0'; +export const LIB_LICENSE = undefined; diff --git a/apps/dashboard/src/app/am/sso/loading.tsx b/apps/dashboard/src/app/am/sso/loading.tsx index 629ceab1..6f7c81a6 100644 --- a/apps/dashboard/src/app/am/sso/loading.tsx +++ b/apps/dashboard/src/app/am/sso/loading.tsx @@ -1,11 +1,11 @@ -import { Box, Title } from "@mantine/core"; +import { Box, Title } from '@mantine/core'; export default async function Page() { - return ( - - - SSO Configuration and Security - - - ); + return ( + + + SSO Configuration and Security + + + ); } diff --git a/apps/dashboard/src/app/am/sso/page.tsx b/apps/dashboard/src/app/am/sso/page.tsx index ca9591f9..35770027 100644 --- a/apps/dashboard/src/app/am/sso/page.tsx +++ b/apps/dashboard/src/app/am/sso/page.tsx @@ -1,160 +1,148 @@ import { - Badge, - Box, - Button, - Card, - Code, - NumberFormatter, - SimpleGrid, - Stack, - Table, - TableTbody, - TableTd, - TableTh, - TableThead, - TableTr, - Tabs, - TabsList, - TabsPanel, - TabsTab, - Text, - Title, -} from "@mantine/core"; + Badge, + Box, + Card, + Code, + NumberFormatter, + SimpleGrid, + Stack, + Table, + TableTbody, + TableTd, + TableTh, + TableThead, + TableTr, + Tabs, + TabsList, + TabsPanel, + TabsTab, + Text, + Title, +} from '@mantine/core'; -import Anchor from "@/components/core/Anchor"; -import { getSession } from "@/util/auth"; -import { globalFetcher } from "@/util/data"; +import Anchor from '@/components/core/Anchor'; +import { getSession } from '@/util/auth'; +import { globalFetcher } from '@/util/data'; export default async function Page() { - const session = await getSession(); - const realm = (await globalFetcher<[any]>( - `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace( - "/realms/website", - "" - )}/admin/realms`, - { headers: { Authorization: `Bearer ${session?.accessToken}` } } - ))[0]; - const adminEvents = await globalFetcher( - `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace( - "/realms/website", - "" - )}/admin/realms/website/admin-events`, - { headers: { Authorization: `Bearer ${session?.accessToken}` } } - ); - const userEvents = await globalFetcher( - `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace( - "/realms/website", - "" - )}/admin/realms/website/events`, - { headers: { Authorization: `Bearer ${session?.accessToken}` } } - ); - const clientStats = await globalFetcher( - `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace( - "/realms/website", - "" - )}/admin/realms/website/client-session-stats`, - { headers: { Authorization: `Bearer ${session?.accessToken}` } }); + const session = await getSession(); + const realm = ( + await globalFetcher<[any]>(`${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace('/realms/website', '')}/admin/realms`, { + headers: { Authorization: `Bearer ${session?.accessToken}` }, + }) + )[0]; + const adminEvents = await globalFetcher( + `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace('/realms/website', '')}/admin/realms/website/admin-events`, + { headers: { Authorization: `Bearer ${session?.accessToken}` } }, + ); + const userEvents = await globalFetcher( + `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace('/realms/website', '')}/admin/realms/website/events`, + { headers: { Authorization: `Bearer ${session?.accessToken}` } }, + ); + const clientStats = await globalFetcher( + `${process.env.NEXT_PUBLIC_KEYCLOAK_URL?.replace('/realms/website', '')}/admin/realms/website/client-session-stats`, + { headers: { Authorization: `Bearer ${session?.accessToken}` } }, + ); - return ( - - - SSO Configuration and Security - - - - Realm Info - Admin Events - User Events - Session Stats - + return ( + + + SSO Configuration and Security + + + + Realm Info + Admin Events + User Events + Session Stats + - - - {Object.keys(realm) - .map((key) => ( - - - {key}: {typeof realm[key] === "number" ? () : typeof realm[key] == "string"? realm[key]: {JSON.stringify(realm[key])}} - - - ))} - - - - - - - Time - Operation - Resource Type - Resource - - - - {adminEvents?.map((event) => ( - - {new Date(event.time).toUTCString()} - {event.operationType} - - {event.resourceType} - - - - {event.resourcePath} - - - - ))} - -
-
- - - - - Time - Operation - Client - User - - - - {userEvents?.map((event) => ( - - {new Date(event.time).toUTCString()} - {event.type} - - {event.clientId} - - {event.userId} - - ))} - -
-
- - - {clientStats?.map((client) => ( - - {client.clientId} - - Active: {" "} - - - - Offline: {" "} - - - - ))} - - -
-
- ); + + + {Object.keys(realm).map((key) => ( + + + {key}:{' '} + {typeof realm[key] === 'number' ? ( + + ) : typeof realm[key] == 'string' ? ( + realm[key] + ) : ( + {JSON.stringify(realm[key])} + )} + + + ))} + + + + + + + Time + Operation + Resource Type + Resource + + + + {adminEvents?.map((event) => ( + + {new Date(event.time).toUTCString()} + {event.operationType} + + {event.resourceType} + + + + {event.resourcePath} + + + + ))} + +
+
+ + + + + Time + Operation + Client + User + + + + {userEvents?.map((event) => ( + + {new Date(event.time).toUTCString()} + {event.type} + + {event.clientId} + + {event.userId} + + ))} + +
+
+ + + {clientStats?.map((client) => ( + + {client.clientId} + + Active: + + + Offline: + + + ))} + + +
+
+ ); } diff --git a/apps/dashboard/src/app/api/auth/[...nextauth]/route.ts b/apps/dashboard/src/app/api/auth/[...nextauth]/route.ts index bea7eaf3..76c1a111 100644 --- a/apps/dashboard/src/app/api/auth/[...nextauth]/route.ts +++ b/apps/dashboard/src/app/api/auth/[...nextauth]/route.ts @@ -1,7 +1,6 @@ -import { authOptions } from "@/util/auth"; -import NextAuth from "next-auth"; +import { authOptions } from '@/util/auth'; +import NextAuth from 'next-auth'; const handler = NextAuth(authOptions); export { handler as GET, handler as POST }; - diff --git a/apps/dashboard/src/app/auth/signin/page.tsx b/apps/dashboard/src/app/auth/signin/page.tsx index 2ab64f7e..03861855 100644 --- a/apps/dashboard/src/app/auth/signin/page.tsx +++ b/apps/dashboard/src/app/auth/signin/page.tsx @@ -1,23 +1,23 @@ -"use client" +'use client'; -import { signIn, useSession } from "next-auth/react"; +import { signIn, useSession } from 'next-auth/react'; -import { useRouter } from "next/navigation"; -import { useEffect } from "react"; +import { useRouter } from 'next/navigation'; +import { useEffect } from 'react'; export default function SigninPage() { - const router = useRouter(); - const { status } = useSession(); + const router = useRouter(); + const { status } = useSession(); - useEffect(() => { - if (status === "unauthenticated") { - console.log("No JWT"); - console.log(status); - void signIn("keycloak", { callbackUrl: "/",redirect:true }); - } else if (status === "authenticated") { - void router.push("/"); - } - }, [status,router]); + useEffect(() => { + if (status === 'unauthenticated') { + console.log('No JWT'); + console.log(status); + void signIn('keycloak', { callbackUrl: '/', redirect: true }); + } else if (status === 'authenticated') { + void router.push('/'); + } + }, [status, router]); - return

Redirecting...

; + return

Redirecting...

; } diff --git a/apps/dashboard/src/app/layout.tsx b/apps/dashboard/src/app/layout.tsx index 342be32b..87a64389 100644 --- a/apps/dashboard/src/app/layout.tsx +++ b/apps/dashboard/src/app/layout.tsx @@ -1,60 +1,53 @@ -import "@/styles/global.css"; -import "@mantine/charts/styles.css"; -import "@mantine/code-highlight/styles.css"; -import "@mantine/core/styles.css"; -import "@mantine/dates/styles.css"; -import "@mantine/notifications/styles.css"; -import "@mantine/nprogress/styles.css"; -import "@mantine/spotlight/styles.css"; -import "mantine-datatable/styles.layer.css"; +import '@/styles/global.css'; +import '@mantine/charts/styles.css'; +import '@mantine/code-highlight/styles.css'; +import '@mantine/core/styles.css'; +import '@mantine/dates/styles.css'; +import '@mantine/notifications/styles.css'; +import '@mantine/nprogress/styles.css'; +import '@mantine/spotlight/styles.css'; +import 'mantine-datatable/styles.layer.css'; -import { ColorSchemeScript, MantineProvider } from "@mantine/core"; +import { ColorSchemeScript, MantineProvider } from '@mantine/core'; -import AuthProvider from "@/components/AuthProvider"; -import SWRSetup from "@/components/core/SWRSetup"; -import AppLayout from "@/components/layout"; -import { getSession } from "@/util/auth"; -import { Notifications } from "@mantine/notifications"; -import { Inter } from "next/font/google"; -import localFont from "next/font/local"; +import AuthProvider from '@/components/AuthProvider'; +import SWRSetup from '@/components/core/SWRSetup'; +import AppLayout from '@/components/layout'; +import { getSession } from '@/util/auth'; +import { Notifications } from '@mantine/notifications'; +import { Inter } from 'next/font/google'; +import localFont from 'next/font/local'; export const interFont = Inter({ - subsets: ["latin"], - variable: "--font-inter", + subsets: ['latin'], + variable: '--font-inter', }); export const minecraftFont = localFont({ - src: "../../public/fonts/Minecraft.ttf", - weight: "100 900", - display: "swap", - style: "normal", - variable: "--font-minecraft", + src: '../../public/fonts/Minecraft.ttf', + weight: '100 900', + display: 'swap', + style: 'normal', + variable: '--font-minecraft', }); -export default async function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - const session = await getSession(); +export default async function RootLayout({ children }: { children: React.ReactNode }) { + const session = await getSession(); - return ( - - - - - - - - - - {children} - - - - - - ); + return ( + + + + + + + + + + {children} + + + + + + ); } diff --git a/apps/dashboard/src/app/me/connections/loading.tsx b/apps/dashboard/src/app/me/connections/loading.tsx index 06436647..0ef6dc19 100644 --- a/apps/dashboard/src/app/me/connections/loading.tsx +++ b/apps/dashboard/src/app/me/connections/loading.tsx @@ -1,22 +1,21 @@ -import { Box, Skeleton, Text, Title } from "@mantine/core"; +import { Box, Skeleton, Text, Title } from '@mantine/core'; export default async function Page() { - - return ( - - - Your Social Accounts - - - Loading... -
- Loading... -
- - Loading... -
- Loading... -
-
- ); + return ( + + + Your Social Accounts + + + Loading... +
+ Loading... +
+ + Loading... +
+ Loading... +
+
+ ); } diff --git a/apps/dashboard/src/app/me/connections/page.tsx b/apps/dashboard/src/app/me/connections/page.tsx index c0fd78ac..bd790505 100644 --- a/apps/dashboard/src/app/me/connections/page.tsx +++ b/apps/dashboard/src/app/me/connections/page.tsx @@ -1,20 +1,20 @@ import { Box, Title } from '@mantine/core'; -import { SocialAccountStack } from "@/components/data/SocialAccount"; -import { getUser } from "@/hooks/useUser"; -import { KeycloakUser } from "@/types/User"; -import { authedFetcher } from "@/util/data"; +import { SocialAccountStack } from '@/components/data/SocialAccount'; +import { getUser } from '@/hooks/useUser'; +import { KeycloakUser } from '@/types/User'; +import { authedFetcher } from '@/util/data'; export default async function Page() { - const user = await getUser(); - const data = await authedFetcher(`/users/${user.id}/kc`); + const user = await getUser(); + const data = await authedFetcher(`/users/${user.id}/kc`); - return ( - - - Your Social Accounts - - - - ); + return ( + + + Your Social Accounts + + + + ); } diff --git a/apps/dashboard/src/app/me/everything/loading.tsx b/apps/dashboard/src/app/me/everything/loading.tsx index e1e5b861..7ec9f8c7 100644 --- a/apps/dashboard/src/app/me/everything/loading.tsx +++ b/apps/dashboard/src/app/me/everything/loading.tsx @@ -1,265 +1,220 @@ import { - Alert, - Box, - Button, - Card, - Flex, - Stack, - Tabs, - TabsList, - TabsPanel, - TabsTab, - Text, - Title, - rem, -} from "@mantine/core"; + Alert, + Box, + Button, + Card, + Flex, + rem, + Stack, + Tabs, + TabsList, + TabsPanel, + TabsTab, + Text, + Title, +} from '@mantine/core'; import { - IconBrandMinecraft, - IconCalendar, - IconCheck, - IconChevronRight, - IconCode, - IconDeviceWatch, - IconId, - IconInfoCircle, - IconLicense, - IconMail, - IconMailCheck, - IconSocial, - IconStatusChange, - IconTable, - IconUser, - IconUsers, -} from "@tabler/icons-react"; + IconBrandMinecraft, + IconCalendar, + IconCheck, + IconChevronRight, + IconCode, + IconDeviceWatch, + IconId, + IconInfoCircle, + IconLicense, + IconMail, + IconMailCheck, + IconSocial, + IconTable, + IconUser, + IconUsers, +} from '@tabler/icons-react'; -import { getUser } from "@/hooks/useUser"; -import { KeycloakUser } from "@/types/User"; -import { getSession } from "@/util/auth"; -import { authedFetcher } from "@/util/data"; -import { CodeHighlight } from "@mantine/code-highlight"; -import Link from "next/link"; +import { getUser } from '@/hooks/useUser'; +import { KeycloakUser } from '@/types/User'; +import { getSession } from '@/util/auth'; +import { authedFetcher } from '@/util/data'; +import { CodeHighlight } from '@mantine/code-highlight'; +import Link from 'next/link'; export default async function Page() { - const user = await getUser(); - const session = await getSession(); - const data = await authedFetcher(`/users/${user.id}/kc`); + const user = await getUser(); + const session = await getSession(); + const data = await authedFetcher(`/users/${user.id}/kc`); - return ( - - - Your Data - - } - > - On this page, you will find all data and user information we have stored - of your account. This is meant for debugging purposes. If you wish to - remove specific information, please message us on Discord. - + return ( + + + Your Data + + }> + On this page, you will find all data and user information we have stored of your account. This is meant for + debugging purposes. If you wish to remove specific information, please message us on Discord. + - - - - } - > - Pretty - - - } - > - Raw - - + + + }> + Pretty + + }> + Raw + + - - - - - - - User Id: {user.id} - - - - - - - - Single Sign On Id: {user.ssoId} - - - - - - - - Username: {user.username} - - - - - - - - E-Mail Address: {user.email} - - - - - - - - E-Mail Status:{" "} - {user.emailVerified ? "Verified" : "Unverified"} - - - - - - - - Minecraft Username: {data.minecraft} - - - + + + + + + + User Id: {user.id} + + + + + + + + Single Sign On Id: {user.ssoId} + + + + + + + + Username: {user.username} + + + + + + + + E-Mail Address: {user.email} + + + + + + + + E-Mail Status: {user.emailVerified ? 'Verified' : 'Unverified'} + + + + + + + + Minecraft Username: {data.minecraft} + + + - - Authentication Data - - - - - - Account Created:{" "} - {new Date(data.createdTimestamp).toUTCString()} - - - - - - - - Account Status: {data.enabled ? "Enabled" : "Disabled"} - - - - - - - - TOTP: {data.totp ? "Set" : "Not Set"} - - - - - - - - Linked Accounts:{" "} - {data.federatedIdentities - .map((idp) => idp.identityProvider) - .join(", ")} - - - - - - - - Manage Group Membership:{" "} - {data.access.manageGroupMembership ? "Yes" : "No"} - - - - - - - - Can Impersonate:{" "} - {data.access.impersonate ? "Yes" : "No"} - - - - - - - - Manage Self: {data.access.manage ? "Yes" : "No"} - - - - - - - - Map Roles: {data.access.mapRoles ? "Yes" : "No"} - - - - - - - - View Self: {data.access.view ? "Yes" : "No"} - - - - + + Authentication Data + + + + + + Account Created: {new Date(data.createdTimestamp).toUTCString()} + + + + + + + + Account Status: {data.enabled ? 'Enabled' : 'Disabled'} + + + + + + + + TOTP: {data.totp ? 'Set' : 'Not Set'} + + + + + + + + Linked Accounts: {data.federatedIdentities.map((idp) => idp.identityProvider).join(', ')} + + + + + + + + Manage Group Membership: {data.access.manageGroupMembership ? 'Yes' : 'No'} + + + + + + + + Can Impersonate: {data.access.impersonate ? 'Yes' : 'No'} + + + + + + + + Manage Self: {data.access.manage ? 'Yes' : 'No'} + + + + + + + + Map Roles: {data.access.mapRoles ? 'Yes' : 'No'} + + + + + + + + View Self: {data.access.view ? 'Yes' : 'No'} + + + + - - Other Data - - - - + + Other Data + + + + - - User Data - - - Authentication Data - - - - Session Data - - - - - - ); + + User Data + + + Authentication Data + + + + Session Data + + + + + + ); } diff --git a/apps/dashboard/src/app/me/everything/page.tsx b/apps/dashboard/src/app/me/everything/page.tsx index 7d5ba6f4..7ec9f8c7 100644 --- a/apps/dashboard/src/app/me/everything/page.tsx +++ b/apps/dashboard/src/app/me/everything/page.tsx @@ -1,179 +1,220 @@ import { - Alert, - Box, - Button, - Card, - Flex, - Stack, - Tabs, - TabsList, - TabsPanel, - TabsTab, - Text, - Title, - rem -} from "@mantine/core"; -import { IconBrandMinecraft, IconCalendar, IconCheck, IconChevronRight, IconCode, IconDeviceWatch, IconId, IconInfoCircle, IconLicense, IconMail, IconMailCheck, IconSocial, IconStatusChange, IconTable, IconUser, IconUsers } from "@tabler/icons-react"; + Alert, + Box, + Button, + Card, + Flex, + rem, + Stack, + Tabs, + TabsList, + TabsPanel, + TabsTab, + Text, + Title, +} from '@mantine/core'; +import { + IconBrandMinecraft, + IconCalendar, + IconCheck, + IconChevronRight, + IconCode, + IconDeviceWatch, + IconId, + IconInfoCircle, + IconLicense, + IconMail, + IconMailCheck, + IconSocial, + IconTable, + IconUser, + IconUsers, +} from '@tabler/icons-react'; -import { getUser } from "@/hooks/useUser"; -import { KeycloakUser } from "@/types/User"; -import { getSession } from "@/util/auth"; -import { authedFetcher } from "@/util/data"; +import { getUser } from '@/hooks/useUser'; +import { KeycloakUser } from '@/types/User'; +import { getSession } from '@/util/auth'; +import { authedFetcher } from '@/util/data'; import { CodeHighlight } from '@mantine/code-highlight'; -import Link from "next/link"; +import Link from 'next/link'; export default async function Page() { - const user = await getUser(); - const session = await getSession(); - const data = await authedFetcher(`/users/${user.id}/kc`); + const user = await getUser(); + const session = await getSession(); + const data = await authedFetcher(`/users/${user.id}/kc`); + return ( + + + Your Data + + }> + On this page, you will find all data and user information we have stored of your account. This is meant for + debugging purposes. If you wish to remove specific information, please message us on Discord. + - return ( - - - Your Data - - } - > - On this page, you will find all data and user information we have stored - of your account. This is meant for debugging purposes. If you wish to - remove specific information, please message us on Discord. - + + + }> + Pretty + + }> + Raw + + - - - - } - > - Pretty - - - } - > - Raw - - + + + + + + + User Id: {user.id} + + + + + + + + Single Sign On Id: {user.ssoId} + + + + + + + + Username: {user.username} + + + + + + + + E-Mail Address: {user.email} + + + + + + + + E-Mail Status: {user.emailVerified ? 'Verified' : 'Unverified'} + + + + + + + + Minecraft Username: {data.minecraft} + + + - - - - - - User Id: {user.id} - - - - - - Single Sign On Id: {user.ssoId} - - - - - - Username: {user.username} - - - - - - E-Mail Address: {user.email} - - - - - - E-Mail Status: {user.emailVerified?"Verified":"Unverified"} - - - - - - Minecraft Username: {data.minecraft} - - + + Authentication Data + + + + + + Account Created: {new Date(data.createdTimestamp).toUTCString()} + + + + + + + + Account Status: {data.enabled ? 'Enabled' : 'Disabled'} + + + + + + + + TOTP: {data.totp ? 'Set' : 'Not Set'} + + + + + + + + Linked Accounts: {data.federatedIdentities.map((idp) => idp.identityProvider).join(', ')} + + + + + + + + Manage Group Membership: {data.access.manageGroupMembership ? 'Yes' : 'No'} + + + + + + + + Can Impersonate: {data.access.impersonate ? 'Yes' : 'No'} + + + + + + + + Manage Self: {data.access.manage ? 'Yes' : 'No'} + + + + + + + + Map Roles: {data.access.mapRoles ? 'Yes' : 'No'} + + + + + + + + View Self: {data.access.view ? 'Yes' : 'No'} + + + + - Authentication Data - - - - Account Created: {new Date(data.createdTimestamp).toUTCString()} - - - - - - Account Status: {data.enabled?"Enabled":"Disabled"} - - - - - - TOTP: {data.totp?"Set":"Not Set"} - - - - - - Linked Accounts: {data.federatedIdentities.map((idp) => idp.identityProvider).join(", ")} - - - - - - Manage Group Membership: {data.access.manageGroupMembership?"Yes":"No"} - - - - - - Can Impersonate: {data.access.impersonate?"Yes":"No"} - - - - - - Manage Self: {data.access.manage?"Yes":"No"} - - - - - - Map Roles: {data.access.mapRoles?"Yes":"No"} - - - - - - View Self: {data.access.view?"Yes":"No"} - - - - - Other Data - - - + + Other Data + + + + - - User Data - - Authentication Data - - Session Data - - - - - ); + + User Data + + + Authentication Data + + + + Session Data + + + + + + ); } diff --git a/apps/dashboard/src/app/me/sessions/loading.tsx b/apps/dashboard/src/app/me/sessions/loading.tsx index 11af7ccf..e48bd3b2 100644 --- a/apps/dashboard/src/app/me/sessions/loading.tsx +++ b/apps/dashboard/src/app/me/sessions/loading.tsx @@ -1,21 +1,21 @@ -import { Box, Skeleton, Text, Title } from "@mantine/core"; +import { Box, Skeleton, Text, Title } from '@mantine/core'; export default async function Page() { - return ( - - - Active Sessions - - - Loading... -
- Loading... -
- - Loading... -
- Loading... -
-
- ); + return ( + + + Active Sessions + + + Loading... +
+ Loading... +
+ + Loading... +
+ Loading... +
+
+ ); } diff --git a/apps/dashboard/src/app/me/sessions/page.tsx b/apps/dashboard/src/app/me/sessions/page.tsx index aa6aeabe..5a609525 100644 --- a/apps/dashboard/src/app/me/sessions/page.tsx +++ b/apps/dashboard/src/app/me/sessions/page.tsx @@ -1,74 +1,65 @@ -import { - Badge, - Box, - Card, - Flex, - Group, - Stack, - Text, - Title, -} from "@mantine/core"; +import { Badge, Box, Card, Flex, Group, Stack, Text, Title } from '@mantine/core'; -import { getUser } from "@/hooks/useUser"; -import { KeycloakUser } from "@/types/User"; -import { authedFetcher } from "@/util/data"; -import { IconDevices } from "@tabler/icons-react"; +import { getUser } from '@/hooks/useUser'; +import { KeycloakUser } from '@/types/User'; +import { authedFetcher } from '@/util/data'; +import { IconDevices } from '@tabler/icons-react'; export default async function Page() { - const user = await getUser(); - const data = await authedFetcher(`/users/${user.id}/kc`); + const user = await getUser(); + const data = await authedFetcher(`/users/${user.id}/kc`); - return ( - - - Active Sessions - - - {data.sessions.map((session) => ( - - ))} - - - ); + return ( + + + Active Sessions + + + {data.sessions.map((session) => ( + + ))} + + + ); } -function UserSession({ session }: { session: KeycloakUser["sessions"][0] }) { - return ( - - - - - - Session #{session.id.split("-")[0]} {" "} - - {Object.values(session.clients).map((client) => ( - - {client} - - ))} - - +function UserSession({ session }: { session: KeycloakUser['sessions'][0] }) { + return ( + + + + + + Session #{session.id.split('-')[0]} {' '} + + {Object.values(session.clients).map((client) => ( + + {client} + + ))} + + - - Last Active: - {new Date(session.lastAccess).toLocaleString("en-GB", { - day: "2-digit", - month: "2-digit", - year: "2-digit", - hour: "2-digit", - minute: "2-digit", - })} - , Started at: - {new Date(session.start).toLocaleString("en-GB", { - day: "2-digit", - month: "2-digit", - year: "2-digit", - hour: "2-digit", - minute: "2-digit", - })} - - - - - ); + + Last Active: + {new Date(session.lastAccess).toLocaleString('en-GB', { + day: '2-digit', + month: '2-digit', + year: '2-digit', + hour: '2-digit', + minute: '2-digit', + })} + , Started at: + {new Date(session.start).toLocaleString('en-GB', { + day: '2-digit', + month: '2-digit', + year: '2-digit', + hour: '2-digit', + minute: '2-digit', + })} + + + + + ); } diff --git a/apps/dashboard/src/app/page.tsx b/apps/dashboard/src/app/page.tsx index 3e14124c..1e43c720 100644 --- a/apps/dashboard/src/app/page.tsx +++ b/apps/dashboard/src/app/page.tsx @@ -1,3 +1,3 @@ export default function Page() { - return "home"; + return 'home'; } diff --git a/apps/dashboard/src/components/AuthProvider.tsx b/apps/dashboard/src/components/AuthProvider.tsx index 15673253..16aa48f8 100644 --- a/apps/dashboard/src/components/AuthProvider.tsx +++ b/apps/dashboard/src/components/AuthProvider.tsx @@ -1,14 +1,8 @@ -"use client"; +'use client'; -import type { Session } from "next-auth"; -import { SessionProvider } from "next-auth/react"; +import type { Session } from 'next-auth'; +import { SessionProvider } from 'next-auth/react'; -export default function AuthProvider({ - session, - children, -}: { - session: Session | null; - children: React.ReactNode; -}) { - return {children}; +export default function AuthProvider({ session, children }: { session: Session | null; children: React.ReactNode }) { + return {children}; } diff --git a/apps/dashboard/src/components/ProtectionProvider.tsx b/apps/dashboard/src/components/ProtectionProvider.tsx index 0d4cb33d..323bde7c 100644 --- a/apps/dashboard/src/components/ProtectionProvider.tsx +++ b/apps/dashboard/src/components/ProtectionProvider.tsx @@ -1,24 +1,18 @@ -"use client"; +'use client'; -import { redirect, usePathname } from "next/navigation"; +import { redirect, usePathname } from 'next/navigation'; -import path from "path"; -import { useSession } from "next-auth/react"; +import { useSession } from 'next-auth/react'; -export default function ProtectionProvider({ - children, -}: { - children: React.ReactNode; -}) { - const pathname = usePathname(); - const session = useSession(); - const isProtected = pathname.startsWith("/am/"); - const isStaff = session.data?.user.realm_access.roles.includes("bte_staff"); +export default function ProtectionProvider({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + const session = useSession(); + const isProtected = pathname.startsWith('/am/'); + const isStaff = session.data?.user.realm_access.roles.includes('bte_staff'); - if (isProtected && !isStaff) { - redirect("/") - } + if (isProtected && !isStaff) { + redirect('/'); + } - - return children; + return children; } diff --git a/apps/dashboard/src/components/core/Anchor.tsx b/apps/dashboard/src/components/core/Anchor.tsx index 6e56ead5..fb8e3e04 100644 --- a/apps/dashboard/src/components/core/Anchor.tsx +++ b/apps/dashboard/src/components/core/Anchor.tsx @@ -1,13 +1,11 @@ -import { AnchorProps, Anchor as MantineAnchor } from "@mantine/core"; -import Link, { LinkProps } from "next/link"; +import { Anchor as MantineAnchor, AnchorProps } from '@mantine/core'; +import Link, { LinkProps } from 'next/link'; /** * Default Anchor component with direct usage of Next.js Link */ export default function Anchor( - props: AnchorProps & - LinkProps & - React.AnchorHTMLAttributes & { children: any }, + props: AnchorProps & LinkProps & React.AnchorHTMLAttributes & { children: any }, ) { - return ; + return ; } diff --git a/apps/dashboard/src/components/core/Banner.tsx b/apps/dashboard/src/components/core/Banner.tsx index ba8fbb3a..1430fad6 100644 --- a/apps/dashboard/src/components/core/Banner.tsx +++ b/apps/dashboard/src/components/core/Banner.tsx @@ -1,29 +1,24 @@ -import { Button, Image, Text, TextInput, Title } from "@mantine/core"; +import { Image, Text, Title } from '@mantine/core'; -import classes from "@/styles/Banner.module.css"; +import classes from '@/styles/Banner.module.css'; -export function Banner(props: { - title: string; - subtitle: string; - children: any; - image: any; -}) { - return ( -
-
- {props.title} - - {props.subtitle} - - {typeof props.children == "string" ? ( - - {props.children} - - ) : ( - props.children - )} -
- Banner Image -
- ); +export function Banner(props: { title: string; subtitle: string; children: any; image: any }) { + return ( +
+
+ {props.title} + + {props.subtitle} + + {typeof props.children == 'string' ? ( + + {props.children} + + ) : ( + props.children + )} +
+ Banner Image +
+ ); } diff --git a/apps/dashboard/src/components/core/DynamicIcon.tsx b/apps/dashboard/src/components/core/DynamicIcon.tsx index 4fdb97f2..7fcabf23 100644 --- a/apps/dashboard/src/components/core/DynamicIcon.tsx +++ b/apps/dashboard/src/components/core/DynamicIcon.tsx @@ -1,21 +1,21 @@ -import { Icon, IconProps, icons } from "@tabler/icons-react"; -import { ForwardRefExoticComponent, RefAttributes } from "react"; +import { Icon, IconProps, icons } from '@tabler/icons-react'; +import { ForwardRefExoticComponent, RefAttributes } from 'react'; export default function DynamicIcon({ - icon, - fallback: Fallback, + icon, + fallback: Fallback, }: { - icon: string; - fallback?: ForwardRefExoticComponent>; + icon: string; + fallback?: ForwardRefExoticComponent>; }) { - const Icon = icons[icon as keyof typeof icons]; - if (isValidIconName(icon)) { - return ; - } + const Icon = icons[icon as keyof typeof icons]; + if (isValidIconName(icon)) { + return ; + } - return Fallback ? : <>; + return Fallback ? : <>; } function isValidIconName(icon: string): icon is keyof typeof icons { - return icon in icons; + return icon in icons; } diff --git a/apps/dashboard/src/components/core/LinkButton.tsx b/apps/dashboard/src/components/core/LinkButton.tsx index 5e398b5e..a6787bc8 100644 --- a/apps/dashboard/src/components/core/LinkButton.tsx +++ b/apps/dashboard/src/components/core/LinkButton.tsx @@ -1,13 +1,9 @@ -import { Button, ButtonProps } from "@mantine/core"; -import Link, { LinkProps } from "next/link"; +import { Button, ButtonProps } from '@mantine/core'; +import Link, { LinkProps } from 'next/link'; /** * Default Button component with direct usage of Next.js Link */ -export default function LinkButton( - props: ButtonProps & - React.AnchorHTMLAttributes & - LinkProps, -) { - return - )} - - - ); + return ( + + + + + + {capitalize(identity?.identityProvider || '')} + + {!isLinked ? ( + + Not Linked + + ) : ( + {identity.userName.replace('#0', '')} + )} + + {!isLinked && ( + + )} + + + ); } export function SocialAccountStack({ - identities, - withUnlinked = false, + identities, + withUnlinked = false, }: { - identities: KeycloakUser["federatedIdentities"]; - withUnlinked?: boolean; + identities: KeycloakUser['federatedIdentities']; + withUnlinked?: boolean; }) { - const linkedProviders = identities.map( - (identity) => identity.identityProvider - ); - const allProviders = withUnlinked - ? availableProviders.map((provider) => { - const identity = identities.find( - (id) => id.identityProvider === provider - ); - if (identity) return { ...identity, isLinked: true }; - return { - identityProvider: provider, - userId: "", - userName: "", - isLinked: false, - }; - }) - : identities.map((identity) => ({ ...identity, isLinked: true })); + const linkedProviders = identities.map((identity) => identity.identityProvider); + const allProviders = withUnlinked + ? availableProviders.map((provider) => { + const identity = identities.find((id) => id.identityProvider === provider); + if (identity) return { ...identity, isLinked: true }; + return { + identityProvider: provider, + userId: '', + userName: '', + isLinked: false, + }; + }) + : identities.map((identity) => ({ ...identity, isLinked: true })); - return ( - - {allProviders.map((identity) => ( - - ))} - - ); + return ( + + {allProviders.map((identity) => ( + + ))} + + ); } function capitalize(s: string) { - return s.charAt(0).toUpperCase() + s.slice(1); + return s.charAt(0).toUpperCase() + s.slice(1); } function getIcon(name: Provider) { - switch (name) { - case "discord": - return IconBrandDiscord; - case "github": - return IconBrandGithub; - default: - return IconWorld; - } + switch (name) { + case 'discord': + return IconBrandDiscord; + case 'github': + return IconBrandGithub; + default: + return IconWorld; + } } async function hash(string: string) { - const encoder = new TextEncoder(); - const data = encoder.encode(string); - const hashBuffer = await crypto.subtle.digest("SHA-256", data); - const hashArray = Array.from(new Uint8Array(hashBuffer)); - const base64UrlHash = btoa(String.fromCharCode.apply(null, hashArray)) - .replace(/\+/g, "-") - .replace(/\//g, "_") - .replace(/=+$/, ""); - return base64UrlHash; + const encoder = new TextEncoder(); + const data = encoder.encode(string); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const base64UrlHash = btoa(String.fromCharCode.apply(null, hashArray)) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + return base64UrlHash; } diff --git a/apps/dashboard/src/components/data/StatusBadge.tsx b/apps/dashboard/src/components/data/StatusBadge.tsx index 40217194..9747b7f7 100644 --- a/apps/dashboard/src/components/data/StatusBadge.tsx +++ b/apps/dashboard/src/components/data/StatusBadge.tsx @@ -1,129 +1,84 @@ -import { Badge, BadgeProps, rem } from "@mantine/core"; +import { Badge, BadgeProps, rem } from '@mantine/core'; -import { IconConfetti } from "@tabler/icons-react"; +import { IconConfetti } from '@tabler/icons-react'; -export default function StatusBadge({ - status, - ...props -}: { status: string } & BadgeProps) { - switch (status.toLowerCase()) { - // Application Status - case "send": - return ( - - Needs Review - - ); - case "accepted": - return ( - - Accepted - - ); - case "trial": - return ( - - Trial - - ); - case "accepted": - return ( - - Accepted - - ); - case "declined": - return ( - - Rejected - - ); +export default function StatusBadge({ status, ...props }: { status: string } & BadgeProps) { + switch (status.toLowerCase()) { + // Application Status + case 'send': + return ( + + Needs Review + + ); + case 'accepted': + return ( + + Accepted + + ); + case 'trial': + return ( + + Trial + + ); + case 'accepted': + return ( + + Accepted + + ); + case 'declined': + return ( + + Rejected + + ); - // Claim Status - case "building": - return ( - - Under Construction - - ); - case "finished": - return ( - - } - {...props} - > - Finished - - ); + // Claim Status + case 'building': + return ( + + Under Construction + + ); + case 'finished': + return ( + } + {...props} + > + Finished + + ); - // Generic Status - case "active": - return ( - - Active - - ); - case "inactive": - return ( - - Inactive - - ); - case "on": - return ( - - On - - ); - case "off": - return ( - - Off - - ); - } + // Generic Status + case 'active': + return ( + + Active + + ); + case 'inactive': + return ( + + Inactive + + ); + case 'on': + return ( + + On + + ); + case 'off': + return ( + + Off + + ); + } } diff --git a/apps/dashboard/src/components/input/CheckboxCard.tsx b/apps/dashboard/src/components/input/CheckboxCard.tsx index de1e20f4..0a039c7c 100644 --- a/apps/dashboard/src/components/input/CheckboxCard.tsx +++ b/apps/dashboard/src/components/input/CheckboxCard.tsx @@ -1,38 +1,35 @@ -import { Checkbox, Text, UnstyledButton } from "@mantine/core"; +import { Checkbox, Text, UnstyledButton } from '@mantine/core'; -import classes from "@/styles/CheckboxCard.module.css"; +import classes from '@/styles/CheckboxCard.module.css'; export function CheckboxCard(props: { - title: string; - subtitle: string; - onChange: (value: boolean) => void; - checked: boolean; - disabled?: boolean; + title: string; + subtitle: string; + onChange: (value: boolean) => void; + checked: boolean; + disabled?: boolean; }) { - return ( - !props.disabled && props.onChange(!props.checked)} - className={classes.button} - > - {}} - tabIndex={-1} - size="md" - mr="xl" - styles={{ input: { cursor: "pointer" } }} - aria-hidden - disabled={props.disabled} - /> + return ( + !props.disabled && props.onChange(!props.checked)} className={classes.button}> + {}} + tabIndex={-1} + size="md" + mr="xl" + styles={{ input: { cursor: 'pointer' } }} + aria-hidden + disabled={props.disabled} + /> -
- - {props.title} - - - {props.subtitle} - -
-
- ); +
+ + {props.title} + + + {props.subtitle} + +
+
+ ); } diff --git a/apps/dashboard/src/components/input/UserMenu.tsx b/apps/dashboard/src/components/input/UserMenu.tsx index f67c7b7e..cdf5f535 100644 --- a/apps/dashboard/src/components/input/UserMenu.tsx +++ b/apps/dashboard/src/components/input/UserMenu.tsx @@ -1,66 +1,49 @@ -import { - Menu, - MenuDropdown, - MenuItem, - MenuTarget, - useMantineColorScheme, -} from "@mantine/core"; -import { - IconFileSearch, - IconLogout, - IconMap, - IconSearch, - IconSettings, - IconWorld, -} from "@tabler/icons-react"; +import { Menu, MenuDropdown, MenuItem, MenuTarget, useMantineColorScheme } from '@mantine/core'; +import { IconLogout, IconMap, IconSettings, IconWorld } from '@tabler/icons-react'; -import { signOut } from "next-auth/react"; -import Link from "next/link"; +import { signOut } from 'next-auth/react'; +import Link from 'next/link'; const UserMenu = ({ children }: { children: any }) => { - const { colorScheme, toggleColorScheme } = useMantineColorScheme(); + const { colorScheme, toggleColorScheme } = useMantineColorScheme(); - return ( - - {children} - - } - > - BuildTheEarth - - } - > - Map - - } - > - Settings - - - } - color="red" - onClick={() => { - window.localStorage.removeItem("auth-permission-state"); - signOut({ callbackUrl: "/", redirect: true }); - }} - > - Sign out - - - - ); + return ( + + {children} + + } + > + BuildTheEarth + + } + > + Map + + }> + Settings + + + } + color="red" + onClick={() => { + window.localStorage.removeItem('auth-permission-state'); + signOut({ callbackUrl: '/', redirect: true }); + }} + > + Sign out + + + + ); }; export default UserMenu; diff --git a/apps/dashboard/src/components/layout/header/HeaderProfile.tsx b/apps/dashboard/src/components/layout/header/HeaderProfile.tsx index f2879097..2ac8e44c 100644 --- a/apps/dashboard/src/components/layout/header/HeaderProfile.tsx +++ b/apps/dashboard/src/components/layout/header/HeaderProfile.tsx @@ -1,112 +1,82 @@ -"use client"; +'use client'; +import { Avatar, Button, Menu, MenuDropdown, MenuItem, MenuTarget, useMantineColorScheme } from '@mantine/core'; import { - Avatar, - Button, - Menu, - MenuDropdown, - MenuItem, - MenuTarget, - useMantineColorScheme, -} from "@mantine/core"; -import { - IconChevronDown, - IconLogout, - IconMap, - IconMoonStars, - IconSettings, - IconSun, - IconWorld, -} from "@tabler/icons-react"; -import { signOut, useSession } from "next-auth/react"; -import { redirect, usePathname } from "next/navigation"; + IconChevronDown, + IconLogout, + IconMap, + IconMoonStars, + IconSettings, + IconSun, + IconWorld, +} from '@tabler/icons-react'; +import { signOut, useSession } from 'next-auth/react'; +import { redirect, usePathname } from 'next/navigation'; -import Link from "next/link"; +import Link from 'next/link'; const HeaderProfile = () => { - const { colorScheme, toggleColorScheme } = useMantineColorScheme(); - const pathname = usePathname(); - const session = useSession(); + const { colorScheme, toggleColorScheme } = useMantineColorScheme(); + const pathname = usePathname(); + const session = useSession(); - if (session.status === "loading" ) return null; - if (session.status === "unauthenticated") { - if (pathname !== "/auth/signin") { - redirect("/auth/signin"); - } - return null; - } - if(!session.data) return null; + if (session.status === 'loading') return null; + if (session.status === 'unauthenticated') { + if (pathname !== '/auth/signin') { + redirect('/auth/signin'); + } + return null; + } + if (!session.data) return null; - return ( - - - - - - } - > - BuildTheEarth - - } - > - Claim Map - - } - > - Settings - - - Quick Actions - - ) : ( - - ) - } - onClick={() => toggleColorScheme()} - > - {colorScheme === "dark" ? "Light Mode" : "Dark Mode"} - + return ( + + + + + + }> + BuildTheEarth + + }> + Claim Map + + }> + Settings + + + Quick Actions + : } + onClick={() => toggleColorScheme()} + > + {colorScheme === 'dark' ? 'Light Mode' : 'Dark Mode'} + - - } - color="red" - onClick={() => { - signOut({ redirect: true, callbackUrl: "/" }); - }} - > - Sign out - - - - ); + + } + color="red" + onClick={() => { + signOut({ redirect: true, callbackUrl: '/' }); + }} + > + Sign out + + + + ); }; export default HeaderProfile; diff --git a/apps/dashboard/src/components/layout/header/index.tsx b/apps/dashboard/src/components/layout/header/index.tsx index 4d943803..a0b817b8 100644 --- a/apps/dashboard/src/components/layout/header/index.tsx +++ b/apps/dashboard/src/components/layout/header/index.tsx @@ -1,39 +1,27 @@ -import { AppShellHeader, Group, Text } from "@mantine/core"; +import { AppShellHeader, Group, Text } from '@mantine/core'; -import Image from "next/image"; -import HeaderProfile from "./HeaderProfile"; +import Image from 'next/image'; +import HeaderProfile from './HeaderProfile'; export interface Header {} const Header = () => { - return ( - - - - Logo - - MyBuildTheEarth - - + return ( + + + + Logo + + MyBuildTheEarth + + - - - - - - ); + + + + + + ); }; export default Header; diff --git a/apps/dashboard/src/components/layout/index.tsx b/apps/dashboard/src/components/layout/index.tsx index 6f04f2cf..7b1ce276 100644 --- a/apps/dashboard/src/components/layout/index.tsx +++ b/apps/dashboard/src/components/layout/index.tsx @@ -1,47 +1,45 @@ -import { AppShell, AppShellMain, Box } from "@mantine/core"; +import { AppShell, AppShellMain, Box } from '@mantine/core'; -import { getSession } from "@/util/auth"; -import ProtectionProvider from "../ProtectionProvider"; -import Header from "./header"; -import { default as Navbar } from "./navbar"; +import { getSession } from '@/util/auth'; +import ProtectionProvider from '../ProtectionProvider'; +import Header from './header'; +import { default as Navbar } from './navbar'; export interface LayoutProps { - children: React.ReactNode; + children: React.ReactNode; } /** * Root layout of Pages */ export default async function AppLayout(props: LayoutProps) { - const session = await getSession(); - const isStaff = session?.user.realm_access.roles.includes("bte_staff"); + const session = await getSession(); + const isStaff = session?.user.realm_access.roles.includes('bte_staff'); - return ( - - + return ( + + -
+
- - - - {props.children} - - - - - ); + + + {props.children} + + + + ); } diff --git a/apps/dashboard/src/components/layout/navbar/NavLink.tsx b/apps/dashboard/src/components/layout/navbar/NavLink.tsx index 7f4c8fca..461ccd76 100644 --- a/apps/dashboard/src/components/layout/navbar/NavLink.tsx +++ b/apps/dashboard/src/components/layout/navbar/NavLink.tsx @@ -1,64 +1,64 @@ -"use client"; +'use client'; import { - IconChartPie, - IconDeviceDesktop, - IconForms, - IconHome, - IconPlugConnected, - IconPolygon, - IconQuestionMark, - IconSettings, - IconUsersGroup, -} from "@tabler/icons-react"; + IconChartPie, + IconDeviceDesktop, + IconForms, + IconHome, + IconPlugConnected, + IconPolygon, + IconQuestionMark, + IconSettings, + IconUsersGroup, +} from '@tabler/icons-react'; -import classes from "@/styles/Navbar.module.css"; -import { Anchor } from "@mantine/core"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; +import classes from '@/styles/Navbar.module.css'; +import { Anchor } from '@mantine/core'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; export interface NavLink { - label: string; - link: string; - icon: string; + label: string; + link: string; + icon: string; } export default function Navbar(props: NavLink) { - const pathname = usePathname(); - const Icon = getIcon(props.icon); - return ( - - - {props.label} - - ); + const pathname = usePathname(); + const Icon = getIcon(props.icon); + return ( + + + {props.label} + + ); } function getIcon(name: string) { - switch (name) { - case "Home": - return IconHome; - case "UsersGroup": - return IconUsersGroup; - case "Forms": - return IconForms; - case "Polygon": - return IconPolygon; - case "ChartPie": - return IconChartPie; - case "PlugConnected": - return IconPlugConnected; - case "DeviceDesktop": - return IconDeviceDesktop; - case "Settings": - return IconSettings; - default: - return IconQuestionMark; - } + switch (name) { + case 'Home': + return IconHome; + case 'UsersGroup': + return IconUsersGroup; + case 'Forms': + return IconForms; + case 'Polygon': + return IconPolygon; + case 'ChartPie': + return IconChartPie; + case 'PlugConnected': + return IconPlugConnected; + case 'DeviceDesktop': + return IconDeviceDesktop; + case 'Settings': + return IconSettings; + default: + return IconQuestionMark; + } } diff --git a/apps/dashboard/src/components/layout/navbar/index.tsx b/apps/dashboard/src/components/layout/navbar/index.tsx index b934c981..0b5dd806 100644 --- a/apps/dashboard/src/components/layout/navbar/index.tsx +++ b/apps/dashboard/src/components/layout/navbar/index.tsx @@ -1,34 +1,31 @@ -"use server" +'use server'; -import { AppShellNavbar, Divider, Stack } from "@mantine/core"; +import { AppShellNavbar, Divider, Stack } from '@mantine/core'; -import { navLinks } from "@/util/links"; -import NavLink from "./NavLink"; +import { navLinks } from '@/util/links'; +import NavLink from './NavLink'; export interface Navbar { - displayProtected?: boolean; + displayProtected?: boolean; } /** * Main Navbar */ export default async function Navbar(props: Navbar) { - - const allowedLinks = navLinks.filter((link) => props.displayProtected || !link.protected); + const allowedLinks = navLinks.filter((link) => props.displayProtected || !link.protected); - const links = allowedLinks.map((item) => - item.divider ? ( - - ) : ( - - ) - ); + const links = allowedLinks.map((item) => + item.divider ? ( + + ) : ( + + ), + ); - return ( - - - {links} - - - ); + return ( + + {links} + + ); } diff --git a/apps/dashboard/src/hooks/useAccessToken.ts b/apps/dashboard/src/hooks/useAccessToken.ts index 5d2bc15e..b5cb570f 100644 --- a/apps/dashboard/src/hooks/useAccessToken.ts +++ b/apps/dashboard/src/hooks/useAccessToken.ts @@ -1,12 +1,12 @@ -import { useSession } from "next-auth/react"; +import { useSession } from 'next-auth/react'; export const useAccessToken = () => { - const session = useSession(); + const session = useSession(); - const token = { - accessToken: session.data?.accessToken, - isLoggedIn: session.status === "authenticated", - isLoading: session.status === "loading", - }; - return token; + const token = { + accessToken: session.data?.accessToken, + isLoggedIn: session.status === 'authenticated', + isLoading: session.status === 'loading', + }; + return token; }; diff --git a/apps/dashboard/src/hooks/useAvailableBuildTeam.ts b/apps/dashboard/src/hooks/useAvailableBuildTeam.ts index d536d7fa..e93f3cee 100644 --- a/apps/dashboard/src/hooks/useAvailableBuildTeam.ts +++ b/apps/dashboard/src/hooks/useAvailableBuildTeam.ts @@ -1,38 +1,38 @@ -import { useLocalStorage } from "@mantine/hooks"; -import { useEffect } from "react"; -import useSWR from "swr"; -import { useUser } from "./useUser"; +import { useLocalStorage } from '@mantine/hooks'; +import { useEffect } from 'react'; +import useSWR from 'swr'; +import { useUser } from './useUser'; export default function useAvailableBuildTeam() { - const [activeTeam, setActiveTeam] = useLocalStorage({ - key: "bte-active-build-team", - }); - const [availableTeamsCache, setAvailableTeams] = useLocalStorage< - { - id: string; - location: string; - slug: string; - name: string; - icon: string; - creatorId: string; - }[] - >({ - key: "bte-available-build-team", - }); + const [activeTeam, setActiveTeam] = useLocalStorage({ + key: 'bte-active-build-team', + }); + const [availableTeamsCache, setAvailableTeams] = useLocalStorage< + { + id: string; + location: string; + slug: string; + name: string; + icon: string; + creatorId: string; + }[] + >({ + key: 'bte-available-build-team', + }); - const { user } = useUser(); - const { data } = useSWR(`/users/${user?.id}`); + const { user } = useUser(); + const { data } = useSWR(`/users/${user?.id}`); - useEffect(() => { - if (data) { - setAvailableTeams(data.createdBuildTeams); - } - }, [data]); + useEffect(() => { + if (data) { + setAvailableTeams(data.createdBuildTeams); + } + }, [data]); - return { - activeBuildTeam: availableTeamsCache?.find((team) => team.id == activeTeam), - activeBuildTeamId: activeTeam, - setActiveBuildTeam: setActiveTeam, - availableBuildTeams: availableTeamsCache, - }; + return { + activeBuildTeam: availableTeamsCache?.find((team) => team.id == activeTeam), + activeBuildTeamId: activeTeam, + setActiveBuildTeam: setActiveTeam, + availableBuildTeams: availableTeamsCache, + }; } diff --git a/apps/dashboard/src/hooks/useBuildTeamData.ts b/apps/dashboard/src/hooks/useBuildTeamData.ts index b35e3621..7dfcde35 100644 --- a/apps/dashboard/src/hooks/useBuildTeamData.ts +++ b/apps/dashboard/src/hooks/useBuildTeamData.ts @@ -1,12 +1,12 @@ -import { useLocalStorage } from "@mantine/hooks"; -import useSWR from "swr"; +import { useLocalStorage } from '@mantine/hooks'; +import useSWR from 'swr'; export default function useBuildTeamData(link: string) { - const [activeBuildTeamId] = useLocalStorage({ - key: "bte-active-build-team", - }); + const [activeBuildTeamId] = useLocalStorage({ + key: 'bte-active-build-team', + }); - const data = useSWR(`/buildteams/${activeBuildTeamId}${link}`); + const data = useSWR(`/buildteams/${activeBuildTeamId}${link}`); - return data; + return data; } diff --git a/apps/dashboard/src/hooks/useUser.ts b/apps/dashboard/src/hooks/useUser.ts index 482bd599..53f5130c 100644 --- a/apps/dashboard/src/hooks/useUser.ts +++ b/apps/dashboard/src/hooks/useUser.ts @@ -1,16 +1,16 @@ -import { User } from "@/types/User"; -import { authedFetcher } from "@/util/data"; -import useSWR from "swr"; +import { User } from '@/types/User'; +import { authedFetcher } from '@/util/data'; +import useSWR from 'swr'; export const useUser = () => { - const { data } = useSWR("/account"); + const { data } = useSWR('/account'); - const user = { - user: data, - }; - return user; + const user = { + user: data, + }; + return user; }; export const getUser = async () => { - return authedFetcher("/account"); -} \ No newline at end of file + return authedFetcher('/account'); +}; diff --git a/apps/dashboard/src/middleware.ts b/apps/dashboard/src/middleware.ts index 1c046082..a14a5367 100644 --- a/apps/dashboard/src/middleware.ts +++ b/apps/dashboard/src/middleware.ts @@ -1,3 +1,3 @@ -export { default } from "next-auth/middleware"; +export { default } from 'next-auth/middleware'; -export const config = { matcher: ["/dashboard/:path*"] }; +export const config = { matcher: ['/dashboard/:path*'] }; diff --git a/apps/dashboard/src/styles/Banner.module.css b/apps/dashboard/src/styles/Banner.module.css index d4c7e4cc..5371a64b 100644 --- a/apps/dashboard/src/styles/Banner.module.css +++ b/apps/dashboard/src/styles/Banner.module.css @@ -1,59 +1,59 @@ .wrapper { - display: flex; - align-items: center; - padding: calc(var(--mantine-spacing-xl) * 2); - border-radius: var(--mantine-radius-md); - background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-8)); - border: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-8)); - - @media (max-width: $mantine-breakpoint-sm) { - flex-direction: column-reverse; - padding: var(--mantine-spacing-xl); - } + display: flex; + align-items: center; + padding: calc(var(--mantine-spacing-xl) * 2); + border-radius: var(--mantine-radius-md); + background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-8)); + border: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-8)); + + @media (max-width: $mantine-breakpoint-sm) { + flex-direction: column-reverse; + padding: var(--mantine-spacing-xl); + } } .image { - max-width: 40%; + max-width: 40%; - @media (max-width: $mantine-breakpoint-sm) { - max-width: 100%; - } + @media (max-width: $mantine-breakpoint-sm) { + max-width: 100%; + } } .body { - padding-right: calc(var(--mantine-spacing-xl) * 4); + padding-right: calc(var(--mantine-spacing-xl) * 4); - @media (max-width: $mantine-breakpoint-sm) { - padding-right: 0; - margin-top: var(--mantine-spacing-xl); - } + @media (max-width: $mantine-breakpoint-sm) { + padding-right: 0; + margin-top: var(--mantine-spacing-xl); + } } .title { - color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); - font-family: - Greycliff CF, - var(--mantine-font-family); - line-height: 1; - margin-bottom: var(--mantine-spacing-md); + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + font-family: + Greycliff CF, + var(--mantine-font-family); + line-height: 1; + margin-bottom: var(--mantine-spacing-md); } .controls { - margin-top: var(--mantine-spacing-xl); + margin-top: var(--mantine-spacing-xl); } .inputWrapper { - width: 100%; - flex: 1; + width: 100%; + flex: 1; } .input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; } .control { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} \ No newline at end of file + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} diff --git a/apps/dashboard/src/styles/CheckboxCard.module.css b/apps/dashboard/src/styles/CheckboxCard.module.css index 9e941f64..c5dd7b7c 100644 --- a/apps/dashboard/src/styles/CheckboxCard.module.css +++ b/apps/dashboard/src/styles/CheckboxCard.module.css @@ -1,12 +1,12 @@ .button { - display: flex; - width: 100%; - border: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-8)); - border-radius: var(--mantine-radius-sm); - padding: var(--mantine-spacing-md); - background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-8)); + display: flex; + width: 100%; + border: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-8)); + border-radius: var(--mantine-radius-sm); + padding: var(--mantine-spacing-md); + background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-8)); - @mixin hover { - background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-9)); - } -} \ No newline at end of file + @mixin hover { + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-9)); + } +} diff --git a/apps/dashboard/src/styles/Error.module.css b/apps/dashboard/src/styles/Error.module.css index e58c310d..77a866e6 100644 --- a/apps/dashboard/src/styles/Error.module.css +++ b/apps/dashboard/src/styles/Error.module.css @@ -1,38 +1,38 @@ .root { - padding-top: rem(80px); - padding-bottom: rem(80px); - height: 100%; + padding-top: rem(80px); + padding-bottom: rem(80px); + height: 100%; } .label { - text-align: center; - font-weight: 900; - font-size: rem(38px); - line-height: 1; - margin-bottom: calc(1.5 * var(--mantine-spacing-xl)); - color: var(--mantine-color-gray-2); + text-align: center; + font-weight: 900; + font-size: rem(38px); + line-height: 1; + margin-bottom: calc(1.5 * var(--mantine-spacing-xl)); + color: var(--mantine-color-gray-2); - @media (max-width: $mantine-breakpoint-sm) { - font-size: rem(32px); - } + @media (max-width: $mantine-breakpoint-sm) { + font-size: rem(32px); + } } .description { - max-width: rem(500px); - margin: auto; - margin-top: var(--mantine-spacing-xl); - margin-bottom: calc(1.5 * var(--mantine-spacing-xl)); + max-width: rem(500px); + margin: auto; + margin-top: var(--mantine-spacing-xl); + margin-bottom: calc(1.5 * var(--mantine-spacing-xl)); } .title { - font-family: - Greycliff CF, - var(--mantine-font-family); - text-align: center; - font-weight: 900; - font-size: rem(38px); + font-family: + Greycliff CF, + var(--mantine-font-family); + text-align: center; + font-weight: 900; + font-size: rem(38px); - @media (max-width: $mantine-breakpoint-sm) { - font-size: rem(32px); - } -} \ No newline at end of file + @media (max-width: $mantine-breakpoint-sm) { + font-size: rem(32px); + } +} diff --git a/apps/dashboard/src/styles/Navbar.module.css b/apps/dashboard/src/styles/Navbar.module.css index 6c0ebfda..d4022585 100644 --- a/apps/dashboard/src/styles/Navbar.module.css +++ b/apps/dashboard/src/styles/Navbar.module.css @@ -1,46 +1,45 @@ .navbarLink { - display: flex; - align-items: center; - text-decoration: none; - font-size: var(--mantine-font-size-sm); - color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1)); - padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm); - border-radius: var(--mantine-radius-default); - font-weight: 500; - cursor: pointer; - margin: 0; - - @mixin hover { - text-decoration: none; - background-color: light-dark( - var(--mantine-color-gray-0), - var(--mantine-color-dark-6) - ); - color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + display: flex; + align-items: center; + text-decoration: none; + font-size: var(--mantine-font-size-sm); + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1)); + padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm); + border-radius: var(--mantine-radius-default); + font-weight: 500; + cursor: pointer; + margin: 0; - .navbarLinkIcon { - color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); - } - } + @mixin hover { + text-decoration: none; + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); - transition: background-color 100ms ease, color 100ms ease; + .navbarLinkIcon { + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + } + } - &[data-active="true"] { - &, - &:hover { - background-color: var(--mantine-color-cyan-light); - color: var(--mantine-color-cyan-light-color); + transition: + background-color 100ms ease, + color 100ms ease; - .navbarLinkIcon { - color: var(--mantine-color-cyan-light-color); - } - } - } + &[data-active='true'] { + &, + &:hover { + background-color: var(--mantine-color-cyan-light); + color: var(--mantine-color-cyan-light-color); + + .navbarLinkIcon { + color: var(--mantine-color-cyan-light-color); + } + } + } } .navbarLinkIcon { - color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2)); - margin-right: var(--mantine-spacing-sm); - width: rem(25px); - height: rem(25px); + color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2)); + margin-right: var(--mantine-spacing-sm); + width: rem(25px); + height: rem(25px); } diff --git a/apps/dashboard/src/styles/RawCard.module.css b/apps/dashboard/src/styles/RawCard.module.css index 667d9825..ac0f8c6b 100644 --- a/apps/dashboard/src/styles/RawCard.module.css +++ b/apps/dashboard/src/styles/RawCard.module.css @@ -1,24 +1,24 @@ .root { - padding: calc(var(--mantine-spacing-xl) * 1.5); + padding: calc(var(--mantine-spacing-xl) * 1.5); } .value { - font-size: rem(24px); - font-weight: 700; - line-height: 1; + font-size: rem(24px); + font-weight: 700; + line-height: 1; } .diff { - line-height: 1; - display: flex; - align-items: center; + line-height: 1; + display: flex; + align-items: center; } .icon { - color: light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-3)); + color: light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-3)); } .title { - font-weight: 700; - text-transform: uppercase; + font-weight: 700; + text-transform: uppercase; } diff --git a/apps/dashboard/src/styles/UserButton.module.css b/apps/dashboard/src/styles/UserButton.module.css index 284aa7ac..b91593dc 100644 --- a/apps/dashboard/src/styles/UserButton.module.css +++ b/apps/dashboard/src/styles/UserButton.module.css @@ -1,13 +1,10 @@ .user { - display: block; - width: 100%; - padding: var(--mantine-spacing-md); - color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0)); + display: block; + width: 100%; + padding: var(--mantine-spacing-md); + color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0)); - @mixin hover { - background-color: light-dark( - var(--mantine-color-gray-0), - var(--mantine-color-dark-8) - ); - } + @mixin hover { + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-8)); + } } diff --git a/apps/dashboard/src/styles/global.css b/apps/dashboard/src/styles/global.css index c659ddf7..6bf3262e 100644 --- a/apps/dashboard/src/styles/global.css +++ b/apps/dashboard/src/styles/global.css @@ -1,7 +1,7 @@ :root { - --mantine-navbar-width: 300; + --mantine-navbar-width: 300; } .xl2 { - font-size: calc(var(--mantine-font-size-xl) * 1.5) !important; + font-size: calc(var(--mantine-font-size-xl) * 1.5) !important; } diff --git a/apps/dashboard/src/types/User.ts b/apps/dashboard/src/types/User.ts index 229d745b..f34f4a56 100644 --- a/apps/dashboard/src/types/User.ts +++ b/apps/dashboard/src/types/User.ts @@ -1,80 +1,80 @@ export type User = { - id: string; - ssoId: string; - discordId: string; - username: string; - email: string; - emailVerified: boolean; - avatar: string; - auth: { - exp: { - unix: number; - readable: string; - }; - iat: { - unix: number; - readable: string; - }; - }; - permissions: ( - | { - id: string; - userId: string; - buildTeamId: string | null; - permissionId: string; - permission: string; - buildTeam: { - slug: string; - }; - buildTeamSlug: string; - } - | { - id: string; - userId: string; - buildTeamId: string | null; - permissionId: string; - permission: string; - buildTeam: null; - buildTeamSlug: null; - } - )[]; + id: string; + ssoId: string; + discordId: string; + username: string; + email: string; + emailVerified: boolean; + avatar: string; + auth: { + exp: { + unix: number; + readable: string; + }; + iat: { + unix: number; + readable: string; + }; + }; + permissions: ( + | { + id: string; + userId: string; + buildTeamId: string | null; + permissionId: string; + permission: string; + buildTeam: { + slug: string; + }; + buildTeamSlug: string; + } + | { + id: string; + userId: string; + buildTeamId: string | null; + permissionId: string; + permission: string; + buildTeam: null; + buildTeamSlug: null; + } + )[]; }; export type KeycloakUser = { - id: string; - ssoId: string; - discordId: string; - avatar: string; - username: string; - minecraft: string; - emailVerified: boolean; - createdTimestamp: number; - enabled: boolean; - totp: boolean; - disableableCredentialTypes: string[]; - requiredActions: string[]; - federatedIdentities: { - identityProvider: string; - userId: string; - userName: string; - }[]; - notBefore: number; - access: { - manageGroupMembership: boolean; - view: boolean; - mapRoles: boolean; - impersonate: boolean; - manage: boolean; - }; - sessions: { - id: string; - username: string; - userId: string; - ipAddress: string; - start: number; - lastAccess: number; - rememberMe: boolean; - clients: { - [key: string]: string; - }; - }[]; + id: string; + ssoId: string; + discordId: string; + avatar: string; + username: string; + minecraft: string; + emailVerified: boolean; + createdTimestamp: number; + enabled: boolean; + totp: boolean; + disableableCredentialTypes: string[]; + requiredActions: string[]; + federatedIdentities: { + identityProvider: string; + userId: string; + userName: string; + }[]; + notBefore: number; + access: { + manageGroupMembership: boolean; + view: boolean; + mapRoles: boolean; + impersonate: boolean; + manage: boolean; + }; + sessions: { + id: string; + username: string; + userId: string; + ipAddress: string; + start: number; + lastAccess: number; + rememberMe: boolean; + clients: { + [key: string]: string; + }; + }[]; }; diff --git a/apps/dashboard/src/util/auth.ts b/apps/dashboard/src/util/auth.ts index 2cfea321..8003af9e 100644 --- a/apps/dashboard/src/util/auth.ts +++ b/apps/dashboard/src/util/auth.ts @@ -1,7 +1,7 @@ -import { AuthOptions, getServerSession } from "next-auth"; +import { AuthOptions, getServerSession } from 'next-auth'; -import { JWT } from "next-auth/jwt"; -import KeycloakProvider from "next-auth/providers/keycloak"; +import { JWT } from 'next-auth/jwt'; +import KeycloakProvider from 'next-auth/providers/keycloak'; /** * Refreshes access token to continue the session after token expiration @@ -9,103 +9,100 @@ import KeycloakProvider from "next-auth/providers/keycloak"; * @returns a new access token with refreshed information */ const refreshAccessToken = async (token: JWT) => { - try { - if (Date.now() > token.refreshTokenExpired) throw Error; - const details = { - client_id: process.env.KEYCLOAK_ID, - client_secret: process.env.KEYCLOAK_SECRET, - grant_type: "refresh_token", - refresh_token: token.refreshToken, - }; - const formBody: string[] = []; - Object.entries(details).forEach(([key, value]: [string, any]) => { - const encodedKey = encodeURIComponent(key); - const encodedValue = encodeURIComponent(value); - formBody.push(encodedKey + "=" + encodedValue); - }); - const formData = formBody.join("&"); - const url = `${process.env.KEYCLOAK_URL}/protocol/openid-connect/token`; - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", - }, - body: formData, - }); - const refreshedTokens = await response.json(); - if (!response.ok) throw refreshedTokens; - return { - ...token, - accessToken: refreshedTokens.access_token, - accessTokenExpired: Date.now() + (refreshedTokens.expires_in - 15) * 1000, - refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, - refreshTokenExpired: - Date.now() + (refreshedTokens.refresh_expires_in - 15) * 1000, - }; - } catch (error) { - return { - ...token, - error: "RefreshAccessTokenError", - }; - } + try { + if (Date.now() > token.refreshTokenExpired) throw Error; + const details = { + client_id: process.env.KEYCLOAK_ID, + client_secret: process.env.KEYCLOAK_SECRET, + grant_type: 'refresh_token', + refresh_token: token.refreshToken, + }; + const formBody: string[] = []; + Object.entries(details).forEach(([key, value]: [string, any]) => { + const encodedKey = encodeURIComponent(key); + const encodedValue = encodeURIComponent(value); + formBody.push(encodedKey + '=' + encodedValue); + }); + const formData = formBody.join('&'); + const url = `${process.env.KEYCLOAK_URL}/protocol/openid-connect/token`; + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', + }, + body: formData, + }); + const refreshedTokens = await response.json(); + if (!response.ok) throw refreshedTokens; + return { + ...token, + accessToken: refreshedTokens.access_token, + accessTokenExpired: Date.now() + (refreshedTokens.expires_in - 15) * 1000, + refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, + refreshTokenExpired: Date.now() + (refreshedTokens.refresh_expires_in - 15) * 1000, + }; + } catch (error) { + return { + ...token, + error: 'RefreshAccessTokenError', + }; + } }; export const authOptions: AuthOptions = { - secret: process.env.NEXTAUTH_SECRET, - providers: [ - KeycloakProvider({ - clientId: process.env.NEXT_PUBLIC_KEYCLOAK_ID || "", - clientSecret: process.env.KEYCLOAK_SECRET || "", - issuer: process.env.NEXT_PUBLIC_KEYCLOAK_URL || "", - profile: (profile) => { - return { - ...profile, - username: profile.preferred_username, - id: profile.sub, - }; - }, - }), - ], - callbacks: { - signIn: async ({ user, account }) => { - if (account && user) { - return true; - } else { - // TODO : Add unauthorized page - return "/unauthorized"; - } - }, - jwt: async ({ token, account, user }: any) => { - // Initial sign in - if (account && user) { - // Add access_token, refresh_token and expirations to the token right after signin - token.accessToken = account.access_token; - token.refreshToken = account.refresh_token; - token.accessTokenExpired = - Date.now() + (account.expires_in - 15) * 1000; - token.refreshTokenExpired = - Date.now() + (account.refresh_expires_in - 15) * 1000; - token.user = user; - return token; - } - // Return previous token if the access token has not expired yet - if (Date.now() < token.accessTokenExpired) return token; + secret: process.env.NEXTAUTH_SECRET, + providers: [ + KeycloakProvider({ + clientId: process.env.NEXT_PUBLIC_KEYCLOAK_ID || '', + clientSecret: process.env.KEYCLOAK_SECRET || '', + issuer: process.env.NEXT_PUBLIC_KEYCLOAK_URL || '', + profile: (profile) => { + return { + ...profile, + username: profile.preferred_username, + id: profile.sub, + }; + }, + }), + ], + callbacks: { + signIn: async ({ user, account }) => { + if (account && user) { + return true; + } else { + // TODO : Add unauthorized page + return '/unauthorized'; + } + }, + jwt: async ({ token, account, user }: any) => { + // Initial sign in + if (account && user) { + // Add access_token, refresh_token and expirations to the token right after signin + token.accessToken = account.access_token; + token.refreshToken = account.refresh_token; + token.accessTokenExpired = Date.now() + (account.expires_in - 15) * 1000; + token.refreshTokenExpired = Date.now() + (account.refresh_expires_in - 15) * 1000; + token.user = user; + return token; + } + // Return previous token if the access token has not expired yet + if (Date.now() < token.accessTokenExpired) return token; - // Access token has expired, try to update it - return refreshAccessToken(token); - }, - session: async ({ session, token }: any) => { - if (token) { - session.user = token.user; - session.error = token.error; - session.accessToken = token.accessToken; - } - return session; - }, - }, - pages: { - signIn: "/auth/signin", - }, + // Access token has expired, try to update it + return refreshAccessToken(token); + }, + session: async ({ session, token }: any) => { + if (token) { + session.user = token.user; + session.error = token.error; + session.accessToken = token.accessToken; + } + return session; + }, + }, + pages: { + signIn: '/auth/signin', + }, }; /** @@ -113,5 +110,3 @@ export const authOptions: AuthOptions = { * @returns The session object or null */ export const getSession = () => getServerSession(authOptions); - - diff --git a/apps/dashboard/src/util/countries.ts b/apps/dashboard/src/util/countries.ts index 611cb0b4..413607bc 100644 --- a/apps/dashboard/src/util/countries.ts +++ b/apps/dashboard/src/util/countries.ts @@ -1,266 +1,266 @@ const isoCountries: { [key: string]: string } = { - AF: "Afghanistan", - AX: "Aland Islands", - AL: "Albania", - DZ: "Algeria", - AS: "American Samoa", - AD: "Andorra", - AO: "Angola", - AI: "Anguilla", - AQ: "Antarctica", - AG: "Antigua And Barbuda", - AR: "Argentina", - AM: "Armenia", - AW: "Aruba", - AU: "Australia", - AT: "Austria", - AZ: "Azerbaijan", - BS: "Bahamas", - BH: "Bahrain", - BD: "Bangladesh", - BB: "Barbados", - BY: "Belarus", - BE: "Belgium", - BZ: "Belize", - BJ: "Benin", - BM: "Bermuda", - BT: "Bhutan", - BO: "Bolivia", - BA: "Bosnia And Herzegovina", - BW: "Botswana", - BV: "Bouvet Island", - BR: "Brazil", - IO: "British Indian Ocean Territory", - BN: "Brunei Darussalam", - BG: "Bulgaria", - BF: "Burkina Faso", - BI: "Burundi", - KH: "Cambodia", - CW: "Curacao", - SX: "Sint Maarten", - BQ: "Bonaire, Saint Eustatius and Saba", - CM: "Cameroon", - CA: "Canada", - CV: "Cape Verde", - KY: "Cayman Islands", - CF: "Central African Republic", - TD: "Chad", - CL: "Chile", - CN: "China", - CX: "Christmas Island", - CC: "Cocos (Keeling) Islands", - CO: "Colombia", - KM: "Comoros", - CG: "Congo", - CD: "Congo, Democratic Republic", - CK: "Cook Islands", - CR: "Costa Rica", - CI: "Cote D'Ivoire", - HR: "Croatia", - CU: "Cuba", - CY: "Cyprus", - CZ: "Czech Republic", - DK: "Denmark", - DJ: "Djibouti", - DM: "Dominica", - DO: "Dominican Republic", - EC: "Ecuador", - EG: "Egypt", - SV: "El Salvador", - GQ: "Equatorial Guinea", - ER: "Eritrea", - EE: "Estonia", - ET: "Ethiopia", - FK: "Falkland Islands (Malvinas)", - FO: "Faroe Islands", - FJ: "Fiji", - FI: "Finland", - FR: "France", - GF: "French Guiana", - PF: "French Polynesia", - TF: "French Southern Territories", - GA: "Gabon", - GM: "Gambia", - GE: "Georgia", - DE: "Germany", - GH: "Ghana", - GI: "Gibraltar", - GR: "Greece", - GL: "Greenland", - GD: "Grenada", - GP: "Guadeloupe", - GU: "Guam", - GT: "Guatemala", - GG: "Guernsey", - GN: "Guinea", - GW: "Guinea-Bissau", - GY: "Guyana", - HT: "Haiti", - HM: "Heard Island & Mcdonald Islands", - VA: "Holy See (Vatican City State)", - HN: "Honduras", - HK: "Hong Kong", - HU: "Hungary", - IS: "Iceland", - IN: "India", - ID: "Indonesia", - IR: "Iran, Islamic Republic Of", - IQ: "Iraq", - IE: "Ireland", - IM: "Isle Of Man", - IL: "Israel", - IT: "Italy", - JM: "Jamaica", - JP: "Japan", - JE: "Jersey", - JO: "Jordan", - KZ: "Kazakhstan", - KE: "Kenya", - KI: "Kiribati", - KR: "Korea", - KW: "Kuwait", - KG: "Kyrgyzstan", - LA: "Lao People's Democratic Republic", - LV: "Latvia", - LB: "Lebanon", - LS: "Lesotho", - LR: "Liberia", - LY: "Libyan Arab Jamahiriya", - LI: "Liechtenstein", - LT: "Lithuania", - LU: "Luxembourg", - MO: "Macao", - MK: "Macedonia", - MG: "Madagascar", - MW: "Malawi", - MY: "Malaysia", - MV: "Maldives", - ML: "Mali", - MT: "Malta", - MH: "Marshall Islands", - MQ: "Martinique", - MR: "Mauritania", - MU: "Mauritius", - YT: "Mayotte", - MX: "Mexico", - FM: "Micronesia, Federated States Of", - MD: "Moldova", - MC: "Monaco", - MN: "Mongolia", - ME: "Montenegro", - MS: "Montserrat", - MA: "Morocco", - MZ: "Mozambique", - MM: "Myanmar", - NA: "Namibia", - NR: "Nauru", - NP: "Nepal", - NL: "Netherlands", - AN: "Netherlands Antilles", - NC: "New Caledonia", - NZ: "New Zealand", - NI: "Nicaragua", - NE: "Niger", - NG: "Nigeria", - NU: "Niue", - NF: "Norfolk Island", - MP: "Northern Mariana Islands", - NO: "Norway", - OM: "Oman", - PK: "Pakistan", - PW: "Palau", - PS: "Palestinian Territory, Occupied", - PA: "Panama", - PG: "Papua New Guinea", - PY: "Paraguay", - PE: "Peru", - PH: "Philippines", - PN: "Pitcairn", - PL: "Poland", - PT: "Portugal", - PR: "Puerto Rico", - QA: "Qatar", - RE: "Reunion", - RO: "Romania", - RU: "Russia", - RW: "Rwanda", - BL: "Saint Barthelemy", - SH: "Saint Helena", - KN: "Saint Kitts And Nevis", - LC: "Saint Lucia", - MF: "Saint Martin", - PM: "Saint Pierre And Miquelon", - VC: "Saint Vincent And Grenadines", - WS: "Samoa", - SM: "San Marino", - ST: "Sao Tome And Principe", - SA: "Saudi Arabia", - SN: "Senegal", - RS: "Serbia", - SC: "Seychelles", - SL: "Sierra Leone", - SG: "Singapore", - SK: "Slovakia", - SI: "Slovenia", - SB: "Solomon Islands", - SO: "Somalia", - ZA: "South Africa", - GS: "South Georgia And Sandwich Isl.", - ES: "Spain", - LK: "Sri Lanka", - SD: "Sudan", - SR: "Suriname", - SJ: "Svalbard And Jan Mayen", - SZ: "Swaziland", - SE: "Sweden", - CH: "Switzerland", - SY: "Syrian Arab Republic", - TW: "Taiwan", - TJ: "Tajikistan", - TZ: "Tanzania", - TH: "Thailand", - TL: "Timor-Leste", - TG: "Togo", - TK: "Tokelau", - TO: "Tonga", - TT: "Trinidad And Tobago", - TN: "Tunisia", - TR: "Turkey", - TM: "Turkmenistan", - TC: "Turks And Caicos Islands", - TV: "Tuvalu", - UG: "Uganda", - UA: "Ukraine", - AE: "United Arab Emirates", - GB: "United Kingdom", - US: "United States", - UM: "United States Outlying Islands", - UY: "Uruguay", - UZ: "Uzbekistan", - VU: "Vanuatu", - VE: "Venezuela", - VN: "Viet Nam", - VG: "Virgin Islands, British", - VI: "Virgin Islands, U.S.", - WF: "Wallis And Futuna", - EH: "Western Sahara", - YE: "Yemen", - ZM: "Zambia", - ZW: "Zimbabwe", - GLB: "Globe", // Not a country, but i need this!!! - OST: "Overseas Territories", // !! - CDP: "Crown Dependencies", // !! + AF: 'Afghanistan', + AX: 'Aland Islands', + AL: 'Albania', + DZ: 'Algeria', + AS: 'American Samoa', + AD: 'Andorra', + AO: 'Angola', + AI: 'Anguilla', + AQ: 'Antarctica', + AG: 'Antigua And Barbuda', + AR: 'Argentina', + AM: 'Armenia', + AW: 'Aruba', + AU: 'Australia', + AT: 'Austria', + AZ: 'Azerbaijan', + BS: 'Bahamas', + BH: 'Bahrain', + BD: 'Bangladesh', + BB: 'Barbados', + BY: 'Belarus', + BE: 'Belgium', + BZ: 'Belize', + BJ: 'Benin', + BM: 'Bermuda', + BT: 'Bhutan', + BO: 'Bolivia', + BA: 'Bosnia And Herzegovina', + BW: 'Botswana', + BV: 'Bouvet Island', + BR: 'Brazil', + IO: 'British Indian Ocean Territory', + BN: 'Brunei Darussalam', + BG: 'Bulgaria', + BF: 'Burkina Faso', + BI: 'Burundi', + KH: 'Cambodia', + CW: 'Curacao', + SX: 'Sint Maarten', + BQ: 'Bonaire, Saint Eustatius and Saba', + CM: 'Cameroon', + CA: 'Canada', + CV: 'Cape Verde', + KY: 'Cayman Islands', + CF: 'Central African Republic', + TD: 'Chad', + CL: 'Chile', + CN: 'China', + CX: 'Christmas Island', + CC: 'Cocos (Keeling) Islands', + CO: 'Colombia', + KM: 'Comoros', + CG: 'Congo', + CD: 'Congo, Democratic Republic', + CK: 'Cook Islands', + CR: 'Costa Rica', + CI: "Cote D'Ivoire", + HR: 'Croatia', + CU: 'Cuba', + CY: 'Cyprus', + CZ: 'Czech Republic', + DK: 'Denmark', + DJ: 'Djibouti', + DM: 'Dominica', + DO: 'Dominican Republic', + EC: 'Ecuador', + EG: 'Egypt', + SV: 'El Salvador', + GQ: 'Equatorial Guinea', + ER: 'Eritrea', + EE: 'Estonia', + ET: 'Ethiopia', + FK: 'Falkland Islands (Malvinas)', + FO: 'Faroe Islands', + FJ: 'Fiji', + FI: 'Finland', + FR: 'France', + GF: 'French Guiana', + PF: 'French Polynesia', + TF: 'French Southern Territories', + GA: 'Gabon', + GM: 'Gambia', + GE: 'Georgia', + DE: 'Germany', + GH: 'Ghana', + GI: 'Gibraltar', + GR: 'Greece', + GL: 'Greenland', + GD: 'Grenada', + GP: 'Guadeloupe', + GU: 'Guam', + GT: 'Guatemala', + GG: 'Guernsey', + GN: 'Guinea', + GW: 'Guinea-Bissau', + GY: 'Guyana', + HT: 'Haiti', + HM: 'Heard Island & Mcdonald Islands', + VA: 'Holy See (Vatican City State)', + HN: 'Honduras', + HK: 'Hong Kong', + HU: 'Hungary', + IS: 'Iceland', + IN: 'India', + ID: 'Indonesia', + IR: 'Iran, Islamic Republic Of', + IQ: 'Iraq', + IE: 'Ireland', + IM: 'Isle Of Man', + IL: 'Israel', + IT: 'Italy', + JM: 'Jamaica', + JP: 'Japan', + JE: 'Jersey', + JO: 'Jordan', + KZ: 'Kazakhstan', + KE: 'Kenya', + KI: 'Kiribati', + KR: 'Korea', + KW: 'Kuwait', + KG: 'Kyrgyzstan', + LA: "Lao People's Democratic Republic", + LV: 'Latvia', + LB: 'Lebanon', + LS: 'Lesotho', + LR: 'Liberia', + LY: 'Libyan Arab Jamahiriya', + LI: 'Liechtenstein', + LT: 'Lithuania', + LU: 'Luxembourg', + MO: 'Macao', + MK: 'Macedonia', + MG: 'Madagascar', + MW: 'Malawi', + MY: 'Malaysia', + MV: 'Maldives', + ML: 'Mali', + MT: 'Malta', + MH: 'Marshall Islands', + MQ: 'Martinique', + MR: 'Mauritania', + MU: 'Mauritius', + YT: 'Mayotte', + MX: 'Mexico', + FM: 'Micronesia, Federated States Of', + MD: 'Moldova', + MC: 'Monaco', + MN: 'Mongolia', + ME: 'Montenegro', + MS: 'Montserrat', + MA: 'Morocco', + MZ: 'Mozambique', + MM: 'Myanmar', + NA: 'Namibia', + NR: 'Nauru', + NP: 'Nepal', + NL: 'Netherlands', + AN: 'Netherlands Antilles', + NC: 'New Caledonia', + NZ: 'New Zealand', + NI: 'Nicaragua', + NE: 'Niger', + NG: 'Nigeria', + NU: 'Niue', + NF: 'Norfolk Island', + MP: 'Northern Mariana Islands', + NO: 'Norway', + OM: 'Oman', + PK: 'Pakistan', + PW: 'Palau', + PS: 'Palestinian Territory, Occupied', + PA: 'Panama', + PG: 'Papua New Guinea', + PY: 'Paraguay', + PE: 'Peru', + PH: 'Philippines', + PN: 'Pitcairn', + PL: 'Poland', + PT: 'Portugal', + PR: 'Puerto Rico', + QA: 'Qatar', + RE: 'Reunion', + RO: 'Romania', + RU: 'Russia', + RW: 'Rwanda', + BL: 'Saint Barthelemy', + SH: 'Saint Helena', + KN: 'Saint Kitts And Nevis', + LC: 'Saint Lucia', + MF: 'Saint Martin', + PM: 'Saint Pierre And Miquelon', + VC: 'Saint Vincent And Grenadines', + WS: 'Samoa', + SM: 'San Marino', + ST: 'Sao Tome And Principe', + SA: 'Saudi Arabia', + SN: 'Senegal', + RS: 'Serbia', + SC: 'Seychelles', + SL: 'Sierra Leone', + SG: 'Singapore', + SK: 'Slovakia', + SI: 'Slovenia', + SB: 'Solomon Islands', + SO: 'Somalia', + ZA: 'South Africa', + GS: 'South Georgia And Sandwich Isl.', + ES: 'Spain', + LK: 'Sri Lanka', + SD: 'Sudan', + SR: 'Suriname', + SJ: 'Svalbard And Jan Mayen', + SZ: 'Swaziland', + SE: 'Sweden', + CH: 'Switzerland', + SY: 'Syrian Arab Republic', + TW: 'Taiwan', + TJ: 'Tajikistan', + TZ: 'Tanzania', + TH: 'Thailand', + TL: 'Timor-Leste', + TG: 'Togo', + TK: 'Tokelau', + TO: 'Tonga', + TT: 'Trinidad And Tobago', + TN: 'Tunisia', + TR: 'Turkey', + TM: 'Turkmenistan', + TC: 'Turks And Caicos Islands', + TV: 'Tuvalu', + UG: 'Uganda', + UA: 'Ukraine', + AE: 'United Arab Emirates', + GB: 'United Kingdom', + US: 'United States', + UM: 'United States Outlying Islands', + UY: 'Uruguay', + UZ: 'Uzbekistan', + VU: 'Vanuatu', + VE: 'Venezuela', + VN: 'Viet Nam', + VG: 'Virgin Islands, British', + VI: 'Virgin Islands, U.S.', + WF: 'Wallis And Futuna', + EH: 'Western Sahara', + YE: 'Yemen', + ZM: 'Zambia', + ZW: 'Zimbabwe', + GLB: 'Globe', // Not a country, but i need this!!! + OST: 'Overseas Territories', // !! + CDP: 'Crown Dependencies', // !! }; export default function getCountryName(countryCode: string): string { - const code = countryCode.toUpperCase(); - if (isoCountries.hasOwnProperty(code)) { - return isoCountries[code]; - } else { - return "Globe"; - } + const code = countryCode.toUpperCase(); + if (isoCountries.hasOwnProperty(code)) { + return isoCountries[code]; + } else { + return 'Globe'; + } } export function getCountryNames(countryCodes: string[]): string[] { - return countryCodes.map((code) => getCountryName(code)); + return countryCodes.map((code) => getCountryName(code)); } diff --git a/apps/dashboard/src/util/data.ts b/apps/dashboard/src/util/data.ts index 9112d903..817f3d68 100644 --- a/apps/dashboard/src/util/data.ts +++ b/apps/dashboard/src/util/data.ts @@ -1,34 +1,28 @@ -import { getSession } from "./auth"; +import { getSession } from './auth'; export default async function fetcher(route: string, ...props: any): Promise { - const res = await fetch(process.env.NEXT_PUBLIC_API_URL + route, { - ...props, - }); - return res.json(); + const res = await fetch(process.env.NEXT_PUBLIC_API_URL + route, { + ...props, + }); + return res.json(); } -export async function authedFetcher( - route: string, - ...props: any -): Promise { - const session = await getSession(); +export async function authedFetcher(route: string, ...props: any): Promise { + const session = await getSession(); - if (!session) { - return {} as T; - } + if (!session) { + return {} as T; + } - const res = await fetch(process.env.NEXT_PUBLIC_API_URL + route, { - headers: { - Authorization: `Bearer ${session?.accessToken}`, - }, - ...props, - }); - return res.json(); + const res = await fetch(process.env.NEXT_PUBLIC_API_URL + route, { + headers: { + Authorization: `Bearer ${session?.accessToken}`, + }, + ...props, + }); + return res.json(); } -export async function globalFetcher( - route: string, - ...props: any -): Promise { - const res = await fetch(route, ...props); - return res.json(); +export async function globalFetcher(route: string, ...props: any): Promise { + const res = await fetch(route, ...props); + return res.json(); } diff --git a/apps/dashboard/src/util/date.ts b/apps/dashboard/src/util/date.ts index 4a972ba9..fe0eb1df 100644 --- a/apps/dashboard/src/util/date.ts +++ b/apps/dashboard/src/util/date.ts @@ -1,11 +1,11 @@ -import moment from "moment"; +import moment from 'moment'; export function toHumanDate(date: string) { - return moment(date).format("DD.MM.YYYY"); + return moment(date).format('DD.MM.YYYY'); } export function toHumanTime(date: string) { - return moment(date).format("HH:mm:ss"); + return moment(date).format('HH:mm:ss'); } export function toHumanDateTime(date: string) { - return moment(date).format("DD.MM.YYYY HH:mm:ss"); + return moment(date).format('DD.MM.YYYY HH:mm:ss'); } diff --git a/apps/dashboard/src/util/links.ts b/apps/dashboard/src/util/links.ts index cc5bb7d9..7e72fdd1 100644 --- a/apps/dashboard/src/util/links.ts +++ b/apps/dashboard/src/util/links.ts @@ -1,101 +1,97 @@ -import { - IconList, - IconTool, - IconUsersGroup -} from "@tabler/icons-react"; +import { IconList, IconTool, IconUsersGroup } from '@tabler/icons-react'; /** * These links are used for navigation between buildteam related pages */ export const teamNavLinks: NavLink[] = [ - { link: "/team", label: "Team Overview", icon: IconList }, - { link: "/team/members", label: "Members", icon: IconUsersGroup }, - { link: "/team/tools", label: "Debug Tools", icon: IconTool }, + { link: '/team', label: 'Team Overview', icon: IconList }, + { link: '/team/members', label: 'Members', icon: IconUsersGroup }, + { link: '/team/tools', label: 'Debug Tools', icon: IconTool }, ]; /** * These links are used for navigation between tool pages */ export const meNavLinks: NavLink[] = [ - { - link: "/", - label: "My Home", - icon: "Home", - }, - { - link: "/me/teams", - label: "Participating Teams", - icon: "UsersGroup", - }, - { - link: "/me/applications", - label: "My Applications", - icon: "Forms", - }, - { - link: "/me/claims", - label: "Claim Overview", - icon: "Polygon", - }, - { - link: "/me/network", - label: "Network Statistics", - icon: "ChartPie", - }, + { + link: '/', + label: 'My Home', + icon: 'Home', + }, + { + link: '/me/teams', + label: 'Participating Teams', + icon: 'UsersGroup', + }, + { + link: '/me/applications', + label: 'My Applications', + icon: 'Forms', + }, + { + link: '/me/claims', + label: 'Claim Overview', + icon: 'Polygon', + }, + { + link: '/me/network', + label: 'Network Statistics', + icon: 'ChartPie', + }, - // ---- Account Links ---- - { link: "", label: "Your Account", icon: null, divider: true }, - { - link: "/me/connections", - label: "Social Connections", - icon: "PlugConnected", - }, - { - link: "/me/sessions", - label: "Active Sessions", - icon: "DeviceDesktop", - }, - { - link: "/me/settings", - label: "Global Settings", - icon: "Settings", - }, + // ---- Account Links ---- + { link: '', label: 'Your Account', icon: null, divider: true }, + { + link: '/me/connections', + label: 'Social Connections', + icon: 'PlugConnected', + }, + { + link: '/me/sessions', + label: 'Active Sessions', + icon: 'DeviceDesktop', + }, + { + link: '/me/settings', + label: 'Global Settings', + icon: 'Settings', + }, - // ---- Staff Links ---- - { - link: "", - label: "Staff Hub", - icon: null, - protected: true, - divider: true, - }, - { - link: "/am/users", - label: "Website Users", - protected: true, - icon: "UsersGroup", - }, - { - link: "/am/claims", - label: "Map Claims", - protected: true, - icon: "Polygon", - }, - { - link: "/am/applications", - label: "Team Applications", - protected: true, - icon: "Forms", - }, - { - link: "/am/sso", - label: "SSO Configuration and Security", - protected: true, - icon: "Settings", - }, + // ---- Staff Links ---- + { + link: '', + label: 'Staff Hub', + icon: null, + protected: true, + divider: true, + }, + { + link: '/am/users', + label: 'Website Users', + protected: true, + icon: 'UsersGroup', + }, + { + link: '/am/claims', + label: 'Map Claims', + protected: true, + icon: 'Polygon', + }, + { + link: '/am/applications', + label: 'Team Applications', + protected: true, + icon: 'Forms', + }, + { + link: '/am/sso', + label: 'SSO Configuration and Security', + protected: true, + icon: 'Settings', + }, ]; -export const navLinks = meNavLinks +export const navLinks = meNavLinks; /** * Converts a NavLink array to an array of href links @@ -103,16 +99,16 @@ export const navLinks = meNavLinks * @returns a array of only the href itself */ export function toBlankLink(links: NavLink[]): string[] { - return links.filter((l) => !l.divider).map((link) => link.link); + return links.filter((l) => !l.divider).map((link) => link.link); } type NavLink = { - link: string; - label: string; - icon: any; - protected?:boolean; - divider?: boolean; + link: string; + label: string; + icon: any; + protected?: boolean; + divider?: boolean; }; interface NavLinkGroup { - [section: string]: NavLink[]; -} \ No newline at end of file + [section: string]: NavLink[]; +} diff --git a/apps/dashboard/src/util/theme/index.ts b/apps/dashboard/src/util/theme/index.ts index 5ec2f16b..1b24dae1 100644 --- a/apps/dashboard/src/util/theme/index.ts +++ b/apps/dashboard/src/util/theme/index.ts @@ -1,60 +1,60 @@ -import { createTheme } from "@mantine/core"; +import { createTheme } from '@mantine/core'; /** * Main Mantine Theme of the Website */ export const theme = createTheme({ - fontFamily: - 'var(--font-inter), -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif', - breakpoints: { - xs: "36em", - sm: "48em", - md: "62em", - lg: "75em", - xl: "88em", - }, - primaryColor: "buildtheearth", - primaryShade: 6, - colors: { - buildtheearth: [ - "#f0f1fa", - "#dddeee", - "#b7b9dd", - "#8f93cf", - "#6e72c2", - "#595dba", - "#4e53b7", - "#3f44a2", - "#373d91", - "#2d3380", - ], - dark: [ - "#d1d1d2", - "#a2a3a5", - "#76777a", - "#4c4e51", - "#26292d", - "#1f2024", - "#1a1b1e", - "#121315", - "#0e0f10", - "#0b0c0d", - ], - // OLD MANTINE - // dark: [ - // '#C1C2C5', - // '#A6A7AB', - // '#909296', - // '#5c5f66', - // '#373A40', - // '#2C2E33', - // '#25262b', - // '#1A1B1E', - // '#141517', - // '#101113', - // ], - }, + fontFamily: + 'var(--font-inter), -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif', + breakpoints: { + xs: '36em', + sm: '48em', + md: '62em', + lg: '75em', + xl: '88em', + }, + primaryColor: 'buildtheearth', + primaryShade: 6, + colors: { + buildtheearth: [ + '#f0f1fa', + '#dddeee', + '#b7b9dd', + '#8f93cf', + '#6e72c2', + '#595dba', + '#4e53b7', + '#3f44a2', + '#373d91', + '#2d3380', + ], + dark: [ + '#d1d1d2', + '#a2a3a5', + '#76777a', + '#4c4e51', + '#26292d', + '#1f2024', + '#1a1b1e', + '#121315', + '#0e0f10', + '#0b0c0d', + ], + // OLD MANTINE + // dark: [ + // '#C1C2C5', + // '#A6A7AB', + // '#909296', + // '#5c5f66', + // '#373A40', + // '#2C2E33', + // '#25262b', + // '#1A1B1E', + // '#141517', + // '#101113', + // ], + }, - autoContrast: true, - luminanceThreshold: 0.33, + autoContrast: true, + luminanceThreshold: 0.33, });