) => {
173 | e.preventDefault();
174 | if (mutation.isLoading) return;
175 | const data = new FormData(e.currentTarget);
176 | const title = data.get("title") as string;
177 | const content = data.get("content") as string;
178 | mutation.mutate({ body: { content, title } });
179 | e.currentTarget.reset();
180 | };
181 |
182 | return { handleSubmit, mutation };
183 | };
184 |
185 | const CreatePost = () => {
186 | const { handleSubmit, mutation } = useCreatePost();
187 | return (
188 |
189 |
190 | Create Post
191 | Write a new post
192 |
193 |
194 |
216 |
217 |
218 | );
219 | };
220 |
--------------------------------------------------------------------------------
/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import "@/components/global.css";
2 |
3 | import { ThemeProvider } from "next-themes";
4 |
5 | import type { AppProps } from "next/app";
6 | import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
7 | import type { ReactElement, ReactNode } from "react";
8 | import type { NextPage } from "next";
9 |
10 | export type NextPageWithLayout = NextPage
& {
11 | getLayout?: (page: ReactElement) => ReactNode;
12 | };
13 |
14 | type AppPropsWithLayout = AppProps & {
15 | Component: NextPageWithLayout;
16 | };
17 |
18 | const client = new QueryClient();
19 |
20 | export default function App({ Component, pageProps }: AppPropsWithLayout) {
21 | const getLayout = Component.getLayout || ((page) => page);
22 | return (
23 |
24 |
25 | {getLayout()}
26 |
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/src/pages/api/[...ts-rest].tsx:
--------------------------------------------------------------------------------
1 | import { createNextRouter } from "@ts-rest/next";
2 |
3 | import { contract } from "@/api/contract";
4 | import { router } from "@/api/router";
5 |
6 | export const config = {
7 | runtime: "edge",
8 | regions: ["syd1"],
9 | };
10 |
11 | export default createNextRouter(contract, router);
12 |
--------------------------------------------------------------------------------
/src/pages/dashboard/index.tsx:
--------------------------------------------------------------------------------
1 | import { getDashboardLayout } from "@/components/layout";
2 | import { ViewPosts } from "@/feature/post";
3 |
4 | export default function Page() {
5 | return ;
6 | }
7 |
8 | Page.getLayout = getDashboardLayout;
9 |
--------------------------------------------------------------------------------
/src/pages/dashboard/posts.tsx:
--------------------------------------------------------------------------------
1 | import { getDashboardLayout } from "@/components/layout";
2 | import { ViewPosts } from "@/feature/post";
3 |
4 | export default function Page() {
5 | return ;
6 | }
7 |
8 | Page.getLayout = getDashboardLayout;
9 |
--------------------------------------------------------------------------------
/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import { text, Button } from "@/components";
3 |
4 | export default function Page() {
5 | return (
6 |
7 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | darkMode: ["class"],
4 | content: [
5 | './pages/**/*.{ts,tsx}',
6 | './components/**/*.{ts,tsx}',
7 | './app/**/*.{ts,tsx}',
8 | './src/**/*.{ts,tsx}',
9 | ],
10 | theme: {
11 | container: {
12 | center: true,
13 | padding: "2rem",
14 | screens: {
15 | "2xl": "1400px",
16 | },
17 | },
18 | extend: {
19 | colors: {
20 | border: "hsl(var(--border))",
21 | input: "hsl(var(--input))",
22 | ring: "hsl(var(--ring))",
23 | background: "hsl(var(--background))",
24 | foreground: "hsl(var(--foreground))",
25 | primary: {
26 | DEFAULT: "hsl(var(--primary))",
27 | foreground: "hsl(var(--primary-foreground))",
28 | },
29 | secondary: {
30 | DEFAULT: "hsl(var(--secondary))",
31 | foreground: "hsl(var(--secondary-foreground))",
32 | },
33 | destructive: {
34 | DEFAULT: "hsl(var(--destructive))",
35 | foreground: "hsl(var(--destructive-foreground))",
36 | },
37 | muted: {
38 | DEFAULT: "hsl(var(--muted))",
39 | foreground: "hsl(var(--muted-foreground))",
40 | },
41 | accent: {
42 | DEFAULT: "hsl(var(--accent))",
43 | foreground: "hsl(var(--accent-foreground))",
44 | },
45 | popover: {
46 | DEFAULT: "hsl(var(--popover))",
47 | foreground: "hsl(var(--popover-foreground))",
48 | },
49 | card: {
50 | DEFAULT: "hsl(var(--card))",
51 | foreground: "hsl(var(--card-foreground))",
52 | },
53 | },
54 | borderRadius: {
55 | lg: "var(--radius)",
56 | md: "calc(var(--radius) - 2px)",
57 | sm: "calc(var(--radius) - 4px)",
58 | },
59 | keyframes: {
60 | "accordion-down": {
61 | from: { height: 0 },
62 | to: { height: "var(--radix-accordion-content-height)" },
63 | },
64 | "accordion-up": {
65 | from: { height: "var(--radix-accordion-content-height)" },
66 | to: { height: 0 },
67 | },
68 | },
69 | animation: {
70 | "accordion-down": "accordion-down 0.2s ease-out",
71 | "accordion-up": "accordion-up 0.2s ease-out",
72 | },
73 | },
74 | },
75 | plugins: [require("tailwindcss-animate")],
76 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./src/*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------