Update Bridge file layout
This commit is contained in:
parent
2c43e81436
commit
b0fb643b6a
47 changed files with 2488 additions and 2087 deletions
14
apps/bridge-frontend/app/(login)/login/page.tsx
Normal file
14
apps/bridge-frontend/app/(login)/login/page.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { Metadata } from "next";
|
||||
import { getSession } from "next-auth/react";
|
||||
import { Login } from "@/app/_components/Login";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Login",
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const session = await getSession();
|
||||
return <Login session={session} />;
|
||||
}
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "ui";
|
||||
// import { db } from "@/app/_lib/database";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
type FacebookBotsListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
export const FacebookBotsList: FC<FacebookBotsListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
|
|
@ -32,14 +36,12 @@ export default async function Page() {
|
|||
},
|
||||
];
|
||||
|
||||
const rows: any = []; // await db.selectFrom("WhatsAppBot").selectAll().execute();
|
||||
|
||||
return (
|
||||
<List
|
||||
title="Whatsapp Bots"
|
||||
title="Facebook Bots"
|
||||
entity="facebook"
|
||||
rows={rows}
|
||||
columns={columns}
|
||||
onRowClick={() => {}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
10
apps/bridge-frontend/app/(main)/facebook/page.tsx
Normal file
10
apps/bridge-frontend/app/(main)/facebook/page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { FacebookBotsList } from "./_components/FacebookBotsList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("FacebookBot").selectAll().execute();
|
||||
|
||||
return <FacebookBotsList rows={rows} />;
|
||||
}
|
||||
9
apps/bridge-frontend/app/(main)/layout.tsx
Normal file
9
apps/bridge-frontend/app/(main)/layout.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { InternalLayout } from "@/app/_components/InternalLayout";
|
||||
|
||||
export default function Layout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return <InternalLayout>{children}</InternalLayout>;
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "ui";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
type SignalBotsListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export const SignalBotsList: FC<SignalBotsListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
|
|
@ -31,14 +36,7 @@ export default function Page() {
|
|||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Voice bots" rows={rows} columns={columns} />;
|
||||
}
|
||||
return (
|
||||
<List title="Signal Bots" entity="signal" rows={rows} columns={columns} />
|
||||
);
|
||||
};
|
||||
10
apps/bridge-frontend/app/(main)/signal/page.tsx
Normal file
10
apps/bridge-frontend/app/(main)/signal/page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { SignalBotsList } from "./_components/SignalBotsList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("SignalBot").selectAll().execute();
|
||||
|
||||
return <SignalBotsList rows={rows} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
type UsersListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export const UsersList: FC<UsersListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "name",
|
||||
headerName: "Name",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "email",
|
||||
headerName: "Email",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "emailVerified",
|
||||
headerName: "Verified",
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Users" entity="users" rows={rows} columns={columns} />;
|
||||
};
|
||||
11
apps/bridge-frontend/app/(main)/users/page.tsx
Normal file
11
apps/bridge-frontend/app/(main)/users/page.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { UsersList } from "./_components/UsersList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("User").selectAll().execute();
|
||||
console.log(rows);
|
||||
|
||||
return <UsersList rows={rows} />;
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "ui";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
type VoiceBotsListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export const VoiceBotsList: FC<VoiceBotsListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
|
|
@ -31,14 +36,5 @@ export default function Page() {
|
|||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Facebook" rows={rows} columns={columns} />;
|
||||
}
|
||||
return <List title="Voice Bots" entity="voice" rows={rows} columns={columns} />;
|
||||
};
|
||||
10
apps/bridge-frontend/app/(main)/voice/page.tsx
Normal file
10
apps/bridge-frontend/app/(main)/voice/page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { VoiceBotsList } from "./_components/VoiceBotsList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("VoiceLine").selectAll().execute();
|
||||
|
||||
return <VoiceBotsList rows={rows} />;
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "ui";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
type WebhooksListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export const WebhooksList: FC<WebhooksListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
|
|
@ -31,14 +36,7 @@ export default function Page() {
|
|||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Users" rows={rows} columns={columns} />;
|
||||
}
|
||||
return (
|
||||
<List title="Webhooks" entity="webhooks" rows={rows} columns={columns} />
|
||||
);
|
||||
};
|
||||
11
apps/bridge-frontend/app/(main)/webhooks/page.tsx
Normal file
11
apps/bridge-frontend/app/(main)/webhooks/page.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { WebhooksList } from "./_components/WebhooksList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("Webhook").selectAll().execute();
|
||||
console.log(rows);
|
||||
|
||||
return <WebhooksList rows={rows} />;
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "ui";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
type WhatsappListProps = {
|
||||
rows: any[];
|
||||
};
|
||||
|
||||
export const WhatsappList: FC<WhatsappListProps> = ({ rows }) => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
|
|
@ -31,14 +36,12 @@ export default function Page() {
|
|||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Signal Bots" rows={rows} columns={columns} />;
|
||||
}
|
||||
return (
|
||||
<List
|
||||
title="WhatsApp Bots"
|
||||
entity="whatsapp"
|
||||
rows={rows}
|
||||
columns={columns}
|
||||
/>
|
||||
);
|
||||
};
|
||||
11
apps/bridge-frontend/app/(main)/whatsapp/page.tsx
Normal file
11
apps/bridge-frontend/app/(main)/whatsapp/page.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { WhatsappList } from "./_components/WhatsappList";
|
||||
import { db } from "@/app/_lib/database";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page() {
|
||||
const rows = await db.selectFrom("WhatsappBot").selectAll().execute();
|
||||
console.log(rows);
|
||||
|
||||
return <WhatsappList rows={rows} />;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
"use server";
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { Grid, Box } from "@mui/material";
|
||||
import { Grid, Box, Dialog } from "@mui/material";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { typography } from "@/app/_styles/theme";
|
||||
|
||||
|
|
@ -16,15 +16,20 @@ export const Detail: FC<DetailProps> = ({ title, entity, children }) => {
|
|||
const { h3 } = typography;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={true}
|
||||
onClose={() => router.push(`/${entity}`)}
|
||||
fullScreen
|
||||
sx={{ backgroundColor: "#ddd" }}
|
||||
>
|
||||
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
|
||||
<Grid container direction="column">
|
||||
<Grid item>
|
||||
<Box sx={h3}>{title}</Box>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
{children}
|
||||
</Grid>
|
||||
<Grid item>{children}</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
import { FC, PropsWithChildren, useState } from "react";
|
||||
import { Grid } from "@mui/material";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
import { CssBaseline } from "@mui/material";
|
||||
import { css, Global } from "@emotion/react";
|
||||
import { fonts } from "@/app/_styles/theme";
|
||||
|
||||
type LayoutProps = PropsWithChildren<{
|
||||
docs?: any;
|
||||
}>;
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
export const InternalLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -28,7 +24,7 @@ export const InternalLayout: FC<PropsWithChildren> = ({ children }) => {
|
|||
<Sidebar open={open} setOpen={setOpen} />
|
||||
<Grid
|
||||
item
|
||||
sx={{ ml: open ? "270px" : "100px", width: "100%", height: "100vh" }}
|
||||
sx={{ ml: open ? "270px" : "70px", width: "100%", height: "100vh" }}
|
||||
>
|
||||
{children as any}
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { Grid, Box } from "@mui/material";
|
||||
import { DataGridPro, GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { typography } from "@/app/_styles/theme";
|
||||
import { List as InternalList } from "ui";
|
||||
|
||||
interface ListProps {
|
||||
title: string;
|
||||
|
|
@ -15,72 +14,17 @@ interface ListProps {
|
|||
|
||||
export const List: FC<ListProps> = ({ title, entity, rows, columns }) => {
|
||||
const router = useRouter();
|
||||
const { h3 } = typography;
|
||||
|
||||
const onRowClick = (id: string) => {
|
||||
router.push(`/${entity}/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
|
||||
<Grid container direction="column">
|
||||
<Grid item>
|
||||
<Box sx={h3}>{title}</Box>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#ddd",
|
||||
border: 0,
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
".MuiDataGrid-row": {
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
backgroundColor: "#1982fc33 !important",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
},
|
||||
".MuiDataGrid-row:nth-of-type(1n)": {
|
||||
backgroundColor: "#f3f3f3",
|
||||
},
|
||||
".MuiDataGrid-row:nth-of-type(2n)": {
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
".MuiDataGrid-columnHeaderTitle": {
|
||||
color: "#333",
|
||||
fontWeight: "bold",
|
||||
fontSize: 11,
|
||||
margin: "0 auto",
|
||||
},
|
||||
".MuiDataGrid-columnHeader": {
|
||||
backgroundColor: "#ccc",
|
||||
border: 0,
|
||||
borderBottom: "3px solid #ddd",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DataGridPro
|
||||
<InternalList
|
||||
title={title}
|
||||
rows={rows}
|
||||
columns={columns}
|
||||
density="compact"
|
||||
pagination
|
||||
initialState={{
|
||||
pagination: { paginationModel: { pageSize: 25 } },
|
||||
}}
|
||||
pageSizeOptions={[5, 10, 25]}
|
||||
paginationMode="client"
|
||||
sx={{ height: "100vh" }}
|
||||
// rowBuffer={30}
|
||||
rowHeight={46}
|
||||
scrollbarSize={0}
|
||||
disableVirtualization
|
||||
disableColumnMenu
|
||||
onRowClick={(row: any) => onRowClick(row.id)}
|
||||
onRowClick={onRowClick}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
184
apps/bridge-frontend/app/_components/Login.tsx
Normal file
184
apps/bridge-frontend/app/_components/Login.tsx
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
"use client";
|
||||
|
||||
import { FC, useState } from "react";
|
||||
import {
|
||||
Box,
|
||||
Grid,
|
||||
Container,
|
||||
IconButton,
|
||||
Typography,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
Apple as AppleIcon,
|
||||
Google as GoogleIcon,
|
||||
Key as KeyIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { signIn } from "next-auth/react";
|
||||
import Image from "next/image";
|
||||
import LinkLogo from "@/app/../public/link-logo-small.png";
|
||||
import { colors } from "@/app/_styles/theme";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
type LoginProps = {
|
||||
session: any;
|
||||
};
|
||||
|
||||
export const Login: FC<LoginProps> = ({ session }) => {
|
||||
const origin =
|
||||
typeof window !== "undefined" && window.location.origin
|
||||
? window.location.origin
|
||||
: "";
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const params = useSearchParams();
|
||||
const error = params.get("error");
|
||||
const { darkGray, cdrLinkOrange, white } = colors;
|
||||
const buttonStyles = {
|
||||
borderRadius: 500,
|
||||
width: "100%",
|
||||
fontSize: "16px",
|
||||
fontWeight: "bold",
|
||||
backgroundColor: white,
|
||||
"&:hover": {
|
||||
color: white,
|
||||
backgroundColor: cdrLinkOrange,
|
||||
},
|
||||
};
|
||||
const fieldStyles = {
|
||||
"& label.Mui-focused": {
|
||||
color: cdrLinkOrange,
|
||||
},
|
||||
"& .MuiInput-underline:after": {
|
||||
borderBottomColor: cdrLinkOrange,
|
||||
},
|
||||
"& .MuiFilledInput-underline:after": {
|
||||
borderBottomColor: cdrLinkOrange,
|
||||
},
|
||||
"& .MuiOutlinedInput-root": {
|
||||
"&.Mui-focused fieldset": {
|
||||
borderColor: cdrLinkOrange,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: darkGray, height: "100vh" }}>
|
||||
<Container maxWidth="md" sx={{ p: 10 }}>
|
||||
<Grid container spacing={2} direction="column" alignItems="center">
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
direction="row"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid item>
|
||||
<Box
|
||||
sx={{
|
||||
width: "70px",
|
||||
height: "70px",
|
||||
margin: "0 auto",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={LinkLogo}
|
||||
alt="Link logo"
|
||||
width={70}
|
||||
height={70}
|
||||
style={{
|
||||
objectFit: "cover",
|
||||
filter: "grayscale(100) brightness(100)",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
fontSize: 36,
|
||||
color: "white",
|
||||
fontWeight: 700,
|
||||
mt: 1,
|
||||
ml: 0.5,
|
||||
fontFamily: "Poppins",
|
||||
}}
|
||||
>
|
||||
CDR Bridge
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item sx={{ width: "100%" }}>
|
||||
{!session ? (
|
||||
<Container
|
||||
maxWidth="xs"
|
||||
sx={{
|
||||
p: 3,
|
||||
mt: 3,
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
spacing={3}
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
>
|
||||
{error ? (
|
||||
<Grid item sx={{ width: "100%" }}>
|
||||
<Box sx={{ backgroundColor: "red", p: 3 }}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
fontSize: 18,
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
{`${error} error`}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
) : null}
|
||||
<Grid item sx={{ width: "100%" }}>
|
||||
<IconButton
|
||||
sx={buttonStyles}
|
||||
onClick={() =>
|
||||
signIn("google", {
|
||||
callbackUrl: `${origin}`,
|
||||
})
|
||||
}
|
||||
>
|
||||
<GoogleIcon sx={{ mr: 1 }} />
|
||||
Sign in with Google
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item sx={{ width: "100%" }}>
|
||||
<IconButton
|
||||
aria-label="Sign in with Apple"
|
||||
sx={buttonStyles}
|
||||
onClick={() =>
|
||||
signIn("apple", {
|
||||
callbackUrl: `${window.location.origin}`,
|
||||
})
|
||||
}
|
||||
>
|
||||
<AppleIcon sx={{ mr: 1 }} />
|
||||
Sign in with Apple
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
) : null}
|
||||
{session ? (
|
||||
<Box component="h4">
|
||||
{` ${session.user.name ?? session.user.email}.`}
|
||||
</Box>
|
||||
) : null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
@ -19,6 +19,7 @@ import {
|
|||
PermPhoneMsg as PhoneIcon,
|
||||
WhatsApp as WhatsAppIcon,
|
||||
Facebook as FacebookIcon,
|
||||
AirlineStops as AirlineStopsIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
|
|
@ -28,7 +29,7 @@ import LinkLogo from "@/public/link-logo-small.png";
|
|||
// import { useSession, signOut } from "next-auth/react";
|
||||
|
||||
const openWidth = 270;
|
||||
const closedWidth = 100;
|
||||
const closedWidth = 70;
|
||||
|
||||
const MenuItem = ({
|
||||
name,
|
||||
|
|
@ -180,7 +181,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
|||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 20,
|
||||
top: 24,
|
||||
right: open ? -8 : -16,
|
||||
color: "#1C75FD",
|
||||
rotate: open ? "90deg" : "-90deg",
|
||||
|
|
@ -191,8 +192,8 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
|||
>
|
||||
<ExpandCircleDownIcon
|
||||
sx={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
width: 24,
|
||||
height: 24,
|
||||
background: "white",
|
||||
borderRadius: 500,
|
||||
}}
|
||||
|
|
@ -308,7 +309,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
|||
}}
|
||||
>
|
||||
<MenuItem
|
||||
name="Whatsapp"
|
||||
name="WhatsApp"
|
||||
href="/whatsapp"
|
||||
selected={pathname.endsWith("/whatsapp")}
|
||||
Icon={WhatsAppIcon}
|
||||
|
|
@ -335,6 +336,13 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
|||
Icon={PhoneIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Webhooks"
|
||||
href="/webhooks"
|
||||
selected={pathname.startsWith("/webhooks")}
|
||||
Icon={AirlineStopsIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Users"
|
||||
href="/users"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import NextAuth from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import { KyselyAdapter } from "@auth/kysely-adapter"
|
||||
import GoogleProvider from "next-auth/providers/google";
|
||||
import { KyselyAdapter } from "@auth/kysely-adapter";
|
||||
import { db } from "./database";
|
||||
|
||||
export const authOptions = NextAuth({
|
||||
export const authOptions = {
|
||||
// @ts-ignore
|
||||
adapter: KyselyAdapter(db),
|
||||
providers: [
|
||||
|
|
@ -12,4 +11,7 @@ export const authOptions = NextAuth({
|
|||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
||||
}),
|
||||
],
|
||||
})
|
||||
session: {
|
||||
strategy: "jwt" as any,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export interface Database {
|
|||
expires: Date;
|
||||
};
|
||||
|
||||
WhatsAppBot: {
|
||||
WhatsappBot: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
phoneNumber: string;
|
||||
|
|
@ -70,7 +70,7 @@ export interface Database {
|
|||
updatedAt: Date;
|
||||
};
|
||||
|
||||
VoiceBot: {
|
||||
VoiceLine: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
createdBy: string;
|
||||
|
|
@ -86,6 +86,14 @@ export interface Database {
|
|||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
Webhook: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
}
|
||||
|
||||
export const db = new KyselyAuth<Database>({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import NextAuth from "next-auth";
|
||||
import { authOptions } from "@/app/_lib/authentication";
|
||||
|
||||
// @ts-expect-error
|
||||
const handler = NextAuth(authOptions);
|
||||
|
||||
export { handler as GET, handler as POST };
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -1,5 +1,4 @@
|
|||
import type { Metadata } from "next";
|
||||
import { InternalLayout } from "./_components/InternalLayout";
|
||||
import { LicenseInfo } from "@mui/x-license";
|
||||
|
||||
LicenseInfo.setLicenseKey(
|
||||
|
|
@ -18,9 +17,7 @@ export default function RootLayout({
|
|||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<InternalLayout>{children}</InternalLayout>
|
||||
</body>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,230 +0,0 @@
|
|||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.description {
|
||||
display: inherit;
|
||||
justify-content: inherit;
|
||||
align-items: inherit;
|
||||
font-size: 0.85rem;
|
||||
max-width: var(--max-width);
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.description a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.description p {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
background-color: rgba(var(--callout-rgb), 0.5);
|
||||
border: 1px solid rgba(var(--callout-border-rgb), 0.3);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.code {
|
||||
font-weight: 700;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(25%, auto));
|
||||
max-width: 100%;
|
||||
width: var(--max-width);
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1rem 1.2rem;
|
||||
border-radius: var(--border-radius);
|
||||
background: rgba(var(--card-rgb), 0);
|
||||
border: 1px solid rgba(var(--card-border-rgb), 0);
|
||||
transition: background 200ms, border 200ms;
|
||||
}
|
||||
|
||||
.card span {
|
||||
display: inline-block;
|
||||
transition: transform 200ms;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.7rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
opacity: 0.6;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
max-width: 30ch;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.center::before {
|
||||
background: var(--secondary-glow);
|
||||
border-radius: 50%;
|
||||
width: 480px;
|
||||
height: 360px;
|
||||
margin-left: -400px;
|
||||
}
|
||||
|
||||
.center::after {
|
||||
background: var(--primary-glow);
|
||||
width: 240px;
|
||||
height: 180px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.center::before,
|
||||
.center::after {
|
||||
content: "";
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
filter: blur(45px);
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
}
|
||||
/* Enable hover only on non-touch devices */
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.card:hover {
|
||||
background: rgba(var(--card-rgb), 0.1);
|
||||
border: 1px solid rgba(var(--card-border-rgb), 0.15);
|
||||
}
|
||||
|
||||
.card:hover span {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
.card:hover span {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 700px) {
|
||||
.content {
|
||||
padding: 4rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
margin-bottom: 120px;
|
||||
max-width: 320px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1rem 2.5rem;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.center {
|
||||
padding: 8rem 0 6rem;
|
||||
}
|
||||
|
||||
.center::before {
|
||||
transform: none;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.description a {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.description p,
|
||||
.description div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.description p {
|
||||
align-items: center;
|
||||
inset: 0 0 auto;
|
||||
padding: 2rem 1rem 1.4rem;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(var(--background-start-rgb), 1),
|
||||
rgba(var(--callout-rgb), 0.5)
|
||||
);
|
||||
background-clip: padding-box;
|
||||
backdrop-filter: blur(24px);
|
||||
}
|
||||
|
||||
.description div {
|
||||
align-items: flex-end;
|
||||
pointer-events: none;
|
||||
inset: auto 0 0;
|
||||
padding: 2rem;
|
||||
height: 200px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent 0%,
|
||||
rgb(var(--background-end-rgb)) 40%
|
||||
);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet and Smaller Desktop */
|
||||
@media (min-width: 701px) and (max-width: 1120px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.vercelLogo {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
24
apps/bridge-frontend/middleware.ts
Normal file
24
apps/bridge-frontend/middleware.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { withAuth } from "next-auth/middleware";
|
||||
|
||||
export default withAuth({
|
||||
pages: {
|
||||
signIn: `/login`,
|
||||
},
|
||||
callbacks: {
|
||||
authorized: ({ token }) => {
|
||||
if (process.env.SETUP_MODE === "true") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token?.email) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const config = {
|
||||
matcher: ["/((?!ws|wss|api|_next/static|_next/image|favicon.ico).*)"],
|
||||
};
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
transpilePackages: ["ui"],
|
||||
experimental: {
|
||||
instrumentationHook: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
3719
package-lock.json
generated
3719
package-lock.json
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -17,7 +17,7 @@ export const List: FC<ListProps> = ({
|
|||
title,
|
||||
rows,
|
||||
columns,
|
||||
onRowClick = () => {},
|
||||
onRowClick,
|
||||
buttons,
|
||||
}) => {
|
||||
const { h3 } = typography;
|
||||
|
|
@ -34,10 +34,11 @@ export const List: FC<ListProps> = ({
|
|||
<Grid item>
|
||||
<Box
|
||||
sx={{
|
||||
mt: 2,
|
||||
backgroundColor: "#ddd",
|
||||
border: 0,
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
height: "calc(100vh - 100px)",
|
||||
".MuiDataGrid-row": {
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
|
|
@ -74,12 +75,12 @@ export const List: FC<ListProps> = ({
|
|||
}}
|
||||
pageSizeOptions={[5, 10, 25]}
|
||||
paginationMode="client"
|
||||
sx={{ height: "100vh" }}
|
||||
sx={{ height: "100%" }}
|
||||
rowHeight={46}
|
||||
scrollbarSize={0}
|
||||
disableVirtualization
|
||||
disableColumnMenu
|
||||
onRowClick={(row: any) => onRowClick(row.id)}
|
||||
onRowClick={(row: any) => onRowClick?.(row.id)}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,8 @@
|
|||
import { LicenseInfo } from "@mui/x-license";
|
||||
|
||||
LicenseInfo.setLicenseKey(
|
||||
"7c9bf25d9e240f76e77cbf7d2ba58a23Tz02NjU4OCxFPTE3MTU4NjIzMzQ2ODgsUz1wcm8sTE09c3Vic2NyaXB0aW9uLEtWPTI=",
|
||||
);
|
||||
|
||||
export { List } from "./components/List";
|
||||
export { fonts, typography, colors } from "./styles/theme";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const playfair = Playfair_Display({
|
|||
});
|
||||
|
||||
const poppins = Poppins({
|
||||
weight: ["400", "700"],
|
||||
weight: ["400", "600", "700"],
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
});
|
||||
|
|
@ -70,7 +70,7 @@ export const typography: any = {
|
|||
},
|
||||
h3: {
|
||||
fontFamily: poppins.style.fontFamily,
|
||||
fontWeight: 400,
|
||||
fontWeight: 600,
|
||||
fontSize: 27,
|
||||
lineHeight: 1.1,
|
||||
margin: 0,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue