Skip to content

Commit 98fab93

Browse files
committed
[BLD-166] Dashboard: Show Manage Contract button if user has used dashboard (#7898)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR introduces a new constant `HAS_USED_DASHBOARD` to track user engagement with the dashboard. It updates several components to include the `isDashboardUser` prop, allowing for conditional rendering based on whether the user has previously accessed the dashboard. ### Detailed summary - Added `HAS_USED_DASHBOARD` constant in `cookie.ts`. - Updated `NFTPublicPageLayout` to accept `isDashboardUser` prop. - Modified `SaveLastVisitedTeamPage` to set `HAS_USED_DASHBOARD` cookie. - Integrated `isDashboardUser` in `NFTPublicPage` and `ERC20PublicPage`. - Updated `ContractHeaderUI` to conditionally render elements based on `isDashboardUser`. - Enhanced storybook stories to include `isDashboardUser` prop for testing. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Dashboard users are now detected via a persistent flag so public ERC20 and NFT pages can tailor the header UI and surface “Manage Contract” controls when appropriate. * Stories updated to cover dashboard vs non-dashboard header states. * **Bug Fixes** * More reliable dashboard-user detection ensures the “Manage Contract” controls display consistently on public contract pages. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 6caba38 commit 98fab93

File tree

7 files changed

+46
-5
lines changed

7 files changed

+46
-5
lines changed

apps/dashboard/src/@/constants/cookie.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export const COOKIE_PREFIX_TOKEN = "tw_token_";
33

44
export const LAST_USED_PROJECT_ID = "last-used-project-id";
55
export const LAST_USED_TEAM_ID = "last-used-team-id";
6+
export const HAS_USED_DASHBOARD = "has-used-dashboard";

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.stories.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,26 @@ export const WithImageAndMultipleSocialUrls: Story = {
9999
website: mockSocialUrls.website,
100100
},
101101
symbol: "SMPL",
102+
isDashboardUser: true,
103+
},
104+
};
105+
106+
export const NotDashboardUser: Story = {
107+
args: {
108+
chainMetadata: ethereumChainMetadata,
109+
clientContract: mockContract,
110+
contractCreator: null,
111+
image: mockTokenImage,
112+
name: "Sample Token",
113+
socialUrls: {
114+
discord: mockSocialUrls.discord,
115+
github: mockSocialUrls.github,
116+
telegram: mockSocialUrls.telegram,
117+
twitter: mockSocialUrls.twitter,
118+
website: mockSocialUrls.website,
119+
},
120+
symbol: "SMPL",
121+
isDashboardUser: false,
102122
},
103123
};
104124

@@ -117,6 +137,7 @@ export const WithContractCreator: Story = {
117137
website: mockSocialUrls.website,
118138
},
119139
symbol: "SMPL",
140+
isDashboardUser: true,
120141
},
121142
};
122143

@@ -131,6 +152,7 @@ export const WithBrokenImageAndSingleSocialUrl: Story = {
131152
website: mockSocialUrls.website,
132153
},
133154
symbol: "SMPL",
155+
isDashboardUser: true,
134156
},
135157
};
136158

@@ -143,6 +165,7 @@ export const WithoutImageAndNoSocialUrls: Story = {
143165
name: "Sample Token",
144166
socialUrls: {},
145167
symbol: "SMPL",
168+
isDashboardUser: true,
146169
},
147170
};
148171

@@ -163,6 +186,7 @@ export const LongNameAndLotsOfSocialUrls: Story = {
163186
youtube: mockSocialUrls.youtube,
164187
},
165188
symbol: "LONG",
189+
isDashboardUser: true,
166190
},
167191
};
168192

@@ -187,6 +211,7 @@ export const AllSocialUrls: Story = {
187211
youtube: mockSocialUrls.youtube,
188212
},
189213
symbol: "SMPL",
214+
isDashboardUser: true,
190215
},
191216
};
192217

@@ -205,6 +230,7 @@ export const InvalidSocialUrls: Story = {
205230
youtube: mockSocialUrls.youtube,
206231
},
207232
symbol: "SMPL",
233+
isDashboardUser: true,
208234
},
209235
};
210236

