Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions apps/superfluid-campaign-web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useMemo, useRef } from 'react'
import { SuperfluidCampaignWidget } from '@goodwidget/superfluid-campaign-widget'
import type { EIP1193Provider } from '@goodwidget/core'
import type { CampaignActionLinkOverrides } from '@goodwidget/superfluid-campaign-widget'
import {
DEFAULT_APPKIT_NETWORKS,
DefaultAppKitProvider,
Expand All @@ -14,6 +15,22 @@ import { YStack, defaultConfig } from '@goodwidget/ui'

const DESKTOP_WIDGET_MAX_WIDTH = 960

/**
* Tracked ubi.gd destinations for the standalone app. Invite, Vote on Flow State
* and Fund GoodBuilders are intentionally absent: those cards are disabled for
* Season 7 and must not carry a link.
*/
const STANDALONE_ACTION_LINKS: CampaignActionLinkOverrides = {
'claim-ubi': 'https://ubi.gd/4BTD7Vb',
'gardens-donation': 'https://ubi.gd/4eunQAd',
'gardens-funding': 'https://ubi.gd/4zEWvDW',
'ai-credits-purchase': 'https://ubi.gd/3UFIqH3',
'ai-credits-subscription': 'https://ubi.gd/4AslL0c',
}

/** Tracked ubi.gd link opened by the header's "Claim SUP rewards" button. */
const STANDALONE_CLAIM_REWARDS_URL = 'https://ubi.gd/4iN7RhK'

/**
* Pressing the disconnect-menu item under AppKit opens AppKit's own Account
* view (see disconnectOverride below) rather than ending the session
Expand Down Expand Up @@ -103,14 +120,8 @@ function AppKitSuperfluidCampaignWidget() {
disconnectOverride={async () => {
await open({ view: 'Account' })
}}
actionLinks={{
'flow-state-vote': 'https://ubi.gd/4fEqvrS',
'flow-state-funding': 'https://ubi.gd/4z2tH8y',
'gardens-donation': 'https://ubi.gd/4xhk4kv',
'gardens-funding': 'https://ubi.gd/3TABl9O',
'invite-users': 'https://ubi.gd/4xhYTyH',
'claim-ubi': 'https://ubi.gd/3RNtzJd',
}}
actionLinks={STANDALONE_ACTION_LINKS}
claimRewardsUrl={STANDALONE_CLAIM_REWARDS_URL}
/>
)
}
Expand All @@ -131,6 +142,8 @@ function CampaignWidgetFrame() {
provider={typeof window === 'undefined' ? undefined : window.ethereum}
defaultTheme="dark"
contentMaxWidth={DESKTOP_WIDGET_MAX_WIDTH}
actionLinks={STANDALONE_ACTION_LINKS}
claimRewardsUrl={STANDALONE_CLAIM_REWARDS_URL}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import {
SuperfluidCampaignWidget,
type CampaignActionLinkOverrides,
type SuperfluidCampaignWidgetProps,
type SuperfluidCampaignView,
} from '@goodwidget/superfluid-campaign-widget'
Expand All @@ -16,6 +17,32 @@ import {
isInjectedProviderUsable,
} from '../../fixtures/injectedEip1193'

/** Integrator link sets reviewed in Storybook; disabled actions intentionally carry no link. */
export const STANDALONE_STORY_LINKS: {
actionLinks: CampaignActionLinkOverrides
claimRewardsUrl: string
} = {
claimRewardsUrl: 'https://ubi.gd/4iN7RhK',
actionLinks: {
'claim-ubi': 'https://ubi.gd/4BTD7Vb',
'gardens-donation': 'https://ubi.gd/4eunQAd',
'gardens-funding': 'https://ubi.gd/4zEWvDW',
'ai-credits-purchase': 'https://ubi.gd/3UFIqH3',
'ai-credits-subscription': 'https://ubi.gd/4AslL0c',
},
}

export const GOODWALLET_STORY_LINKS: typeof STANDALONE_STORY_LINKS = {
claimRewardsUrl: 'https://ubi.gd/4sR6vY1',
actionLinks: {
'claim-ubi': 'https://ubi.gd/3UuQxWV',
'gardens-donation': 'https://ubi.gd/4zzqRrj',
'gardens-funding': 'https://ubi.gd/4C02hl6',
'ai-credits-purchase': 'https://ubi.gd/4sRkCwz',
'ai-credits-subscription': 'https://ubi.gd/4Ap8chU',
},
}

function StoryShell({ children, dataTestId }: { children: React.ReactNode; dataTestId: string }) {
return (
<MiniAppShell>
Expand All @@ -34,6 +61,8 @@ interface MockStoryProps {
initialView?: SuperfluidCampaignView
leaderboardScenario?: MockLeaderboardScenario
programSupTotalsScenario?: MockProgramSupTotalsScenario
actionLinks?: CampaignActionLinkOverrides
claimRewardsUrl?: string
}

function MockSuperfluidCampaignWidgetStoryShell({
Expand All @@ -43,6 +72,8 @@ function MockSuperfluidCampaignWidgetStoryShell({
initialView = 'content',
leaderboardScenario,
programSupTotalsScenario,
actionLinks,
claimRewardsUrl,
}: MockStoryProps & { provider: unknown; dataTestId: string }) {
return (
<StoryShell dataTestId={dataTestId}>
Expand All @@ -52,6 +83,8 @@ function MockSuperfluidCampaignWidgetStoryShell({
initialView={initialView}
leaderboardScenario={leaderboardScenario}
programSupTotalsScenario={programSupTotalsScenario}
actionLinks={actionLinks}
claimRewardsUrl={claimRewardsUrl}
/>
</StoryShell>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from '@storybook/react'
import { MockSuperfluidCampaignWidget } from '@goodwidget/superfluid-campaign-widget/mocked'
import {
GOODWALLET_STORY_LINKS,
STANDALONE_STORY_LINKS,
CustodialLocalFixtureStory,
NoWalletLeaderboardStory,
NoWalletStory,
Expand Down Expand Up @@ -33,6 +35,28 @@ export const NoWalletLeaderboard: Story = {
render: ({ defaultTheme }) => <NoWalletStory defaultTheme={defaultTheme} initialView="leaderboard" />,
}

// Season 7 integrator link sets: the standalone app and the GoodWallet-hosted widget
// use different tracked links for the same cards.
export const StandaloneLinksContent: Story = {
render: ({ defaultTheme }) => (
<NoWalletStory
defaultTheme={defaultTheme}
initialView="content"
{...STANDALONE_STORY_LINKS}
/>
),
}

export const GoodWalletLinksContent: Story = {
render: ({ defaultTheme }) => (
<NoWalletStory
defaultTheme={defaultTheme}
initialView="content"
{...GOODWALLET_STORY_LINKS}
/>
),
}

export const CustodialLocalFixtureContent: Story = {
render: ({ defaultTheme }) => (
<CustodialLocalFixtureStory defaultTheme={defaultTheme} initialView="content" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import type {
CampaignActionDefinition,
CampaignActionLinkOverrides,
CampaignDefinition,
FaqAnswerSegment,
FaqItemDefinition,
LeaderboardSummaryData,
SuperfluidCampaignView,
SuperfluidCampaignWidgetProps,
Expand All @@ -33,6 +35,7 @@ const GOODDOLLAR_PAGE_URL = 'https://goodwallet.xyz/en/gooddollar'
interface SuperfluidCampaignRuntimeProps {
data: SuperfluidCampaignWidgetProps['data']
actionLinks?: CampaignActionLinkOverrides
claimRewardsUrl?: SuperfluidCampaignWidgetProps['claimRewardsUrl']
leaderboardSummary?: LeaderboardSummaryData
dataClient: SuperfluidCampaignDataClient
citizenClaimEnvironment: SuperfluidCampaignWidgetProps['citizenClaimEnvironment']
Expand Down Expand Up @@ -93,6 +96,30 @@ function handleActionCta(
}
}

/** Replaces the href of FAQ link segments that mirror an action card's destination. */
function applyFaqLinkOverrides(
faq: FaqItemDefinition[],
actionLinks: CampaignActionLinkOverrides,
): FaqItemDefinition[] {
const overrideSegment = (segment: FaqAnswerSegment): FaqAnswerSegment => {
if (typeof segment === 'string' || !segment.actionLinkActivity) return segment
const href = actionLinks[segment.actionLinkActivity]
return href ? { ...segment, href } : segment
}

return faq.map((item) => {
if (typeof item.answer === 'string') return item
return {
...item,
answer: item.answer.map((block) =>
Array.isArray(block)
? block.map(overrideSegment)
: { ...block, items: block.items.map((bullet) => bullet.map(overrideSegment)) },
),
}
})
}

function applyActionLinkOverrides(
campaign: CampaignDefinition,
actionLinks?: CampaignActionLinkOverrides,
Expand All @@ -101,6 +128,7 @@ function applyActionLinkOverrides(

return {
...campaign,
faq: applyFaqLinkOverrides(campaign.faq, actionLinks),
pools: campaign.pools.map((pool) => ({
...pool,
actions: pool.actions.map((action) => {
Expand All @@ -114,6 +142,7 @@ function applyActionLinkOverrides(
function SuperfluidCampaignRuntime({
data,
actionLinks,
claimRewardsUrl,
leaderboardSummary,
dataClient,
citizenClaimEnvironment,
Expand Down Expand Up @@ -155,6 +184,7 @@ function SuperfluidCampaignRuntime({
<YStack gap="$5" width="100%" padding="$5" style={{ boxSizing: 'border-box' }}>
<CampaignHeader
data={campaignData}
claimRewardsUrl={claimRewardsUrl}
isConnected={isConnected}
onConnect={connect}
onClose={() => setEmbeddedClaimTab(null)}
Expand Down Expand Up @@ -201,7 +231,7 @@ function SuperfluidCampaignRuntime({
top-right slot (see CampaignHeader) instead of its own row here. */}
<CampaignHeader
data={campaignData}
notice={campaignData.notice}
claimRewardsUrl={claimRewardsUrl}
isConnected={isConnected}
onConnect={connect}
disableWalletButton={disableWalletButton}
Expand Down Expand Up @@ -262,6 +292,7 @@ export function SuperfluidCampaignWidgetWithClient({
contentMaxWidth,
data,
actionLinks,
claimRewardsUrl,
citizenClaimEnvironment = 'production',
citizenClaimExecution,
disableClaim = false,
Expand Down Expand Up @@ -291,6 +322,7 @@ export function SuperfluidCampaignWidgetWithClient({
<SuperfluidCampaignRuntime
data={data}
actionLinks={actionLinks}
claimRewardsUrl={claimRewardsUrl}
leaderboardSummary={leaderboardSummary}
dataClient={dataClient}
citizenClaimEnvironment={citizenClaimEnvironment}
Expand Down
Loading
Loading