feat: replace DashboardShell and SignedOut/SignedIn components with DashboardPageLayout for improved structure and state handling

This commit is contained in:
Abhimanyu Saharan
2026-02-09 00:10:35 +05:30
parent 746b909ed6
commit 9a8fd3558d
2 changed files with 187 additions and 237 deletions

View File

@@ -5,7 +5,7 @@ export const dynamic = "force-dynamic";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { SignedIn, SignedOut, useAuth } from "@/auth/clerk"; import { useAuth } from "@/auth/clerk";
import { import {
type ColumnDef, type ColumnDef,
flexRender, flexRender,
@@ -22,8 +22,7 @@ import {
useListBoardGroupsApiV1BoardGroupsGet, useListBoardGroupsApiV1BoardGroupsGet,
} from "@/api/generated/board-groups/board-groups"; } from "@/api/generated/board-groups/board-groups";
import type { BoardGroupRead } from "@/api/generated/model"; import type { BoardGroupRead } from "@/api/generated/model";
import { DashboardSidebar } from "@/components/organisms/DashboardSidebar"; import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
import { DashboardShell } from "@/components/templates/DashboardShell";
import { Button, buttonVariants } from "@/components/ui/button"; import { Button, buttonVariants } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -33,7 +32,6 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { SignedOutPanel } from "@/components/auth/SignedOutPanel";
import { formatTimestamp } from "@/lib/formatters"; import { formatTimestamp } from "@/lib/formatters";
import { TableEmptyStateRow, TableLoadingRow } from "@/components/ui/table-state"; import { TableEmptyStateRow, TableLoadingRow } from "@/components/ui/table-state";
@@ -179,39 +177,24 @@ export default function BoardGroupsPage() {
}); });
return ( return (
<DashboardShell> <>
<SignedOut> <DashboardPageLayout
<SignedOutPanel signedOut={{
message="Sign in to view board groups." message: "Sign in to view board groups.",
forceRedirectUrl="/board-groups" forceRedirectUrl: "/board-groups",
/> }}
</SignedOut> title="Board groups"
<SignedIn> description={`Group boards so agents can see related work. ${groups.length} group${groups.length === 1 ? "" : "s"} total.`}
<DashboardSidebar /> headerActions={
<main className="flex-1 overflow-y-auto bg-slate-50">
<div className="sticky top-0 z-30 border-b border-slate-200 bg-white">
<div className="px-8 py-6">
<div className="flex flex-wrap items-center justify-between gap-4">
<div>
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
Board groups
</h1>
<p className="mt-1 text-sm text-slate-500">
Group boards so agents can see related work. {groups.length}{" "}
group{groups.length === 1 ? "" : "s"} total.
</p>
</div>
<Link <Link
href="/board-groups/new" href="/board-groups/new"
className={buttonVariants({ size: "md", variant: "primary" })} className={buttonVariants({ size: "md", variant: "primary" })}
> >
Create group Create group
</Link> </Link>
</div> }
</div> stickyHeader
</div> >
<div className="p-8">
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm"> <div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full text-left text-sm"> <table className="w-full text-left text-sm">
@@ -239,10 +222,7 @@ export default function BoardGroupsPage() {
<TableLoadingRow colSpan={columns.length} /> <TableLoadingRow colSpan={columns.length} />
) : table.getRowModel().rows.length ? ( ) : table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => ( table.getRowModel().rows.map((row) => (
<tr <tr key={row.id} className="transition hover:bg-slate-50">
key={row.id}
className="transition hover:bg-slate-50"
>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td key={cell.id} className="px-6 py-4 align-top"> <td key={cell.id} className="px-6 py-4 align-top">
{flexRender( {flexRender(
@@ -285,14 +265,9 @@ export default function BoardGroupsPage() {
</div> </div>
{groupsQuery.error ? ( {groupsQuery.error ? (
<p className="mt-4 text-sm text-red-500"> <p className="mt-4 text-sm text-red-500">{groupsQuery.error.message}</p>
{groupsQuery.error.message}
</p>
) : null} ) : null}
</div> </DashboardPageLayout>
</main>
</SignedIn>
<Dialog <Dialog
open={!!deleteTarget} open={!!deleteTarget}
onOpenChange={(nextOpen) => { onOpenChange={(nextOpen) => {
@@ -324,6 +299,6 @@ export default function BoardGroupsPage() {
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</DashboardShell> </>
); );
} }

View File

@@ -5,7 +5,7 @@ export const dynamic = "force-dynamic";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { SignedIn, SignedOut, useAuth } from "@/auth/clerk"; import { useAuth } from "@/auth/clerk";
import { import {
type ColumnDef, type ColumnDef,
flexRender, flexRender,
@@ -28,8 +28,7 @@ import {
import { formatTimestamp } from "@/lib/formatters"; import { formatTimestamp } from "@/lib/formatters";
import { useOrganizationMembership } from "@/lib/use-organization-membership"; import { useOrganizationMembership } from "@/lib/use-organization-membership";
import type { BoardGroupRead, BoardRead } from "@/api/generated/model"; import type { BoardGroupRead, BoardRead } from "@/api/generated/model";
import { DashboardSidebar } from "@/components/organisms/DashboardSidebar"; import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
import { DashboardShell } from "@/components/templates/DashboardShell";
import { Button, buttonVariants } from "@/components/ui/button"; import { Button, buttonVariants } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -39,7 +38,6 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { SignedOutPanel } from "@/components/auth/SignedOutPanel";
import { TableEmptyStateRow, TableLoadingRow } from "@/components/ui/table-state"; import { TableEmptyStateRow, TableLoadingRow } from "@/components/ui/table-state";
const compactId = (value: string) => const compactId = (value: string) =>
@@ -228,30 +226,17 @@ export default function BoardsPage() {
}); });
return ( return (
<DashboardShell> <>
<SignedOut> <DashboardPageLayout
<SignedOutPanel signedOut={{
message="Sign in to view boards." message: "Sign in to view boards.",
forceRedirectUrl="/boards" forceRedirectUrl: "/boards",
signUpForceRedirectUrl="/boards" signUpForceRedirectUrl: "/boards",
/> }}
</SignedOut> title="Boards"
<SignedIn> description={`Manage boards and task workflows. ${boards.length} board${boards.length === 1 ? "" : "s"} total.`}
<DashboardSidebar /> headerActions={
<main className="flex-1 overflow-y-auto bg-slate-50"> boards.length > 0 && isAdmin ? (
<div className="sticky top-0 z-30 border-b border-slate-200 bg-white">
<div className="px-8 py-6">
<div className="flex flex-wrap items-center justify-between gap-4">
<div>
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
Boards
</h1>
<p className="mt-1 text-sm text-slate-500">
Manage boards and task workflows. {boards.length} board
{boards.length === 1 ? "" : "s"} total.
</p>
</div>
{boards.length > 0 && isAdmin ? (
<Link <Link
href="/boards/new" href="/boards/new"
className={buttonVariants({ className={buttonVariants({
@@ -261,12 +246,10 @@ export default function BoardsPage() {
> >
Create board Create board
</Link> </Link>
) : null} ) : null
</div> }
</div> stickyHeader
</div> >
<div className="p-8">
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm"> <div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full text-left text-sm"> <table className="w-full text-left text-sm">
@@ -294,10 +277,7 @@ export default function BoardsPage() {
<TableLoadingRow colSpan={columns.length} /> <TableLoadingRow colSpan={columns.length} />
) : table.getRowModel().rows.length ? ( ) : table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => ( table.getRowModel().rows.map((row) => (
<tr <tr key={row.id} className="transition hover:bg-slate-50">
key={row.id}
className="transition hover:bg-slate-50"
>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td key={cell.id} className="px-6 py-4 align-top"> <td key={cell.id} className="px-6 py-4 align-top">
{flexRender( {flexRender(
@@ -339,14 +319,9 @@ export default function BoardsPage() {
</div> </div>
{boardsQuery.error ? ( {boardsQuery.error ? (
<p className="mt-4 text-sm text-red-500"> <p className="mt-4 text-sm text-red-500">{boardsQuery.error.message}</p>
{boardsQuery.error.message}
</p>
) : null} ) : null}
</div> </DashboardPageLayout>
</main>
</SignedIn>
<Dialog <Dialog
open={!!deleteTarget} open={!!deleteTarget}
onOpenChange={(nextOpen) => { onOpenChange={(nextOpen) => {
@@ -378,6 +353,6 @@ export default function BoardsPage() {
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</DashboardShell> </>
); );
} }