fix: use getLayout to persist layout state across pages

This commit is contained in:
Henry
2025-07-18 16:48:45 +01:00
parent c58c8c753c
commit 076fe1d922
10 changed files with 94 additions and 56 deletions

View File

@@ -10,6 +10,7 @@ import { authClient } from "@kan/auth/client";
import { useClickOutside } from "~/hooks/useClickOutside";
import { useTheme } from "~/providers/theme";
import { WorkspaceProvider } from "~/providers/workspace";
import SideNavigation from "./SideNavigation";
interface DashboardProps {
@@ -18,6 +19,20 @@ interface DashboardProps {
hasRightPanel?: boolean;
}
export function getDashboardLayout(
page: React.ReactElement,
rightPanel?: React.ReactNode,
hasRightPanel = false,
) {
return (
<WorkspaceProvider>
<Dashboard rightPanel={rightPanel} hasRightPanel={hasRightPanel}>
{page}
</Dashboard>
</WorkspaceProvider>
);
}
export default function Dashboard({
children,
rightPanel,
@@ -26,6 +41,7 @@ export default function Dashboard({
const theme = useTheme();
const { data: session, isPending: sessionLoading } = authClient.useSession();
const [isSideNavOpen, setIsSideNavOpen] = useState(false);
const [isRightPanelOpen, setIsRightPanelOpen] = useState(false);

View File

@@ -88,7 +88,7 @@ export default function SideNavigation({
<>
<nav
className={twMerge(
"flex h-full flex-col justify-between bg-light-100 pr-3 transition-all duration-300 dark:bg-dark-100",
"flex h-full flex-col justify-between bg-light-100 pr-3 dark:bg-dark-100",
isCollapsed ? "w-auto" : "w-64",
)}
>
@@ -96,7 +96,7 @@ export default function SideNavigation({
<div className="flex h-14 items-center justify-between pb-[18px] pt-1.5">
{!isCollapsed && (
<Link href="/" className="block">
<h1 className="pl-2 text-lg font-bold tracking-tight text-neutral-700 dark:text-dark-950">
<h1 className="pl-2 text-lg font-bold tracking-tight text-neutral-700 dark:text-dark-1000">
kan.bn
</h1>
</Link>

View File

@@ -1,8 +1,9 @@
import "~/styles/globals.css";
import "~/utils/i18n";
import type { Viewport } from "next";
import type { AppType } from "next/app";
import type { NextPage, Viewport } from "next";
import type { AppProps, AppType } from "next/app";
import type { ReactElement, ReactNode } from "react";
import { Plus_Jakarta_Sans } from "next/font/google";
import Script from "next/script";
import { env } from "next-runtime-env";
@@ -34,7 +35,15 @@ export const viewport: Viewport = {
userScalable: false,
};
const MyApp: AppType = ({ Component, pageProps }) => {
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode;
};
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
const posthogKey = env("NEXT_PUBLIC_POSTHOG_KEY");
useEffect(() => {
@@ -50,6 +59,8 @@ const MyApp: AppType = ({ Component, pageProps }) => {
}
}, [posthogKey]);
const getLayout = Component.getLayout ?? ((page) => page);
return (
<>
<style jsx global>{`
@@ -75,10 +86,10 @@ const MyApp: AppType = ({ Component, pageProps }) => {
<PopupProvider>
{posthogKey ? (
<PostHogProvider client={posthog}>
<Component {...pageProps} />
{getLayout(<Component {...pageProps} />)}
</PostHogProvider>
) : (
<Component {...pageProps} />
getLayout(<Component {...pageProps} />)
)}
</PopupProvider>
</ModalProvider>

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardView from "~/views/board";
export default function BoardPage() {
const BoardPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<BoardView />
</Dashboard>
<>
<BoardView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
BoardPage.getLayout = (page) => getDashboardLayout(page);
export default BoardPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "../_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardsView from "~/views/boards";
export default function BoardsPage() {
const BoardsPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<BoardsView />
</Dashboard>
<>
<BoardsView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
BoardsPage.getLayout = (page) => getDashboardLayout(page);
export default BoardsPage;

View File

@@ -1,15 +1,18 @@
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import { WorkspaceProvider } from "~/providers/workspace";
import CardView, { CardRightPanel } from "~/views/card";
export default function CardPage() {
const CardPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard hasRightPanel rightPanel={<CardRightPanel />}>
<CardView />
</Dashboard>
<>
<CardView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
CardPage.getLayout = (page) =>
getDashboardLayout(page, <CardRightPanel />, true);
export default CardPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import MembersView from "~/views/members";
export default function MembersPage() {
const MembersPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<MembersView />
</Dashboard>
<>
<MembersView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
MembersPage.getLayout = (page) => getDashboardLayout(page);
export default MembersPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import SettingsView from "~/views/settings";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import SettingsView from "~/views/settings";
export default function SettingsPage() {
const SettingsPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<SettingsView />
</Dashboard>
<>
<SettingsView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
SettingsPage.getLayout = (page) => getDashboardLayout(page);
export default SettingsPage;

View File

@@ -44,7 +44,7 @@ export function BoardsList() {
);
return (
<div className="grid h-fit w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-7">
<div className="grid h-fit w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-7">
{data?.map((board) => (
<Link key={board.publicId} href={`boards/${board.publicId}`}>
<div className="align-center relative mr-5 flex h-[150px] w-full items-center justify-center rounded-md border border-dashed border-light-400 bg-light-50 shadow-sm hover:bg-light-200 dark:border-dark-600 dark:bg-dark-50 dark:hover:bg-dark-100">

View File

@@ -21,8 +21,8 @@ export default function BoardsPage() {
return (
<>
<PageHead title={t`Boards | ${workspace.name ?? "Workspace"}`} />
<div className="relative m-auto h-full max-w-[1600px] px-5 py-6 md:px-8 md:py-8">
<PatternedBackground />
<PatternedBackground />
<div className="m-auto h-full max-w-[1200px] p-6 px-5 md:px-28 md:py-12">
<div className="relative z-10 mb-8 flex w-full items-center justify-between">
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Boards`}