Skip to content

Commit

Permalink
docs: the example will be better for improving the UI
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelvelasquezdev committed May 10, 2023
1 parent 9409cdd commit 10f333a
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 126 deletions.
3 changes: 3 additions & 0 deletions examples/next-prisma-starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,19 @@
"@types/react": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"autoprefixer": "^10.4.7",
"eslint": "^8.40.0",
"eslint-config-next": "^13.3.4",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.14",
"prettier": "^2.8.8",
"prisma": "^4.12.0",
"start-server-and-test": "^1.12.0",
"tailwindcss": "^3.3.0",
"tsx": "^3.12.7",
"typescript": "^4.8.3",
"vite": "^4.1.2",
Expand Down
6 changes: 6 additions & 0 deletions examples/next-prisma-starter/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const DefaultLayout = ({ children }: DefaultLayoutProps) => {
<link rel="icon" href="/favicon.ico" />
</Head>

<main>{children}</main>
<main className="h-screen">{children}</main>
</>
);
};
15 changes: 15 additions & 0 deletions examples/next-prisma-starter/src/pages/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Link from 'next/link';

export default function Custom404() {
return (
<div className="flex flex-col items-center justify-center h-screen text-center">
<Link href="/" className="text-gray-300 underline">
Home
</Link>
<div className="flex flex-col">
<h1 className="text-9xl font-bold">404</h1>
<h2 className="text-4xl font-bold">Page not found</h2>
</div>
</div>
);
}
2 changes: 2 additions & 0 deletions examples/next-prisma-starter/src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { NextPage } from 'next';
import type { AppType, AppProps } from 'next/app';
import type { ReactElement, ReactNode } from 'react';

import { DefaultLayout } from '~/components/DefaultLayout';
import { trpc } from '~/utils/trpc';
import '~/styles/globals.css';

