feat(app): add react query and changelog hooks
Some checks failed
Build and Push Docker Image / tests (push) Successful in 28s
Build and Push Docker Image / build (push) Failing after 39s

This commit is contained in:
Lars Hampe 2024-10-03 10:52:50 +02:00
parent de3b1a1c66
commit ea8440f86f
6 changed files with 139 additions and 2 deletions

View File

@ -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",

View File

@ -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<typeof ChangelogOutput>
type ChangelogCreate = z.infer<typeof ChangelogCreateInput>
export const useChangelogList = () => {
const { getToken } = useAuth()
return useQuery({
queryKey: ['changelogList'],
queryFn: async (): Promise<ReadonlyArray<Changelog>> =>
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<ReadOnlyDict<Changelog>> =>
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<ReadonlySet<Changelog>> =>
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<ReadOnlyDict<Changelog>> =>
await queryFetch({
path: `changelog/${id}`,
method: 'delete',
token: await getToken(),
}),
onSuccess: (data) => {
queryClient.invalidateQueries({
queryKey: ['changelogList', 'changelogById', data.id],
})
},
})
}

View File

@ -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) {
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<ThemeProvider defaultTheme="dark" storageKey="ui-theme">
<RouterProvider router={router} />
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</ThemeProvider>
</ClerkProvider>
</StrictMode>,

View File

@ -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 (
<div className="flex items-center justify-center mt-32 flex-col">
<h1 className="text-3xl">Changelogs</h1>
<p>Please try again later</p>
</div>
)
}
return (
<div>
<h1 className="text-3xl">Changelogs</h1>
{!isPending &&
data &&
data.map((changelog) => {
return <div key={changelog.id}>{changelog.title}</div>
})}
</div>
)
}
export const Route = createLazyFileRoute('/changelog/')({
component: () => <div>Hello /changelog/!</div>,
component: Component,
})

View File

@ -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
}

BIN
bun.lockb

Binary file not shown.