feat(app): add pagewrapper component with breadcrumbs
All checks were successful
Build and Push Docker Image / tests (push) Successful in 44s
Build and Push Docker Image / build (push) Successful in 1m56s

This commit is contained in:
Lars Hampe 2024-10-20 20:53:30 +02:00
parent 41ee7a7849
commit 599bdd2978
5 changed files with 230 additions and 167 deletions

View File

@ -1,4 +1,4 @@
import { Separator, SidebarInset, SidebarTrigger } from '@boring.tools/ui'
import { SidebarInset } from '@boring.tools/ui'
import type { ReactNode } from 'react'
import { Sidebar } from './Sidebar'
@ -8,37 +8,8 @@ export const description =
export const Layout = ({ children }: { children: ReactNode | ReactNode[] }) => {
return (
<>
{/* <Navigation /> */}
<Sidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
{/* <Separator orientation="vertical" className="mr-2 h-4" /> */}
{/* <Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb> */}
</div>
</header>
<Separator />
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="flex flex-col">
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
{children}
</main>
</div>
</div>
</SidebarInset>
<SidebarInset>{children}</SidebarInset>
</>
)
}

View File

@ -0,0 +1,63 @@
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
Separator,
SidebarTrigger,
} from '@boring.tools/ui'
import { Link } from '@tanstack/react-router'
type Breadcrumbs = {
name: string
to: string
}
export const PageWrapper = ({
children,
breadcrumbs,
}: { children: React.ReactNode; breadcrumbs?: Breadcrumbs[] }) => {
return (
<>
<header className="flex h-16 shrink-0 items-center gap-2">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
{/* <Separator orientation="vertical" className="mr-2 h-4" /> */}
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
{breadcrumbs?.map((crumb, key) => {
if (breadcrumbs.length - 1 === key) {
return (
<BreadcrumbItem key={crumb.to}>
<BreadcrumbPage>{crumb.name}</BreadcrumbPage>
</BreadcrumbItem>
)
}
return (
<div className="flex items-center gap-2" key={crumb.to}>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink asChild>
<Link to={crumb.to}>{crumb.name}</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
</div>
)
})}
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<Separator />
<div className="flex flex-col">
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
{children}
</main>
</div>
</>
)
}

View File

@ -7,6 +7,7 @@ import {
import { Link, Outlet, createLazyFileRoute } from '@tanstack/react-router'
import { FileStackIcon, PencilIcon } from 'lucide-react'
import { ChangelogDelete } from '../components/Changelog/Delete'
import { PageWrapper } from '../components/PageWrapper'
import { useChangelogById } from '../hooks/useChangelog'
const Component = () => {
@ -25,24 +26,35 @@ const Component = () => {
}
return (
<div className="flex flex-col gap-5">
{!isPending && data && (
<div>
<div className="flex justify-between items-center">
<div className="flex gap-3 items-center">
<FileStackIcon
strokeWidth={1.5}
className="w-10 h-10 text-muted-foreground"
/>
<div>
<h1 className="text-3xl">{data.title}</h1>
<PageWrapper
breadcrumbs={[
{
name: 'Changelog',
to: '/changelog',
},
{ name: data?.title ?? '', to: `/changelog/${data?.id}` },
]}
>
<div className="flex flex-col gap-5">
{!isPending && data && (
<div>
<div className="flex justify-between items-center">
<div className="flex gap-3 items-center">
<FileStackIcon
strokeWidth={1.5}
className="w-10 h-10 text-muted-foreground"
/>
<div>
<h1 className="text-3xl">{data.title}</h1>
<p className="text-muted-foreground mt-2">{data.description}</p>
<p className="text-muted-foreground mt-2">
{data.description}
</p>
</div>
</div>
</div>
<div className="flex items-center gap-3">
{/* <Tooltip>
<div className="flex items-center gap-3">
{/* <Tooltip>
<TooltipTrigger asChild>
<Button variant={'ghost'}>
<TerminalSquareIcon strokeWidth={1.5} />
@ -64,28 +76,29 @@ const Component = () => {
</TooltipContent>
</Tooltip> */}
<Tooltip>
<TooltipTrigger asChild>
<Link to={'/changelog/$id/edit'} params={{ id }}>
<Button variant={'ghost'}>
<PencilIcon strokeWidth={1.5} />
</Button>
</Link>
</TooltipTrigger>
<TooltipContent>
<p>Edit</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Link to={'/changelog/$id/edit'} params={{ id }}>
<Button variant={'ghost'}>
<PencilIcon strokeWidth={1.5} />
</Button>
</Link>
</TooltipTrigger>
<TooltipContent>
<p>Edit</p>
</TooltipContent>
</Tooltip>
<ChangelogDelete id={id} />
<ChangelogDelete id={id} />
</div>
</div>
<div className="mt-5">
<Outlet />
</div>
</div>
<div className="mt-5">
<Outlet />
</div>
</div>
)}
</div>
)}
</div>
</PageWrapper>
)
}

View File

@ -17,6 +17,7 @@ import { createLazyFileRoute } from '@tanstack/react-router'
import { useNavigate } from '@tanstack/react-router'
import { useForm } from 'react-hook-form'
import type { z } from 'zod'
import { PageWrapper } from '../components/PageWrapper'
import { useChangelogCreate } from '../hooks/useChangelog'
const Component = () => {
@ -40,75 +41,85 @@ const Component = () => {
}
return (
<div className="flex flex-col gap-5">
<h1 className="text-3xl">New changelog</h1>
<PageWrapper
breadcrumbs={[
{
name: 'Changelog',
to: '/changelog',
},
{ name: 'New', to: '/changelog/create' },
]}
>
<div className="flex flex-col gap-5">
<h1 className="text-3xl">New changelog</h1>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 max-w-screen-md"
>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input placeholder="My changelog" {...field} autoFocus />
</FormControl>{' '}
<FormMessage />
</FormItem>
)}
/>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 max-w-screen-md"
>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input placeholder="My changelog" {...field} autoFocus />
</FormControl>{' '}
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Description</FormLabel>
<FormControl>
<Textarea
placeholder="Some details about the changelog..."
{...field}
/>
</FormControl>{' '}
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Description</FormLabel>
<FormControl>
<Textarea
placeholder="Some details about the changelog..."
{...field}
/>
</FormControl>{' '}
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="isSemver"
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md ">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<div className="space-y-1 leading-none">
<FormLabel>Using Semver</FormLabel>
<FormDescription>
If this changelog is following the{' '}
<a
href="https://semver.org/lang/de/"
className="text-emerald-700"
>
semantic versioning?
</a>
</FormDescription>
</div>
</FormItem>
)}
/>
<Button type="submit">Create</Button>
</form>
</Form>
</div>
<FormField
control={form.control}
name="isSemver"
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md ">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<div className="space-y-1 leading-none">
<FormLabel>Using Semver</FormLabel>
<FormDescription>
If this changelog is following the{' '}
<a
href="https://semver.org/lang/de/"
className="text-emerald-700"
>
semantic versioning?
</a>
</FormDescription>
</div>
</FormItem>
)}
/>
<Button type="submit">Create</Button>
</form>
</Form>
</div>
</PageWrapper>
)
}

