diff --git a/actions/GameSystems/create.ts b/actions/GameSystems/create.ts
new file mode 100644
index 0000000..bb5bf9e
--- /dev/null
+++ b/actions/GameSystems/create.ts
@@ -0,0 +1,15 @@
+"use server";
+
+import { prisma } from "@/prisma/prismaClient";
+
+export const createGameSystem = async (name: string) => {
+ const { id } = await prisma.gameSystem.create({
+ data: {
+ name,
+ },
+ select: {
+ id: true,
+ },
+ });
+ return id;
+};
diff --git a/actions/GameSystems/deleteAll.ts b/actions/GameSystems/deleteAll.ts
new file mode 100644
index 0000000..c486aa6
--- /dev/null
+++ b/actions/GameSystems/deleteAll.ts
@@ -0,0 +1,7 @@
+"use server";
+import { prisma } from "@/prisma/prismaClient";
+
+// DEV TOOL ONLY
+export async function deleteAllGameSystems() {
+ await prisma.gameSystem.deleteMany();
+}
diff --git a/app/game-systems/[id]/page.tsx b/app/game-systems/[id]/page.tsx
new file mode 100644
index 0000000..dbb24d8
--- /dev/null
+++ b/app/game-systems/[id]/page.tsx
@@ -0,0 +1,49 @@
+import { Sticky } from "@/lib/sticky";
+import { prisma } from "@/prisma/prismaClient";
+
+export default async function GameSystem(
+ { params: { id } }: { params: { id: string } },
+) {
+ if (!id) throw "HOW DID YOU GET HERE?";
+
+ const gameSystem = await prisma.gameSystem.findFirst({
+ where: {
+ id,
+ },
+ select: {
+ id: true,
+ name: true,
+ schemas: {
+ select: {
+ name: true,
+ id: true,
+ publications: {
+ select: {
+ name: true,
+ id: true,
+ },
+ },
+ },
+ },
+ },
+ });
+
+ return (
+ <>
+
+ Game System
+ {gameSystem?.name}
+
+
+
+ {gameSystem?.schemas.map((schema) => (
+ - {schema.name}
+ ))}
+
+
+
+ HELLO!
+
+ >
+ );
+}
diff --git a/app/game-systems/client.tsx b/app/game-systems/client.tsx
new file mode 100644
index 0000000..81b625a
--- /dev/null
+++ b/app/game-systems/client.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import { deleteAllGameSystems } from "@/actions/GameSystems/deleteAll";
+import { DevTool } from "@/components/devtools/DevTool";
+import { useRouter } from "next/navigation";
+import { FC, PropsWithChildren } from "react";
+
+export const GameSystemsClient: FC = ({ children }) => {
+ const router = useRouter();
+ // DEV TOOL ONLY
+ async function deleteAll() {
+ await deleteAllGameSystems();
+ router.refresh();
+ }
+
+ return (
+ <>
+
+
+
+ {children}
+ >
+ );
+};
diff --git a/app/game-systems/create.tsx b/app/game-systems/create.tsx
new file mode 100644
index 0000000..f55a2a1
--- /dev/null
+++ b/app/game-systems/create.tsx
@@ -0,0 +1,35 @@
+import { prisma } from "@/prisma/prismaClient";
+import { redirect } from "next/navigation";
+
+export default function CreateGameSystem() {
+ async function create(form: FormData) {
+ "use server";
+
+ const name = form.get("name")?.toString();
+ if (!name) return;
+ const { id } = await prisma.gameSystem.create({
+ data: {
+ name,
+ },
+ select: {
+ id: true,
+ },
+ });
+ redirect(`/game-systems/${id}`);
+ }
+
+ return (
+
+ );
+}
diff --git a/app/game-systems/page.tsx b/app/game-systems/page.tsx
new file mode 100644
index 0000000..1d90f58
--- /dev/null
+++ b/app/game-systems/page.tsx
@@ -0,0 +1,33 @@
+import { prisma } from "@/prisma/prismaClient";
+import CreateGameSystem from "./create";
+import { GameSystemsClient } from "./client";
+import Link from "next/link";
+
+export default async function GameSystems() {
+ const existingGameSystems = await prisma.gameSystem.findMany({
+ orderBy: {
+ created: "asc",
+ },
+ });
+
+ return (
+
+
+ Tabletop Commander
+ Game Systems
+
+
+
+
+ {existingGameSystems.map((g) => (
+ -
+ {g.name}
+
+ ))}
+
+
+
+ );
+}
diff --git a/components/devtools/DevTool.tsx b/components/devtools/DevTool.tsx
new file mode 100644
index 0000000..f1c0539
--- /dev/null
+++ b/components/devtools/DevTool.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import { FC, PropsWithChildren, use, useEffect } from "react";
+import { DevToolboxContext } from "./context";
+
+export const DevTool: FC> = (
+ { children, id },
+) => {
+ const { addTool, removeTool } = use(DevToolboxContext);
+ useEffect(() => {
+ addTool(id, children);
+ (() => removeTool(id));
+ }, [addTool, children, id, removeTool]);
+
+ return <>>;
+};
diff --git a/components/devtools/Toolbox.tsx b/components/devtools/Toolbox.tsx
index a45f130..5764377 100644
--- a/components/devtools/Toolbox.tsx
+++ b/components/devtools/Toolbox.tsx
@@ -1,5 +1,5 @@
import { Portal } from "@/lib/portal/components";
-import { FC, PropsWithChildren, use, useEffect, useState } from "react";
+import { FC, use, useState } from "react";
import { DevToolboxContext } from "./context";
import { WrenchScrewdriverIcon } from "@heroicons/react/24/solid";
import { XMarkIcon } from "@heroicons/react/16/solid";
@@ -38,15 +38,3 @@ export const DevToolbox: FC = () => {
)
: <>>;
};
-
-export const DevTool: FC> = (
- { children, id },
-) => {
- const { addTool, removeTool } = use(DevToolboxContext);
- useEffect(() => {
- addTool(id, children);
- (() => removeTool(id));
- }, [addTool, children, id, removeTool]);
-
- return <>>;
-};
diff --git a/lib/portal/components/index.ts b/lib/portal/components/index.ts
index 5d5690a..e0590c2 100644
--- a/lib/portal/components/index.ts
+++ b/lib/portal/components/index.ts
@@ -9,20 +9,17 @@ interface IProps {
export const Portal: FC> = (
{ children, className = "root-portal", el = "div" },
) => {
- const [container] = useState(() => {
- // This will be executed only on the initial render
- // https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
- return document.createElement(el);
- });
+ const [container, setContainer] = useState();
- // todo: this smells. appending the same element?
useEffect(() => {
+ const container = document.createElement(el);
container.classList.add(className);
document.body.appendChild(container);
+ setContainer(container);
return () => {
document.body.removeChild(container);
};
- }, [className, container]);
+ }, [className, el]);
- return createPortal(children, container);
+ return container && createPortal(children, container);
};
diff --git a/prisma/prismaClient.ts b/prisma/prismaClient.ts
new file mode 100644
index 0000000..ba52e49
--- /dev/null
+++ b/prisma/prismaClient.ts
@@ -0,0 +1,13 @@
+import { PrismaClient } from "@prisma/client";
+
+const prismaClientSingleton = () => {
+ return new PrismaClient();
+};
+
+declare global {
+ var prismaGlobal: undefined | ReturnType;
+}
+
+export const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
+
+if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;