Skip to content

Commit

Permalink
Added <TokenInformationStep/> for tokenized community launch
Browse files Browse the repository at this point in the history
  • Loading branch information
mzparacha committed Sep 11, 2024
1 parent a584b9c commit 925bb04
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
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';
import { MixpanelCommunityCreationEvent } from '../../../../../shared/analytics/types';
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();

Expand All @@ -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 (
<TokenInformationStep
handleGoBack={() => navigate('/')} // redirect to home
handleContinue={() => onChangeStep(true)}
/>
);
case CreateTokenCommunityStep.CommunityInformation:
// TODO: https://github.com/hicommonwealth/commonwealth/issues/8706
return <>Not Implemented</>;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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 (
<CWForm
validationSchema={tokenInformationFormValidationSchema}
onSubmit={handleSubmit}
className="TokenInformationForm"
>
<div>
<CWLabel label="Launching On" />
<CWCommunitySelector
key={baseOption.type}
img={baseOption.img}
title={baseOption.title}
onClick={() => {}}
withRadioButton={{
value: baseOption.chainBase,
checked: true,
hideLabels: true,
hookToForm: true,
name: 'tokenChain',
}}
/>
</div>

<CWTextInput
name="tokenName"
hookToForm
label="Token name"
placeholder="Name your token"
fullWidth
/>

<CWTextInput
name="tokenTicker"
hookToForm
label="Ticker"
placeholder="ABCD"
fullWidth
/>

<CWTextArea
name="tokenDescription"
hookToForm
label="Description (Optional)"
placeholder="Describe your token"
charCount={250}
/>

<CWCoverImageUploader
subheaderText="Image (Optional - Accepts JPG and PNG files)"
canSelectImageBehaviour={false}
showUploadAndGenerateText
onImageProcessStatusChange={setIsProcessingProfileImage}
name="tokenImageURL"
hookToForm
defaultImageBehaviour={ImageBehavior.Fill}
enableGenerativeAI
/>

{/* Action buttons */}
<section className="action-buttons">
<CWButton
type="button"
label="Cancel"
buttonWidth="wide"
buttonType="secondary"
onClick={handleCancel}
/>
<CWButton
type="submit"
buttonWidth="wide"
label="Next"
disabled={isProcessingProfileImage}
/>
</section>
</CWForm>
);
};

export default TokenInformationForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type FormSubmitValues = {
tokenChain: string;
tokenName: string;
tokenTicker: string;
tokenDescription: string;
tokenImageURL: string;
};

export type TokenInformationFormProps = {
onSubmit: () => void;
onCancel: () => void;
};
Original file line number Diff line number Diff line change
@@ -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(),
});
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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 (
<div className="TokenInformationStep">
<section className="header">
<CWText type="h2">Launch Token</CWText>
<CWText type="b1" className="description">
Something about launching a token
</CWText>
</section>

<TokenInformationForm onSubmit={handleContinue} onCancel={handleGoBack} />
</div>
);
};

export default TokenInformationStep;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import TokenInformationStep from './TokenInformationStep';

export default TokenInformationStep;

0 comments on commit 925bb04

Please sign in to comment.