From a22359a8eba718129f498990067bed05fde6a4df Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:38:00 +0500 Subject: [PATCH 01/10] Added `FLAG_TOKENIZED_COMMUNITY` feature flag --- packages/commonwealth/client/scripts/helpers/feature-flags.ts | 1 + packages/commonwealth/client/vite.config.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/commonwealth/client/scripts/helpers/feature-flags.ts b/packages/commonwealth/client/scripts/helpers/feature-flags.ts index ed00bbcd8d7..387f5e8f38a 100644 --- a/packages/commonwealth/client/scripts/helpers/feature-flags.ts +++ b/packages/commonwealth/client/scripts/helpers/feature-flags.ts @@ -28,6 +28,7 @@ const featureFlags = { ), farcasterContest: buildFlag(process.env.FLAG_FARCASTER_CONTEST), newEditor: buildFlag(process.env.FLAG_NEW_EDITOR), + tokenizedCommunity: buildFlag(process.env.FLAG_TOKENIZED_COMMUNITY), }; export type AvailableFeatureFlag = keyof typeof featureFlags; diff --git a/packages/commonwealth/client/vite.config.ts b/packages/commonwealth/client/vite.config.ts index 772e09ba80e..3dc91832724 100644 --- a/packages/commonwealth/client/vite.config.ts +++ b/packages/commonwealth/client/vite.config.ts @@ -41,6 +41,9 @@ export default defineConfig(({ mode }) => { 'process.env.FLAG_FARCASTER_CONTEST': JSON.stringify( env.FLAG_FARCASTER_CONTEST, ), + 'process.env.FLAG_TOKENIZED_COMMUNITY': JSON.stringify( + env.FLAG_TOKENIZED_COMMUNITY, + ), }; const config = { From 8dd4ee369f6bf5b7366ca24371aaef86e0388612 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:40:57 +0500 Subject: [PATCH 02/10] Added create token community page template --- .../scripts/navigation/CommonDomainRoutes.tsx | 11 +++ .../scripts/navigation/CustomDomainRoutes.tsx | 11 +++ .../client/scripts/navigation/Router.tsx | 7 ++ .../views/pages/LaunchToken/LaunchToken.scss | 7 ++ .../views/pages/LaunchToken/LaunchToken.tsx | 53 +++++++++++++++ .../scripts/views/pages/LaunchToken/index.ts | 3 + .../pages/LaunchToken/useCreateCommunity.ts | 24 +++++++ .../scripts/views/pages/LaunchToken/utils.ts | 67 +++++++++++++++++++ .../commonwealth/shared/analytics/types.ts | 2 + 9 files changed, 185 insertions(+) create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.scss create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/index.ts create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/utils.ts diff --git a/packages/commonwealth/client/scripts/navigation/CommonDomainRoutes.tsx b/packages/commonwealth/client/scripts/navigation/CommonDomainRoutes.tsx index 4fac51647ad..17348d5518f 100644 --- a/packages/commonwealth/client/scripts/navigation/CommonDomainRoutes.tsx +++ b/packages/commonwealth/client/scripts/navigation/CommonDomainRoutes.tsx @@ -11,6 +11,7 @@ const CommunitiesPage = lazy(() => import('views/pages/Communities')); const SearchPage = lazy(() => import('views/pages/search')); const CreateCommunityPage = lazy(() => import('views/pages/CreateCommunity')); +const LaunchToken = lazy(() => import('views/pages/LaunchToken')); const OverviewPage = lazy(() => import('views/pages/overview')); const MembersPage = lazy( () => @@ -112,6 +113,7 @@ const CommunityNotFoundPage = lazy( const CommonDomainRoutes = ({ contestEnabled, farcasterContestEnabled, + tokenizedCommunityEnabled, }: RouteFeatureFlags) => [ } />, @@ -125,6 +127,15 @@ const CommonDomainRoutes = ({ path="/createCommunity" element={withLayout(CreateCommunityPage, { type: 'common' })} />, + ...(tokenizedCommunityEnabled + ? [ + , + ] + : []), import('views/pages/search')); const CreateCommunityPage = lazy(() => import('views/pages/CreateCommunity')); +const LaunchTokenPage = lazy(() => import('views/pages/LaunchToken')); const OverviewPage = lazy(() => import('views/pages/overview')); const MembersPage = lazy( () => @@ -103,6 +104,7 @@ const ProfilePageRedirect = lazy(() => import('views/pages/profile_redirect')); const CustomDomainRoutes = ({ contestEnabled, farcasterContestEnabled, + tokenizedCommunityEnabled, }: RouteFeatureFlags) => { return [ , + ...(tokenizedCommunityEnabled + ? [ + , + ] + : []), } />, { @@ -26,9 +27,15 @@ const Router = () => { false, ); + const tokenizedCommunityEnabled = client.getBooleanValue( + 'tokenizedCommunity', + false, + ); + const flags = { contestEnabled, farcasterContestEnabled, + tokenizedCommunityEnabled, }; const { isCustomDomain } = fetchCachedCustomDomain() || {}; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.scss b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.scss new file mode 100644 index 00000000000..855ba4271cf --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.scss @@ -0,0 +1,7 @@ +@import '../../../../styles/shared'; + +.LaunchToken { + display: flex; + flex-direction: column; + gap: 16px; +} diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx new file mode 100644 index 00000000000..ef841c91972 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import CWFormSteps from 'views/components/component_kit/new_designs/CWFormSteps'; +import CWPageLayout from 'views/components/component_kit/new_designs/CWPageLayout'; +import { MixpanelCommunityCreationEvent } from '../../../../../shared/analytics/types'; +import useAppStatus from '../../../hooks/useAppStatus'; +import { useBrowserAnalyticsTrack } from '../../../hooks/useBrowserAnalyticsTrack'; +import './LaunchToken.scss'; +import useCreateCommunity from './useCreateCommunity'; +import { CreateTokenCommunityStep, getFormSteps } from './utils'; + +const LaunchToken = () => { + const { createTokenCommunityStep } = useCreateCommunity(); + + const { isAddedToHomeScreen } = useAppStatus(); + + useBrowserAnalyticsTrack({ + payload: { + event: MixpanelCommunityCreationEvent.CREATE_TOKEN_COMMUNITY_VISITED, + isPWA: isAddedToHomeScreen, + }, + }); + + const isSuccessStep = + createTokenCommunityStep === CreateTokenCommunityStep.Success; + + const getCurrentStep = () => { + switch (createTokenCommunityStep) { + case CreateTokenCommunityStep.TokenInformation: + // TODO: https://github.com/hicommonwealth/commonwealth/issues/8705 + return <>Not Implemented; + case CreateTokenCommunityStep.CommunityInformation: + // TODO: https://github.com/hicommonwealth/commonwealth/issues/8706 + return <>Not Implemented; + case CreateTokenCommunityStep.SignatureLaunch: + // TODO: https://github.com/hicommonwealth/commonwealth/issues/8707 + return <>Not Implemented; + } + }; + + return ( + +
+ {!isSuccessStep && ( + + )} + + {getCurrentStep()} +
+
+ ); +}; + +export default LaunchToken; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/index.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/index.ts new file mode 100644 index 00000000000..41918969a59 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/index.ts @@ -0,0 +1,3 @@ +import LaunchToken from './LaunchToken'; + +export default LaunchToken; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts new file mode 100644 index 00000000000..3f052f77e01 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts @@ -0,0 +1,24 @@ +import { useState } from 'react'; +import { CreateTokenCommunityStep, handleChangeStep } from './utils'; + +const useCreateCommunity = () => { + const [createTokenCommunityStep, setCreateTokenCommunityStep] = + useState( + CreateTokenCommunityStep.TokenInformation, + ); + + const onChangeStep = (forward: boolean) => { + handleChangeStep( + forward, + createTokenCommunityStep, + setCreateTokenCommunityStep, + ); + }; + + return { + createTokenCommunityStep, + onChangeStep, + }; +}; + +export default useCreateCommunity; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/utils.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/utils.ts new file mode 100644 index 00000000000..8cc705fc89d --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/utils.ts @@ -0,0 +1,67 @@ +import React from 'react'; +import { CWFormStepsProps } from 'views/components/component_kit/new_designs/CWFormSteps/CWFormSteps'; + +export enum CreateTokenCommunityStep { + TokenInformation = 'TokenInformation', + CommunityInformation = 'CommunityInformation', + SignatureLaunch = 'SignatureLaunch', + Success = 'Success', +} + +export const getFormSteps = ( + activeStep: CreateTokenCommunityStep, +): CWFormStepsProps['steps'] => { + return [ + { + label: 'Token Details', + state: + activeStep === CreateTokenCommunityStep.TokenInformation + ? 'active' + : 'completed', + }, + { + label: 'Community', + state: + activeStep < CreateTokenCommunityStep.CommunityInformation + ? 'inactive' + : activeStep === CreateTokenCommunityStep.CommunityInformation + ? 'active' + : 'completed', + }, + { + label: 'Sign and Launch', + state: + activeStep < CreateTokenCommunityStep.SignatureLaunch + ? 'inactive' + : activeStep === CreateTokenCommunityStep.SignatureLaunch + ? 'active' + : 'completed', + }, + ]; +}; + +export const handleChangeStep = ( + forward: boolean, + activeStep: CreateTokenCommunityStep, + setActiveStep: React.Dispatch>, +) => { + switch (activeStep) { + case CreateTokenCommunityStep.TokenInformation: + setActiveStep(CreateTokenCommunityStep.CommunityInformation); + return; + case CreateTokenCommunityStep.CommunityInformation: + setActiveStep( + forward + ? CreateTokenCommunityStep.SignatureLaunch + : CreateTokenCommunityStep.TokenInformation, + ); + return; + case CreateTokenCommunityStep.SignatureLaunch: + setActiveStep( + forward + ? CreateTokenCommunityStep.Success + : CreateTokenCommunityStep.CommunityInformation, + ); + return; + } +}; diff --git a/packages/commonwealth/shared/analytics/types.ts b/packages/commonwealth/shared/analytics/types.ts index 0145dc8f2d7..e8b9d70230d 100644 --- a/packages/commonwealth/shared/analytics/types.ts +++ b/packages/commonwealth/shared/analytics/types.ts @@ -65,6 +65,8 @@ export const enum MixpanelCommunityCreationEvent { CONNECT_NEW_WALLET_PRESSED = 'Connect New Wallet Button Pressed', NEW_COMMUNITY_CREATION = 'New Community Creation', CREATE_COMMUNITY_CANCELLED = 'Create Community Cancel Button Pressed', + CREATE_TOKEN_COMMUNITY_VISITED = '/createTokenCommunity Page Visited', + CREATE_TOKEN_COMMUNITY_CANCELLED = 'Create Token Community Cancel Button Pressed', } export const enum MixpanelSnapshotEvents { From 9378acd0658c7a94c751c00d7afaafe0426fbe6f Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:41:52 +0500 Subject: [PATCH 03/10] Adjusted word counter for `` --- .../scripts/views/components/component_kit/cw_text_area.tsx | 6 ++---- .../styles/components/component_kit/cw_text_area.scss | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/cw_text_area.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/cw_text_area.tsx index 576ca421367..09a478ad459 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/cw_text_area.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/cw_text_area.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState } from 'react'; import 'components/component_kit/cw_text_area.scss'; import { useFormContext } from 'react-hook-form'; -import { CWText } from 'views/components/component_kit/cw_text'; +import { CWLabel } from './cw_label'; import type { BaseTextInputProps } from './cw_text_input'; import { MessageRow, useTextInputWithValidation } from './cw_text_input'; import type { ValidationStatus } from './cw_validation_text'; @@ -164,9 +164,7 @@ export const CWTextArea = (props: TextAreaProps) => { )} {charCount && (
- - Character count: {characterCount}/{charCount} - +
)} diff --git a/packages/commonwealth/client/styles/components/component_kit/cw_text_area.scss b/packages/commonwealth/client/styles/components/component_kit/cw_text_area.scss index 664351d3239..28f39d6ac76 100644 --- a/packages/commonwealth/client/styles/components/component_kit/cw_text_area.scss +++ b/packages/commonwealth/client/styles/components/component_kit/cw_text_area.scss @@ -17,6 +17,6 @@ } .character-count { - margin-top: 12px; + margin-top: 4px; } } From 5d743111012469255ef6a08c9e99e9de61f83bc9 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 03:09:21 +0500 Subject: [PATCH 04/10] Renamed `BasicInformationStep` to `CommunityInformationStep` --- .../steps/BasicInformationStep/index.ts | 3 -- .../CommunityInformationForm.scss} | 2 +- .../CommunityInformationForm.tsx} | 28 +++++++++++-------- .../CommunityInformationForm}/constants.ts | 0 .../CommunityInformationForm}/types.ts | 2 +- .../useSocialLinks.ts | 2 +- .../CommunityInformationForm}/validation.ts | 2 +- .../CommunityInformationStep.scss} | 2 +- .../CommunityInformationStep.tsx} | 18 ++++++------ .../steps/CommunityInformationStep/index.ts | 3 ++ 10 files changed, 33 insertions(+), 29 deletions(-) delete mode 100644 packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/index.ts rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm/BasicInformationForm.scss => CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss} (97%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm/BasicInformationForm.tsx => CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx} (93%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm => CommunityInformationStep/CommunityInformationForm}/constants.ts (100%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm => CommunityInformationStep/CommunityInformationForm}/types.ts (93%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm => CommunityInformationStep/CommunityInformationForm}/useSocialLinks.ts (95%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationForm => CommunityInformationStep/CommunityInformationForm}/validation.ts (93%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationStep.scss => CommunityInformationStep/CommunityInformationStep.scss} (95%) rename packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/{BasicInformationStep/BasicInformationStep.tsx => CommunityInformationStep/CommunityInformationStep.tsx} (74%) create mode 100644 packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/index.ts diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/index.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/index.ts deleted file mode 100644 index fd5c1578b90..00000000000 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import BasicInformationStep from './BasicInformationStep'; - -export default BasicInformationStep; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.scss b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss similarity index 97% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.scss rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss index 9ee471f64c1..1221d475b21 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.scss +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss @@ -1,6 +1,6 @@ @import '../../../../../../../styles/shared.scss'; -.BasicInformationForm { +.CommunityInformationForm { display: flex; flex-direction: column; gap: 24px; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx similarity index 93% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.tsx rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx index 58b4e438b6c..c2870d001bd 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/BasicInformationForm.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx @@ -27,7 +27,7 @@ import { } from '../../../../../../../../shared/analytics/types'; import useAppStatus from '../../../../../../hooks/useAppStatus'; import { useBrowserAnalyticsTrack } from '../../../../../../hooks/useBrowserAnalyticsTrack'; -import './BasicInformationForm.scss'; +import './CommunityInformationForm.scss'; import { BASE_ID, BLAST_ID, @@ -36,19 +36,19 @@ import { POLYGON_ETH_CHAIN_ID, alphabeticallyStakeWiseSortedChains as sortedChains, } from './constants'; -import { BasicInformationFormProps, FormSubmitValues } from './types'; +import { CommunityInformationFormProps, FormSubmitValues } from './types'; import useSocialLinks from './useSocialLinks'; -import { basicInformationFormValidationSchema } from './validation'; +import { communityInformationFormValidationSchema } from './validation'; const socialLinksDisplay = false; // TODO: Set this when design figures out how we will integrate the social links -const BasicInformationForm = ({ +const CommunityInformationForm = ({ selectedAddress, selectedCommunity, onSubmit, onCancel, handleSelectedChainId, -}: BasicInformationFormProps) => { +}: CommunityInformationFormProps) => { const [communityName, setCommunityName] = useState(''); const [isProcessingProfileImage, setIsProcessingProfileImage] = useState(false); @@ -206,9 +206,9 @@ const BasicInformationForm = ({ return ( @@ -297,12 +297,16 @@ const BasicInformationForm = ({ ) } onBlur={() => - // @ts-expect-error StrictNullChecks - updateAndValidateSocialLinkAtIndex(socialLink.value, index) + updateAndValidateSocialLinkAtIndex( + socialLink.value || '', + index, + ) } onFocus={() => - // @ts-expect-error StrictNullChecks - updateAndValidateSocialLinkAtIndex(socialLink.value, index) + updateAndValidateSocialLinkAtIndex( + socialLink.value || '', + index, + ) } /> any; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/useSocialLinks.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/useSocialLinks.ts similarity index 95% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/useSocialLinks.ts rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/useSocialLinks.ts index d60e28cd0ea..62fd99da053 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/useSocialLinks.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/useSocialLinks.ts @@ -1,7 +1,7 @@ import { linkValidationSchema } from 'helpers/formValidations/common'; import { useState } from 'react'; -import { SocialLinkField } from 'views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/types'; import { ZodError } from 'zod'; +import { SocialLinkField } from './types'; const useSocialLinks = () => { const [socialLinks, setSocialLinks] = useState([ diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/validation.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts similarity index 93% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/validation.ts rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts index 062d2213efa..3a101efdb22 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/validation.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts @@ -1,7 +1,7 @@ import { VALIDATION_MESSAGES } from 'helpers/formValidations/messages'; import z from 'zod'; -export const basicInformationFormValidationSchema = z.object({ +export const communityInformationFormValidationSchema = z.object({ communityName: z .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }) diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.scss b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.scss similarity index 95% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.scss rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.scss index 0f56c23de30..0c39a7c6515 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.scss +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.scss @@ -2,7 +2,7 @@ $form-width: 596px; -.BasicInformationStep { +.CommunityInformationStep { display: flex; flex-direction: column; gap: 24px; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx similarity index 74% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.tsx rename to packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx index 93484cf23e8..8f849b1cb06 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationStep.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx @@ -4,11 +4,11 @@ import AddressInfo from 'models/AddressInfo'; import FeatureHint from 'views/components/FeatureHint'; import { CWText } from 'views/components/component_kit/cw_text'; import { SelectedCommunity } from 'views/components/component_kit/new_designs/CWCommunitySelector'; -import BasicInformationForm from './BasicInformationForm/BasicInformationForm'; +import CommunityInformationForm from './CommunityInformationForm/CommunityInformationForm'; -import './BasicInformationStep.scss'; +import './CommunityInformationStep.scss'; -interface BasicInformationStepProps { +interface CommunityInformationStepProps { selectedAddress: AddressInfo; selectedCommunity: SelectedCommunity; handleGoBack: () => void; @@ -16,19 +16,19 @@ interface BasicInformationStepProps { handleSelectedChainId: (chainId: string) => void; } -const BasicInformationStep = ({ +const CommunityInformationStep = ({ selectedAddress, selectedCommunity, handleGoBack, handleContinue, handleSelectedChainId, -}: BasicInformationStepProps) => { +}: CommunityInformationStepProps) => { return ( -
+
Tell us about your community - Let’s start with some basic information about your community + Let’s start with some Community information about your community
@@ -38,7 +38,7 @@ const BasicInformationStep = ({ If you’re not sure what to choose you can select the Ethereum Mainnet." /> - Date: Thu, 12 Sep 2024 04:32:39 +0500 Subject: [PATCH 05/10] Converted `` to generic component --- .../CommunityInformationForm.scss | 2 +- .../CommunityInformationForm.tsx | 207 ++++++------------ .../CommunityInformationForm/constants.ts | 0 .../CommunityInformationForm/types.ts | 32 +++ .../useSocialLinks.ts | 0 .../CommunityInformationForm/validation.ts | 5 +- .../component_kit/cw_cover_image_uploader.tsx | 9 +- .../pages/CreateCommunity/CreateCommunity.tsx | 10 +- .../CommunityInformationForm/types.ts | 26 --- .../CommunityInformationStep.tsx | 112 +++++++++- .../CreateCommunity/useCreateCommunity.ts | 6 +- .../views/pages/CreateCommunity/utils.ts | 22 +- 12 files changed, 234 insertions(+), 197 deletions(-) rename packages/commonwealth/client/scripts/views/{pages/CreateCommunity/steps/CommunityInformationStep => components}/CommunityInformationForm/CommunityInformationForm.scss (95%) rename packages/commonwealth/client/scripts/views/{pages/CreateCommunity/steps/CommunityInformationStep => components}/CommunityInformationForm/CommunityInformationForm.tsx (59%) rename packages/commonwealth/client/scripts/views/{pages/CreateCommunity/steps/CommunityInformationStep => components}/CommunityInformationForm/constants.ts (100%) create mode 100644 packages/commonwealth/client/scripts/views/components/CommunityInformationForm/types.ts rename packages/commonwealth/client/scripts/views/{pages/CreateCommunity/steps/CommunityInformationStep => components}/CommunityInformationForm/useSocialLinks.ts (100%) rename packages/commonwealth/client/scripts/views/{pages/CreateCommunity/steps/CommunityInformationStep => components}/CommunityInformationForm/validation.ts (88%) delete mode 100644 packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/types.ts diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.scss similarity index 95% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss rename to packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.scss index 1221d475b21..a21e4a75988 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.scss +++ b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.scss @@ -1,4 +1,4 @@ -@import '../../../../../../../styles/shared.scss'; +@import '../../../../styles/shared'; .CommunityInformationForm { display: flex; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.tsx similarity index 59% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx rename to packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.tsx index c2870d001bd..1941e4901ec 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/CommunityInformationForm.tsx +++ b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/CommunityInformationForm.tsx @@ -1,11 +1,6 @@ import React, { useState } from 'react'; import { slugifyPreserveDashes } from 'utils'; -import { ChainBase } from '@hicommonwealth/shared'; -import { notifyError } from 'controllers/app/notifications'; -import useCreateCommunityMutation, { - buildCreateCommunityInput, -} from 'state/api/communities/createCommunity'; import { useFetchConfigurationQuery } from 'state/api/configuration'; import { CWCoverImageUploader, @@ -19,14 +14,6 @@ import { CommunityType } from 'views/components/component_kit/new_designs/CWComm import { CWForm } from 'views/components/component_kit/new_designs/CWForm'; import { CWSelectList } from 'views/components/component_kit/new_designs/CWSelectList'; import { CWTextInput } from 'views/components/component_kit/new_designs/CWTextInput'; -import { openConfirmation } from 'views/modals/confirmation_modal'; -import { - BaseMixpanelPayload, - MixpanelCommunityCreationEvent, - MixpanelLoginPayload, -} from '../../../../../../../../shared/analytics/types'; -import useAppStatus from '../../../../../../hooks/useAppStatus'; -import { useBrowserAnalyticsTrack } from '../../../../../../hooks/useBrowserAnalyticsTrack'; import './CommunityInformationForm.scss'; import { BASE_ID, @@ -36,18 +23,25 @@ import { POLYGON_ETH_CHAIN_ID, alphabeticallyStakeWiseSortedChains as sortedChains, } from './constants'; -import { CommunityInformationFormProps, FormSubmitValues } from './types'; +import { + CommunityInformationFormProps, + CommunityInformationFormSubmitValues, +} from './types'; import useSocialLinks from './useSocialLinks'; -import { communityInformationFormValidationSchema } from './validation'; - -const socialLinksDisplay = false; // TODO: Set this when design figures out how we will integrate the social links +import { + baseCommunityInformationFormValidationSchema, + communityChainValidation, +} from './validation'; const CommunityInformationForm = ({ - selectedAddress, - selectedCommunity, onSubmit, onCancel, - handleSelectedChainId, + onWatch, + withChainsConfig, + withSocialLinks = false, + initialValues, + isCreatingCommunity, + submitBtnLabel, }: CommunityInformationFormProps) => { const [communityName, setCommunityName] = useState(''); const [isProcessingProfileImage, setIsProcessingProfileImage] = @@ -63,22 +57,15 @@ const CommunityInformationForm = ({ const { data: configurationData } = useFetchConfigurationQuery(); - const { isAddedToHomeScreen } = useAppStatus(); - - const { trackAnalytics } = useBrowserAnalyticsTrack< - MixpanelLoginPayload | BaseMixpanelPayload - >({ - onAction: true, - }); - - const { - mutateAsync: createCommunityMutation, - isLoading: createCommunityLoading, - } = useCreateCommunityMutation(); - const communityId = slugifyPreserveDashes(communityName.toLowerCase()); const isCommunityNameTaken = !!configurationData?.redirects?.[communityId]; + const validation = withChainsConfig + ? baseCommunityInformationFormValidationSchema.merge( + communityChainValidation, + ) + : baseCommunityInformationFormValidationSchema; + const getChainOptions = () => { const mappedChainValue = (chainType) => ({ helpText: chainType.hasStakeEnabled ? 'Community Stake' : '', @@ -88,13 +75,13 @@ const CommunityInformationForm = ({ // Since we are treating polygon as an ecosystem, we will only have a single option, which will be // preselected and further input's will be disabled - if (selectedCommunity.type === CommunityType.Polygon) { + if (withChainsConfig?.community?.type === CommunityType.Polygon) { return sortedChains .filter((chainType) => chainType.value === POLYGON_ETH_CHAIN_ID) .map(mappedChainValue); } - if (selectedCommunity.type === CommunityType.Solana) { + if (withChainsConfig?.community?.type === CommunityType.Solana) { return sortedChains .filter((chainType) => chainType.chainBase === CommunityType.Solana) .map(mappedChainValue); @@ -104,7 +91,7 @@ const CommunityInformationForm = ({ .filter( (chainType) => chainType.chainBase === - (selectedCommunity.type === CommunityType.Cosmos + (withChainsConfig?.community?.type === CommunityType.Cosmos ? CommunityType.Cosmos : CommunityType.Ethereum), ) @@ -112,105 +99,47 @@ const CommunityInformationForm = ({ }; const getInitialValue = () => { - switch (selectedCommunity.type) { - case CommunityType.Base: - return { - chain: getChainOptions()?.find((o) => o.value === BASE_ID), - }; - case CommunityType.Ethereum: - return { - chain: getChainOptions()?.find( - (o) => o.value === ETHEREUM_MAINNET_ID, - ), - }; - case CommunityType.Cosmos: - return { - chain: getChainOptions()?.find((o) => o.value === OSMOSIS_ID), - }; - case CommunityType.Blast: - return { - chain: getChainOptions()?.find((o) => o.value === BLAST_ID), - }; - case CommunityType.Polygon: - case CommunityType.Solana: - return { chain: getChainOptions()?.[0] }; - } + return { + ...(initialValues || {}), + ...(withChainsConfig && { + chain: (() => { + const options = getChainOptions(); + + switch (withChainsConfig.community.type) { + case CommunityType.Base: + return options?.find((o) => o.value === BASE_ID); + case CommunityType.Ethereum: + return options?.find((o) => o.value === ETHEREUM_MAINNET_ID); + case CommunityType.Cosmos: + return options?.find((o) => o.value === OSMOSIS_ID); + case CommunityType.Blast: + return options?.find((o) => o.value === BLAST_ID); + case CommunityType.Polygon: + case CommunityType.Solana: + return options?.[0]; + } + })(), + }), + }; }; - const handleSubmit = async (values: FormSubmitValues) => { + const handleSubmit = async (values: CommunityInformationFormSubmitValues) => { const hasLinksError = validateSocialLinks(); if (isCommunityNameTaken || hasLinksError) return; // @ts-expect-error StrictNullChecks values.links = socialLinks.map((link) => link.value).filter(Boolean); - const selectedChainNode = sortedChains.find( - (chain) => String(chain.value) === values.chain.value, - ); - - try { - const input = buildCreateCommunityInput({ - id: communityId, - name: values.communityName, - chainBase: selectedCommunity.chainBase, - description: values.communityDescription, - iconUrl: values.communityProfileImageURL, - socialLinks: values.links ?? [], - nodeUrl: selectedChainNode!.nodeUrl!, - altWalletUrl: selectedChainNode!.altWalletUrl!, - userAddress: selectedAddress.address, - ...(selectedCommunity.chainBase === ChainBase.Ethereum && { - ethChainId: values.chain.value, - }), - ...(selectedCommunity.chainBase === ChainBase.CosmosSDK && { - cosmosChainId: values.chain.value, - bech32Prefix: selectedChainNode?.bech32Prefix, - }), - isPWA: isAddedToHomeScreen, - }); - await createCommunityMutation(input); - onSubmit(communityId, values.communityName); - } catch (err) { - notifyError(err.message); - } - }; - - const handleCancel = () => { - trackAnalytics({ - event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_CANCELLED, - isPWA: isAddedToHomeScreen, - }); - - openConfirmation({ - title: 'Are you sure you want to cancel?', - description: 'Your details will not be saved. Cancel create community?', - buttons: [ - { - label: 'Yes, cancel', - buttonType: 'destructive', - buttonHeight: 'sm', - onClick: onCancel, - }, - { - label: 'No, continue', - buttonType: 'primary', - buttonHeight: 'sm', - }, - ], - }); - }; - - const handleWatchForm = (values: any) => { - handleSelectedChainId(values?.chain?.value); + await onSubmit({ ...values, communityId }).catch(console.error); }; return ( {/* Form fields */} - + {withChainsConfig && ( + + )} - {socialLinksDisplay ? ( + {withSocialLinks ? ( <>
@@ -324,7 +255,9 @@ const CommunityInformationForm = ({
- ) : null} + ) : ( + <> + )} {/* Action buttons */}
@@ -333,13 +266,13 @@ const CommunityInformationForm = ({ label="Cancel" buttonWidth="wide" buttonType="secondary" - onClick={handleCancel} + onClick={onCancel} />
diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/constants.ts b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/constants.ts similarity index 100% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/constants.ts rename to packages/commonwealth/client/scripts/views/components/CommunityInformationForm/constants.ts diff --git a/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/types.ts b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/types.ts new file mode 100644 index 00000000000..c4842053a92 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/types.ts @@ -0,0 +1,32 @@ +import { SelectedCommunity } from 'views/components/component_kit/new_designs/CWCommunitySelector'; + +export type SocialLinkField = { + value?: string; + error?: string; +}; + +export type CommunityInformationFormSubmitValues = { + communityName: string; + communityDescription: string; + communityProfileImageURL: string; + chain?: { + label: string; + value: string; + }; + links?: string[]; +}; + +export type CommunityInformationFormProps = { + onSubmit: ( + values: CommunityInformationFormSubmitValues & { communityId: string }, + ) => Promise; + onCancel: () => void; + onWatch?: (values: CommunityInformationFormSubmitValues) => void; + withChainsConfig?: { + community: SelectedCommunity; + }; + withSocialLinks?: boolean; + isCreatingCommunity: boolean; + initialValues?: CommunityInformationFormSubmitValues; + submitBtnLabel: string; +}; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/useSocialLinks.ts b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts similarity index 100% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/useSocialLinks.ts rename to packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/validation.ts similarity index 88% rename from packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts rename to packages/commonwealth/client/scripts/views/components/CommunityInformationForm/validation.ts index 3a101efdb22..f46dd2aa96d 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/validation.ts +++ b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/validation.ts @@ -1,7 +1,7 @@ import { VALIDATION_MESSAGES } from 'helpers/formValidations/messages'; import z from 'zod'; -export const communityInformationFormValidationSchema = z.object({ +export const baseCommunityInformationFormValidationSchema = z.object({ communityName: z .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }) @@ -13,6 +13,9 @@ export const communityInformationFormValidationSchema = z.object({ communityProfileImageURL: z .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }), +}); + +export const communityChainValidation = z.object({ chain: z.object( { value: z.any().default(-1).optional(), diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx index c2c6e7860e4..9989cba9b42 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx @@ -228,7 +228,10 @@ export const CWCoverImageUploader = ({ setIsUploading(true); - const [_imageURL, _uploadStatus] = await uploadImage(file); + // const [_imageURL, _uploadStatus] = await uploadImage(file); + const _imageURL = URL.createObjectURL(file); + const _uploadStatus = 'success'; + setIsUploading(false); setUploadStatus(_uploadStatus); @@ -352,8 +355,8 @@ export const CWCoverImageUploader = ({ uploadStatus === 'success' ? 'Image upload succeeded.' : uploadStatus === 'failure' - ? 'Image upload failed.' - : null + ? 'Image upload failed.' + : null } validationStatus={uploadStatus} /> diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx index e580cad4776..cec327ad8a3 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx @@ -4,7 +4,6 @@ import CWFormSteps from 'views/components/component_kit/new_designs/CWFormSteps' import { MixpanelCommunityCreationEvent } from '../../../../../shared/analytics/types'; import { useBrowserAnalyticsTrack } from '../../../hooks/useBrowserAnalyticsTrack'; -import BasicInformationStep from './steps/BasicInformationStep'; import CommunityStakeStep from './steps/CommunityStakeStep'; import CommunityTypeStep from './steps/CommunityTypeStep'; import SuccessStep from './steps/SuccessStep'; @@ -14,6 +13,7 @@ import { CreateCommunityStep, getFormSteps } from './utils'; import CWPageLayout from 'views/components/component_kit/new_designs/CWPageLayout'; import useAppStatus from '../../../hooks/useAppStatus'; import './CreateCommunity.scss'; +import CommunityInformationStep from './steps/CommunityInformationStep'; const CreateCommunity = () => { const { @@ -25,7 +25,7 @@ const CreateCommunity = () => { setSelectedChainId, createdCommunityId, createdCommunityName, - handleCompleteBasicInformationStep, + handleCompleteCommunityInformationStep, onChangeStep, showCommunityStakeStep, selectedChainId, @@ -54,15 +54,15 @@ const CreateCommunity = () => { /> ); - case CreateCommunityStep.BasicInformation: + case CreateCommunityStep.CommunityInformation: return ( - handleSelectedChainId={setSelectedChainId} handleGoBack={() => onChangeStep(false)} - handleContinue={handleCompleteBasicInformationStep} + handleContinue={handleCompleteCommunityInformationStep} /> ); diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/types.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/types.ts deleted file mode 100644 index c9e8835096c..00000000000 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationForm/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SelectedCommunity } from 'views/components/component_kit/new_designs/CWCommunitySelector'; -import AddressInfo from '../../../../../../models/AddressInfo'; - -export type SocialLinkField = { - value?: string; - error?: string; -}; - -export type FormSubmitValues = { - communityName: string; - communityDescription: string; - communityProfileImageURL: string; - chain: { - label: string; - value: string; - }; - links?: string[]; -}; - -export type CommunityInformationFormProps = { - selectedAddress: AddressInfo; - selectedCommunity: SelectedCommunity; - onSubmit: (communityId: string, communityName: string) => any; - onCancel: () => any; - handleSelectedChainId: (chainId: string) => void; -}; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx index 8f849b1cb06..24803af8a60 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityInformationStep/CommunityInformationStep.tsx @@ -1,11 +1,25 @@ -import React from 'react'; - +import { ChainBase } from '@hicommonwealth/shared'; +import { notifyError } from 'controllers/app/notifications'; +import useAppStatus from 'hooks/useAppStatus'; +import { useBrowserAnalyticsTrack } from 'hooks/useBrowserAnalyticsTrack'; import AddressInfo from 'models/AddressInfo'; +import React from 'react'; +import { + BaseMixpanelPayload, + MixpanelCommunityCreationEvent, + MixpanelLoginPayload, +} from 'shared/analytics/types'; +import useCreateCommunityMutation, { + buildCreateCommunityInput, +} from 'state/api/communities/createCommunity'; +import CommunityInformationForm from 'views/components/CommunityInformationForm/CommunityInformationForm'; +// eslint-disable-next-line max-len +import { alphabeticallyStakeWiseSortedChains as sortedChains } from 'views/components/CommunityInformationForm/constants'; +import { CommunityInformationFormSubmitValues } from 'views/components/CommunityInformationForm/types'; import FeatureHint from 'views/components/FeatureHint'; import { CWText } from 'views/components/component_kit/cw_text'; import { SelectedCommunity } from 'views/components/component_kit/new_designs/CWCommunitySelector'; -import CommunityInformationForm from './CommunityInformationForm/CommunityInformationForm'; - +import { openConfirmation } from 'views/modals/confirmation_modal'; import './CommunityInformationStep.scss'; interface CommunityInformationStepProps { @@ -23,12 +37,88 @@ const CommunityInformationStep = ({ handleContinue, handleSelectedChainId, }: CommunityInformationStepProps) => { + const { isAddedToHomeScreen } = useAppStatus(); + + const { trackAnalytics } = useBrowserAnalyticsTrack< + MixpanelLoginPayload | BaseMixpanelPayload + >({ + onAction: true, + }); + + const { + mutateAsync: createCommunityMutation, + isLoading: createCommunityLoading, + } = useCreateCommunityMutation(); + + const handleSubmit = async ( + values: CommunityInformationFormSubmitValues & { communityId: string }, + ) => { + const selectedChainNode = sortedChains.find( + (chain) => String(chain.value) === values?.chain?.value, + ); + + try { + const input = buildCreateCommunityInput({ + id: values.communityId, + name: values.communityName, + chainBase: selectedCommunity.chainBase, + description: values.communityDescription, + iconUrl: values.communityProfileImageURL, + socialLinks: values.links ?? [], + nodeUrl: selectedChainNode!.nodeUrl!, + altWalletUrl: selectedChainNode!.altWalletUrl!, + userAddress: selectedAddress.address, + ...(selectedCommunity.chainBase === ChainBase.Ethereum && { + ethChainId: values?.chain?.value, + }), + ...(selectedCommunity.chainBase === ChainBase.CosmosSDK && { + cosmosChainId: values?.chain?.value, + bech32Prefix: selectedChainNode?.bech32Prefix, + }), + isPWA: isAddedToHomeScreen, + }); + await createCommunityMutation(input); + handleContinue(values.communityId, values.communityName); + } catch (err) { + notifyError(err.message); + } + }; + + const handleCancel = () => { + trackAnalytics({ + event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_CANCELLED, + isPWA: isAddedToHomeScreen, + }); + + openConfirmation({ + title: 'Are you sure you want to cancel?', + description: 'Your details will not be saved. Cancel create community?', + buttons: [ + { + label: 'Yes, cancel', + buttonType: 'destructive', + buttonHeight: 'sm', + onClick: handleGoBack, + }, + { + label: 'No, continue', + buttonType: 'primary', + buttonHeight: 'sm', + }, + ], + }); + }; + + const handleWatchForm = (values: CommunityInformationFormSubmitValues) => { + values?.chain?.value && handleSelectedChainId(values.chain.value); + }; + return (
Tell us about your community - Let’s start with some Community information about your community + Let's start with some Community information about your community
@@ -39,11 +129,13 @@ const CommunityInformationStep = ({ />
); diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts index b21d328fec3..a2bae3e3fad 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts @@ -26,7 +26,7 @@ const useCreateCommunity = () => { ); }; - const handleCompleteBasicInformationStep = ( + const handleCompleteCommunityInformationStep = ( communityId: string, communityName: string, ) => { @@ -36,7 +36,7 @@ const useCreateCommunity = () => { }; const isValidStepToShowCommunityStakeFormStep = [ - CreateCommunityStep.BasicInformation, + CreateCommunityStep.CommunityInformation, CreateCommunityStep.CommunityStake, ].includes(createCommunityStep); @@ -57,7 +57,7 @@ const useCreateCommunity = () => { setSelectedChainId, createdCommunityId, createdCommunityName, - handleCompleteBasicInformationStep, + handleCompleteCommunityInformationStep, onChangeStep, showCommunityStakeStep, selectedChainId, diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/utils.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/utils.ts index a2c291fbe29..56321c2418e 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/utils.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/utils.ts @@ -3,7 +3,7 @@ import { CWFormStepsProps } from 'views/components/component_kit/new_designs/CWF export enum CreateCommunityStep { CommunityTypeSelection = 'CommunityTypeSelection', - BasicInformation = 'BasicInformation', + CommunityInformation = 'CommunityInformation', CommunityStake = 'CommunityStake', Success = 'Success', } @@ -21,13 +21,13 @@ export const getFormSteps = ( : 'completed', }, { - label: 'Basic Information', + label: 'Community Information', state: - createCommunityStep < CreateCommunityStep.BasicInformation + createCommunityStep < CreateCommunityStep.CommunityInformation ? 'inactive' - : createCommunityStep === CreateCommunityStep.BasicInformation - ? 'active' - : 'completed', + : createCommunityStep === CreateCommunityStep.CommunityInformation + ? 'active' + : 'completed', }, ...((showCommunityStakeStep ? [ @@ -37,8 +37,8 @@ export const getFormSteps = ( createCommunityStep < CreateCommunityStep.CommunityStake ? 'inactive' : createCommunityStep === CreateCommunityStep.CommunityStake - ? 'active' - : 'completed', + ? 'active' + : 'completed', }, ] : []) as CWFormStepsProps['steps']), @@ -55,9 +55,9 @@ export const handleChangeStep = ( ) => { switch (createCommunityStep) { case CreateCommunityStep.CommunityTypeSelection: - setCreateCommunityStep(CreateCommunityStep.BasicInformation); + setCreateCommunityStep(CreateCommunityStep.CommunityInformation); return; - case CreateCommunityStep.BasicInformation: + case CreateCommunityStep.CommunityInformation: setCreateCommunityStep( forward ? showCommunityStakeStep @@ -70,7 +70,7 @@ export const handleChangeStep = ( setCreateCommunityStep( forward ? CreateCommunityStep.Success - : CreateCommunityStep.BasicInformation, + : CreateCommunityStep.CommunityInformation, ); return; } From 8aa6f614dd6d3a2a15fc2634b94069b6f3bb5d87 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 04:33:22 +0500 Subject: [PATCH 06/10] Added `` to create tokenized community flow --- .../views/pages/LaunchToken/LaunchToken.tsx | 10 ++- .../CommunityInformationStep.scss | 24 ++++++ .../CommunityInformationStep.tsx | 83 +++++++++++++++++++ .../steps/CommunityInformationStep/index.ts | 3 + .../pages/LaunchToken/useCreateCommunity.ts | 2 +- 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/index.ts diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx index ef841c91972..1639750bfc6 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx @@ -5,11 +5,12 @@ import { MixpanelCommunityCreationEvent } from '../../../../../shared/analytics/ import useAppStatus from '../../../hooks/useAppStatus'; import { useBrowserAnalyticsTrack } from '../../../hooks/useBrowserAnalyticsTrack'; import './LaunchToken.scss'; +import CommunityInformationStep from './steps/CommunityInformationStep'; import useCreateCommunity from './useCreateCommunity'; import { CreateTokenCommunityStep, getFormSteps } from './utils'; const LaunchToken = () => { - const { createTokenCommunityStep } = useCreateCommunity(); + const { createTokenCommunityStep, onChangeStep } = useCreateCommunity(); const { isAddedToHomeScreen } = useAppStatus(); @@ -29,7 +30,12 @@ const LaunchToken = () => { // TODO: https://github.com/hicommonwealth/commonwealth/issues/8705 return <>Not Implemented; case CreateTokenCommunityStep.CommunityInformation: - // TODO: https://github.com/hicommonwealth/commonwealth/issues/8706 + return ( + onChangeStep(false)} + handleContinue={() => onChangeStep(true)} + /> + ); return <>Not Implemented; case CreateTokenCommunityStep.SignatureLaunch: // TODO: https://github.com/hicommonwealth/commonwealth/issues/8707 diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss new file mode 100644 index 00000000000..4dd8ba2a28a --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss @@ -0,0 +1,24 @@ +@import '../../../../../../styles/shared'; + +$form-width: 596px; + +.CommunityInformationStep { + display: flex; + flex-direction: column; + gap: 24px; + position: relative; + + .header { + margin-top: 8px; + width: 100%; + + .description { + color: $neutral-500; + } + } + + @include smallInclusive { + flex-direction: column; + gap: 16px; + } +} diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx new file mode 100644 index 00000000000..1a0d2c4b49c --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx @@ -0,0 +1,83 @@ +import useAppStatus from 'hooks/useAppStatus'; +import { useBrowserAnalyticsTrack } from 'hooks/useBrowserAnalyticsTrack'; +import React from 'react'; +import { + BaseMixpanelPayload, + MixpanelCommunityCreationEvent, + MixpanelLoginPayload, +} from 'shared/analytics/types'; +import CommunityInformationForm from 'views/components/CommunityInformationForm/CommunityInformationForm'; +import { CWText } from 'views/components/component_kit/cw_text'; +import { openConfirmation } from 'views/modals/confirmation_modal'; +import './CommunityInformationStep.scss'; + +interface CommunityInformationStepProps { + handleGoBack: () => void; + handleContinue: () => void; +} + +const CommunityInformationStep = ({ + handleGoBack, + handleContinue, +}: CommunityInformationStepProps) => { + const { isAddedToHomeScreen } = useAppStatus(); + + const { trackAnalytics } = useBrowserAnalyticsTrack< + MixpanelLoginPayload | BaseMixpanelPayload + >({ + onAction: true, + }); + + const handleSubmit = async (values: any) => { + // TODO 8706: integrate endpoint + console.log('values => ', values); + handleContinue(); + }; + + const handleCancel = () => { + trackAnalytics({ + event: MixpanelCommunityCreationEvent.CREATE_TOKEN_COMMUNITY_CANCELLED, + isPWA: isAddedToHomeScreen, + }); + + openConfirmation({ + title: 'Are you sure you want to cancel?', + description: + 'Your details will not be saved. Cancel create token community flow?', + buttons: [ + { + label: 'Yes, cancel', + buttonType: 'destructive', + buttonHeight: 'sm', + onClick: handleGoBack, + }, + { + label: 'No, continue', + buttonType: 'primary', + buttonHeight: 'sm', + }, + ], + }); + }; + + return ( +
+
+ Tell us about your community + + Let's start with some basic information about your community + +
+ + +
+ ); +}; + +export default CommunityInformationStep; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/index.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/index.ts new file mode 100644 index 00000000000..4c30a45a445 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/index.ts @@ -0,0 +1,3 @@ +import CommunityInformationStep from './CommunityInformationStep'; + +export default CommunityInformationStep; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts index 3f052f77e01..bcc37715fcb 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/useCreateCommunity.ts @@ -4,7 +4,7 @@ import { CreateTokenCommunityStep, handleChangeStep } from './utils'; const useCreateCommunity = () => { const [createTokenCommunityStep, setCreateTokenCommunityStep] = useState( - CreateTokenCommunityStep.TokenInformation, + CreateTokenCommunityStep.CommunityInformation, ); const onChangeStep = (forward: boolean) => { From e9c76ef2bb5eca8c12fed2c36f3be8c80a3b2a91 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 04:54:34 +0500 Subject: [PATCH 07/10] Added info banner in create community step --- .../components/component_kit/new_designs/CWBanner.tsx | 10 ++++++---- .../CommunityInformationStep.scss | 10 +++++++++- .../CommunityInformationStep.tsx | 6 ++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWBanner.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWBanner.tsx index 2f33b222112..2ba2b83cef0 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWBanner.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWBanner.tsx @@ -32,7 +32,7 @@ export type BannerType = 'default' | 'info' | 'success' | 'warning' | 'error'; interface CWBannerProps { type?: BannerType; - title: string; + title?: string; body?: string | ReactNode; buttons?: ButtonProps[]; className?: string; @@ -74,9 +74,11 @@ const CWBanner = ({ )}
- - {title} - + {title && ( + + {title} + + )} {body && (
diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss index 4dd8ba2a28a..8a858a0f9f3 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.scss @@ -8,7 +8,7 @@ $form-width: 596px; gap: 24px; position: relative; - .header { + > .header { margin-top: 8px; width: 100%; @@ -17,6 +17,14 @@ $form-width: 596px; } } + .CWBanner { + max-width: $form-width !important; + + .content-container { + max-width: calc($form-width - 70px) !important; + } + } + @include smallInclusive { flex-direction: column; gap: 16px; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx index 1a0d2c4b49c..ec2afaf7281 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx @@ -8,6 +8,7 @@ import { } from 'shared/analytics/types'; import CommunityInformationForm from 'views/components/CommunityInformationForm/CommunityInformationForm'; import { CWText } from 'views/components/component_kit/cw_text'; +import CWBanner from 'views/components/component_kit/new_designs/CWBanner'; import { openConfirmation } from 'views/modals/confirmation_modal'; import './CommunityInformationStep.scss'; @@ -69,6 +70,11 @@ const CommunityInformationStep = ({ + + Date: Thu, 12 Sep 2024 19:42:07 +0500 Subject: [PATCH 08/10] Removed cover image test code --- .../components/component_kit/cw_cover_image_uploader.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx index 9989cba9b42..b04e2d478bb 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/cw_cover_image_uploader.tsx @@ -228,9 +228,7 @@ export const CWCoverImageUploader = ({ setIsUploading(true); - // const [_imageURL, _uploadStatus] = await uploadImage(file); - const _imageURL = URL.createObjectURL(file); - const _uploadStatus = 'success'; + const [_imageURL, _uploadStatus] = await uploadImage(file); setIsUploading(false); setUploadStatus(_uploadStatus); From 245d916a2b5e571b16ebe69f1dc183b7d493c710 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Fri, 13 Sep 2024 00:05:11 +0500 Subject: [PATCH 09/10] Fix lint --- .../components/CommunityInformationForm/useSocialLinks.ts | 4 ++-- .../CommunityInformationStep/CommunityInformationStep.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts index 62fd99da053..68c6d5cb3db 100644 --- a/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts +++ b/packages/commonwealth/client/scripts/views/components/CommunityInformationForm/useSocialLinks.ts @@ -37,7 +37,7 @@ const useSocialLinks = () => { ...updatedSocialLinks[index], error: '', }; - } catch (e: any) { + } catch (e) { const zodError = e as ZodError; updatedSocialLinks[index] = { ...updatedSocialLinks[index], @@ -67,7 +67,7 @@ const useSocialLinks = () => { ...updatedSocialLinks[index], error: '', }; - } catch (e: any) { + } catch (e) { const zodError = e as ZodError; updatedSocialLinks[index] = { ...updatedSocialLinks[index], diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx index ec2afaf7281..b8f19d1f5e0 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/CommunityInformationStep/CommunityInformationStep.tsx @@ -29,9 +29,10 @@ const CommunityInformationStep = ({ onAction: true, }); - const handleSubmit = async (values: any) => { + const handleSubmit = async (values: unknown) => { // TODO 8706: integrate endpoint console.log('values => ', values); + await new Promise((r) => setTimeout(r, 10)); handleContinue(); }; From 4b96eb308435a6772b423eb6bf16f9587756b60c Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Fri, 13 Sep 2024 17:39:18 +0500 Subject: [PATCH 10/10] Fix imports --- .../Topics/WVERC20Details/WVERC20Details.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/pages/CommunityManagement/Topics/WVERC20Details/WVERC20Details.tsx b/packages/commonwealth/client/scripts/views/pages/CommunityManagement/Topics/WVERC20Details/WVERC20Details.tsx index e9bdd06fd7a..f64b7442d37 100644 --- a/packages/commonwealth/client/scripts/views/pages/CommunityManagement/Topics/WVERC20Details/WVERC20Details.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CommunityManagement/Topics/WVERC20Details/WVERC20Details.tsx @@ -4,14 +4,13 @@ import { useDebounce } from 'usehooks-ts'; import { commonProtocol } from '@hicommonwealth/shared'; import { useCommonNavigate } from 'navigation/helpers'; import useTokenMetadataQuery from 'state/api/tokens/getTokenMetadata'; +import { alphabeticallySortedChains } from 'views/components/CommunityInformationForm/constants'; import TokenBanner from 'views/components/TokenBanner'; import { CWDivider } from 'views/components/component_kit/cw_divider'; import { CWText } from 'views/components/component_kit/cw_text'; import { CWButton } from 'views/components/component_kit/new_designs/CWButton'; import { CWSelectList } from 'views/components/component_kit/new_designs/CWSelectList'; import { CWTextInput } from 'views/components/component_kit/new_designs/CWTextInput'; -// eslint-disable-next-line max-len -import { alphabeticallySortedChains } from 'views/pages/CreateCommunity/steps/BasicInformationStep/BasicInformationForm/constants'; import { CreateTopicStep } from '../utils';