add mantine

This commit is contained in:
Kyle Corbitt
2023-06-21 17:29:19 -07:00
parent 3be022786a
commit 0f3c381e1d
14 changed files with 1101 additions and 225 deletions

View File

@@ -11,9 +11,16 @@
"start": "next start"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/server": "^11.11.0",
"@mantine/core": "^6.0.14",
"@mantine/form": "^6.0.14",
"@mantine/hooks": "^6.0.14",
"@mantine/next": "^6.0.14",
"@next-auth/prisma-adapter": "^1.0.5",
"@prisma/client": "^4.14.0",
"@t3-oss/env-nextjs": "^0.3.1",
"@tabler/icons-react": "^2.22.0",
"@tanstack/react-query": "^4.29.7",
"@trpc/client": "^10.26.0",
"@trpc/next": "^10.26.0",

931
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
import { useState } from "react";
import { createStyles, Navbar, Group, Code, getStylesRef, rem } from "@mantine/core";
import {
IconBellRinging,
IconFingerprint,
IconKey,
IconSettings,
Icon2fa,
IconDatabaseImport,
IconReceipt2,
IconSwitchHorizontal,
IconLogout,
} from "@tabler/icons-react";
// import { MantineLogo } from '@mantine/ds';
const useStyles = createStyles((theme) => ({
header: {
paddingBottom: theme.spacing.md,
marginBottom: `calc(${theme.spacing.md} * 1.5)`,
borderBottom: `${rem(1)} solid ${
theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[2]
}`,
},
footer: {
paddingTop: theme.spacing.md,
marginTop: theme.spacing.md,
borderTop: `${rem(1)} solid ${
theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[2]
}`,
},
link: {
...theme.fn.focusStyles(),
display: "flex",
alignItems: "center",
textDecoration: "none",
fontSize: theme.fontSizes.sm,
color: theme.colorScheme === "dark" ? theme.colors.dark[1] : theme.colors.gray[7],
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
borderRadius: theme.radius.sm,
fontWeight: 500,
"&:hover": {
backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0],
color: theme.colorScheme === "dark" ? theme.white : theme.black,
[`& .${getStylesRef("icon")}`]: {
color: theme.colorScheme === "dark" ? theme.white : theme.black,
},
},
},
linkIcon: {
ref: getStylesRef("icon"),
color: theme.colorScheme === "dark" ? theme.colors.dark[2] : theme.colors.gray[6],
marginRight: theme.spacing.sm,
},
linkActive: {
"&, &:hover": {
backgroundColor: theme.fn.variant({ variant: "light", color: theme.primaryColor }).background,
color: theme.fn.variant({ variant: "light", color: theme.primaryColor }).color,
[`& .${getStylesRef("icon")}`]: {
color: theme.fn.variant({ variant: "light", color: theme.primaryColor }).color,
},
},
},
}));
const data = [
{ link: "", label: "Notifications", icon: IconBellRinging },
{ link: "", label: "Billing", icon: IconReceipt2 },
{ link: "", label: "Security", icon: IconFingerprint },
{ link: "", label: "SSH Keys", icon: IconKey },
{ link: "", label: "Databases", icon: IconDatabaseImport },
{ link: "", label: "Authentication", icon: Icon2fa },
{ link: "", label: "Other Settings", icon: IconSettings },
];
export default function AppNav({ children }: { children: React.ReactNode }) {
const { classes, cx } = useStyles();
const [active, setActive] = useState("Billing");
const links = data.map((item) => (
<a
className={cx(classes.link, { [classes.linkActive]: item.label === active })}
href={item.link}
key={item.label}
onClick={(event) => {
event.preventDefault();
setActive(item.label);
}}
>
<item.icon className={classes.linkIcon} stroke={1.5} />
<span>{item.label}</span>
</a>
));
return (
<Group h="100vh">
<Navbar height="100%" width={{ sm: 300 }} p="md">
<Navbar.Section grow>
<Group className={classes.header} position="apart">
{/* <MantineLogo size={28} /> */}
<Code sx={{ fontWeight: 700 }}>v3.1.2</Code>
</Group>
{links}
</Navbar.Section>
<Navbar.Section className={classes.footer}>
<a href="#" className={classes.link} onClick={(event) => event.preventDefault()}>
<IconSwitchHorizontal className={classes.linkIcon} stroke={1.5} />
<span>Change account</span>
</a>
<a href="#" className={classes.link} onClick={(event) => event.preventDefault()}>
<IconLogout className={classes.linkIcon} stroke={1.5} />
<span>Logout</span>
</a>
</Navbar.Section>
</Navbar>
{children}
</Group>
);
}

View File

