feat(app): add version create
This commit is contained in:
parent
d542cd14da
commit
0c408a5041
@ -14,6 +14,8 @@
|
||||
"@boring.tools/ui": "workspace:*",
|
||||
"@clerk/clerk-react": "^5.9.4",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@mdxeditor/editor": "^3.14.0",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tanstack/react-query": "^5.59.0",
|
||||
"@tanstack/react-router": "^1.58.15",
|
||||
"axios": "^1.7.7",
|
||||
|
@ -77,6 +77,12 @@
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
font-feature-settings: "rlig" 1, "calt" 1;
|
||||
font-feature-settings:
|
||||
"rlig" 1,
|
||||
"calt" 1;
|
||||
}
|
||||
|
||||
.prose {
|
||||
@apply text-foreground;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ import type {
|
||||
ChangelogCreateInput,
|
||||
ChangelogOutput,
|
||||
ChangelogUpdateInput,
|
||||
VersionCreateInput,
|
||||
VersionOutput,
|
||||
VersionUpdateInput,
|
||||
} from '@boring.tools/schema'
|
||||
import { useAuth } from '@clerk/clerk-react'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
@ -12,6 +15,10 @@ type Changelog = z.infer<typeof ChangelogOutput>
|
||||
type ChangelogCreate = z.infer<typeof ChangelogCreateInput>
|
||||
type ChangelogUpdate = z.infer<typeof ChangelogUpdateInput>
|
||||
|
||||
type Version = z.infer<typeof VersionOutput>
|
||||
type VersionCreate = z.infer<typeof VersionCreateInput>
|
||||
type VersionUpdate = z.infer<typeof VersionUpdateInput>
|
||||
|
||||
export const useChangelogList = () => {
|
||||
const { getToken } = useAuth()
|
||||
return useQuery({
|
||||
@ -103,3 +110,24 @@ export const useChangelogRemove = () => {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useChangelogVersionCreate = () => {
|
||||
const { getToken } = useAuth()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (payload: VersionCreate): Promise<Readonly<Version>> =>
|
||||
await queryFetch({
|
||||
path: 'changelog/version',
|
||||
data: payload,
|
||||
method: 'post',
|
||||
token: await getToken(),
|
||||
}),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['changelogList'] })
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['changelogById', data.changelogId],
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ const UserIndexLazyImport = createFileRoute('/user/')()
|
||||
const ChangelogIndexLazyImport = createFileRoute('/changelog/')()
|
||||
const ChangelogCreateLazyImport = createFileRoute('/changelog/create')()
|
||||
const ChangelogIdLazyImport = createFileRoute('/changelog/$id')()
|
||||
const ChangelogIdIndexLazyImport = createFileRoute('/changelog/$id/')()
|
||||
const ChangelogIdVersionCreateLazyImport = createFileRoute(
|
||||
'/changelog/$id/versionCreate',
|
||||
)()
|
||||
const ChangelogIdEditLazyImport = createFileRoute('/changelog/$id/edit')()
|
||||
|
||||
// Create/Update Routes
|
||||
@ -54,6 +58,21 @@ const ChangelogIdLazyRoute = ChangelogIdLazyImport.update({
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any).lazy(() => import('./routes/changelog.$id.lazy').then((d) => d.Route))
|
||||
|
||||
const ChangelogIdIndexLazyRoute = ChangelogIdIndexLazyImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => ChangelogIdLazyRoute,
|
||||
} as any).lazy(() =>
|
||||
import('./routes/changelog.$id.index.lazy').then((d) => d.Route),
|
||||
)
|
||||
|
||||
const ChangelogIdVersionCreateLazyRoute =
|
||||
ChangelogIdVersionCreateLazyImport.update({
|
||||
path: '/versionCreate',
|
||||
getParentRoute: () => ChangelogIdLazyRoute,
|
||||
} as any).lazy(() =>
|
||||
import('./routes/changelog.$id.versionCreate.lazy').then((d) => d.Route),
|
||||
)
|
||||
|
||||
const ChangelogIdEditLazyRoute = ChangelogIdEditLazyImport.update({
|
||||
path: '/edit',
|
||||
getParentRoute: () => ChangelogIdLazyRoute,
|
||||
@ -107,6 +126,20 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ChangelogIdEditLazyImport
|
||||
parentRoute: typeof ChangelogIdLazyImport
|
||||
}
|
||||
'/changelog/$id/versionCreate': {
|
||||
id: '/changelog/$id/versionCreate'
|
||||
path: '/versionCreate'
|
||||
fullPath: '/changelog/$id/versionCreate'
|
||||
preLoaderRoute: typeof ChangelogIdVersionCreateLazyImport
|
||||
parentRoute: typeof ChangelogIdLazyImport
|
||||
}
|
||||
'/changelog/$id/': {
|
||||
id: '/changelog/$id/'
|
||||
path: '/'
|
||||
fullPath: '/changelog/$id/'
|
||||
preLoaderRoute: typeof ChangelogIdIndexLazyImport
|
||||
parentRoute: typeof ChangelogIdLazyImport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,10 +147,14 @@ declare module '@tanstack/react-router' {
|
||||
|
||||
interface ChangelogIdLazyRouteChildren {
|
||||
ChangelogIdEditLazyRoute: typeof ChangelogIdEditLazyRoute
|
||||
ChangelogIdVersionCreateLazyRoute: typeof ChangelogIdVersionCreateLazyRoute
|
||||
ChangelogIdIndexLazyRoute: typeof ChangelogIdIndexLazyRoute
|
||||
}
|
||||
|
||||
const ChangelogIdLazyRouteChildren: ChangelogIdLazyRouteChildren = {
|
||||
ChangelogIdEditLazyRoute: ChangelogIdEditLazyRoute,
|
||||
ChangelogIdVersionCreateLazyRoute: ChangelogIdVersionCreateLazyRoute,
|
||||
ChangelogIdIndexLazyRoute: ChangelogIdIndexLazyRoute,
|
||||
}
|
||||
|
||||
const ChangelogIdLazyRouteWithChildren = ChangelogIdLazyRoute._addFileChildren(
|
||||
@ -131,15 +168,18 @@ export interface FileRoutesByFullPath {
|
||||
'/changelog': typeof ChangelogIndexLazyRoute
|
||||
'/user': typeof UserIndexLazyRoute
|
||||
'/changelog/$id/edit': typeof ChangelogIdEditLazyRoute
|
||||
'/changelog/$id/versionCreate': typeof ChangelogIdVersionCreateLazyRoute
|
||||
'/changelog/$id/': typeof ChangelogIdIndexLazyRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexLazyRoute
|
||||
'/changelog/$id': typeof ChangelogIdLazyRouteWithChildren
|
||||
'/changelog/create': typeof ChangelogCreateLazyRoute
|
||||
'/changelog': typeof ChangelogIndexLazyRoute
|
||||
'/user': typeof UserIndexLazyRoute
|
||||
'/changelog/$id/edit': typeof ChangelogIdEditLazyRoute
|
||||
'/changelog/$id/versionCreate': typeof ChangelogIdVersionCreateLazyRoute
|
||||
'/changelog/$id': typeof ChangelogIdIndexLazyRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
@ -150,6 +190,8 @@ export interface FileRoutesById {
|
||||
'/changelog/': typeof ChangelogIndexLazyRoute
|
||||
'/user/': typeof UserIndexLazyRoute
|
||||
'/changelog/$id/edit': typeof ChangelogIdEditLazyRoute
|
||||
'/changelog/$id/versionCreate': typeof ChangelogIdVersionCreateLazyRoute
|
||||
'/changelog/$id/': typeof ChangelogIdIndexLazyRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
@ -161,14 +203,17 @@ export interface FileRouteTypes {
|
||||
| '/changelog'
|
||||
| '/user'
|
||||
| '/changelog/$id/edit'
|
||||
| '/changelog/$id/versionCreate'
|
||||
| '/changelog/$id/'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| '/changelog/$id'
|
||||
| '/changelog/create'
|
||||
| '/changelog'
|
||||
| '/user'
|
||||
| '/changelog/$id/edit'
|
||||
| '/changelog/$id/versionCreate'
|
||||
| '/changelog/$id'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
@ -177,6 +222,8 @@ export interface FileRouteTypes {
|
||||
| '/changelog/'
|
||||
| '/user/'
|
||||
| '/changelog/$id/edit'
|
||||
| '/changelog/$id/versionCreate'
|
||||
| '/changelog/$id/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
@ -221,7 +268,9 @@ export const routeTree = rootRoute
|
||||
"/changelog/$id": {
|
||||
"filePath": "changelog.$id.lazy.tsx",
|
||||
"children": [
|
||||
"/changelog/$id/edit"
|
||||
"/changelog/$id/edit",
|
||||
"/changelog/$id/versionCreate",
|
||||
"/changelog/$id/"
|
||||
]
|
||||
},
|
||||
"/changelog/create": {
|
||||
@ -236,6 +285,14 @@ export const routeTree = rootRoute
|
||||
"/changelog/$id/edit": {
|
||||
"filePath": "changelog.$id.edit.lazy.tsx",
|
||||
"parent": "/changelog/$id"
|
||||
},
|
||||
"/changelog/$id/versionCreate": {
|
||||
"filePath": "changelog.$id.versionCreate.lazy.tsx",
|
||||
"parent": "/changelog/$id"
|
||||
},
|
||||
"/changelog/$id/": {
|
||||
"filePath": "changelog.$id.index.lazy.tsx",
|
||||
"parent": "/changelog/$id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
apps/app/src/routes/changelog.$id.index.lazy.tsx
Normal file
49
apps/app/src/routes/changelog.$id.index.lazy.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@boring.tools/ui'
|
||||
import { Link, Outlet, createLazyFileRoute } from '@tanstack/react-router'
|
||||
import { PlusCircleIcon } from 'lucide-react'
|
||||
import { useChangelogById } from '../hooks/useChangelog'
|
||||
|
||||
const Component = () => {
|
||||
const { id } = Route.useParams()
|
||||
const { data, isPending } = useChangelogById({ id })
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-5">
|
||||
{!isPending && data && (
|
||||
<div>
|
||||
<Card className="w-full max-w-screen-sm">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle>Versions ({data.versions?.length})</CardTitle>
|
||||
|
||||
<Link to="/changelog/$id/versionCreate" params={{ id }}>
|
||||
<Button variant={'ghost'} size={'icon'}>
|
||||
<PlusCircleIcon strokeWidth={1.5} className="w-5 h-5" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{data.versions?.map((version) => {
|
||||
return <div key={version.id}>{version.version}</div>
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Route = createLazyFileRoute('/changelog/$id/')({
|
||||
component: Component,
|
||||
})
|
@ -47,7 +47,7 @@ const Component = () => {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<Tooltip>
|
||||
{/* <Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={'ghost'}>
|
||||
<TerminalSquareIcon strokeWidth={1.5} />
|
||||
@ -67,7 +67,7 @@ const Component = () => {
|
||||
<TooltipContent>
|
||||
<p>Public Page</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</Tooltip> */}
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
@ -85,8 +85,9 @@ const Component = () => {
|
||||
<ChangelogDelete id={id} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Outlet />
|
||||
<div className="mt-5">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
120
apps/app/src/routes/changelog.$id.versionCreate.lazy.tsx
Normal file
120
apps/app/src/routes/changelog.$id.versionCreate.lazy.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
import { VersionCreateInput } from '@boring.tools/schema'
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
Input,
|
||||
} from '@boring.tools/ui'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import {
|
||||
BlockTypeSelect,
|
||||
BoldItalicUnderlineToggles,
|
||||
ListsToggle,
|
||||
MDXEditor,
|
||||
UndoRedo,
|
||||
headingsPlugin,
|
||||
listsPlugin,
|
||||
quotePlugin,
|
||||
thematicBreakPlugin,
|
||||
toolbarPlugin,
|
||||
} from '@mdxeditor/editor'
|
||||
import { createLazyFileRoute } from '@tanstack/react-router'
|
||||
import { useNavigate } from '@tanstack/react-router'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import type { z } from 'zod'
|
||||
import { useChangelogVersionCreate } from '../hooks/useChangelog'
|
||||
import '@mdxeditor/editor/style.css'
|
||||
|
||||
const Component = () => {
|
||||
const { id } = Route.useParams()
|
||||
const navigate = useNavigate({ from: `/changelog/${id}/versionCreate` })
|
||||
const versionCreate = useChangelogVersionCreate()
|
||||
const form = useForm<z.infer<typeof VersionCreateInput>>({
|
||||
resolver: zodResolver(VersionCreateInput),
|
||||
defaultValues: {
|
||||
changelogId: id,
|
||||
version: '',
|
||||
markdown: '',
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = (values: z.infer<typeof VersionCreateInput>) => {
|
||||
versionCreate.mutate(values, {
|
||||
onSuccess(data) {
|
||||
navigate({ to: '/changelog/$id', params: { id: data.changelogId } })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-5">
|
||||
<h1 className="text-3xl">New version</h1>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-8 max-w-screen-md"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="version"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Version</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="v1.0.1" {...field} autoFocus />
|
||||
</FormControl>{' '}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="markdown"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Notes</FormLabel>
|
||||
<FormControl>
|
||||
<MDXEditor
|
||||
className="dark-theme"
|
||||
contentEditableClassName="prose dark:prose-invert max-w-none"
|
||||
markdown={field.value}
|
||||
plugins={[
|
||||
headingsPlugin(),
|
||||
listsPlugin(),
|
||||
thematicBreakPlugin(),
|
||||
quotePlugin(),
|
||||
|
||||
toolbarPlugin({
|
||||
toolbarContents: () => (
|
||||
<>
|
||||
<BlockTypeSelect />
|
||||
<BoldItalicUnderlineToggles />
|
||||
<ListsToggle />
|
||||
<UndoRedo />
|
||||
</>
|
||||
),
|
||||
}),
|
||||
]}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>{' '}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Button type="submit">Create</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Route = createLazyFileRoute('/changelog/$id/versionCreate')({
|
||||
component: Component,
|
||||
})
|
@ -76,5 +76,5 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('tailwindcss-animate')],
|
||||
plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')],
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user