game systems: game system pages, game system create
components: moved DevTool to client component
This commit is contained in:
parent
50e5ff0663
commit
56f0442d33
15
actions/GameSystems/create.ts
Normal file
15
actions/GameSystems/create.ts
Normal file
@ -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;
|
||||
};
|
7
actions/GameSystems/deleteAll.ts
Normal file
7
actions/GameSystems/deleteAll.ts
Normal file
@ -0,0 +1,7 @@
|
||||
"use server";
|
||||
import { prisma } from "@/prisma/prismaClient";
|
||||
|
||||
// DEV TOOL ONLY
|
||||
export async function deleteAllGameSystems() {
|
||||
await prisma.gameSystem.deleteMany();
|
||||
}
|
49
app/game-systems/[id]/page.tsx
Normal file
49
app/game-systems/[id]/page.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<section className="heading">
|
||||
<h2 className="strapline">Game System</h2>
|
||||
<h1>{gameSystem?.name}</h1>
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
{gameSystem?.schemas.map((schema) => (
|
||||
<li key={schema.id}>{schema.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
<Sticky sidedness={-1}>
|
||||
<h1>HELLO!</h1>
|
||||
</Sticky>
|
||||
</>
|
||||
);
|
||||
}
|
26
app/game-systems/client.tsx
Normal file
26
app/game-systems/client.tsx
Normal file
@ -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<PropsWithChildren> = ({ children }) => {
|
||||
const router = useRouter();
|
||||
// DEV TOOL ONLY
|
||||
async function deleteAll() {
|
||||
await deleteAllGameSystems();
|
||||
router.refresh();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DevTool id="game-system-home">
|
||||
<button onClick={deleteAll} className="btn-primary bg-lime-600">
|
||||
Delete All Game Systems
|
||||
</button>
|
||||
</DevTool>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
35
app/game-systems/create.tsx
Normal file
35
app/game-systems/create.tsx
Normal file
@ -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 (
|
||||
<form action={create}>
|
||||
<input
|
||||
type="text"
|
||||
// {...bind}
|
||||
name="name"
|
||||
placeholder="Create a new game system..."
|
||||
className="w-min"
|
||||
/>
|
||||
<button className="btn-primary p-2 px-2 ml-2" type="submit">
|
||||
Create
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
33
app/game-systems/page.tsx
Normal file
33
app/game-systems/page.tsx
Normal file
@ -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 (
|
||||
<GameSystemsClient>
|
||||
<section className="heading">
|
||||
<h2 className="strapline">Tabletop Commander</h2>
|
||||
<h1>Game Systems</h1>
|
||||
</section>
|
||||
<section className="mb-6">
|
||||
<CreateGameSystem />
|
||||
</section>
|
||||
<section className="">
|
||||
<ul>
|
||||
{existingGameSystems.map((g) => (
|
||||
<li key={g.id} className="odd:bg-black/20 p-2 text-lg">
|
||||
<Link href={`/game-systems/${g.id}`}>{g.name}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
</GameSystemsClient>
|
||||
);
|
||||
}
|
16
components/devtools/DevTool.tsx
Normal file
16
components/devtools/DevTool.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { FC, PropsWithChildren, use, useEffect } from "react";
|
||||
import { DevToolboxContext } from "./context";
|
||||
|
||||
export const DevTool: FC<PropsWithChildren<{ id: string }>> = (
|
||||
{ children, id },
|
||||
) => {
|
||||
const { addTool, removeTool } = use(DevToolboxContext);
|
||||
useEffect(() => {
|
||||
addTool(id, children);
|
||||
(() => removeTool(id));
|
||||
}, [addTool, children, id, removeTool]);
|
||||
|
||||
return <></>;
|
||||
};
|
@ -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<PropsWithChildren<{ id: string }>> = (
|
||||
{ children, id },
|
||||
) => {
|
||||
const { addTool, removeTool } = use(DevToolboxContext);
|
||||
useEffect(() => {
|
||||
addTool(id, children);
|
||||
(() => removeTool(id));
|
||||
}, [addTool, children, id, removeTool]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
@ -9,20 +9,17 @@ interface IProps {
|
||||
export const Portal: FC<PropsWithChildren<IProps>> = (
|
||||
{ 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<HTMLElement>();
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
13
prisma/prismaClient.ts
Normal file
13
prisma/prismaClient.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prismaClientSingleton = () => {
|
||||
return new PrismaClient();
|
||||
};
|
||||
|
||||
declare global {
|
||||
var prismaGlobal: undefined | ReturnType<typeof prismaClientSingleton>;
|
||||
}
|
||||
|
||||
export const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;
|
Loading…
x
Reference in New Issue
Block a user