export type NextPageWithLayout<
TProps = Record<string, unknown>,
Expand Down
13 changes: 13 additions & 0 deletions examples/next-prisma-starter/src/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
return (
<Html>
<Head />
<body className="h-screen bg-gray-800 text-white px-8 text-xl">
<Main />
<NextScript />
</body>
</Html>
);
}
189 changes: 110 additions & 79 deletions examples/next-prisma-starter/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,97 +34,128 @@ const IndexPage: NextPageWithLayout = () => {
// }, [postsQuery.data, utils]);

return (
<>
<h1>Welcome to your tRPC starter!</h1>
<p>
If you get stuck, check <a href="https://trpc.io">the docs</a>, write a
message in our <a href="https://trpc.io/discord">Discord-channel</a>, or
write a message in{' '}
<a href="https://github.com/trpc/trpc/discussions">
<div className="flex flex-col bg-gray-800 py-8">
<h1 className="text-4xl font-bold">
Welcome to your tRPC with Prisma starter!
</h1>
<p className="text-gray-400">
If you get stuck, check{' '}
<Link className="underline" href="https://trpc.io">
the docs
</Link>
, write a message in our{' '}
<Link className="underline" href="https://trpc.io/discord">
Discord-channel
</Link>
, or write a message in{' '}
<Link
className="underline"
href="https://github.com/trpc/trpc/discussions"
>
GitHub Discussions
</a>
</Link>
.
</p>

<h2>
Latest Posts
{postsQuery.status === 'loading' && '(loading)'}
</h2>
<div className="flex flex-col py-8 items-start gap-y-2">
<div className="flex flex-col"></div>
<h2 className="text-3xl font-semibold">
Latest Posts
{postsQuery.status === 'loading' && '(loading)'}
</h2>

<button
onClick={() => postsQuery.fetchPreviousPage()}
disabled={
!postsQuery.hasPreviousPage || postsQuery.isFetchingPreviousPage
}
>
{postsQuery.isFetchingPreviousPage
? 'Loading more...'
: postsQuery.hasPreviousPage
? 'Load More'
: 'Nothing more to load'}
</button>
<button
className="bg-gray-900 p-2 rounded-md font-semibold disabled:bg-gray-700 disabled:text-gray-400"
onClick={() => postsQuery.fetchPreviousPage()}
disabled={
!postsQuery.hasPreviousPage || postsQuery.isFetchingPreviousPage
}
>
{postsQuery.isFetchingPreviousPage
? 'Loading more...'
: postsQuery.hasPreviousPage
? 'Load More'
: 'Nothing more to load'}
</button>

{postsQuery.data?.pages.map((page, index) => (
<Fragment key={page.items[0]?.id || index}>
{page.items.map((item) => (
<article key={item.id}>
<h3>{item.title}</h3>
<Link href={`/post/${item.id}`}>View more</Link>
</article>
))}
</Fragment>
))}
{postsQuery.data?.pages.map((page, index) => (
<Fragment key={page.items[0]?.id || index}>
{page.items.map((item) => (
<article key={item.id}>
<h3 className="text-2xl font-semibold">{item.title}</h3>
<Link className="text-gray-400" href={`/post/${item.id}`}>
View more
</Link>
</article>
))}
</Fragment>
))}
</div>

<hr />

<h3>Add a Post</h3>
<div className="flex flex-col py-8 items-center">
<h2 className="text-3xl font-semibold pb-2">Add a Post</h2>

<form
onSubmit={async (e) => {
/**
* In a real app you probably don't want to use this manually
* Checkout React Hook Form - it works great with tRPC
* @see https://react-hook-form.com/
* @see https://kitchen-sink.trpc.io/react-hook-form
*/
e.preventDefault();
const $form = e.currentTarget;
const values = Object.fromEntries(new FormData($form));
type Input = inferProcedureInput<AppRouter['post']['add']>;
// ^?
const input: Input = {
title: values.title as string,
text: values.text as string,
};
try {
await addPost.mutateAsync(input);
<form
className="py-2 w-4/6"
onSubmit={async (e) => {
/**
* In a real app you probably don't want to use this manually
* Checkout React Hook Form - it works great with tRPC
* @see https://react-hook-form.com/
* @see https://kitchen-sink.trpc.io/react-hook-form
*/
e.preventDefault();
const $form = e.currentTarget;
const values = Object.fromEntries(new FormData($form));
type Input = inferProcedureInput<AppRouter['post']['add']>;
// ^?
const input: Input = {
title: values.title as string,
text: values.text as string,
};
try {
await addPost.mutateAsync(input);

$form.reset();
} catch (cause) {
console.error({ cause }, 'Failed to add post');
}
}}
>
<label htmlFor="title">Title:</label>
<br />
<input
id="title"
name="title"
type="text"
disabled={addPost.isLoading}
/>
$form.reset();
} catch (cause) {
console.error({ cause }, 'Failed to add post');
}
}}
>
<div className="flex flex-col gap-y-4 font-semibold">
<input
className="focus-visible:outline-dashed outline-offset-4 outline-2 outline-gray-700 rounded-xl px-4 py-3 bg-gray-900"
id="title"
name="title"
type="text"
placeholder="Title"
disabled={addPost.isLoading}
/>
<textarea
className="resize-none focus-visible:outline-dashed outline-offset-4 outline-2 outline-gray-700 rounded-xl px-4 py-3 bg-gray-900"
id="text"
name="text"
placeholder="Text"
disabled={addPost.isLoading}
rows={6}
/>

<br />
<label htmlFor="text">Text:</label>
<br />
<textarea id="text" name="text" disabled={addPost.isLoading} />
<br />
<input type="submit" disabled={addPost.isLoading} />
{addPost.error && (
<p style={{ color: 'red' }}>{addPost.error.message}</p>
)}
</form>
</>
<div className="flex justify-center">
<input
className="cursor-pointer bg-gray-900 p-2 rounded-md px-16"
type="submit"
disabled={addPost.isLoading}
/>
{addPost.error && (
<p style={{ color: 'red' }}>{addPost.error.message}</p>
)}
</div>
</div>
</form>
</div>
</div>
);
};

Expand Down
23 changes: 14 additions & 9 deletions examples/next-prisma-starter/src/pages/post/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import NextError from 'next/error';
import { useRouter } from 'next/router';

import { NextPageWithLayout } from '~/pages/_app';
import { RouterOutput, trpc } from '~/utils/trpc';

Expand All @@ -8,15 +9,19 @@ type PostByIdOutput = RouterOutput['post']['byId'];
function PostItem(props: { post: PostByIdOutput }) {
const { post } = props;
return (
<>
<h1>{post.title}</h1>
<em>Created {post.createdAt.toLocaleDateString('en-us')}</em>

<p>{post.text}</p>

<h2>Raw data:</h2>
<pre>{JSON.stringify(post, null, 4)}</pre>
</>
<div className="flex flex-col justify-center h-full px-8 ">
<h1 className="text-4xl font-bold">{post.title}</h1>
<em className="text-gray-400">
Created {post.createdAt.toLocaleDateString('en-us')}
</em>

<p className="py-4 break-all">{post.text}</p>

<h2 className="text-2xl font-semibold py-2">Raw data:</h2>
<pre className="bg-gray-900 p-4 rounded-xl overflow-x-scroll">
{JSON.stringify(post, null, 4)}
</pre>
</div>
);
}

Expand Down
3 changes: 3 additions & 0 deletions examples/next-prisma-starter/src/styles/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
8 changes: 8 additions & 0 deletions examples/next-prisma-starter/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/pages/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
};
Loading

0 comments on commit 10f333a

Please sign in to comment.