@@ -220,5 +246,6 @@ export const SomeSocialUrls: Story = {
220246
website: mockSocialUrls.website,
221247
},
222248
symbol: "SMPL",
249+
isDashboardUser: true,
223250
},
224251
};

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import Link from "next/link";
99
import { useMemo } from "react";
1010
import { type ThirdwebContract, ZERO_ADDRESS } from "thirdweb";
1111
import type { ChainMetadata } from "thirdweb/chains";
12-
import { useActiveAccount } from "thirdweb/react";
1312
import { Img } from "@/components/blocks/Img";
1413
import { Button } from "@/components/ui/button";
1514
import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
@@ -51,6 +50,7 @@ export function ContractHeaderUI(props: {
5150
imageClassName?: string;
5251
contractCreator: string | null;
5352
className?: string;
53+
isDashboardUser: boolean;
5454
}) {
5555
const socialUrls = useMemo(() => {
5656
const socialUrlsValue: { name: string; href: string }[] = [];
@@ -66,7 +66,6 @@ export function ContractHeaderUI(props: {
6666

6767
return socialUrlsValue;
6868
}, [props.socialUrls]);
69-
const activeAccount = useActiveAccount();
7069

7170
const cleanedChainName = props.chainMetadata?.name
7271
?.replace("Mainnet", "")
@@ -172,8 +171,7 @@ export function ContractHeaderUI(props: {
172171
variant="outline"
173172
/>
174173

175-
{props.contractCreator?.toLowerCase() ===
176-
activeAccount?.address?.toLowerCase() && (
174+
{props.isDashboardUser && (
177175
<ToolTipLabel
178176
contentClassName="max-w-[300px]"
179177
label={

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/erc20.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import { cookies } from "next/headers";
12
import type { ThirdwebContract } from "thirdweb";
23
import type { ChainMetadata } from "thirdweb/chains";
34
import { getContractMetadata } from "thirdweb/extensions/common";
45
import { decimals, getActiveClaimCondition } from "thirdweb/extensions/erc20";
56
import { GridPattern } from "@/components/ui/background-patterns";
7+
import { HAS_USED_DASHBOARD } from "@/constants/cookie";
68
import { resolveFunctionSelectors } from "@/lib/selectors";
79
import { AssetPageView } from "../_components/asset-page-view";
810
import { getContractCreator } from "../_components/getContractCreator";
@@ -65,6 +67,9 @@ export async function ERC20PublicPage(props: {
6567
: undefined,
6668
]);
6769

70+
const cookieStore = await cookies();
71+
const isDashboardUser = cookieStore.has(HAS_USED_DASHBOARD);
72+
6873
const buyEmbed = (
6974
<BuyEmbed
7075
chainMetadata={props.chainMetadata}
@@ -96,6 +101,7 @@ export async function ERC20PublicPage(props: {
96101
clientContract={props.clientContract}
97102
contractCreator={contractCreator}
98103
image={contractMetadata.image}
104+
isDashboardUser={isDashboardUser}
99105
name={contractMetadata.name}
100106
socialUrls={
101107
typeof contractMetadata.social_urls === "object" &&

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/nft-page-layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export function NFTPublicPageLayout(props: {
1414
};
1515
children: React.ReactNode;
1616
contractCreator: string | null;
17+
isDashboardUser: boolean;
1718
}) {
1819
return (
1920
<div className="flex grow flex-col">
@@ -38,6 +39,7 @@ export function NFTPublicPageLayout(props: {
3839
: {}
3940
}
4041
symbol={props.contractMetadata.symbol}
42+
isDashboardUser={props.isDashboardUser}
4143
/>
4244
</div>
4345
</div>

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/nft-page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { cookies } from "next/headers";
12
import type { ThirdwebContract } from "thirdweb";
23
import type { ChainMetadata } from "thirdweb/chains";
34
import { getContractMetadata } from "thirdweb/extensions/common";
45
import { isTokenByIndexSupported } from "thirdweb/extensions/erc721";
56
import { ResponsiveLayout } from "@/components/blocks/Responsive";
67
import { Skeleton } from "@/components/ui/skeleton";
8+
import { HAS_USED_DASHBOARD } from "@/constants/cookie";
79
import { resolveFunctionSelectors } from "@/lib/selectors";
810
import { cn } from "@/lib/utils";
911
import { getContractCreator } from "../_components/getContractCreator";
@@ -100,12 +102,16 @@ export async function NFTPublicPage(props: {
100102
<Skeleton className="h-[620px] border" />
101103
) : null;
102104

105+
const cookieStore = await cookies();
106+
const isDashboardUser = cookieStore.has(HAS_USED_DASHBOARD);
107+
103108
return (
104109
<NFTPublicPageLayout
105110
chainMetadata={props.chainMetadata}
106111
clientContract={props.clientContract}
107112
contractCreator={contractCreator}
108113
contractMetadata={contractMetadata}
114+
isDashboardUser={isDashboardUser}
109115
>
110116
<ResponsiveLayout
111117
desktop={

apps/dashboard/src/app/(app)/team/components/last-visited-page/SaveLastVisitedPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { usePathname } from "next/navigation";
44
import { useEffect } from "react";
5-
import { LAST_USED_TEAM_ID } from "@/constants/cookie";
5+
import { HAS_USED_DASHBOARD, LAST_USED_TEAM_ID } from "@/constants/cookie";
66
import { setCookie } from "@/utils/cookie";
77
import { LAST_VISITED_TEAM_PAGE_PATH } from "./consts";
88

@@ -13,6 +13,7 @@ export function SaveLastVisitedTeamPage(props: { teamId: string }) {
1313
useEffect(() => {
1414
setCookie(LAST_VISITED_TEAM_PAGE_PATH, pathname);
1515
setCookie(LAST_USED_TEAM_ID, props.teamId);
16+
setCookie(HAS_USED_DASHBOARD, "true");
1617
}, [pathname, props.teamId]);
1718

1819
return null;

0 commit comments

Comments
 (0)