Add metamigo-frontend
This commit is contained in:
parent
486f989494
commit
4e0b5ae215
46 changed files with 1695 additions and 0 deletions
21
apps/metamigo-frontend/app/_components/InternalLayout.tsx
Normal file
21
apps/metamigo-frontend/app/_components/InternalLayout.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
"use client";
|
||||
|
||||
import { FC, PropsWithChildren, useState } from "react";
|
||||
import { Grid } from "@mui/material";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
export const InternalLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
||||
return (
|
||||
<Grid container direction="row">
|
||||
<Sidebar open={open} setOpen={setOpen} />
|
||||
<Grid
|
||||
item
|
||||
sx={{ ml: open ? "270px" : "100px", width: "100%", height: "100vh" }}
|
||||
>
|
||||
{children as any}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
84
apps/metamigo-frontend/app/_components/List.tsx
Normal file
84
apps/metamigo-frontend/app/_components/List.tsx
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { Grid, Box } from "@mui/material";
|
||||
import { DataGridPro, GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
interface ListProps {
|
||||
title: string;
|
||||
entity: string;
|
||||
rows: any;
|
||||
columns: GridColDef<any>[];
|
||||
}
|
||||
|
||||
export const List: FC<ListProps> = ({ title, entity, rows, columns }) => {
|
||||
const router = useRouter();
|
||||
|
||||
const onRowClick = (id: string) => {
|
||||
router.push(`/${entity}/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
|
||||
<Grid container direction="column">
|
||||
<Grid item>
|
||||
<h1>{title}</h1>
|
||||
</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
|
||||
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)}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
349
apps/metamigo-frontend/app/_components/Sidebar.tsx
Normal file
349
apps/metamigo-frontend/app/_components/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
Box,
|
||||
Grid,
|
||||
Typography,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
ListItemSecondaryAction,
|
||||
Drawer,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
ExpandCircleDown as ExpandCircleDownIcon,
|
||||
AccountCircle as AccountCircleIcon,
|
||||
Chat as ChatIcon,
|
||||
PermPhoneMsg as PhoneIcon,
|
||||
WhatsApp as WhatsAppIcon,
|
||||
Facebook as FacebookIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
// import LinkLogo from "public/link-logo-small.png";
|
||||
// import { useSession, signOut } from "next-auth/react";
|
||||
|
||||
const openWidth = 270;
|
||||
const closedWidth = 100;
|
||||
|
||||
const MenuItem = ({
|
||||
name,
|
||||
href,
|
||||
Icon,
|
||||
iconSize,
|
||||
inset = false,
|
||||
selected = false,
|
||||
open = true,
|
||||
badge,
|
||||
target = "_self",
|
||||
}: any) => (
|
||||
<Link href={href} target={target}>
|
||||
<ListItemButton
|
||||
sx={{
|
||||
p: 0,
|
||||
mb: 1,
|
||||
bl: iconSize === 0 ? "1px solid white" : "inherit",
|
||||
}}
|
||||
selected={selected}
|
||||
>
|
||||
{iconSize > 0 ? (
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
color: `white`,
|
||||
minWidth: 0,
|
||||
mr: 2,
|
||||
textAlign: "center",
|
||||
margin: open ? "0 8 0 0" : "0 auto",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
mr: 0.5,
|
||||
mt: "-4px",
|
||||
}}
|
||||
>
|
||||
<Icon />
|
||||
</Box>
|
||||
</ListItemIcon>
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
width: 30,
|
||||
height: "28px",
|
||||
position: "relative",
|
||||
ml: "9px",
|
||||
mr: "1px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: "1px",
|
||||
height: "56px",
|
||||
backgroundColor: "white",
|
||||
position: "absolute",
|
||||
left: "3px",
|
||||
top: "-10px",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
width: "42px",
|
||||
height: "42px",
|
||||
position: "absolute",
|
||||
top: "-27px",
|
||||
left: "3px",
|
||||
border: "solid 1px #fff",
|
||||
borderColor: "transparent transparent transparent #fff",
|
||||
borderRadius: "60px",
|
||||
rotate: "-35deg",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{open && (
|
||||
<ListItemText
|
||||
inset={inset}
|
||||
primary={
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
fontFamily: "Roboto",
|
||||
fontWeight: "bold",
|
||||
border: 0,
|
||||
textAlign: "left",
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{badge && badge > 0 ? (
|
||||
<ListItemSecondaryAction>
|
||||
<Typography
|
||||
color="textSecondary"
|
||||
variant="body1"
|
||||
className="badge"
|
||||
sx={{
|
||||
backgroundColor: "#FFB620",
|
||||
color: "black !important",
|
||||
borderRadius: 10,
|
||||
px: 1,
|
||||
fontSize: 12,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{badge}
|
||||
</Typography>
|
||||
</ListItemSecondaryAction>
|
||||
) : null}
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
);
|
||||
|
||||
interface SidebarProps {
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||
const pathname = usePathname();
|
||||
// const { data: session } = useSession();
|
||||
// const username = session?.user?.name || "User";
|
||||
|
||||
// const logout = () => {
|
||||
// signOut({ callbackUrl: "/login" });
|
||||
// };
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
sx={{ width: open ? openWidth : closedWidth, flexShrink: 0 }}
|
||||
variant="permanent"
|
||||
anchor="left"
|
||||
open={open}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
width: open ? openWidth : closedWidth,
|
||||
border: 0,
|
||||
overflow: "visible",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 20,
|
||||
right: open ? -8 : -16,
|
||||
color: "#1C75FD",
|
||||
rotate: open ? "90deg" : "-90deg",
|
||||
}}
|
||||
onClick={() => {
|
||||
setOpen!(!open);
|
||||
}}
|
||||
>
|
||||
<ExpandCircleDownIcon
|
||||
sx={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
background: "white",
|
||||
borderRadius: 500,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
wrap="nowrap"
|
||||
spacing={0}
|
||||
sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }}
|
||||
>
|
||||
<Grid item container>
|
||||
<Grid item sx={{ width: open ? "40px" : "100%" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: "40px",
|
||||
height: "40px",
|
||||
margin: open ? "0" : "0 auto",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={"" /* LinkLogo */}
|
||||
alt="Link logo"
|
||||
width={40}
|
||||
height={40}
|
||||
style={{
|
||||
objectFit: "cover",
|
||||
filter: "grayscale(100) brightness(100)",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
.
|
||||
</Grid>
|
||||
{open && (
|
||||
<Grid item>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
fontSize: 26,
|
||||
color: "white",
|
||||
fontWeight: 700,
|
||||
mt: 1,
|
||||
ml: 0.5,
|
||||
fontFamily: "Poppins",
|
||||
}}
|
||||
>
|
||||
Metamigo
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Box
|
||||
sx={{
|
||||
height: "0.5px",
|
||||
width: "100%",
|
||||
backgroundColor: "#666",
|
||||
mb: 1,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
direction="column"
|
||||
sx={{
|
||||
mt: "6px",
|
||||
overflow: "scroll",
|
||||
scrollbarWidth: "none",
|
||||
msOverflowStyle: "none",
|
||||
"&::-webkit-scrollbar": { display: "none" },
|
||||
}}
|
||||
flexGrow={1}
|
||||
>
|
||||
<List
|
||||
component="nav"
|
||||
sx={{
|
||||
a: {
|
||||
textDecoration: "none",
|
||||
|
||||
".MuiListItemButton-root": {
|
||||
p: 1,
|
||||
borderRadius: 2,
|
||||
"&:hover": {
|
||||
background: "#555",
|
||||
},
|
||||
".MuiTypography-root": {
|
||||
p: {
|
||||
color: "#999 !important",
|
||||
fontSize: 16,
|
||||
},
|
||||
},
|
||||
".badge": {
|
||||
p: { fontSize: 12, color: "black !important" },
|
||||
},
|
||||
},
|
||||
".Mui-selected": {
|
||||
background: "#444",
|
||||
color: "#fff !important",
|
||||
".MuiTypography-root": {
|
||||
p: {
|
||||
color: "#fff !important",
|
||||
fontSize: 16,
|
||||
},
|
||||
},
|
||||
".badge": {
|
||||
p: { fontSize: 12, color: "black !important" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
name="Whatsapp"
|
||||
href="/whatsapp"
|
||||
selected={pathname.endsWith("/whatsapp")}
|
||||
Icon={WhatsAppIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Signal"
|
||||
href="/signal"
|
||||
selected={pathname.startsWith("/signal")}
|
||||
Icon={ChatIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Facebook"
|
||||
href="/facebook"
|
||||
selected={pathname.startsWith("/facebook")}
|
||||
Icon={FacebookIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Voice"
|
||||
href="/voice"
|
||||
selected={pathname.startsWith("/voice")}
|
||||
Icon={PhoneIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
<MenuItem
|
||||
name="Users"
|
||||
href="/users"
|
||||
selected={pathname.startsWith("/users")}
|
||||
Icon={AccountCircleIcon}
|
||||
iconSize={20}
|
||||
/>
|
||||
</List>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
0
apps/metamigo-frontend/app/_lib/database.ts
Normal file
0
apps/metamigo-frontend/app/_lib/database.ts
Normal file
0
apps/metamigo-frontend/app/_lib/facebook.ts
Normal file
0
apps/metamigo-frontend/app/_lib/facebook.ts
Normal file
0
apps/metamigo-frontend/app/_lib/routing.ts
Normal file
0
apps/metamigo-frontend/app/_lib/routing.ts
Normal file
0
apps/metamigo-frontend/app/_lib/signal.ts
Normal file
0
apps/metamigo-frontend/app/_lib/signal.ts
Normal file
0
apps/metamigo-frontend/app/_lib/voice.ts
Normal file
0
apps/metamigo-frontend/app/_lib/voice.ts
Normal file
0
apps/metamigo-frontend/app/_lib/whatsapp.ts
Normal file
0
apps/metamigo-frontend/app/_lib/whatsapp.ts
Normal file
107
apps/metamigo-frontend/app/_styles/globals.css
Normal file
107
apps/metamigo-frontend/app/_styles/globals.css
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
:root {
|
||||
--max-width: 1100px;
|
||||
--border-radius: 12px;
|
||||
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
|
||||
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
|
||||
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
|
||||
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
|
||||
--primary-glow: conic-gradient(
|
||||
from 180deg at 50% 50%,
|
||||
#16abff33 0deg,
|
||||
#0885ff33 55deg,
|
||||
#54d6ff33 120deg,
|
||||
#0071ff33 160deg,
|
||||
transparent 360deg
|
||||
);
|
||||
--secondary-glow: radial-gradient(
|
||||
rgba(255, 255, 255, 1),
|
||||
rgba(255, 255, 255, 0)
|
||||
);
|
||||
|
||||
--tile-start-rgb: 239, 245, 249;
|
||||
--tile-end-rgb: 228, 232, 233;
|
||||
--tile-border: conic-gradient(
|
||||
#00000080,
|
||||
#00000040,
|
||||
#00000030,
|
||||
#00000020,
|
||||
#00000010,
|
||||
#00000010,
|
||||
#00000080
|
||||
);
|
||||
|
||||
--callout-rgb: 238, 240, 241;
|
||||
--callout-border-rgb: 172, 175, 176;
|
||||
--card-rgb: 180, 185, 188;
|
||||
--card-border-rgb: 131, 134, 135;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
|
||||
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
|
||||
--secondary-glow: linear-gradient(
|
||||
to bottom right,
|
||||
rgba(1, 65, 255, 0),
|
||||
rgba(1, 65, 255, 0),
|
||||
rgba(1, 65, 255, 0.3)
|
||||
);
|
||||
|
||||
--tile-start-rgb: 2, 13, 46;
|
||||
--tile-end-rgb: 2, 5, 19;
|
||||
--tile-border: conic-gradient(
|
||||
#ffffff80,
|
||||
#ffffff40,
|
||||
#ffffff30,
|
||||
#ffffff20,
|
||||
#ffffff10,
|
||||
#ffffff10,
|
||||
#ffffff80
|
||||
);
|
||||
|
||||
--callout-rgb: 20, 20, 20;
|
||||
--callout-border-rgb: 108, 108, 108;
|
||||
--card-rgb: 100, 100, 100;
|
||||
--card-border-rgb: 200, 200, 200;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
0
apps/metamigo-frontend/app/api/[service]/bots/route.ts
Normal file
0
apps/metamigo-frontend/app/api/[service]/bots/route.ts
Normal file
3
apps/metamigo-frontend/app/facebook/[id]/edit/page.tsx
Normal file
3
apps/metamigo-frontend/app/facebook/[id]/edit/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Facebook view</h1>;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/facebook/[id]/page.tsx
Normal file
3
apps/metamigo-frontend/app/facebook/[id]/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Facebook view</h1>;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/facebook/new/page.tsx
Normal file
3
apps/metamigo-frontend/app/facebook/new/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Facebook Home</h1>;
|
||||
}
|
||||
46
apps/metamigo-frontend/app/facebook/page.tsx
Normal file
46
apps/metamigo-frontend/app/facebook/page.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"use client";
|
||||
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "phoneNumber",
|
||||
headerName: "Phone Number",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "createdAt",
|
||||
headerName: "Created At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.createdAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "updatedAt",
|
||||
headerName: "Updated At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.updatedAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<List title="Facebook" entity="facebook" rows={rows} columns={columns} />
|
||||
);
|
||||
}
|
||||
BIN
apps/metamigo-frontend/app/favicon.ico
Normal file
BIN
apps/metamigo-frontend/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
25
apps/metamigo-frontend/app/layout.tsx
Normal file
25
apps/metamigo-frontend/app/layout.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import { InternalLayout } from "./_components/InternalLayout";
|
||||
import "./_styles/globals.css";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Metamigo",
|
||||
description: "",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<InternalLayout>{children}</InternalLayout>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
230
apps/metamigo-frontend/app/page.module.css
Normal file
230
apps/metamigo-frontend/app/page.module.css
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
.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);
|
||||
}
|
||||
}
|
||||
3
apps/metamigo-frontend/app/page.tsx
Normal file
3
apps/metamigo-frontend/app/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Home</h1>;
|
||||
}
|
||||
0
apps/metamigo-frontend/app/signal/[id]/page.tsx
Normal file
0
apps/metamigo-frontend/app/signal/[id]/page.tsx
Normal file
0
apps/metamigo-frontend/app/signal/new/page.tsx
Normal file
0
apps/metamigo-frontend/app/signal/new/page.tsx
Normal file
46
apps/metamigo-frontend/app/signal/page.tsx
Normal file
46
apps/metamigo-frontend/app/signal/page.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"use client";
|
||||
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "phoneNumber",
|
||||
headerName: "Phone Number",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "createdAt",
|
||||
headerName: "Created At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.createdAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "updatedAt",
|
||||
headerName: "Updated At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.updatedAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<List title="Signal Bots" entity="signal" rows={rows} columns={columns} />
|
||||
);
|
||||
}
|
||||
44
apps/metamigo-frontend/app/users/page.tsx
Normal file
44
apps/metamigo-frontend/app/users/page.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"use client";
|
||||
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "phoneNumber",
|
||||
headerName: "Phone Number",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "createdAt",
|
||||
headerName: "Created At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.createdAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "updatedAt",
|
||||
headerName: "Updated At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.updatedAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return <List title="Users" entity="users" rows={rows} columns={columns} />;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/voice/[id]/edit/page.tsx
Normal file
3
apps/metamigo-frontend/app/voice/[id]/edit/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Voice Edit</h1>;
|
||||
}
|
||||
0
apps/metamigo-frontend/app/voice/[id]/page.tsx
Normal file
0
apps/metamigo-frontend/app/voice/[id]/page.tsx
Normal file
0
apps/metamigo-frontend/app/voice/new/page.tsx
Normal file
0
apps/metamigo-frontend/app/voice/new/page.tsx
Normal file
46
apps/metamigo-frontend/app/voice/page.tsx
Normal file
46
apps/metamigo-frontend/app/voice/page.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"use client";
|
||||
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "phoneNumber",
|
||||
headerName: "Phone Number",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "createdAt",
|
||||
headerName: "Created At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.createdAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "updatedAt",
|
||||
headerName: "Updated At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.updatedAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<List title="Voice bots" entity="users" rows={rows} columns={columns} />
|
||||
);
|
||||
}
|
||||
3
apps/metamigo-frontend/app/whatsapp/[id]/edit/page.tsx
Normal file
3
apps/metamigo-frontend/app/whatsapp/[id]/edit/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Whatsapp edit</h1>;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/whatsapp/[id]/page.tsx
Normal file
3
apps/metamigo-frontend/app/whatsapp/[id]/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Whatsapp View</h1>;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/whatsapp/new/page.tsx
Normal file
3
apps/metamigo-frontend/app/whatsapp/new/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <h1>Whatsapp new</h1>;
|
||||
}
|
||||
105
apps/metamigo-frontend/app/whatsapp/page.tsx
Normal file
105
apps/metamigo-frontend/app/whatsapp/page.tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
"use client";
|
||||
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { List } from "@/app/_components/List";
|
||||
|
||||
export default function Page() {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "phoneNumber",
|
||||
headerName: "Phone Number",
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
field: "createdAt",
|
||||
headerName: "Created At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.createdAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
field: "updatedAt",
|
||||
headerName: "Updated At",
|
||||
valueGetter: (params: any) =>
|
||||
new Date(params.row?.updatedAt).toLocaleString(),
|
||||
flex: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{
|
||||
id: 1,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
phoneNumber: "1234567890",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<List
|
||||
title="Whatsapp Bots"
|
||||
entity="whatsapp"
|
||||
rows={rows}
|
||||
columns={columns}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue