Refactor
This commit is contained in:
16
src/app/(admin)/admin/_components/dashboard-title.tsx
Normal file
16
src/app/(admin)/admin/_components/dashboard-title.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
type DashBoardTitleProps = {
|
||||||
|
renderSubtitle: true
|
||||||
|
subtitle: string
|
||||||
|
} | {
|
||||||
|
renderSubtitle?: false
|
||||||
|
subtitle?: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DashBoardTitle({ title, subtitle, renderSubtitle }: DashBoardTitleProps & { title: string }) {
|
||||||
|
return (
|
||||||
|
<div className="pb-6">
|
||||||
|
<h1 className="mb-2 text-2xl font-bold text-foreground">{title}</h1>
|
||||||
|
{renderSubtitle && <p className="text-sm text-muted-foreground">{subtitle}</p>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
7
src/app/(admin)/admin/_components/password.tsx
Normal file
7
src/app/(admin)/admin/_components/password.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { getSession } from "@/lib/auth/session"
|
||||||
|
|
||||||
|
export default async function PasswordSettings() {
|
||||||
|
const {} = await getSession()
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { HomeIcon, LayoutDashboard, List, PanelLeft, Plus, User2 } from "lucide-react"
|
import { HomeIcon, KeyRoundIcon, LayoutDashboard, List, PanelLeft, Plus, User2 } from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
|
|
||||||
@@ -20,24 +20,37 @@ import {
|
|||||||
import { SidebarThemeToggle } from "./sidebar-theme-toggle"
|
import { SidebarThemeToggle } from "./sidebar-theme-toggle"
|
||||||
import { SidebarUserDropdown } from "./sidebar-user-dropdown"
|
import { SidebarUserDropdown } from "./sidebar-user-dropdown"
|
||||||
|
|
||||||
const items = [
|
const dashboardItems = [
|
||||||
{
|
{
|
||||||
title: "Dashboard",
|
title: "Dashboard",
|
||||||
url: "/dashboard",
|
url: "/admin/dashboard",
|
||||||
icon: LayoutDashboard
|
icon: LayoutDashboard
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "List",
|
title: "List",
|
||||||
url: "/dashboard/list",
|
url: "/admin/dashboard/list",
|
||||||
icon: List
|
icon: List
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Create",
|
title: "Create",
|
||||||
url: "/dashboard/create",
|
url: "/admin/dashboard/create",
|
||||||
icon: Plus
|
icon: Plus
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const userItems = [
|
||||||
|
{
|
||||||
|
title: "Profile",
|
||||||
|
url: "/admin/user",
|
||||||
|
icon: User2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Auth",
|
||||||
|
url: "/admin/user/auth",
|
||||||
|
icon: KeyRoundIcon
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
export function DashboardSidebar() {
|
export function DashboardSidebar() {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const { toggleSidebar } = useSidebar()
|
const { toggleSidebar } = useSidebar()
|
||||||
@@ -81,7 +94,7 @@ export function DashboardSidebar() {
|
|||||||
</SidebarGroupLabel>
|
</SidebarGroupLabel>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
{items.map((item) => (
|
{dashboardItems.map((item) => (
|
||||||
<SidebarMenuItem key={item.title}>
|
<SidebarMenuItem key={item.title}>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
asChild
|
asChild
|
||||||
@@ -99,23 +112,25 @@ export function DashboardSidebar() {
|
|||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>
|
<SidebarGroupLabel className="group-data-[collapsible=icon]:hidden">
|
||||||
Other
|
User
|
||||||
</SidebarGroupLabel>
|
</SidebarGroupLabel>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
<SidebarMenuItem>
|
{userItems.map((item) => (
|
||||||
|
<SidebarMenuItem key={item.title}>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
asChild
|
asChild
|
||||||
isActive={pathname === "/dashboard/user"}
|
isActive={pathname === item.url}
|
||||||
tooltip="User Profile"
|
tooltip={item.title}
|
||||||
>
|
>
|
||||||
<Link href="/dashboard/user">
|
<Link href={item.url}>
|
||||||
<User2 />
|
<item.icon />
|
||||||
<span>User Profile</span>
|
<span>{item.title}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
|
))}
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
@@ -226,12 +226,12 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) {
|
|||||||
toast.error(res.message)
|
toast.error(res.message)
|
||||||
} else {
|
} else {
|
||||||
toast.success(res.message)
|
toast.success(res.message)
|
||||||
router.push("/dashboard/list")
|
router.push("/admin/dashboard/list")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
router.push("/dashboard/list")
|
router.push("/admin/dashboard/list")
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -283,7 +283,7 @@ export function UrlsDataTable({ data }: UrlsDataTableProps) {
|
|||||||
Copy URL
|
Copy URL
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Link href={`/dashboard/edit/${urlRecord.id}`}>
|
<Link href={`/admin/dashboard/edit/${urlRecord.id}`}>
|
||||||
<Copy className="mr-2 w-4 h-4" />
|
<Copy className="mr-2 w-4 h-4" />
|
||||||
Edit URL
|
Edit URL
|
||||||
</Link>
|
</Link>
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { getSession } from "@/lib/auth/session"
|
import { getSession } from "@/lib/auth/session"
|
||||||
import { UrlFormCard } from "../_components/url-form-card"
|
import { UrlFormCard } from "../../_components/url-form-card"
|
||||||
|
|
||||||
export default async function DashboardCreatePage() {
|
export default async function DashboardCreatePage() {
|
||||||
const { session, redirect } = await getSession()
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
redirect("/sign-in")
|
redirectToSignIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="mb-2 text-2xl font-bold text-foreground">Create Short Link</h1>
|
<h1 className="mb-2 text-2xl font-bold text-foreground">Create Short Link</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,12 +25,12 @@ export default function NotFound() {
|
|||||||
</ul>
|
</ul>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<Link href="/dashboard/list">
|
<Link href="/admin/dashboard/list">
|
||||||
View All Links
|
View All Links
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button asChild variant="outline">
|
<Button asChild variant="outline">
|
||||||
<Link href="/dashboard/create">
|
<Link href="/admin/dashboard/create">
|
||||||
Create New Link
|
Create New Link
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { getSession } from "@/lib/auth/session"
|
import { getSession } from "@/lib/auth/session"
|
||||||
import { getUrlById } from "@/lib/db/urls"
|
import { getUrlById } from "@/lib/db/urls"
|
||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { UrlFormCard } from "../../_components/url-form-card"
|
import { UrlFormCard } from "../../../_components/url-form-card"
|
||||||
|
|
||||||
export default async function EditPage({
|
export default async function EditPage({
|
||||||
params
|
params
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ id: string }>
|
params: Promise<{ id: string }>
|
||||||
}) {
|
}) {
|
||||||
const { session, redirect } = await getSession()
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
redirect("/sign-in")
|
redirectToSignIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = await params
|
const { id } = await params
|
||||||
@@ -23,7 +23,7 @@ export default async function EditPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="mb-2 text-2xl font-bold text-foreground">Edit Short Link</h1>
|
<h1 className="mb-2 text-2xl font-bold text-foreground">Edit Short Link</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { getSession } from "@/lib/auth/session"
|
import { getSession } from "@/lib/auth/session"
|
||||||
import { getAllUrls } from "@/lib/db/urls"
|
import { getAllUrls } from "@/lib/db/urls"
|
||||||
import { UrlsDataTable } from "../_components/urls-data-table"
|
import { UrlsDataTable } from "../../_components/urls-data-table"
|
||||||
|
|
||||||
export default async function DashboardListPage() {
|
export default async function DashboardListPage() {
|
||||||
const { session, redirect } = await getSession()
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
redirect("/sign-in")
|
redirectToSignIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
const urls = await getAllUrls()
|
const urls = await getAllUrls()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h1 className="block mb-2 text-2xl font-bold text-foreground">URLs</h1>
|
<h1 className="block mb-2 text-2xl font-bold text-foreground">URLs</h1>
|
||||||
<h1 className="block text-muted-foreground">Manage all your shortened URLs.</h1>
|
<h1 className="block text-muted-foreground">Manage all your shortened URLs.</h1>
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { getSession } from "@/lib/auth/session"
|
import { getSession } from "@/lib/auth/session"
|
||||||
import { getDashboardStats } from "@/lib/dashboard/stats"
|
import { getDashboardStats } from "@/lib/dashboard/stats"
|
||||||
import { LinkIcon, MousePointerClick, TrendingUp } from "lucide-react"
|
import { LinkIcon, MousePointerClick, TrendingUp } from "lucide-react"
|
||||||
import { UrlFormCard } from "./_components/simple-url-form-card"
|
import { UrlFormCard } from "../_components/simple-url-form-card"
|
||||||
import { StatsCard } from "./_components/stats-card"
|
import { StatsCard } from "../_components/stats-card"
|
||||||
|
|
||||||
export default async function Dashboard() {
|
export default async function Dashboard() {
|
||||||
const { session, redirect } = await getSession()
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
redirect("/sign-in")
|
redirectToSignIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
const stats = await getDashboardStats()
|
const stats = await getDashboardStats()
|
||||||
@@ -20,7 +20,7 @@ export default async function Dashboard() {
|
|||||||
: "No URLs"
|
: "No URLs"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div>
|
||||||
<h1 className="block mb-4 text-2xl font-bold text-foreground">Dashboard</h1>
|
<h1 className="block mb-4 text-2xl font-bold text-foreground">Dashboard</h1>
|
||||||
<div className="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<StatsCard
|
<StatsCard
|
||||||
@@ -13,7 +13,7 @@ export default function DashboardLayout({
|
|||||||
<SidebarClient>
|
<SidebarClient>
|
||||||
<div className="flex w-full min-h-screen">
|
<div className="flex w-full min-h-screen">
|
||||||
<DashboardSidebar />
|
<DashboardSidebar />
|
||||||
<main className="overflow-auto flex-1">
|
<main className="overflow-auto flex-1 p-6">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
22
src/app/(admin)/admin/user/auth/page.tsx
Normal file
22
src/app/(admin)/admin/user/auth/page.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { getSession } from "@/lib/auth/session"
|
||||||
|
import DashBoardTitle from "../../_components/dashboard-title"
|
||||||
|
import { PasskeyAdd } from "../../_components/passkey"
|
||||||
|
import PasskeysList from "../../_components/passkeys-list"
|
||||||
|
|
||||||
|
export default async function UserAuthPage() {
|
||||||
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
redirectToSignIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<DashBoardTitle title="User Auth" renderSubtitle subtitle="Manage user settings" />
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
<PasskeyAdd />
|
||||||
|
<PasskeysList />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
18
src/app/(admin)/admin/user/page.tsx
Normal file
18
src/app/(admin)/admin/user/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { getSession } from "@/lib/auth/session"
|
||||||
|
import DashBoardTitle from "../_components/dashboard-title"
|
||||||
|
import UserProfile from "../_components/user-profile"
|
||||||
|
|
||||||
|
export default async function UserPage() {
|
||||||
|
const { session, redirectToSignIn } = await getSession()
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
redirectToSignIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<DashBoardTitle title="User Profile" renderSubtitle subtitle="Manage Profile" />
|
||||||
|
<UserProfile />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import { getSession } from "@/lib/auth/session"
|
|
||||||
import { PasskeyAdd } from "../_components/passkey"
|
|
||||||
import PasskeysList from "../_components/passkeys-list"
|
|
||||||
import UserProfile from "../_components/user-profile"
|
|
||||||
|
|
||||||
export default async function UserPage() {
|
|
||||||
const { session, redirect } = await getSession()
|
|
||||||
|
|
||||||
if (!session) {
|
|
||||||
redirect("/login")
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="p-6">
|
|
||||||
<div className="pb-6">
|
|
||||||
<h1 className="block mb-2 text-2xl font-bold text-foreground">User Profile</h1>
|
|
||||||
<h1 className="block text-muted-foreground">Manage user settings</h1>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-6">
|
|
||||||
<UserProfile />
|
|
||||||
<PasskeyAdd />
|
|
||||||
<PasskeysList />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@ export function OAuthSignInButton({
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
const res = await authClient.signIn.oauth2({
|
const res = await authClient.signIn.oauth2({
|
||||||
providerId: "authentik",
|
providerId: "authentik",
|
||||||
callbackURL: "/dashboard"
|
callbackURL: "/admin/dashboard"
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res && res.error) {
|
if (res && res.error) {
|
||||||
@@ -39,7 +39,7 @@ export function OAuthSignInButton({
|
|||||||
const res = await authClient.signIn.passkey({
|
const res = await authClient.signIn.passkey({
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
router.push("/dashboard")
|
router.push("/admin/dashboard")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { getSession } from "@/lib/auth/session"
|
|||||||
import { LogIn } from "lucide-react"
|
import { LogIn } from "lucide-react"
|
||||||
|
|
||||||
export default async function SignInPage() {
|
export default async function SignInPage() {
|
||||||
const { session, redirect } = await getSession()
|
const { session, redirectToHome } = await getSession()
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
redirect("/dashboard")
|
redirectToHome()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -85,9 +85,9 @@ export function UserDropdown({ className }: UserDropdownProps) {
|
|||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Link href="/dashboard">
|
<Link href="/admin/dashboard">
|
||||||
<Settings className="mr-2 w-4 h-4" />
|
<Settings className="mr-2 w-4 h-4" />
|
||||||
<span>Dashboard</span>
|
<span>Admin</span>
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export async function addUrl(unsafeData: unknown): Promise<Response> {
|
|||||||
title: await getWebsiteTitle(data.url)
|
title: await getWebsiteTitle(data.url)
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/dashboard")
|
revalidatePath("/admin/dashboard")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
error: false,
|
error: false,
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ export async function getSession() {
|
|||||||
const session = await auth.api.getSession({
|
const session = await auth.api.getSession({
|
||||||
headers: await headers()
|
headers: await headers()
|
||||||
})
|
})
|
||||||
const redirectFunc = (path: string) => {
|
function redirectToSignIn() {
|
||||||
redirect(path)
|
redirect("/sign-in")
|
||||||
|
}
|
||||||
|
function redirectToHome() {
|
||||||
|
redirect("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
return { session, redirect: redirectFunc }
|
return { session, redirectToSignIn, redirectToHome }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ export async function middleware(request: NextRequest) {
|
|||||||
return NextResponse.next()
|
return NextResponse.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = { matcher: ["/dashboard"] }
|
export const config = { matcher: ["/admin"] }
|
||||||
|
|||||||
Reference in New Issue
Block a user