@@ -2,7 +2,7 @@ import { type Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import { type AppType } from "next/app";
import { api } from "~/utils/api";
import "~/styles/globals.css";
import { MantineProvider } from "@mantine/core";
const MyApp: AppType<{ session: Session | null }> = ({
Component,
@@ -10,7 +10,9 @@ const MyApp: AppType<{ session: Session | null }> = ({
}) => {
return (
<SessionProvider session={session}>
<MantineProvider withGlobalStyles withNormalizeCSS>
<Component {...pageProps} />
</MantineProvider>
</SessionProvider>
);
};

20
src/pages/_document.tsx Normal file
View File

@@ -0,0 +1,20 @@
import { createGetInitialProps } from "@mantine/next";
import Document, { Head, Html, Main, NextScript } from "next/document";
const getInitialProps = createGetInitialProps();
export default class _Document extends Document {
static getInitialProps = getInitialProps;
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

View File

@@ -1,6 +1,6 @@
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { env } from "~/env.mjs";
import { appRouter } from "~/server/api/root";
import { appRouter } from "~/server/api/root.router";
import { createTRPCContext } from "~/server/api/trpc";
// export API handler
@@ -10,9 +10,7 @@ export default createNextApiHandler({
onError:
env.NODE_ENV === "development"
? ({ path, error }) => {
console.error(
`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`,
);
console.error(`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`);
}
: undefined,
});

View File

@@ -0,0 +1,9 @@
import AppNav from "~/components/nav/AppNav";
export default function Experiment() {
return (
<AppNav>
<div>test content</div>
</AppNav>
);
}

View File

@@ -1,149 +0,0 @@
.main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background-image: linear-gradient(to bottom, #2e026d, #15162c);
}
.container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3rem;
padding: 4rem 1rem;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
.title {
font-size: 3rem;
line-height: 1;
font-weight: 800;
letter-spacing: -0.025em;
margin: 0;
color: white;
}
@media (min-width: 640px) {
.title {
font-size: 5rem;
}
}
.pinkSpan {
color: hsl(280 100% 70%);
}
.cardRow {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 1rem;
}
@media (min-width: 640px) {
.cardRow {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 768px) {
.cardRow {
gap: 2rem;
}
}
.card {
max-width: 20rem;
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
border-radius: 0.75rem;
color: white;
background-color: rgb(255 255 255 / 0.1);
}
.card:hover {
background-color: rgb(255 255 255 / 0.2);
transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
}
.cardTitle {
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
margin: 0;
}
.cardText {
font-size: 1.125rem;
line-height: 1.75rem;
}
.showcaseContainer {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.showcaseText {
color: white;
text-align: center;
font-size: 1.5rem;
line-height: 2rem;
}
.authContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
}
.loginButton {
border-radius: 9999px;
background-color: rgb(255 255 255 / 0.1);
padding: 0.75rem 2.5rem;
font-weight: 600;
color: white;
text-decoration-line: none;
transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
}
.loginButton:hover {
background-color: rgb(255 255 255 / 0.2);
}

View File

@@ -27,8 +27,8 @@ export default function Home() {
>
<h3 className={styles.cardTitle}>First Steps </h3>
<div className={styles.cardText}>
Just the basics - Everything you need to know to set up your
database and authentication.
Just the basics - Everything you need to know to set up your database and
authentication.
</div>
</Link>
<Link
@@ -38,8 +38,7 @@ export default function Home() {
>
<h3 className={styles.cardTitle}>Documentation </h3>
<div className={styles.cardText}>
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
Learn more about Create T3 App, the libraries it uses, and how to deploy it.
</div>
</Link>
</div>
@@ -60,7 +59,7 @@ function AuthShowcase() {
const { data: secretMessage } = api.example.getSecretMessage.useQuery(
undefined, // no input
{ enabled: sessionData?.user !== undefined },
{ enabled: sessionData?.user !== undefined }
);
return (

View File

@@ -1,4 +1,4 @@
import { exampleRouter } from "~/server/api/routers/example";
import { promptVariantsRouter } from "~/server/api/routers/promptVariants.router";
import { createTRPCRouter } from "~/server/api/trpc";
/**
@@ -7,7 +7,7 @@ import { createTRPCRouter } from "~/server/api/trpc";
* All routers added in /api/routers should be manually added here.
*/
export const appRouter = createTRPCRouter({
example: exampleRouter,
promptVariants: promptVariantsRouter,
});
// export type definition of API

View File

@@ -1,24 +0,0 @@
import { z } from "zod";
import {
createTRPCRouter,
publicProcedure,
protectedProcedure,
} from "~/server/api/trpc";
export const exampleRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
getAll: publicProcedure.query(({ ctx }) => {
return ctx.prisma.example.findMany();
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
});

View File

@@ -0,0 +1,17 @@
import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db";
export const promptVariantsRouter = createTRPCRouter({
getAll: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => {
return await prisma.promptVariant.findMany({
where: {
experimentId: input.experimentId,
},
});
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
});

View File

@@ -1,16 +0,0 @@
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}

View File

@@ -8,7 +8,7 @@ import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";
import { type AppRouter } from "~/server/api/root";
import { type AppRouter } from "~/server/api/root.router";
const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url