diff --git a/apps/app/package.json b/apps/app/package.json index 0404338..fbd65b7 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -12,7 +12,9 @@ "dependencies": { "@boring.tools/ui": "workspace:*", "@clerk/clerk-react": "^5.9.4", + "@tanstack/react-query": "^5.59.0", "@tanstack/react-router": "^1.58.15", + "axios": "^1.7.7", "lucide-react": "^0.446.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/apps/app/src/hooks/useChangelog.ts b/apps/app/src/hooks/useChangelog.ts new file mode 100644 index 0000000..74ee00f --- /dev/null +++ b/apps/app/src/hooks/useChangelog.ts @@ -0,0 +1,79 @@ +import type { + ChangelogCreateInput, + ChangelogOutput, +} from '@boring.tools/schema' +import { useAuth } from '@clerk/clerk-react' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import type { z } from 'zod' +import { queryFetch } from '../utils/queryFetch' + +type Changelog = z.infer +type ChangelogCreate = z.infer + +export const useChangelogList = () => { + const { getToken } = useAuth() + return useQuery({ + queryKey: ['changelogList'], + queryFn: async (): Promise> => + await queryFetch({ + path: 'changelog', + method: 'get', + token: await getToken(), + }), + }) +} + +export const useChangelogById = ({ id }: { id: string }) => { + const { getToken } = useAuth() + + return useQuery({ + queryKey: ['changelogById', id], + queryFn: async (): Promise> => + await queryFetch({ + path: `changelog/${id}`, + method: 'get', + token: await getToken(), + }), + }) +} + +export const useChangelogCreate = () => { + const { getToken } = useAuth() + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ( + payload: ChangelogCreate, + ): Promise> => + await queryFetch({ + path: 'changelog', + data: payload, + method: 'post', + token: await getToken(), + }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['changelogList'] }) + }, + }) +} + +export const useChangelogRemove = () => { + const { getToken } = useAuth() + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + id, + }: { id: string }): Promise> => + await queryFetch({ + path: `changelog/${id}`, + method: 'delete', + token: await getToken(), + }), + onSuccess: (data) => { + queryClient.invalidateQueries({ + queryKey: ['changelogList', 'changelogById', data.id], + }) + }, + }) +} diff --git a/apps/app/src/main.tsx b/apps/app/src/main.tsx index 57e58b5..0ad22fa 100644 --- a/apps/app/src/main.tsx +++ b/apps/app/src/main.tsx @@ -5,12 +5,15 @@ import { StrictMode } from 'react' import ReactDOM from 'react-dom/client' import './base.css' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' // Import the generated route tree import { routeTree } from './routeTree.gen' // Create a new router instance const router = createRouter({ routeTree }) +const queryClient = new QueryClient() + // Register the router instance for type safety declare module '@tanstack/react-router' { interface Register { @@ -33,7 +36,9 @@ if (!rootElement.innerHTML) { - + + + , diff --git a/apps/app/src/routes/changelog/index.lazy.tsx b/apps/app/src/routes/changelog/index.lazy.tsx index a631627..f1f3194 100644 --- a/apps/app/src/routes/changelog/index.lazy.tsx +++ b/apps/app/src/routes/changelog/index.lazy.tsx @@ -1,5 +1,31 @@ import { createLazyFileRoute } from '@tanstack/react-router' +import { useChangelogList } from '../../hooks/useChangelog' + +const Component = () => { + const { data, error, isPending } = useChangelogList() + + if (error) { + return ( +
+

Changelogs

+

Please try again later

+
+ ) + } + + return ( +
+

Changelogs

+ + {!isPending && + data && + data.map((changelog) => { + return
{changelog.title}
+ })} +
+ ) +} export const Route = createLazyFileRoute('/changelog/')({ - component: () =>
Hello /changelog/!
, + component: Component, }) diff --git a/apps/app/src/utils/queryFetch.ts b/apps/app/src/utils/queryFetch.ts new file mode 100644 index 0000000..c249b67 --- /dev/null +++ b/apps/app/src/utils/queryFetch.ts @@ -0,0 +1,25 @@ +import axios from 'axios' + +type Fetch = { + path: string + method: 'get' | 'post' | 'put' | 'delete' + data?: unknown + token?: string | null +} + +const url = + import.meta.env.NODE_ENV === 'production' + ? 'https://api.boring.tools' + : 'http://localhost:3000' + +export const queryFetch = async ({ path, method, data, token }: Fetch) => { + const response = await axios({ + method, + url: `${url}/v1/${path}`, + data, + headers: { + Authorization: `Bearer ${token}`, + }, + }) + return response.data +} diff --git a/bun.lockb b/bun.lockb index 3193d2b..e35d768 100755 Binary files a/bun.lockb and b/bun.lockb differ