Add Project Setting pages Layout (#4620)
## Problem solved
Short description of the bug fixed or feature added
<!-- start pr-codex -->
---
## PR-Codex overview
The focus of this PR is to update the layout and styling of various pages in the dashboard app.
### Detailed summary
- Updated body and html styles for full height
- Added new pages for Pay Settings, In-App Wallet Settings, and Account Abstraction Settings
- Modified project selector UI link
- Updated text and layout for General Settings page
- Adjusted layout in TeamLayout and RootTeamLayout components
- Added a new Layout component for settings with sidebar links
- Added a new page for API key details with editing functionality
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -139,3 +139,8 @@
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function RootLayout({
|
||||
<PostHogProvider>
|
||||
<body
|
||||
className={cn(
|
||||
"h-screen bg-background font-sans antialiased",
|
||||
"bg-background font-sans antialiased",
|
||||
fontSans.variable,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -34,7 +34,7 @@ export default async function TeamLayout(props: {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex flex-col grow">
|
||||
<div className="bg-muted/50">
|
||||
<TeamHeader
|
||||
currentProject={project}
|
||||
@@ -63,7 +63,7 @@ export default async function TeamLayout(props: {
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<main className="grow">{props.children}</main>
|
||||
<div className="grow flex flex-col">{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="grow flex flex-col items-center justify-center">
|
||||
<h1 className="text-4xl tracking-tighter text-muted-foreground">
|
||||
Account Abstraction Settings
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="grow flex flex-col items-center justify-center">
|
||||
<h1 className="text-4xl tracking-tighter text-muted-foreground">
|
||||
In-App wallet Settings
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
|
||||
|
||||
export default function Layout(props: {
|
||||
children: React.ReactNode;
|
||||
params: {
|
||||
team_slug: string;
|
||||
project_slug: string;
|
||||
};
|
||||
}) {
|
||||
const { project_slug, team_slug } = props.params;
|
||||
const layoutPath = `/team/${team_slug}/${project_slug}/settings`;
|
||||
|
||||
return (
|
||||
<SidebarLayout
|
||||
sidebarLinks={[
|
||||
{
|
||||
label: "General",
|
||||
href: `${layoutPath}`,
|
||||
exactMatch: true,
|
||||
},
|
||||
{
|
||||
label: "In-App Wallets",
|
||||
href: `${layoutPath}/in-app-wallets`,
|
||||
},
|
||||
{
|
||||
label: "Account Abstraction",
|
||||
href: `${layoutPath}/account-abstraction`,
|
||||
},
|
||||
{
|
||||
label: "Pay",
|
||||
href: `${layoutPath}/pay`,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{props.children}
|
||||
</SidebarLayout>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="h-full py-6 container flex items-center justify-center">
|
||||
<h1 className="text-4xl tracking-tighter text-muted-foreground">Usage</h1>
|
||||
<div className="grow flex flex-col items-center justify-center">
|
||||
<h1 className="text-4xl tracking-tighter text-muted-foreground">
|
||||
General Settings
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="grow flex flex-col items-center justify-center">
|
||||
<h1 className="text-4xl tracking-tighter text-muted-foreground">
|
||||
Pay Settings
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { AppFooter } from "@/components/blocks/app-footer";
|
||||
import { TWAutoConnect } from "../../components/autoconnect";
|
||||
|
||||
export default async function RootTeamLayout(props: {
|
||||
export default function RootTeamLayout(props: {
|
||||
children: React.ReactNode;
|
||||
params: { team_slug: string };
|
||||
}) {
|
||||
return (
|
||||
<div className="min-h-full flex flex-col bg-background">
|
||||
<div className="grow">{props.children}</div>
|
||||
<div className="grow flex flex-col">{props.children}</div>
|
||||
<TWAutoConnect />
|
||||
<AppFooter />
|
||||
</div>
|
||||
|
||||
@@ -56,7 +56,9 @@ export function ProjectSelectorUI(props: {
|
||||
asChild
|
||||
>
|
||||
{/* TODO - when we have overview page, remove /connect */}
|
||||
<Link href={`/team/${team.slug}/${project.slug}/connect`}>
|
||||
<Link
|
||||
href={`/team/${team.slug}/${project.slug}/connect/analytics`}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* TODO - placeholder for now */}
|
||||
<div className="size-4 bg-muted border rounded-full" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useApiKeys } from "@3rdweb-sdk/react/hooks/useApi";
|
||||
import { Spinner } from "@/components/ui/Spinner/Spinner";
|
||||
import { type ApiKey, useApiKeys } from "@3rdweb-sdk/react/hooks/useApi";
|
||||
import { useLoggedInUser } from "@3rdweb-sdk/react/hooks/useLoggedInUser";
|
||||
import { AppLayout } from "components/app-layouts/app";
|
||||
import { ApiKeyDetails } from "components/settings/ApiKeys/Details";
|
||||
@@ -10,7 +11,6 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import type { ThirdwebNextPage } from "utils/types";
|
||||
|
||||
const SettingsApiKeyPage: ThirdwebNextPage = () => {
|
||||
const [editing, setEditing] = useState(false);
|
||||
const keysQuery = useApiKeys();
|
||||
const router = useRouter();
|
||||
const { user } = useLoggedInUser();
|
||||
@@ -27,20 +27,29 @@ const SettingsApiKeyPage: ThirdwebNextPage = () => {
|
||||
}
|
||||
}, [apiKey, keysQuery.isSuccess, router]);
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
if (!user || !apiKey) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<Spinner className="size-10" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!apiKey) {
|
||||
return null;
|
||||
}
|
||||
return <APIKeyDetailsPage apiKey={apiKey} />;
|
||||
};
|
||||
|
||||
function APIKeyDetailsPage(props: {
|
||||
apiKey: ApiKey;
|
||||
}) {
|
||||
const { apiKey } = props;
|
||||
const [editing, setEditing] = useState(false);
|
||||
|
||||
return editing ? (
|
||||
<EditApiKey apiKey={apiKey} onCancel={() => setEditing(false)} />
|
||||
) : (
|
||||
<ApiKeyDetails apiKey={apiKey} onEdit={() => setEditing(true)} />
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
SettingsApiKeyPage.getLayout = (page, props) => (
|
||||
<AppLayout
|
||||
|
||||
Reference in New Issue
Block a user