From 04dc4a95c75e88bb7bd97ab7ada012cbfd0582fb Mon Sep 17 00:00:00 2001 From: Camila Sosa Morales Date: Fri, 10 Feb 2023 17:49:30 -0500 Subject: [PATCH] chore: mint form (#115) * wip: form for mint * style: change bgcolor for disabled button * fix: add key to list items * styles: add some spacings and border radius * refactor: change type file and move file validation to form * feat: add minted nft card. add wallet step * refactor: add mint card header to not repeat code * styles: add border radius to svg * styles: fix styles on mint view * style: fix height mint view * fix: fix save repository config * chore: changes based on PR review --- ui/src/components/card/card.styles.ts | 2 + .../components/core/button/button.styles.ts | 3 +- ui/src/components/core/combobox/dropdown.tsx | 3 +- ui/src/components/core/icon/icon-library.tsx | 4 + ui/src/components/core/input/input-file.tsx | 38 +--- ui/src/theme/foundations/spacing.ts | 1 + .../fields/app-description-field.tsx | 24 +++ .../mint/form-step/fields/app-name-field.tsx | 20 ++ .../fields/ens-domain-field/domain-field.tsx | 20 ++ .../ens-domain-field/ens-domain-field.tsx | 10 + .../fields/ens-domain-field/ens-field.tsx | 37 ++++ .../fields/ens-domain-field/index.ts | 1 + ui/src/views/mint/form-step/fields/index.ts | 5 + .../fields/logo-field/color-picker.tsx | 39 ++++ .../mint/form-step/fields/logo-field/index.ts | 1 + .../fields/logo-field/logo-field.tsx | 39 ++++ .../form-step/fields/verify-nfa-field.tsx | 29 +++ ui/src/views/mint/form-step/form.utils.ts | 31 +++ ui/src/views/mint/form-step/index.tsx | 1 + ui/src/views/mint/form-step/mint-form.tsx | 44 ++++ .../github-step/github-repo-configuration.tsx | 130 ------------ ui/src/views/mint/github-step/github-step.tsx | 10 +- .../github-connect}/github-connect-step.tsx | 2 +- .../github-step/steps/github-connect/index.ts | 1 + .../steps/github-repo-configuration/index.ts | 1 + .../repo-configuration-body.tsx | 97 +++++++++ .../repo-configuration-header.tsx | 19 ++ .../repo-configuration.tsx | 12 ++ .../github-repository-selection.tsx | 27 +-- .../github-repository-selection/index.ts | 1 + ui/src/views/mint/github-step/steps/index.ts | 3 + ui/src/views/mint/mint-card/index.ts | 1 + ui/src/views/mint/mint-card/mint-card.tsx | 35 ++++ ui/src/views/mint/mint-stepper.tsx | 77 ++----- ui/src/views/mint/mint.context.tsx | 56 ++++- ui/src/views/mint/mint.tsx | 19 +- ui/src/views/mint/nft-card/index.ts | 1 + ui/src/views/mint/nft-card/nft-card.tsx | 60 ++++++ ui/src/views/mint/nft-card/svg-preview.tsx | 193 ++++++++++++++++++ ui/src/views/mint/nft-minted.tsx | 22 ++ ui/src/views/mint/preview-step/indext.ts | 1 + .../views/mint/preview-step/mint-preview.tsx | 39 ++++ ui/src/views/mint/wallet-step/index.ts | 1 + ui/src/views/mint/wallet-step/wallet-step.tsx | 39 ++++ ui/tailwind.config.js | 4 +- 45 files changed, 939 insertions(+), 264 deletions(-) create mode 100644 ui/src/views/mint/form-step/fields/app-description-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/app-name-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/ens-domain-field/domain-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/ens-domain-field/ens-domain-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/ens-domain-field/ens-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/ens-domain-field/index.ts create mode 100644 ui/src/views/mint/form-step/fields/index.ts create mode 100644 ui/src/views/mint/form-step/fields/logo-field/color-picker.tsx create mode 100644 ui/src/views/mint/form-step/fields/logo-field/index.ts create mode 100644 ui/src/views/mint/form-step/fields/logo-field/logo-field.tsx create mode 100644 ui/src/views/mint/form-step/fields/verify-nfa-field.tsx create mode 100644 ui/src/views/mint/form-step/form.utils.ts create mode 100644 ui/src/views/mint/form-step/index.tsx create mode 100644 ui/src/views/mint/form-step/mint-form.tsx delete mode 100644 ui/src/views/mint/github-step/github-repo-configuration.tsx rename ui/src/views/mint/github-step/{ => steps/github-connect}/github-connect-step.tsx (93%) create mode 100644 ui/src/views/mint/github-step/steps/github-connect/index.ts create mode 100644 ui/src/views/mint/github-step/steps/github-repo-configuration/index.ts create mode 100644 ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-body.tsx create mode 100644 ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-header.tsx create mode 100644 ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration.tsx rename ui/src/views/mint/github-step/{ => steps/github-repository-selection}/github-repository-selection.tsx (85%) create mode 100644 ui/src/views/mint/github-step/steps/github-repository-selection/index.ts create mode 100644 ui/src/views/mint/github-step/steps/index.ts create mode 100644 ui/src/views/mint/mint-card/index.ts create mode 100644 ui/src/views/mint/mint-card/mint-card.tsx create mode 100644 ui/src/views/mint/nft-card/index.ts create mode 100644 ui/src/views/mint/nft-card/nft-card.tsx create mode 100644 ui/src/views/mint/nft-card/svg-preview.tsx create mode 100644 ui/src/views/mint/nft-minted.tsx create mode 100644 ui/src/views/mint/preview-step/indext.ts create mode 100644 ui/src/views/mint/preview-step/mint-preview.tsx create mode 100644 ui/src/views/mint/wallet-step/index.ts create mode 100644 ui/src/views/mint/wallet-step/wallet-step.tsx diff --git a/ui/src/components/card/card.styles.ts b/ui/src/components/card/card.styles.ts index 085bc7a..a91234f 100644 --- a/ui/src/components/card/card.styles.ts +++ b/ui/src/components/card/card.styles.ts @@ -24,6 +24,7 @@ export abstract class CardStyles { static readonly Text = styled('div', { backgroundColor: '$slate1', + width: '$full', borderRadius: '$xl', display: 'flex', flexDirection: 'column', @@ -31,5 +32,6 @@ export abstract class CardStyles { alignItems: 'center', textAlign: 'center', color: '$slate8', + fontSize: '$sm', }); } diff --git a/ui/src/components/core/button/button.styles.ts b/ui/src/components/core/button/button.styles.ts index 6ae496e..389f869 100644 --- a/ui/src/components/core/button/button.styles.ts +++ b/ui/src/components/core/button/button.styles.ts @@ -160,10 +160,11 @@ export const StyledButton = styled('button', { whiteSpace: 'nowrap', verticalAlign: 'middle', userSelect: 'none', - fontWeight: '$medium', + fontWeight: '$normal', '&:disabled': { cursor: 'not-allowed', opacity: '0.4', + backgroundColor: '$slate3', }, variants: { diff --git a/ui/src/components/core/combobox/dropdown.tsx b/ui/src/components/core/combobox/dropdown.tsx index b96d187..cf19939 100644 --- a/ui/src/components/core/combobox/dropdown.tsx +++ b/ui/src/components/core/combobox/dropdown.tsx @@ -9,7 +9,6 @@ type DropdownOptionProps = { const DropdownOption = ({ option }: DropdownOptionProps) => ( `relative cursor-default select-none py-2 px-3.5 text-slate11 rounded-xl mb-2 text-sm ${ active ? 'bg-slate5 text-slate12' : 'bg-transparent' @@ -35,7 +34,7 @@ type DropdownButtonProps = { const DropdownButton = ({ selectedValue, open }: DropdownButtonProps) => ( diff --git a/ui/src/components/core/icon/icon-library.tsx b/ui/src/components/core/icon/icon-library.tsx index a4b658d..d4a39fe 100644 --- a/ui/src/components/core/icon/icon-library.tsx +++ b/ui/src/components/core/icon/icon-library.tsx @@ -6,10 +6,13 @@ import { AiOutlineDown } from '@react-icons/all-files/ai/AiOutlineDown'; import { BiSearch } from '@react-icons/all-files/bi/BiSearch'; import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadSharp'; import { MetamaskIcon, EthereumIcon } from './custom'; +import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp'; +import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter'; export const IconLibrary = Object.freeze({ back: IoArrowBackCircleSharp, check: AiOutlineCheck, + 'check-circle': IoCheckmarkCircleSharp, 'chevron-down': AiOutlineDown, ethereum: EthereumIcon, github: IoLogoGithub, @@ -17,6 +20,7 @@ export const IconLibrary = Object.freeze({ upload: IoCloudUploadSharp, metamask: MetamaskIcon, //remove if not used search: BiSearch, + twitter: AiOutlineTwitter, }); export type IconName = keyof typeof IconLibrary; diff --git a/ui/src/components/core/input/input-file.tsx b/ui/src/components/core/input/input-file.tsx index 8dff12d..b337802 100644 --- a/ui/src/components/core/input/input-file.tsx +++ b/ui/src/components/core/input/input-file.tsx @@ -1,8 +1,7 @@ import { Flex } from '../../layout'; import { dripStitches } from '../../../theme'; -import { forwardRef, useRef, useState } from 'react'; +import { forwardRef, useRef } from 'react'; import { Icon } from '../icon'; -import { Form } from '../../../components/form/form'; const { styled } = dripStitches; @@ -15,44 +14,24 @@ const BorderInput = styled('div', { borderWidth: '$default', borderRadius: '$lg', zIndex: '$docked', - my: '$1h', '&:hover': { borderColor: '$gray8', }, }); -const DEFAULT_MAX_FILE_SIZE = 10; // in KB - -// The file size must be capped to a size that the contract can handle -const validateFileSize = ( - file: File, - maxSize = DEFAULT_MAX_FILE_SIZE -): boolean => { - return file.size <= 1024 * maxSize; -}; - type InputFileProps = { - value: File | null; - onChange: (file: File | null) => void; + value: string; + onChange: (e: React.ChangeEvent) => void; } & React.ComponentProps; export const StyledInputFile = forwardRef( ({ value: file, onChange, css, ...props }, ref) => { const inputFileRef = useRef(null); - const [errorMessage, setErrorMessage] = useState(null); const handleFileChange = (e: React.ChangeEvent) => { e.preventDefault(); - setErrorMessage(null); - - if (e.target.files && e.target.files.length > 0) { - if (validateFileSize(e.target.files[0])) onChange(e.target.files[0]); - else { - onChange(null); - setErrorMessage('File size is too big'); - } - } + onChange(e); }; return ( @@ -68,12 +47,8 @@ export const StyledInputFile = forwardRef( {...props} onClick={() => inputFileRef.current?.click()} > - {file ? ( - logo + {file !== '' ? ( + logo ) : ( )} @@ -87,7 +62,6 @@ export const StyledInputFile = forwardRef( onChange={handleFileChange} /> - {errorMessage && {errorMessage}} ); } diff --git a/ui/src/theme/foundations/spacing.ts b/ui/src/theme/foundations/spacing.ts index 11d2deb..a803842 100644 --- a/ui/src/theme/foundations/spacing.ts +++ b/ui/src/theme/foundations/spacing.ts @@ -8,6 +8,7 @@ export const spacing = { 3: '0.75rem', // 12px '3h': '0.875rem', // 14px 4: '1rem', // 16px + '4h': '1.125rem', // 18px 5: '1.25rem', // 20px 6: '1.5rem', // 24px 7: '1.75rem', // 28px diff --git a/ui/src/views/mint/form-step/fields/app-description-field.tsx b/ui/src/views/mint/form-step/fields/app-description-field.tsx new file mode 100644 index 0000000..d441757 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/app-description-field.tsx @@ -0,0 +1,24 @@ +import { Form } from '@/components'; +import { Mint } from '../../mint.context'; + +export const AppDescriptionField = () => { + const { appDescription, setAppDescription } = Mint.useContext(); + + const handleAppDescriptionChange = ( + e: React.ChangeEvent + ) => { + setAppDescription(e.target.value); + }; + + return ( + + Description + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/app-name-field.tsx b/ui/src/views/mint/form-step/fields/app-name-field.tsx new file mode 100644 index 0000000..d6c3a5b --- /dev/null +++ b/ui/src/views/mint/form-step/fields/app-name-field.tsx @@ -0,0 +1,20 @@ +import { Form } from '@/components'; +import { Mint } from '../../mint.context'; + +export const AppNameField = () => { + const { appName, setAppName } = Mint.useContext(); + + const handleAppNameChange = (e: React.ChangeEvent) => { + setAppName(e.target.value); + }; + return ( + + Name + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/ens-domain-field/domain-field.tsx b/ui/src/views/mint/form-step/fields/ens-domain-field/domain-field.tsx new file mode 100644 index 0000000..bf3f25e --- /dev/null +++ b/ui/src/views/mint/form-step/fields/ens-domain-field/domain-field.tsx @@ -0,0 +1,20 @@ +import { Form } from '@/components'; +import { Mint } from '@/views/mint/mint.context'; + +export const DomainField = () => { + const { domain, setDomain } = Mint.useContext(); + + const handleDomainChange = (e: React.ChangeEvent) => { + setDomain(e.target.value); + }; + return ( + + Domain + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/ens-domain-field/ens-domain-field.tsx b/ui/src/views/mint/form-step/fields/ens-domain-field/ens-domain-field.tsx new file mode 100644 index 0000000..2965d75 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/ens-domain-field/ens-domain-field.tsx @@ -0,0 +1,10 @@ +import { Flex } from '@/components'; +import { DomainField } from './domain-field'; +import { EnsField } from './ens-field'; + +export const EnsDomainField = () => ( + + + + +); diff --git a/ui/src/views/mint/form-step/fields/ens-domain-field/ens-field.tsx b/ui/src/views/mint/form-step/fields/ens-domain-field/ens-field.tsx new file mode 100644 index 0000000..810052f --- /dev/null +++ b/ui/src/views/mint/form-step/fields/ens-domain-field/ens-field.tsx @@ -0,0 +1,37 @@ +import { Dropdown, DropdownItem, Form } from '@/components'; +import { Mint } from '@/views/mint/mint.context'; + +// TODO remove after integration with wallet +const ensList: DropdownItem[] = [ + { + value: 'fleek.eth', + label: 'fleek.eth', + }, + { + value: 'ens.eth', + label: 'ens.eth', + }, + { + value: 'cami.eth', + label: 'cami.eth', + }, +]; + +export const EnsField = () => { + const { ens, setEns } = Mint.useContext(); + + const handleEnsChange = (item: DropdownItem) => { + setEns(item); + }; + + return ( + + ENS + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/ens-domain-field/index.ts b/ui/src/views/mint/form-step/fields/ens-domain-field/index.ts new file mode 100644 index 0000000..664ed56 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/ens-domain-field/index.ts @@ -0,0 +1 @@ +export * from './ens-domain-field'; diff --git a/ui/src/views/mint/form-step/fields/index.ts b/ui/src/views/mint/form-step/fields/index.ts new file mode 100644 index 0000000..abfeb6e --- /dev/null +++ b/ui/src/views/mint/form-step/fields/index.ts @@ -0,0 +1,5 @@ +export * from './logo-field'; +export * from './app-name-field'; +export * from './app-description-field'; +export * from './ens-domain-field'; +export * from './verify-nfa-field'; diff --git a/ui/src/views/mint/form-step/fields/logo-field/color-picker.tsx b/ui/src/views/mint/form-step/fields/logo-field/color-picker.tsx new file mode 100644 index 0000000..2d8b73b --- /dev/null +++ b/ui/src/views/mint/form-step/fields/logo-field/color-picker.tsx @@ -0,0 +1,39 @@ +import { Card, Flex } from '@/components'; +import { useRef } from 'react'; +// @ts-ignore +import ColorThief from 'colorthief'; +import { Mint } from '../../../mint.context'; + +export const ColorPicker = () => { + const { appLogo, logoColor, setLogoColor } = Mint.useContext(); + const imageRef = useRef(null); + + const handleLogoLoad = (e: React.SyntheticEvent) => { + const colorArray = new ColorThief().getColor(imageRef.current); + const hexColor = `#${colorArray + .map((c: number) => c.toString(16).padStart(2, '0')) + .join('')}`; + setLogoColor(hexColor); + }; + + return ( + + + Primary Color + {/* TODO crate color picker component */} + setLogoColor(e.target.value)} + /> + + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/logo-field/index.ts b/ui/src/views/mint/form-step/fields/logo-field/index.ts new file mode 100644 index 0000000..11ab381 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/logo-field/index.ts @@ -0,0 +1 @@ +export * from './logo-field'; diff --git a/ui/src/views/mint/form-step/fields/logo-field/logo-field.tsx b/ui/src/views/mint/form-step/fields/logo-field/logo-field.tsx new file mode 100644 index 0000000..cb52cc0 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/logo-field/logo-field.tsx @@ -0,0 +1,39 @@ +import { Flex, Form } from '@/components'; +import { useState } from 'react'; +import { Mint } from '../../../mint.context'; +import { fileToBase64, validateFileSize } from '../../form.utils'; +import { ColorPicker } from './color-picker'; + +export const LogoField = () => { + const { appLogo, setAppLogo, setLogoColor } = Mint.useContext(); + const [errorMessage, setErrorMessage] = useState(null); + + const handleFileChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + + if (file) { + if (validateFileSize(file)) { + const fileBase64 = await fileToBase64(file); + setAppLogo(fileBase64); + setErrorMessage(null); + //TODO remove console.log + // To send to the contract the logo needs to be a base64 string + console.log('Sending to contract:', fileBase64); + } else { + setAppLogo(''); + setLogoColor(''); + setErrorMessage('File size is too big'); + } + } + }; + return ( + + + Logo + + {errorMessage && {errorMessage}} + + + + ); +}; diff --git a/ui/src/views/mint/form-step/fields/verify-nfa-field.tsx b/ui/src/views/mint/form-step/fields/verify-nfa-field.tsx new file mode 100644 index 0000000..d5dea67 --- /dev/null +++ b/ui/src/views/mint/form-step/fields/verify-nfa-field.tsx @@ -0,0 +1,29 @@ +import { Card, Flex, Grid } from '@/components'; +import { Mint } from '@/views/mint/mint.context'; + +export const VerifyNFAField = () => { + const { verifyNFA, setVerifyNFA } = Mint.useContext(); + + const handleVerifyNFAChange = (e: React.ChangeEvent) => { + setVerifyNFA(e.target.checked); + }; + + return ( + + {/* TODO replace for grid */} + + + Verify NFA + + Add Fleek as a controller to be verified, learn more here. + + + + + + ); +}; diff --git a/ui/src/views/mint/form-step/form.utils.ts b/ui/src/views/mint/form-step/form.utils.ts new file mode 100644 index 0000000..8a8de48 --- /dev/null +++ b/ui/src/views/mint/form-step/form.utils.ts @@ -0,0 +1,31 @@ +//TODO create env variable +const DEFAULT_MAX_FILE_SIZE = 10; // in KB + +/** + * The file size must be capped to a size that the contract can handle + */ +export const validateFileSize = ( + file: File, + maxSize = DEFAULT_MAX_FILE_SIZE +): boolean => { + return file.size <= 1024 * maxSize; +}; + +/** + * Converts the File from the input to a base64 string. + */ +export const fileToBase64 = (file: File): Promise => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result?.toString() || ''); + reader.onerror = reject; + }); + +/** + * Converts a hex color string to a number. + */ +export const parseColorToNumber = (color: string): number => { + const hexColor = color.replace('#', ''); + return parseInt(hexColor, 16); +}; diff --git a/ui/src/views/mint/form-step/index.tsx b/ui/src/views/mint/form-step/index.tsx new file mode 100644 index 0000000..789195f --- /dev/null +++ b/ui/src/views/mint/form-step/index.tsx @@ -0,0 +1 @@ +export * from './mint-form'; diff --git a/ui/src/views/mint/form-step/mint-form.tsx b/ui/src/views/mint/form-step/mint-form.tsx new file mode 100644 index 0000000..56a60f6 --- /dev/null +++ b/ui/src/views/mint/form-step/mint-form.tsx @@ -0,0 +1,44 @@ +import { Button, Card, Grid, Stepper } from '@/components'; +import { Mint } from '../mint.context'; +import { + LogoField, + AppDescriptionField, + AppNameField, + EnsDomainField, + VerifyNFAField, +} from './fields'; +import { MintCardHeader } from '../mint-card'; + +export const FormStep = () => { + const { prevStep, nextStep } = Stepper.useContext(); + const { appName, appDescription, domain } = Mint.useContext(); + + return ( + + + + + + + + + + + + + + + + ); +}; diff --git a/ui/src/views/mint/github-step/github-repo-configuration.tsx b/ui/src/views/mint/github-step/github-repo-configuration.tsx deleted file mode 100644 index b95657e..0000000 --- a/ui/src/views/mint/github-step/github-repo-configuration.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { - Button, - Card, - Dropdown, - DropdownItem, - Form, - Grid, - Icon, - IconButton, - Stepper, -} from '@/components'; -import React, { useState } from 'react'; -import { Mint } from '../mint.context'; -import { RepoRow } from './github-repository-selection'; - -//TODO remove once it's integrated with GH login -const branches: DropdownItem[] = [ - { - label: 'master', - value: 'master', - }, - { - label: 'develop', - value: 'develop', - }, - { - label: 'feature/branch', - value: 'feature/branch', - }, -]; - -export const GithubRepoConfiguration: React.FC = () => { - const { - repositoryName, - branchName, - commitHash, - setGithubStep, - setRepositoryConfig, - } = Mint.useContext(); - const { nextStep } = Stepper.useContext(); - const [branchSelected, setBranchSelected] = useState(branchName); - const [commitHashSelected, setCommitHashSelected] = useState(commitHash); - - const handlePrevStepClick = () => { - setGithubStep(2); - setRepositoryConfig('', ''); - }; - - const handleBranchChange = (dorpdownOption: DropdownItem) => { - //TODO we'll have to check the data that GH API returns - setBranchSelected(dorpdownOption.value); - }; - - const handleCommitHashChange = (e: React.ChangeEvent) => { - setCommitHashSelected(e.target.value); - }; - - const handleContinueClick = () => { - setRepositoryConfig(branchSelected, commitHashSelected); - nextStep(); - }; - - return ( - - } - css={{ mr: '$2' }} - onClick={handlePrevStepClick} - /> - } - rightIcon={ - } - /> - } - /> - - - - Use for NFA - - } - /> - - Git Branch - - - - Git Commit - - - - - - - ); -}; diff --git a/ui/src/views/mint/github-step/github-step.tsx b/ui/src/views/mint/github-step/github-step.tsx index 7cf3a2d..2e29832 100644 --- a/ui/src/views/mint/github-step/github-step.tsx +++ b/ui/src/views/mint/github-step/github-step.tsx @@ -1,9 +1,9 @@ -import { Stepper } from '@/components'; -import { useState } from 'react'; import { Mint } from '../mint.context'; -import { GithubConnect } from './github-connect-step'; -import { GithubRepoConfiguration } from './github-repo-configuration'; -import { GithubRepositoryConnection } from './github-repository-selection'; +import { + GithubConnect, + GithubRepoConfiguration, + GithubRepositoryConnection, +} from './steps'; export const GithubStep = () => { const { githubStep } = Mint.useContext(); diff --git a/ui/src/views/mint/github-step/github-connect-step.tsx b/ui/src/views/mint/github-step/steps/github-connect/github-connect-step.tsx similarity index 93% rename from ui/src/views/mint/github-step/github-connect-step.tsx rename to ui/src/views/mint/github-step/steps/github-connect/github-connect-step.tsx index 1133d7c..eefe4a0 100644 --- a/ui/src/views/mint/github-step/github-connect-step.tsx +++ b/ui/src/views/mint/github-step/steps/github-connect/github-connect-step.tsx @@ -1,5 +1,5 @@ import { Button, Card, Grid, Icon, IconButton } from '@/components'; -import { Mint } from '../mint.context'; +import { Mint } from '../../../mint.context'; export const GithubConnect: React.FC = () => { const { setGithubStep } = Mint.useContext(); diff --git a/ui/src/views/mint/github-step/steps/github-connect/index.ts b/ui/src/views/mint/github-step/steps/github-connect/index.ts new file mode 100644 index 0000000..3c52b82 --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-connect/index.ts @@ -0,0 +1 @@ +export * from './github-connect-step'; diff --git a/ui/src/views/mint/github-step/steps/github-repo-configuration/index.ts b/ui/src/views/mint/github-step/steps/github-repo-configuration/index.ts new file mode 100644 index 0000000..84fa144 --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-repo-configuration/index.ts @@ -0,0 +1 @@ +export * from './repo-configuration'; diff --git a/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-body.tsx b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-body.tsx new file mode 100644 index 0000000..51cd016 --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-body.tsx @@ -0,0 +1,97 @@ +import { + Button, + Card, + Dropdown, + DropdownItem, + Form, + Grid, + Stepper, +} from '@/components'; +import { Mint } from '@/views/mint/mint.context'; +import { useState } from 'react'; +import { RepoRow } from '../github-repository-selection'; + +//TODO remove once it's integrated with GH login +const branches: DropdownItem[] = [ + { + label: 'master', + value: 'master', + }, + { + label: 'develop', + value: 'develop', + }, + { + label: 'feature/branch', + value: 'feature/branch', + }, +]; + +export const RepoConfigurationBody = () => { + const { repositoryName, branchName, commitHash, setRepositoryConfig } = + Mint.useContext(); + + const { nextStep } = Stepper.useContext(); + const [branchSelected, setBranchSelected] = useState(branchName); + const [commitHashSelected, setCommitHashSelected] = useState(commitHash); + console.log(branchSelected); + const handleBranchChange = (dorpdownOption: DropdownItem) => { + //TODO we'll have to check the data that GH API returns + console.log(dorpdownOption); + setBranchSelected(dorpdownOption); + }; + + const handleCommitHashChange = (e: React.ChangeEvent) => { + setCommitHashSelected(e.target.value); + }; + + const handleContinueClick = () => { + setRepositoryConfig(branchSelected, commitHashSelected); + nextStep(); + }; + + return ( + + + + Use for NFA + + } + /> + + Git Branch + + + + Git Commit + + + + + + ); +}; diff --git a/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-header.tsx b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-header.tsx new file mode 100644 index 0000000..5d1b641 --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration-header.tsx @@ -0,0 +1,19 @@ +import { DropdownItem } from '@/components'; +import { MintCardHeader } from '@/views/mint/mint-card'; +import { Mint } from '@/views/mint/mint.context'; + +export const RepoConfigurationHeader = () => { + const { setGithubStep, setRepositoryConfig } = Mint.useContext(); + + const handlePrevStepClick = () => { + setGithubStep(2); + setRepositoryConfig({} as DropdownItem, ''); + }; + + return ( + + ); +}; diff --git a/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration.tsx b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration.tsx new file mode 100644 index 0000000..f62ffec --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-repo-configuration/repo-configuration.tsx @@ -0,0 +1,12 @@ +import { Card } from '@/components'; +import { RepoConfigurationBody } from './repo-configuration-body'; +import { RepoConfigurationHeader } from './repo-configuration-header'; + +export const GithubRepoConfiguration: React.FC = () => { + return ( + + + + + ); +}; diff --git a/ui/src/views/mint/github-step/github-repository-selection.tsx b/ui/src/views/mint/github-step/steps/github-repository-selection/github-repository-selection.tsx similarity index 85% rename from ui/src/views/mint/github-step/github-repository-selection.tsx rename to ui/src/views/mint/github-step/steps/github-repository-selection/github-repository-selection.tsx index 1756497..2958bb8 100644 --- a/ui/src/views/mint/github-step/github-repository-selection.tsx +++ b/ui/src/views/mint/github-step/steps/github-repository-selection/github-repository-selection.tsx @@ -3,6 +3,7 @@ import { Card, Combobox, ComboboxItem, + DropdownItem, Flex, Grid, Icon, @@ -11,8 +12,9 @@ import { } from '@/components'; import { Input } from '@/components/core/input'; import { Separator } from '@/components/core/separator.styles'; +import { MintCardHeader } from '@/views/mint/mint-card'; +import { Mint } from '@/views/mint/mint.context'; import React, { forwardRef, useRef, useState } from 'react'; -import { Mint } from '../mint.context'; //TODO remove once it's integrated with GH login const repos = [ @@ -80,7 +82,7 @@ export const GithubRepositoryConnection: React.FC = () => { const handleSelectRepo = (repo: string) => { setRepositoryName(repo); setGithubStep(3); - setRepositoryConfig('', ''); + setRepositoryConfig({} as DropdownItem, ''); }; const filteredRepositories = @@ -92,26 +94,9 @@ export const GithubRepositoryConnection: React.FC = () => { return ( - } - css={{ mr: '$2' }} - onClick={handlePrevStepClick} - /> - } - rightIcon={ - } - /> - } + onClickBack={handlePrevStepClick} /> diff --git a/ui/src/views/mint/github-step/steps/github-repository-selection/index.ts b/ui/src/views/mint/github-step/steps/github-repository-selection/index.ts new file mode 100644 index 0000000..2b10653 --- /dev/null +++ b/ui/src/views/mint/github-step/steps/github-repository-selection/index.ts @@ -0,0 +1 @@ +export * from './github-repository-selection'; diff --git a/ui/src/views/mint/github-step/steps/index.ts b/ui/src/views/mint/github-step/steps/index.ts new file mode 100644 index 0000000..cb74b0e --- /dev/null +++ b/ui/src/views/mint/github-step/steps/index.ts @@ -0,0 +1,3 @@ +export * from './github-repository-selection'; +export * from './github-repo-configuration'; +export * from './github-connect'; diff --git a/ui/src/views/mint/mint-card/index.ts b/ui/src/views/mint/mint-card/index.ts new file mode 100644 index 0000000..805d982 --- /dev/null +++ b/ui/src/views/mint/mint-card/index.ts @@ -0,0 +1 @@ +export * from './mint-card'; diff --git a/ui/src/views/mint/mint-card/mint-card.tsx b/ui/src/views/mint/mint-card/mint-card.tsx new file mode 100644 index 0000000..015cc61 --- /dev/null +++ b/ui/src/views/mint/mint-card/mint-card.tsx @@ -0,0 +1,35 @@ +import { Card, Icon, IconButton } from '@/components'; + +type MintCardHeaderProps = { + title: string; + onClickBack: () => void; +}; + +export const MintCardHeader: React.FC = ({ + title, + onClickBack, +}) => { + return ( + } + css={{ mr: '$2' }} + onClick={onClickBack} + /> + } + rightIcon={ + } + /> + } + /> + ); +}; diff --git a/ui/src/views/mint/mint-stepper.tsx b/ui/src/views/mint/mint-stepper.tsx index 50a8f4a..40794ad 100644 --- a/ui/src/views/mint/mint-stepper.tsx +++ b/ui/src/views/mint/mint-stepper.tsx @@ -1,41 +1,18 @@ -import { IconButton, Icon, Stepper, Card } from '@/components'; +import { Stepper } from '@/components'; +import { FormStep } from './form-step'; +import { MintPreview } from './preview-step/mint-preview'; import { GithubStep } from './github-step'; import { MintStep } from './mint-step'; +import { WalletStep } from './wallet-step'; import { Mint } from './mint.context'; - -//TODO remove after mint flow is done -const Heading = ({ title }: { title: string }) => { - const { prevStep } = Stepper.useContext(); - - return ( - } - css={{ mr: '$2' }} - onClick={prevStep} - /> - } - rightIcon={ - } - /> - } - /> - ); -}; +import { NftMinted } from './nft-minted'; export const MintStepper = () => { - return ( - - + const { sucessMint } = Mint.useContext(); + + if (!sucessMint) { + return ( + @@ -45,41 +22,25 @@ export const MintStepper = () => { - - - - Step 2 - - + - - - - - Step 3 - - + + - - - - - Step 4 - - + + - + + ); + } - {/* TODO remove buttons when finish to integrate all the flow */} - {/* */} - - ); + return ; }; diff --git a/ui/src/views/mint/mint.context.tsx b/ui/src/views/mint/mint.context.tsx index b59b094..b32f74c 100644 --- a/ui/src/views/mint/mint.context.tsx +++ b/ui/src/views/mint/mint.context.tsx @@ -1,14 +1,31 @@ +import { DropdownItem } from '@/components'; import { createContext } from '@/utils'; import { useState } from 'react'; export type MintContext = { repositoryName: string; - branchName: string; + branchName: DropdownItem; //get value from DropdownItem to mint commitHash: string; githubStep: number; + appName: string; + appDescription: string; + appLogo: string; + logoColor: string; + ens: DropdownItem; //maybe it would be a DropdownItem + domain: string; + verifyNFA: boolean; + sucessMint: boolean | undefined; setGithubStep: (step: number) => void; setRepositoryName: (repo: string) => void; - setRepositoryConfig: (branch: string, hash: string) => void; + setRepositoryConfig: (branch: DropdownItem, hash: string) => void; + setAppName: (name: string) => void; + setAppDescription: (description: string) => void; + setAppLogo: (logo: string) => void; + setLogoColor: (color: string) => void; + setEns: (ens: DropdownItem) => void; + setDomain: (domain: string) => void; + setVerifyNFA: (verify: boolean) => void; + setSucessMint: (sucess: boolean) => void; }; const [MintProvider, useContext] = createContext({ @@ -21,18 +38,33 @@ export abstract class Mint { static readonly useContext = useContext; static readonly Provider: React.FC = ({ children }) => { + //Github Connection const [repositoryName, setRepositoryName] = useState(''); - const [branchName, setBranchName] = useState(''); + const [branchName, setBranchName] = useState({} as DropdownItem); const [commitHash, setCommitHash] = useState(''); const [githubStep, setGithubStepContext] = useState(1); + //NFA Details + const [appName, setAppName] = useState(''); + const [appDescription, setAppDescription] = useState(''); + const [appLogo, setAppLogo] = useState(''); + const [logoColor, setLogoColor] = useState(''); + const [ens, setEns] = useState({} as DropdownItem); + const [domain, setDomain] = useState(''); + const [verifyNFA, setVerifyNFA] = useState(true); + + //Mint state + //true means it's minted + //false means it's not minted yet + const [sucessMint, setSucessMint] = useState(false); + const setGithubStep = (step: number): void => { if (step > 0 && step <= 3) { setGithubStepContext(step); } }; - const setRepositoryConfig = (branch: string, hash: string) => { + const setRepositoryConfig = (branch: DropdownItem, hash: string) => { setBranchName(branch); setCommitHash(hash); }; @@ -44,9 +76,25 @@ export abstract class Mint { branchName, commitHash, githubStep, + appName, + appDescription, + appLogo, + logoColor, + ens, + domain, + verifyNFA, + sucessMint, setGithubStep, setRepositoryConfig, setRepositoryName, + setAppName, + setAppDescription, + setAppLogo, + setLogoColor, + setEns, + setDomain, + setVerifyNFA, + setSucessMint, }} > {children} diff --git a/ui/src/views/mint/mint.tsx b/ui/src/views/mint/mint.tsx index a429b44..61b402e 100644 --- a/ui/src/views/mint/mint.tsx +++ b/ui/src/views/mint/mint.tsx @@ -1,15 +1,18 @@ import { Flex } from '@/components'; import { MintStepper } from './mint-stepper'; +import { Mint as MintContext } from './mint.context'; export const Mint = () => ( - - + + - + ); diff --git a/ui/src/views/mint/nft-card/index.ts b/ui/src/views/mint/nft-card/index.ts new file mode 100644 index 0000000..7e0da3c --- /dev/null +++ b/ui/src/views/mint/nft-card/index.ts @@ -0,0 +1 @@ +export * from './nft-card'; diff --git a/ui/src/views/mint/nft-card/nft-card.tsx b/ui/src/views/mint/nft-card/nft-card.tsx new file mode 100644 index 0000000..03eea9e --- /dev/null +++ b/ui/src/views/mint/nft-card/nft-card.tsx @@ -0,0 +1,60 @@ +import { Button, Card, Grid } from '@/components'; +import { Mint } from '../mint.context'; +import { SVGPreview } from './svg-preview'; + +type NftCardProps = { + title: string; + leftIcon: React.ReactNode; + rightIcon?: React.ReactNode; + message: string; + buttonText: string; + leftIconButton?: React.ReactNode; + onClick: () => void; +}; + +export const NftCard: React.FC = ({ + title, + leftIcon, + rightIcon, + message, + buttonText, + leftIconButton, + onClick, +}) => { + const size = '26.5rem'; + const { appLogo, logoColor, appName, ens } = Mint.useContext(); + + return ( + + + + + + {/* TODO replace for real price when integrate with wallet */} + {message} + {/* TODO add desabled when user doesnt have enough MATIC */} + {/* TODO repalce for app name when connect with context */} + + + + + ); +}; diff --git a/ui/src/views/mint/nft-card/svg-preview.tsx b/ui/src/views/mint/nft-card/svg-preview.tsx new file mode 100644 index 0000000..738eebf --- /dev/null +++ b/ui/src/views/mint/nft-card/svg-preview.tsx @@ -0,0 +1,193 @@ +type SVGPreviewProps = { + color: string; + logo: string; + name: string; + ens?: string; + css?: string; + size: string; +}; + +/** + * SVGPreview renders the NFA image based in the provided props. + */ +export const SVGPreview: React.FC = ({ + color, + logo, + name, + ens = '', + css = '', + size, +}) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + {name} + + + {ens} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/ui/src/views/mint/nft-minted.tsx b/ui/src/views/mint/nft-minted.tsx new file mode 100644 index 0000000..f2e3c2f --- /dev/null +++ b/ui/src/views/mint/nft-minted.tsx @@ -0,0 +1,22 @@ +import { Icon } from '@/components'; +import { NftCard } from './nft-card'; + +export const NftMinted = () => { + return ( + + } + message="You have successfully minted your NFA." + buttonText="Tweet about your NFA!" + onClick={() => { + alert('TODO: Tweet about your NFA!'); + }} + leftIconButton={} + /> + ); +}; diff --git a/ui/src/views/mint/preview-step/indext.ts b/ui/src/views/mint/preview-step/indext.ts new file mode 100644 index 0000000..e7f46ac --- /dev/null +++ b/ui/src/views/mint/preview-step/indext.ts @@ -0,0 +1 @@ +export * from './mint-preview'; diff --git a/ui/src/views/mint/preview-step/mint-preview.tsx b/ui/src/views/mint/preview-step/mint-preview.tsx new file mode 100644 index 0000000..31fc467 --- /dev/null +++ b/ui/src/views/mint/preview-step/mint-preview.tsx @@ -0,0 +1,39 @@ +import { Icon, IconButton, Stepper } from '@/components'; +import { Mint } from '@/views/mint/mint.context'; +import { NftCard } from '../nft-card'; + +export const MintPreview = () => { + const { prevStep } = Stepper.useContext(); + const { setSucessMint } = Mint.useContext(); + + //TODO handle error when minting + + return ( + } + css={{ mr: '$2' }} + onClick={prevStep} + /> + } + rightIcon={ + } + /> + } + message="Minting this NFA will cost 0.0008 MATIC." + buttonText="Mint NFA" + onClick={() => { + setSucessMint(true); + }} + /> + ); +}; diff --git a/ui/src/views/mint/wallet-step/index.ts b/ui/src/views/mint/wallet-step/index.ts new file mode 100644 index 0000000..ec11e07 --- /dev/null +++ b/ui/src/views/mint/wallet-step/index.ts @@ -0,0 +1 @@ +export * from './wallet-step'; diff --git a/ui/src/views/mint/wallet-step/wallet-step.tsx b/ui/src/views/mint/wallet-step/wallet-step.tsx new file mode 100644 index 0000000..ce9746f --- /dev/null +++ b/ui/src/views/mint/wallet-step/wallet-step.tsx @@ -0,0 +1,39 @@ +import { Button, Card, Grid, Icon, Stepper } from '@/components'; +import { MintCardHeader } from '../mint-card'; + +export const WalletStep = () => { + const { prevStep, nextStep } = Stepper.useContext(); + return ( + + + + + + + Connect with the wallet you want to mint & own the NFA. + + + + + ); +}; diff --git a/ui/tailwind.config.js b/ui/tailwind.config.js index 1297dba..904edc7 100644 --- a/ui/tailwind.config.js +++ b/ui/tailwind.config.js @@ -11,8 +11,8 @@ module.exports = { slate11: 'rgba(155, 161, 166, 1)', slate12: 'rgba(236, 237, 238, 1)', }, - width: { - inherit: 'inherit', + borderRadius: { + xhl: '1.25rem', }, }, },