From cabeee28047b75addd113d302121d0f6b3f92631 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:38:00 +0500 Subject: [PATCH 1/9] 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 e11c939c6a2f3c7360c6f7f216765fc5c1cac4d2 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:40:57 +0500 Subject: [PATCH 2/9] 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 2c128ac9956aedf56eb989306ec6a90fcf439c9e Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:41:52 +0500 Subject: [PATCH 3/9] 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 a584b9c441f7799a937cd2fd6f8cba5cb83de381 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:43:15 +0500 Subject: [PATCH 4/9] Added checkbox mode to `` --- .../CWCommunitySelector.scss | 14 +++++++++++++- .../CWCommunitySelector.tsx | 18 ++++++++++++++++-- .../new_designs/cw_radio_button.tsx | 12 ++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss index a302fed228a..8bc65e17985 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss @@ -11,7 +11,14 @@ border: 1px solid $neutral-300; background-color: $white; cursor: pointer; - transition: border, background-color 0.3s; + transition: + border, + background-color 0.3s; + + &.active { + border-color: $primary-500; + background-color: $primary-50; + } &:hover { border: 1px solid $neutral-200; @@ -23,6 +30,11 @@ align-items: start; } + .radio-button { + width: fit-content; + min-width: 24px !important; + } + .chain-logo-container { img { width: 48px; diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx index a0e6fde320a..f6423e23c38 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx @@ -6,6 +6,8 @@ import { CWText } from 'views/components/component_kit/cw_text'; import { CWTag } from 'views/components/component_kit/new_designs/CWTag'; import { ChainBase } from '@hicommonwealth/shared'; +import clsx from 'clsx'; +import { CWRadioButton, RadioButtonProps } from '../cw_radio_button'; import './CWCommunitySelector.scss'; export enum CommunityType { @@ -26,8 +28,9 @@ interface CWCommunitySelectorProps { img: string; title: string; isRecommended?: boolean; - description: string; + description?: string; onClick: () => void; + withRadioButton?: RadioButtonProps; } const CWCommunitySelector = ({ @@ -36,9 +39,20 @@ const CWCommunitySelector = ({ isRecommended, description, onClick, + withRadioButton, }: CWCommunitySelectorProps) => { return ( -
+
+ {withRadioButton && ( +
+ +
+ )}
{title}
diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/cw_radio_button.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/cw_radio_button.tsx index e3a56e4070c..ec1f9f96205 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/cw_radio_button.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/cw_radio_button.tsx @@ -20,9 +20,10 @@ type RadioButtoFormValidationProps = { hookToForm?: boolean; }; -type RadioButtonProps = { +export type RadioButtonProps = { groupName?: string; onChange?: (e?: any) => void; + hideLabels?: boolean; } & Omit & RadioButtonStyleProps & RadioButtoFormValidationProps; @@ -37,6 +38,7 @@ export const CWRadioButton = (props: RadioButtonProps) => { onChange, checked, value, + hideLabels, } = props; const formContext = useFormContext(); @@ -64,9 +66,11 @@ export const CWRadioButton = (props: RadioButtonProps) => { await onChange?.(e); }} /> - - {label || value} - + {!hideLabels && ( + + {label || value} + + )} ); }; From 925bb048a9b24b8797eebee7ccb98ad116250fbd Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 02:46:18 +0500 Subject: [PATCH 5/9] Added `` for tokenized community launch --- .../views/pages/LaunchToken/LaunchToken.tsx | 13 +- .../TokenInformationForm.scss | 30 ++++ .../TokenInformationForm.tsx | 151 ++++++++++++++++++ .../TokenInformationForm/types.ts | 12 ++ .../TokenInformationForm/validation.ts | 24 +++ .../TokenInformationStep.scss | 24 +++ .../TokenInformationStep.tsx | 31 ++++ .../steps/TokenInformationStep/index.ts | 3 + 8 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.scss create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/types.ts create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/validation.ts create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.scss create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.tsx create mode 100644 packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/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..7c679eafd0b 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/LaunchToken.tsx @@ -1,3 +1,4 @@ +import { useCommonNavigate } from 'navigation/helpers'; import React from 'react'; import CWFormSteps from 'views/components/component_kit/new_designs/CWFormSteps'; import CWPageLayout from 'views/components/component_kit/new_designs/CWPageLayout'; @@ -5,11 +6,13 @@ import { MixpanelCommunityCreationEvent } from '../../../../../shared/analytics/ import useAppStatus from '../../../hooks/useAppStatus'; import { useBrowserAnalyticsTrack } from '../../../hooks/useBrowserAnalyticsTrack'; import './LaunchToken.scss'; +import TokenInformationStep from './steps/TokenInformationStep'; import useCreateCommunity from './useCreateCommunity'; import { CreateTokenCommunityStep, getFormSteps } from './utils'; const LaunchToken = () => { - const { createTokenCommunityStep } = useCreateCommunity(); + const navigate = useCommonNavigate(); + const { createTokenCommunityStep, onChangeStep } = useCreateCommunity(); const { isAddedToHomeScreen } = useAppStatus(); @@ -26,8 +29,12 @@ const LaunchToken = () => { const getCurrentStep = () => { switch (createTokenCommunityStep) { case CreateTokenCommunityStep.TokenInformation: - // TODO: https://github.com/hicommonwealth/commonwealth/issues/8705 - return <>Not Implemented; + return ( + navigate('/')} // redirect to home + handleContinue={() => onChangeStep(true)} + /> + ); case CreateTokenCommunityStep.CommunityInformation: // TODO: https://github.com/hicommonwealth/commonwealth/issues/8706 return <>Not Implemented; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.scss b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.scss new file mode 100644 index 00000000000..06f321bad4d --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.scss @@ -0,0 +1,30 @@ +@import '../../../../../../../styles/shared.scss'; + +.TokenInformationForm { + display: flex; + flex-direction: column; + gap: 24px; + width: 100%; + max-width: 596px; + + .optional-label { + font-family: $font-family-silka; + color: $neutral-500; + margin-left: 6px; + margin-top: auto; + } + + .action-buttons { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + margin-top: 24px; + margin-bottom: 24px; + gap: 10px; + + @include smallInclusive { + justify-content: flex-end; + } + } +} diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx new file mode 100644 index 00000000000..f11b30ffe37 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx @@ -0,0 +1,151 @@ +import useAppStatus from 'hooks/useAppStatus'; +import { useBrowserAnalyticsTrack } from 'hooks/useBrowserAnalyticsTrack'; +import React, { useState } from 'react'; +import { + BaseMixpanelPayload, + MixpanelCommunityCreationEvent, + MixpanelLoginPayload, +} from 'shared/analytics/types'; +import { + CWCoverImageUploader, + ImageBehavior, +} from 'views/components/component_kit/cw_cover_image_uploader'; +import { CWLabel } from 'views/components/component_kit/cw_label'; +import { CWTextArea } from 'views/components/component_kit/cw_text_area'; +import { CWButton } from 'views/components/component_kit/new_designs/CWButton'; +import CWCommunitySelector from 'views/components/component_kit/new_designs/CWCommunitySelector'; +import { CWForm } from 'views/components/component_kit/new_designs/CWForm'; +import { CWTextInput } from 'views/components/component_kit/new_designs/CWTextInput'; +import { openConfirmation } from 'views/modals/confirmation_modal'; +import { communityTypeOptions } from 'views/pages/CreateCommunity/steps/CommunityTypeStep/helpers'; +import './TokenInformationForm.scss'; +import { FormSubmitValues, TokenInformationFormProps } from './types'; +import { tokenInformationFormValidationSchema } from './validation'; + +const TokenInformationForm = ({ + onSubmit, + onCancel, +}: TokenInformationFormProps) => { + const [isProcessingProfileImage, setIsProcessingProfileImage] = + useState(false); + + const { isAddedToHomeScreen } = useAppStatus(); + + const [baseOption] = communityTypeOptions; + + const { trackAnalytics } = useBrowserAnalyticsTrack< + MixpanelLoginPayload | BaseMixpanelPayload + >({ + onAction: true, + }); + + const handleSubmit = async (values: FormSubmitValues) => { + // TODO 8705: call token launch endpoint + console.log('values => ', values); + onSubmit(); + }; + + 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 flow?', + buttons: [ + { + label: 'Yes, cancel', + buttonType: 'destructive', + buttonHeight: 'sm', + onClick: onCancel, + }, + { + label: 'No, continue', + buttonType: 'primary', + buttonHeight: 'sm', + }, + ], + }); + }; + + return ( + +
+ + {}} + withRadioButton={{ + value: baseOption.chainBase, + checked: true, + hideLabels: true, + hookToForm: true, + name: 'tokenChain', + }} + /> +
+ + + + + + + + + + {/* Action buttons */} +
+ + +
+
+ ); +}; + +export default TokenInformationForm; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/types.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/types.ts new file mode 100644 index 00000000000..ec00d841d58 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/types.ts @@ -0,0 +1,12 @@ +export type FormSubmitValues = { + tokenChain: string; + tokenName: string; + tokenTicker: string; + tokenDescription: string; + tokenImageURL: string; +}; + +export type TokenInformationFormProps = { + onSubmit: () => void; + onCancel: () => void; +}; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/validation.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/validation.ts new file mode 100644 index 00000000000..db7866ace0d --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/validation.ts @@ -0,0 +1,24 @@ +import { VALIDATION_MESSAGES } from 'helpers/formValidations/messages'; +import z from 'zod'; + +export const tokenInformationFormValidationSchema = z.object({ + tokenChain: z + .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) + .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }) + .max(100, { message: VALIDATION_MESSAGES.MAX_CHAR_LIMIT_REACHED }), + tokenName: z + .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) + .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }) + .max(100, { message: VALIDATION_MESSAGES.MAX_CHAR_LIMIT_REACHED }), + tokenTicker: z + .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) + .nonempty({ message: VALIDATION_MESSAGES.NO_INPUT }) + .max(255, { message: VALIDATION_MESSAGES.MAX_CHAR_LIMIT_REACHED }), + tokenDescription: z + .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) + .max(250, { message: VALIDATION_MESSAGES.MAX_CHAR_LIMIT_REACHED }) + .optional(), + tokenImageURL: z + .string({ invalid_type_error: VALIDATION_MESSAGES.NO_INPUT }) + .optional(), +}); diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.scss b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.scss new file mode 100644 index 00000000000..a99ac7e490f --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.scss @@ -0,0 +1,24 @@ +@import '../../../../../../styles/shared'; + +$form-width: 596px; + +.TokenInformationStep { + 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/TokenInformationStep/TokenInformationStep.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.tsx new file mode 100644 index 00000000000..cdb59beeb14 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationStep.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import { CWText } from 'views/components/component_kit/cw_text'; +import TokenInformationForm from './TokenInformationForm/TokenInformationForm'; + +import './TokenInformationStep.scss'; + +interface TokenInformationStepProps { + handleGoBack: () => void; + handleContinue: () => void; +} + +const TokenInformationStep = ({ + handleGoBack, + handleContinue, +}: TokenInformationStepProps) => { + return ( +
+
+ Launch Token + + Something about launching a token + +
+ + +
+ ); +}; + +export default TokenInformationStep; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/index.ts b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/index.ts new file mode 100644 index 00000000000..ead76717620 --- /dev/null +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/index.ts @@ -0,0 +1,3 @@ +import TokenInformationStep from './TokenInformationStep'; + +export default TokenInformationStep; From 6fbd5131852b6bf38448685824b906bcc04ced9c Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 19:44:36 +0500 Subject: [PATCH 6/9] Updated cancel community creation to happen when user confirms cancelation --- .../TokenInformationForm/TokenInformationForm.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx index f11b30ffe37..27c2ca27a03 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx @@ -46,11 +46,6 @@ const TokenInformationForm = ({ }; 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 flow?', @@ -59,7 +54,15 @@ const TokenInformationForm = ({ label: 'Yes, cancel', buttonType: 'destructive', buttonHeight: 'sm', - onClick: onCancel, + onClick: () => { + trackAnalytics({ + event: + MixpanelCommunityCreationEvent.CREATE_TOKEN_COMMUNITY_CANCELLED, + isPWA: isAddedToHomeScreen, + }); + + onCancel(); + }, }, { label: 'No, continue', From d31305761073d5b3b983d8a85bea18c51b521a59 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 19:56:17 +0500 Subject: [PATCH 7/9] Updated validations for token information form --- .../client/scripts/helpers/formValidations/messages.ts | 2 ++ .../TokenInformationForm/TokenInformationForm.tsx | 2 +- .../TokenInformationStep/TokenInformationForm/validation.ts | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/commonwealth/client/scripts/helpers/formValidations/messages.ts b/packages/commonwealth/client/scripts/helpers/formValidations/messages.ts index 2db718b3c9d..c60ac467ec8 100644 --- a/packages/commonwealth/client/scripts/helpers/formValidations/messages.ts +++ b/packages/commonwealth/client/scripts/helpers/formValidations/messages.ts @@ -1,5 +1,7 @@ export const VALIDATION_MESSAGES = { NO_INPUT: 'No input', + MIN_CHAR_LIMIT_REQUIRED: (charLimit: number) => + `Minimum ${charLimit} characters required`, MAX_CHAR_LIMIT_REACHED: 'Max character limit reached', INVALID_INPUT: 'Invalid input', }; diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx index 27c2ca27a03..0eb1a810874 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx @@ -117,7 +117,7 @@ const TokenInformationForm = ({ hookToForm label="Description (Optional)" placeholder="Describe your token" - charCount={250} + charCount={180} /> Date: Thu, 12 Sep 2024 20:01:30 +0500 Subject: [PATCH 8/9] Updated mobile styles for --- .../CWCommunitySelector.scss | 25 ++++++++++++++----- .../CWCommunitySelector.tsx | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss index 8bc65e17985..1f7458918eb 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.scss @@ -24,12 +24,6 @@ border: 1px solid $neutral-200; background-color: $neutral-100; } - - @include extraSmall { - flex-direction: column; - align-items: start; - } - .radio-button { width: fit-content; min-width: 24px !important; @@ -53,4 +47,23 @@ margin-top: 8px; } } + + @include extraSmall { + flex-direction: column; + align-items: start; + + &.withRadio { + padding: 16px 12px; + gap: 8px; + flex-direction: row !important; + align-items: center !important; + + .chain-logo-container { + img { + width: 36px; + height: 36px; + } + } + } + } } diff --git a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx index f6423e23c38..b32e07f173c 100644 --- a/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx +++ b/packages/commonwealth/client/scripts/views/components/component_kit/new_designs/CWCommunitySelector/CWCommunitySelector.tsx @@ -45,6 +45,7 @@ const CWCommunitySelector = ({
From 8692085423f41d7884f464a7c307061a46b4f587 Mon Sep 17 00:00:00 2001 From: Malik Zulqurnain Date: Thu, 12 Sep 2024 20:08:07 +0500 Subject: [PATCH 9/9] Fix lint --- .../TokenInformationForm/TokenInformationForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx index 0eb1a810874..719b5927d58 100644 --- a/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx +++ b/packages/commonwealth/client/scripts/views/pages/LaunchToken/steps/TokenInformationStep/TokenInformationForm/TokenInformationForm.tsx @@ -39,7 +39,7 @@ const TokenInformationForm = ({ onAction: true, }); - const handleSubmit = async (values: FormSubmitValues) => { + const handleSubmit = (values: FormSubmitValues) => { // TODO 8705: call token launch endpoint console.log('values => ', values); onSubmit();