Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/(server)/controllers/users.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'

import { eq } from 'drizzle-orm'

Expand Down Expand Up @@ -82,4 +83,8 @@ export class UsersController extends BaseController<typeof users> {

await setSession(foundUser)
}

async signOut() {
cookies().delete('session')
}
}
3 changes: 3 additions & 0 deletions app/(server)/routers/users.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export const usersRouter = new Elysia({ prefix })
body: usersFrontendSchema
}
)
.get('/signout', async ({ UsersController }) => {
await UsersController.signOut()
})
.patch(
'/:id',
async ({ UsersController, params: { id }, body }) => {
Expand Down
5 changes: 2 additions & 3 deletions app/(site)/_components/local-revalidation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ import { Button } from '@/components/ui/button'
/** Force a revalidation of the current page you are on, when working locally */
export const LocalRevalidation = () => {
const path = usePathname()
const router = useRouter()
if (process.env.NODE_ENV !== 'development') {
return null
}

return (
<Button
variant="link"
onClick={() => {
client.api.revalidate.post({ path })
router.refresh()
typeof window !== undefined && window.location.reload()
}}
className="text-muted-foreground"
>
Revalidate Current Page
</Button>
Expand Down
10 changes: 7 additions & 3 deletions app/(site)/admin/blog/_components/blog-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ export const BlogCard = ({ blog }: { blog: Blog }) => {
const isAdmin = pathname.includes('/admin')
return (
<Card key={blog.id} className="max-w-96">
<CardHeader>
<Button className="pl-0" asChild variant="link">
<Link href={`/blog/${blog.id}`}>
<CardHeader className="text-left">
<Button asChild variant="link">
<Link
style={{ justifyContent: 'start' }}
className="pl-0"
href={`/blog/${blog.id}`}
>
<CardTitle>{blog.title}</CardTitle>
</Link>
</Button>
Expand Down
6 changes: 3 additions & 3 deletions app/(site)/admin/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ export default async function BlogsPage() {
throw new Error((error.value as string) ?? 'An Error Occurred')
}
return (
<div className="mt-8">
<div className="flex flex-wrap justify-center gap-6">
<div className="mt-8 px-4">
<div className="flex flex-wrap justify-between gap-6">
<h1 className="text-center text-3xl font-bold sm:text-4xl">Blogs</h1>
<Button variant="outline" asChild>
<Link href="/admin/blog/new">Add New Blog</Link>
</Button>
</div>
<div className="mt-8 flex flex-wrap justify-center gap-4">
<div className="mt-8 flex flex-wrap gap-4">
{data?.map(blog => <BlogCard key={blog.id} blog={blog} />)}
</div>
</div>
Expand Down
62 changes: 62 additions & 0 deletions app/(site)/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use client'
import { Fragment } from 'react'
import { usePathname } from 'next/navigation'

import { LocalRevalidation } from '@/app/(site)/_components/local-revalidation'
import { AppSidebar } from '@/components/app-sidebar'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator
} from '@/components/ui/breadcrumb'
import { Separator } from '@/components/ui/separator'
import {
SidebarInset,
SidebarProvider,
SidebarTrigger
} from '@/components/ui/sidebar'

export default function DashboardLayout({
children
}: {
children: React.ReactNode
}) {
const pathname = usePathname()
const pages = [{ href: '/', name: 'Home' }]
if (pathname.endsWith('blog') || pathname.includes('/blog/')) {
pages.push({ href: '/admin/blog', name: 'Blog' })
}
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
{pages.map((page, index) => (
<Fragment key={page.href}>
{index !== 0 && (
<BreadcrumbSeparator className="hidden md:block" />
)}
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href={page.href}>
{page.name}
</BreadcrumbLink>
</BreadcrumbItem>
</Fragment>
))}
</BreadcrumbList>
</Breadcrumb>
<div className="ml-auto">
<LocalRevalidation />
</div>
</header>
<main className="p-4 sm:px-12">{children}</main>
</SidebarInset>
</SidebarProvider>
)
}
3 changes: 0 additions & 3 deletions app/(site)/admin/me/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ export default async function UsersPage() {
<h2 className="text-xl font-bold">
You are logged in as: {currentSession.data?.email}
</h2>
<Button className="mt-4" asChild>
<Link href="/admin/blog">Manage Blog</Link>
</Button>
</div>
)}
{currentSession.data?.id && (
Expand Down
21 changes: 1 addition & 20 deletions app/(site)/admin/users/_components/user-card.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
'use client'

import Link from 'next/link'

import type { User } from '@/app/(server)/validators/users.validator'
import { client } from '@/app/(site)/client'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle
} from '@/components/ui/card'
import { DeleteButton } from '@/components/ui/delete-button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'

export const UserCard = ({ user }: { user: User }) => {
return (
Expand All @@ -29,14 +18,6 @@ export const UserCard = ({ user }: { user: User }) => {
))}
</ul>
</CardContent>
<CardFooter className="justify-end gap-2">
<DeleteButton
description="This will permanently delete this user."
handleDelete={async () => {
await client.api.users({ id: user.id }).delete()
}}
/>
</CardFooter>
</Card>
)
}
2 changes: 1 addition & 1 deletion app/(site)/blog/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const EditBlog = async ({ params }: { params: { id: string } }) => {
}

return (
<div className="prose mt-16">
<div className="prose mt-16 dark:prose-invert">
{data.content?.map((element, index) => {
switch (element.type) {
case 'h1':
Expand Down
1 change: 1 addition & 0 deletions app/(site)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default function SiteLayout({
}: {
children: React.ReactNode
}) {
return children
return (
<div className="container mx-auto bg-background py-12">
<Header />
Expand Down
52 changes: 52 additions & 0 deletions app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { AppSidebar } from "@/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar"

export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<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>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}
25 changes: 25 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 20 14.3% 4.1%;
Expand All @@ -55,6 +63,14 @@
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}

Expand All @@ -63,3 +79,12 @@
@apply border-border;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
Binary file modified bun.lockb
Binary file not shown.
67 changes: 67 additions & 0 deletions components/app-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client'

import * as React from 'react'
import Link from 'next/link'

import { Command } from 'lucide-react'

import { NavMain } from '@/components/nav-main'
import { NavUser } from '@/components/nav-user'
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem
} from '@/components/ui/sidebar'
import { useUser } from '@/lib/auth/user-context'

import { SidebarThemeToggle } from './ui/theme-toggle'

export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { user } = useUser()
return (
<Sidebar variant="inset" {...props}>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<Link href="/">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Command className="size-4" />
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">Acme Inc</span>
<span className="truncate text-xs">Enterprise</span>
</div>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<NavMain />
<SidebarGroup className="mt-auto">
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarThemeToggle />
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
{user?.id ? (
<NavUser user={{ ...user, name: user?.email.split('@')[0] ?? '' }} />
) : (
<div></div>
)}
</SidebarFooter>
</Sidebar>
)
}
Loading