feat(app): add react query and changelog hooks
This commit is contained in:
parent
de3b1a1c66
commit
ea8440f86f
@ -12,7 +12,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@boring.tools/ui": "workspace:*",
|
"@boring.tools/ui": "workspace:*",
|
||||||
"@clerk/clerk-react": "^5.9.4",
|
"@clerk/clerk-react": "^5.9.4",
|
||||||
|
"@tanstack/react-query": "^5.59.0",
|
||||||
"@tanstack/react-router": "^1.58.15",
|
"@tanstack/react-router": "^1.58.15",
|
||||||
|
"axios": "^1.7.7",
|
||||||
"lucide-react": "^0.446.0",
|
"lucide-react": "^0.446.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
79
apps/app/src/hooks/useChangelog.ts
Normal file
79
apps/app/src/hooks/useChangelog.ts
Normal 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],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@ -5,12 +5,15 @@ import { StrictMode } from 'react'
|
|||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import './base.css'
|
import './base.css'
|
||||||
|
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||||
// Import the generated route tree
|
// Import the generated route tree
|
||||||
import { routeTree } from './routeTree.gen'
|
import { routeTree } from './routeTree.gen'
|
||||||
|
|
||||||
// Create a new router instance
|
// Create a new router instance
|
||||||
const router = createRouter({ routeTree })
|
const router = createRouter({ routeTree })
|
||||||
|
|
||||||
|
const queryClient = new QueryClient()
|
||||||
|
|
||||||
// Register the router instance for type safety
|
// Register the router instance for type safety
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
interface Register {
|
interface Register {
|
||||||
@ -33,7 +36,9 @@ if (!rootElement.innerHTML) {
|
|||||||
<StrictMode>
|
<StrictMode>
|
||||||
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
|
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="ui-theme">
|
<ThemeProvider defaultTheme="dark" storageKey="ui-theme">
|
||||||
<RouterProvider router={router} />
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
</QueryClientProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ClerkProvider>
|
</ClerkProvider>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
|
@ -1,5 +1,31 @@
|
|||||||
import { createLazyFileRoute } from '@tanstack/react-router'
|
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/')({
|
export const Route = createLazyFileRoute('/changelog/')({
|
||||||
component: () => <div>Hello /changelog/!</div>,
|
component: Component,
|
||||||
})
|
})
|
||||||
|
25
apps/app/src/utils/queryFetch.ts
Normal file
25
apps/app/src/utils/queryFetch.ts
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user