View File

@ -7,6 +7,7 @@ import {
} from '@boring.tools/ui'
import { Link, createLazyFileRoute } from '@tanstack/react-router'
import { PlusCircleIcon } from 'lucide-react'
import { PageWrapper } from '../components/PageWrapper'
import { useChangelogList } from '../hooks/useChangelog'
const Component = () => {
@ -24,45 +25,49 @@ const Component = () => {
}
return (
<div className="flex flex-col gap-5">
<h1 className="text-3xl">Changelogs</h1>
<PageWrapper breadcrumbs={[{ name: 'Changelog', to: '/changelog' }]}>
<>
<div className="flex flex-col gap-5">
<h1 className="text-3xl">Changelog</h1>
<div className="flex gap-10 w-full">
{!isPending &&
data &&
data.map((changelog) => {
return (
<Link
to="/changelog/$id"
params={{ id: changelog.id }}
key={changelog.id}
>
<Card className="max-w-56 min-w-56 w-full h-36 hover:border-emerald-700 transition">
<CardHeader className="flex items-center justify-center">
<CardTitle>{changelog.title}</CardTitle>
</CardHeader>
<CardContent className="flex items-center justify-center flex-col">
<span>Versions: {changelog.computed.versionCount}</span>
<div className="flex gap-10 w-full">
{!isPending &&
data &&
data.map((changelog) => {
return (
<Link
to="/changelog/$id"
params={{ id: changelog.id }}
key={changelog.id}
>
<Card className="max-w-56 min-w-56 w-full h-36 hover:border-emerald-700 transition">
<CardHeader className="flex items-center justify-center">
<CardTitle>{changelog.title}</CardTitle>
</CardHeader>
<CardContent className="flex items-center justify-center flex-col">
<span>Versions: {changelog.computed.versionCount}</span>
<span>Commits: {changelog.computed.commitCount}</span>
</CardContent>
</Card>
</Link>
)
})}
<span>Commits: {changelog.computed.commitCount}</span>
</CardContent>
</Card>
</Link>
)
})}
<Link to="/changelog/create">
<Card className="max-w-56 min-w-56 w-full h-36 hover:border-emerald-700 transition">
<CardHeader className="flex items-center justify-center">
<CardTitle>New Changelog</CardTitle>
</CardHeader>
<CardContent className="flex items-center justify-center">
<PlusCircleIcon strokeWidth={1.5} className="w-10 h-10" />
</CardContent>
</Card>
</Link>
</div>
</div>
<Link to="/changelog/create">
<Card className="max-w-56 min-w-56 w-full h-36 hover:border-emerald-700 transition">
<CardHeader className="flex items-center justify-center">
<CardTitle>New Changelog</CardTitle>
</CardHeader>
<CardContent className="flex items-center justify-center">
<PlusCircleIcon strokeWidth={1.5} className="w-10 h-10" />
</CardContent>
</Card>
</Link>
</div>
</div>
</>
</PageWrapper>
)
}