diff --git a/apps/app/package.json b/apps/app/package.json index d3a854c..e3ae267 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -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", diff --git a/apps/app/src/base.css b/apps/app/src/base.css index 70758f5..968abf4 100644 --- a/apps/app/src/base.css +++ b/apps/app/src/base.css @@ -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; } } diff --git a/apps/app/src/hooks/useChangelog.ts b/apps/app/src/hooks/useChangelog.ts index 71db74f..1e0b681 100644 --- a/apps/app/src/hooks/useChangelog.ts +++ b/apps/app/src/hooks/useChangelog.ts @@ -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 type ChangelogCreate = z.infer type ChangelogUpdate = z.infer +type Version = z.infer +type VersionCreate = z.infer +type VersionUpdate = z.infer + 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> => + await queryFetch({ + path: 'changelog/version', + data: payload, + method: 'post', + token: await getToken(), + }), + onSuccess: (data) => { + queryClient.invalidateQueries({ queryKey: ['changelogList'] }) + queryClient.invalidateQueries({ + queryKey: ['changelogById', data.changelogId], + }) + }, + }) +} diff --git a/apps/app/src/routeTree.gen.ts b/apps/app/src/routeTree.gen.ts index 5a1e246..eaf6464 100644 --- a/apps/app/src/routeTree.gen.ts +++ b/apps/app/src/routeTree.gen.ts @@ -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" } } } diff --git a/apps/app/src/routes/changelog.$id.index.lazy.tsx b/apps/app/src/routes/changelog.$id.index.lazy.tsx new file mode 100644 index 0000000..5abe24f --- /dev/null +++ b/apps/app/src/routes/changelog.$id.index.lazy.tsx @@ -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 ( +
+ {!isPending && data && ( +
+ + +
+ Versions ({data.versions?.length}) + + + + +
+
+ + {data.versions?.map((version) => { + return
{version.version}
+ })} +
+
+
+ )} +
+ ) +} + +export const Route = createLazyFileRoute('/changelog/$id/')({ + component: Component, +}) diff --git a/apps/app/src/routes/changelog.$id.lazy.tsx b/apps/app/src/routes/changelog.$id.lazy.tsx index 0f2b416..f2cc60b 100644 --- a/apps/app/src/routes/changelog.$id.lazy.tsx +++ b/apps/app/src/routes/changelog.$id.lazy.tsx @@ -47,7 +47,7 @@ const Component = () => {
- + {/*
- - +
+ +
)} diff --git a/apps/app/src/routes/changelog.$id.versionCreate.lazy.tsx b/apps/app/src/routes/changelog.$id.versionCreate.lazy.tsx new file mode 100644 index 0000000..a572c99 --- /dev/null +++ b/apps/app/src/routes/changelog.$id.versionCreate.lazy.tsx @@ -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>({ + resolver: zodResolver(VersionCreateInput), + defaultValues: { + changelogId: id, + version: '', + markdown: '', + }, + }) + + const onSubmit = (values: z.infer) => { + versionCreate.mutate(values, { + onSuccess(data) { + navigate({ to: '/changelog/$id', params: { id: data.changelogId } }) + }, + }) + } + + return ( +
+

New version

+
+ + ( + + Version + + + {' '} + + + )} + /> + + ( + + Notes + + ( + <> + + + + + + ), + }), + ]} + {...field} + /> + {' '} + + + )} + /> + + + + +
+ ) +} + +export const Route = createLazyFileRoute('/changelog/$id/versionCreate')({ + component: Component, +}) diff --git a/apps/app/tailwind.config.js b/apps/app/tailwind.config.js index 1659a14..5cff6b1 100644 --- a/apps/app/tailwind.config.js +++ b/apps/app/tailwind.config.js @@ -76,5 +76,5 @@ export default { }, }, }, - plugins: [require('tailwindcss-animate')], + plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')], } diff --git a/bun.lockb b/bun.lockb index c99871e..89ddb2f 100755 Binary files a/bun.lockb and b/bun.lockb differ