diff --git a/src/components/IconLabel/IconLabel.tsx b/src/components/IconLabel/IconLabel.tsx index dd904278..95236fe7 100644 --- a/src/components/IconLabel/IconLabel.tsx +++ b/src/components/IconLabel/IconLabel.tsx @@ -72,32 +72,35 @@ export const IconLabel: React.FC< ))} )) - .with({ type: "roundPeriod" }, ({ startDate, endDate = undefined, className, isLoading }) => ( - - {match(isLoading) - .with(true, () => ( -
- {`Review period:`} - -
- )) - .otherwise(() => ( - {`Review period: ${formatDate( - startDate, - DateFormat.ShortMonthDayYear24HourUTC, - )} - ${ - endDate - ? formatDate(endDate, DateFormat.ShortMonthDayYear24HourUTC) - : "No end date (open round)" - }`} - ))} -
- )) + .with( + { type: "roundPeriod" }, + ({ startDate, endDate = undefined, className, isLoading, label = "Review Period" }) => ( + + {match(isLoading) + .with(true, () => ( +
+ {label} + +
+ )) + .otherwise(() => ( + {`${label}: ${formatDate( + startDate, + DateFormat.ShortMonthDayYear24HourUTC, + )} - ${ + endDate + ? formatDate(endDate, DateFormat.ShortMonthDayYear24HourUTC) + : "No end date (open round)" + }`} + ))} +
+ ), + ) .with({ type: "dateWithPrefix" }, ({ date, prefix, className, isLoading }) => ( { + const { setEvaluationBody, isSuccess, isEvaluating, isError } = usePerformEvaluation(); + const { steps, setReviewBody, isReviewing } = usePerformOnChainReview(); + + return ( + + ); + }; + return ( + + + + ); + }, +}; diff --git a/src/features/checker/apps/Checker.tsx b/src/features/checker/apps/Checker.tsx index 4be514e0..72bd0c32 100644 --- a/src/features/checker/apps/Checker.tsx +++ b/src/features/checker/apps/Checker.tsx @@ -19,6 +19,7 @@ export interface CheckerProps { steps: Step[]; setReviewBody: (reviewBody: ReviewBody | null) => void; isReviewing: boolean; + isStandalone: boolean; } export const Checker = (props: CheckerProps) => { diff --git a/src/features/checker/pages/ApplicationEvaluationOverviewPage/ApplicationEvaluationOverviewPage.tsx b/src/features/checker/pages/ApplicationEvaluationOverviewPage/ApplicationEvaluationOverviewPage.tsx index 246776c9..b85e0e2e 100644 --- a/src/features/checker/pages/ApplicationEvaluationOverviewPage/ApplicationEvaluationOverviewPage.tsx +++ b/src/features/checker/pages/ApplicationEvaluationOverviewPage/ApplicationEvaluationOverviewPage.tsx @@ -20,6 +20,7 @@ export interface ApplicationEvaluationOverviewPageProps { poolId: string; applicationId: string; address: Hex; + isStandalone: boolean; } export const ApplicationEvaluationOverviewPage = ({ @@ -27,6 +28,7 @@ export const ApplicationEvaluationOverviewPage = ({ poolId, applicationId, address, + isStandalone, }: ApplicationEvaluationOverviewPageProps) => { useInitialize({ address, poolId, chainId }); @@ -49,17 +51,19 @@ export const ApplicationEvaluationOverviewPage = ({ return (
- + {isStandalone && ( + + )}
+ {isStandalone && ( +
+
+ )}
diff --git a/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.stories.tsx b/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.stories.tsx index 8f1a4af5..afe37ec2 100644 --- a/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.stories.tsx +++ b/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.stories.tsx @@ -60,6 +60,7 @@ export const Default: Story = { chainId={args.chainId} poolId={args.poolId} address={args.address} + isStandalone={true} /> ); }, diff --git a/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.tsx b/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.tsx index cf88a302..efd6fa53 100644 --- a/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.tsx +++ b/src/features/checker/pages/SubmitApplicationEvaluationPage/SubmitApplicationEvaluationPage.tsx @@ -33,6 +33,7 @@ export interface SubmitApplicationEvaluationPageProps { isSuccess: boolean; isEvaluating: boolean; isError: boolean; + isStandalone: boolean; } export const SubmitApplicationEvaluationPage = ({ @@ -44,6 +45,7 @@ export const SubmitApplicationEvaluationPage = ({ isSuccess, isEvaluating, isError, + isStandalone, }: SubmitApplicationEvaluationPageProps) => { useInitialize({ address, poolId, chainId }); @@ -134,17 +136,19 @@ export const SubmitApplicationEvaluationPage = ({ return (
- + {isStandalone && ( + + )}
void; isReviewing: boolean; + isStandalone: boolean; } export const SubmitFinalEvaluationPage = ({ steps, setReviewBody, isReviewing, + isStandalone, }: SubmitFinalEvaluationPageProps) => { const { categorizedReviews, statCardsProps, reviewBody, poolData } = useGetApplicationsFinalEvaluationPage() || {}; @@ -115,24 +117,32 @@ export const SubmitFinalEvaluationPage = ({ return (
- + {isStandalone && ( + + )}
diff --git a/src/features/checker/routers/CheckerRouter.tsx b/src/features/checker/routers/CheckerRouter.tsx index 62c220a7..2b1445c1 100644 --- a/src/features/checker/routers/CheckerRouter.tsx +++ b/src/features/checker/routers/CheckerRouter.tsx @@ -29,6 +29,7 @@ export interface CheckerRouterProps { steps: Step[]; setReviewBody: (reviewBody: ReviewBody | null) => void; isReviewing: boolean; + isStandalone: boolean; } export const CheckerRouter = ({ @@ -42,6 +43,7 @@ export const CheckerRouter = ({ steps, setReviewBody, isReviewing, + isStandalone = true, }: CheckerRouterProps) => { useInitialize({ address, poolId, chainId }); @@ -53,7 +55,9 @@ export const CheckerRouter = ({ }, [route]); return match(route) - .with({ id: CheckerRoute.ReviewApplications }, () => ) + .with({ id: CheckerRoute.ReviewApplications }, () => ( + + )) .with( { id: CheckerRoute.ApplicationEvaluationOverview, projectId: P.string.minLength(1) }, ({ projectId }) => ( @@ -62,6 +66,7 @@ export const CheckerRouter = ({ poolId={poolId} applicationId={projectId} address={address} + isStandalone={isStandalone} /> ), ) @@ -78,6 +83,7 @@ export const CheckerRouter = ({ chainId={chainId} poolId={poolId} address={address} + isStandalone={isStandalone} /> ); }, @@ -87,6 +93,7 @@ export const CheckerRouter = ({ steps={steps} setReviewBody={setReviewBody} isReviewing={isReviewing} + isStandalone={isStandalone} /> )) .otherwise(() =>
{`Route Not Found: ${JSON.stringify(route)}`}
); diff --git a/src/features/checker/utils/getGitcoinLinks.ts b/src/features/checker/utils/getGitcoinLinks.ts index 08415a07..3c257aee 100644 --- a/src/features/checker/utils/getGitcoinLinks.ts +++ b/src/features/checker/utils/getGitcoinLinks.ts @@ -1,5 +1,7 @@ import { getChains, TChain } from "@gitcoin/gitcoin-chain-data"; +import { PoolType } from "@/types"; + type ChainIdToType = Record; const chainData = getChains(); @@ -9,23 +11,108 @@ const chainIdToType: ChainIdToType = chainData.reduce((acc, chain: TChain) => { return acc; }, {} as ChainIdToType); -export const getManagerUrl = (chainId: number): string => { +const getUrlByChainType = (chainId: number, mainnetUrl: string, stagingUrl: string): string => { const chainType = chainIdToType[chainId]; - return chainType === "mainnet" - ? "https://manager.gitcoin.co" - : "https://grants-stack-manager-staging.vercel.app"; + return chainType === "mainnet" ? mainnetUrl : stagingUrl; }; -export const getBuilderUrl = (chainId: number): string => { - const chainType = chainIdToType[chainId]; - return chainType === "mainnet" - ? "https://builder.gitcoin.co" - : "https://grants-stack-builder-staging.vercel.app"; +// --- Manager --- + +export const getManagerUrl = (chainId: number, strategyName?: PoolType): string => { + switch (strategyName) { + case PoolType.Retrofunding: + return "https://retrofunding-amber.vercel.app"; + default: + return getUrlByChainType( + chainId, + "https://manager.gitcoin.co", + "https://grants-stack-manager-staging.vercel.app", + ); + } }; -export const getExplorerUrl = (chainId: number): string => { - const chainType = chainIdToType[chainId]; - return chainType === "mainnet" - ? "https://explorer.gitcoin.co" - : "https://grants-stack-explorer-staging.vercel.app"; +export const getProgramLinkOnManager = ( + chainId: number, + programId: string, + strategyName?: PoolType, +) => { + switch (strategyName) { + default: + return `${getManagerUrl(chainId, strategyName)}/#/chain/${chainId}/program/${programId}`; + } +}; + +export const getRoundLinkOnManager = (chainId: number, poolId: string, strategyName?: PoolType) => { + switch (strategyName) { + default: + return `${getManagerUrl(chainId, strategyName)}/#/chain/${chainId}/round/${poolId}`; + } +}; + +// Builder + +export const getBuilderUrl = (chainId: number, strategyName?: PoolType): string => { + switch (strategyName) { + case PoolType.Retrofunding: + default: + return getUrlByChainType( + chainId, + "https://builder.gitcoin.co", + "https://grants-stack-builder-staging.vercel.app", + ); + } +}; + +export const getApplyLink = (chainId: number, poolId: string, strategyName?: PoolType) => { + switch (strategyName) { + default: + return `${getBuilderUrl(chainId, strategyName)}/#/chains/${chainId}/rounds/${poolId}/apply`; + } +}; + +// --- Explorer --- +export const getExplorerUrl = (chainId: number, strategyName?: PoolType): string => { + switch (strategyName) { + case PoolType.Retrofunding: + return "https://retrofunding-vote.vercel.app"; + default: + return getUrlByChainType( + chainId, + "https://explorer.gitcoin.co", + "https://grants-stack-explorer-staging.vercel.app", + ); + } +}; + +export const getPoolLinkOnExplorer = (chainId: number, poolId: string, strategyName?: PoolType) => { + switch (strategyName) { + default: + return `${getExplorerUrl(chainId, strategyName)}/#/round/${chainId}/${poolId}`; + } +}; + +export const getApplicationLinkOnExplorer = ( + chainId: number, + poolId: string, + applicationId: string, + strategyName?: PoolType, +) => { + switch (strategyName) { + default: + return `${getExplorerUrl( + chainId, + strategyName, + )}/#/round/${chainId}/${poolId}/${applicationId}`; + } +}; + +export const getVotingInterfaceLinkOnExplorer = ( + chainId: number, + poolId: string, + strategyName?: PoolType, +) => { + switch (strategyName) { + default: + return `${getExplorerUrl(chainId, strategyName)}/#/round/${chainId}/${poolId}/voting`; + } }; diff --git a/src/features/pool/components/PoolSummary/PoolSummary.stories.tsx b/src/features/pool/components/PoolSummary/PoolSummary.stories.tsx index 2fbe48e9..c0b8fc5f 100644 --- a/src/features/pool/components/PoolSummary/PoolSummary.stories.tsx +++ b/src/features/pool/components/PoolSummary/PoolSummary.stories.tsx @@ -1,20 +1,24 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { PoolType } from "@/types"; + import { PoolSummary, PoolSummaryProps } from "./PoolSummary"; +const defaultProps = { + chainId: 1, + name: "Beta Round", + poolId: "1", + strategyName: PoolType.QuadraticFunding, + applicationsStartTime: "2024-12-09T19:22:56.413Z", + applicationsEndTime: "2024-12-10T19:23:30.678Z", + donationsStartTime: "2024-12-09T19:22:56.413Z", + donationsEndTime: "2024-12-09T19:22:56.413Z", +}; + const meta: Meta = { title: "Features/Pool/PoolSummary", component: PoolSummary, - args: { - chainId: 1, - name: "Beta Round", - poolId: "1", - strategyName: "allov2.DonationVotingMerkleDistributionDirectTransferStrategy", - applicationsStartTime: "2024-12-09T19:22:56.413Z", - applicationsEndTime: "2024-12-10T19:23:30.678Z", - donationsStartTime: "2024-12-09T19:22:56.413Z", - donationsEndTime: "2024-12-09T19:22:56.413Z", - }, + args: defaultProps, } satisfies Meta; export default meta; @@ -22,3 +26,10 @@ export default meta; type Story = StoryObj; export const Default: Story = {}; + +export const Retrofunding: Story = { + args: { + ...defaultProps, + strategyName: PoolType.Retrofunding, + }, +}; diff --git a/src/features/pool/components/PoolSummary/PoolSummary.tsx b/src/features/pool/components/PoolSummary/PoolSummary.tsx index 0779d2e0..f9b4a250 100644 --- a/src/features/pool/components/PoolSummary/PoolSummary.tsx +++ b/src/features/pool/components/PoolSummary/PoolSummary.tsx @@ -11,7 +11,13 @@ import { Button } from "@/primitives/Button"; import { Icon, IconType } from "@/primitives/Icon"; import { PoolStatus, PoolType } from "@/types"; -import { getManagerUrl, getBuilderUrl, getExplorerUrl } from "~checker/utils"; +import { + getApplyLink, + getPoolLinkOnExplorer, + getProgramLinkOnManager, + getManagerUrl, + getVotingInterfaceLinkOnExplorer, +} from "~checker/utils"; import { PoolBadge } from "../PoolBadge"; @@ -38,13 +44,11 @@ export const PoolSummary = (pool: PoolSummaryProps) => { const { toast } = useToast(); const chainInfo = getChainInfo(pool.chainId); - const managerUrl = getManagerUrl(pool.chainId); - const builderUrl = getBuilderUrl(pool.chainId); - const explorerUrl = getExplorerUrl(pool.chainId); - let poolStatus: PoolStatus; const poolType = pool.strategyName as PoolType; + const managerUrl = getManagerUrl(pool.chainId, poolType); + const now = new Date(); const registerStartDate = pool.applicationsStartTime @@ -67,9 +71,9 @@ export const PoolSummary = (pool: PoolSummaryProps) => { } else { poolStatus = PoolStatus.PreRound; } - const applyLink = `${builderUrl}/#/chains/${pool.chainId}/rounds/${pool.poolId}/apply`; - const explorerLink = `${explorerUrl}/#/round/${pool.chainId}/${pool.poolId}`; - const managerProgramLink = `${managerUrl}/#/chain/${pool.chainId}/program/${pool.programId}`; + const applyLink = getApplyLink(pool.chainId, pool.poolId, poolType); + const explorerLink = getPoolLinkOnExplorer(pool.chainId, pool.poolId, poolType); + const managerProgramLink = getProgramLinkOnManager(pool.chainId, pool.programId, poolType); const breadcrumbItems = [ { label: "My Programs", href: managerUrl }, { @@ -81,11 +85,18 @@ export const PoolSummary = (pool: PoolSummaryProps) => { href: explorerLink, }, ]; + + const { registerDateLabel, allocationDateLabel, viewButton } = getInfoBasedOnPoolType( + poolType, + pool, + explorerLink, + ); + return ( -
+
-
+
@@ -98,12 +109,23 @@ export const PoolSummary = (pool: PoolSummaryProps) => { isLoading={pool.isLoading} laodingSkeletonClassName="h-10 w-72 rounded-lg" /> - + +
+ + +
@@ -129,14 +151,45 @@ export const PoolSummary = (pool: PoolSummaryProps) => { ); }} /> -
); }; + +function getInfoBasedOnPoolType(poolType: PoolType, pool: PoolSummaryProps, explorerLink: string) { + let allocationDateLabel; + let registerDateLabel; + let viewButton; + + if (poolType === PoolType.Retrofunding) { + registerDateLabel = "Applications"; + allocationDateLabel = "Voting"; + viewButton = ( +