trpc demo
This commit is contained in:
3
src/app/_trpc/Client.ts
Normal file
3
src/app/_trpc/Client.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { createTRPCReact } from "@trpc/react-query";
|
||||
import type { TrpcRouter } from "~/server/routers/_app";
|
||||
export const trpc = createTRPCReact<TrpcRouter>({})
|
||||
22
src/app/_trpc/ServerClient.ts
Normal file
22
src/app/_trpc/ServerClient.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { httpBatchLink } from "@trpc/client";
|
||||
import { trpcRouter } from "~/server/routers/_app";
|
||||
|
||||
function getBaseUrl() {
|
||||
if (typeof window !== 'undefined')
|
||||
// browser should use relative path
|
||||
return '';
|
||||
if (process.env.VERCEL_URL)
|
||||
// reference for vercel.com
|
||||
return `https://${process.env.VERCEL_URL}`;
|
||||
if (process.env.RENDER_INTERNAL_HOSTNAME)
|
||||
// reference for render.com
|
||||
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
|
||||
// assume localhost
|
||||
return `http://localhost:${process.env.PORT ?? 3000}`;
|
||||
};
|
||||
|
||||
export const servTrpc = trpcRouter.createCaller({
|
||||
links: [
|
||||
httpBatchLink({url: `${getBaseUrl()}/api/trpc`}),
|
||||
],
|
||||
});
|
||||
38
src/app/_trpc/TrpcProvider.tsx
Normal file
38
src/app/_trpc/TrpcProvider.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
'use client'
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { httpBatchLink } from "@trpc/client";
|
||||
import React, { useState } from "react"
|
||||
import { trpc } from "./Client";
|
||||
|
||||
function getBaseUrl() {
|
||||
if (typeof window !== 'undefined')
|
||||
// browser should use relative path
|
||||
return '';
|
||||
if (process.env.VERCEL_URL)
|
||||
// reference for vercel.com
|
||||
return `https://${process.env.VERCEL_URL}`;
|
||||
if (process.env.RENDER_INTERNAL_HOSTNAME)
|
||||
// reference for render.com
|
||||
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
|
||||
// assume localhost
|
||||
return `http://localhost:${process.env.PORT ?? 3000}`;
|
||||
}
|
||||
|
||||
export default function TrpcProvider({children}:{children: React.ReactNode}) {
|
||||
const [queryClient] = useState(() => new QueryClient({}));
|
||||
const [trpcClient] = useState(() => {
|
||||
return trpc.createClient({
|
||||
links: [
|
||||
httpBatchLink({
|
||||
url: `${getBaseUrl()}/api/trpc`,
|
||||
}),
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
||||
<QueryClientProvider client={queryClient}> {children} </QueryClientProvider>
|
||||
</trpc.Provider>
|
||||
)
|
||||
}
|
||||
10
src/app/api/trpc/[trpc]/route.ts
Normal file
10
src/app/api/trpc/[trpc]/route.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
|
||||
import { trpcRouter } from '~/server/routers/_app'
|
||||
const handler = (req: Request) => fetchRequestHandler({
|
||||
endpoint: "/api/trpc",
|
||||
req,
|
||||
router: trpcRouter,
|
||||
createContext: () => ({}),
|
||||
});
|
||||
|
||||
export {handler as GET, handler as POST}
|
||||
26
src/app/cv/_components/CvCategory.tsx
Normal file
26
src/app/cv/_components/CvCategory.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { trpc } from "~/app/_trpc/Client"
|
||||
import CvEntry, { type CvEntryProps } from "./CvEntry"
|
||||
import type { servTrpc } from "~/app/_trpc/ServerClient"
|
||||
type CvCategoryProps = {
|
||||
initialData: Awaited<ReturnType<typeof servTrpc.cvCategory.get>>,
|
||||
children?: React.ReactElement<CvEntryProps>
|
||||
}
|
||||
export default function CvCategory(props:CvCategoryProps) {
|
||||
const cvCategories = trpc.cvCategory.get.useQuery(undefined,{
|
||||
initialData: props.initialData,
|
||||
refetchOnMount: false,
|
||||
refetchOnReconnect: false,
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
{cvCategories.data.map((cat) => {
|
||||
return (
|
||||
<div key={cat.id}>
|
||||
{cat.name}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
7
src/app/cv/_components/CvEntry.tsx
Normal file
7
src/app/cv/_components/CvEntry.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { cvEntry } from "~/server/db/schema"
|
||||
|
||||
export type CvEntryProps = typeof cvEntry
|
||||
|
||||
export default function CvEntry(cvEntry: CvEntryProps) {
|
||||
return (<></>)
|
||||
}
|
||||
3
src/app/cv/_components/CvLayout.tsx
Normal file
3
src/app/cv/_components/CvLayout.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function CvLayout({children,}: Readonly<{ children: React.ReactNode }>) {
|
||||
return (<></>)
|
||||
}
|
||||
@@ -1,18 +1,10 @@
|
||||
import { getCvCategories } from "~/server/db/query"
|
||||
|
||||
import { servTrpc } from "~/app/_trpc/ServerClient"
|
||||
import CvCategory from "./_components/CvCategory";
|
||||
export default async function CvPage() {
|
||||
const cvCategories = await getCvCategories();
|
||||
const cvCategories = await servTrpc.cvCategory.get();
|
||||
return (
|
||||
<div>
|
||||
{cvCategories.map((category) => {
|
||||
return (
|
||||
<div key={category.id}>
|
||||
<div>
|
||||
{category.name}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<CvCategory initialData={cvCategories}>
|
||||
<></>
|
||||
</CvCategory>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ClerkProvider } from "@clerk/nextjs";
|
||||
import { config } from "@fortawesome/fontawesome-svg-core"
|
||||
import "@fortawesome/fontawesome-svg-core/styles.css"
|
||||
import TopNav from "./_components/TopNav";
|
||||
import TrpcProvider from "./_trpc/TrpcProvider";
|
||||
config.autoAddCss = false;
|
||||
export const metadata: Metadata = {
|
||||
title: "Gregor Lohaus",
|
||||
@@ -24,13 +25,15 @@ export default function RootLayout({
|
||||
}: Readonly<{ children: React.ReactNode, modal: React.ReactNode }>) {
|
||||
return (
|
||||
<ClerkProvider>
|
||||
<html lang="en" className={`${geist.variable}`}>
|
||||
<body className="flex flex-col gap-2 bg-black text-white">
|
||||
<TopNav/>
|
||||
{children}
|
||||
{modal}
|
||||
</body>
|
||||
</html>
|
||||
<TrpcProvider>
|
||||
<html lang="en" className={`${geist.variable}`}>
|
||||
<body className="flex flex-col gap-2 bg-black text-white">
|
||||
<TopNav/>
|
||||
{children}
|
||||
{modal}
|
||||
</body>
|
||||
</html>
|
||||
</TrpcProvider>
|
||||
</ClerkProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import "server-only"
|
||||
import { db } from "."
|
||||
|
||||
export async function getCvCategories() {
|
||||
const categories = await db.query.cvCategory.findMany({
|
||||
orderBy: (model, {desc} ) => desc(model.name)
|
||||
})
|
||||
return categories;
|
||||
}
|
||||
10
src/server/routers/_app.ts
Normal file
10
src/server/routers/_app.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { router } from "../trpc";
|
||||
import { CvCategoryRouter } from "./cvCategory";
|
||||
import { publicProcedure } from "~/server/trpc";
|
||||
|
||||
export const trpcRouter = router({
|
||||
hello: publicProcedure.query(async () => "world"),
|
||||
cvCategory: CvCategoryRouter
|
||||
})
|
||||
|
||||
export type TrpcRouter = typeof trpcRouter
|
||||
12
src/server/routers/cvCategory/index.ts
Normal file
12
src/server/routers/cvCategory/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { db } from "~/server/db";
|
||||
import { publicProcedure, router } from "~/server/trpc";
|
||||
|
||||
export const CvCategoryRouter = router({
|
||||
get: publicProcedure.query(async () => {
|
||||
const categories = await db.query.cvCategory.findMany({
|
||||
orderBy: (model, {desc} ) => desc(model.name)
|
||||
});
|
||||
return categories;
|
||||
})
|
||||
})
|
||||
|
||||
5
src/server/trpc.ts
Normal file
5
src/server/trpc.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { initTRPC } from "@trpc/server"
|
||||
|
||||
const t = initTRPC.create();
|
||||
export const router = t.router;
|
||||
export const publicProcedure = t.procedure;
|
||||
Reference in New Issue
Block a user