From 88aa8e8d1451c9482cc81b0e883360851f43d1ad Mon Sep 17 00:00:00 2001 From: Kapil Date: Mon, 1 Apr 2024 08:49:02 +0530 Subject: [PATCH 001/280] IXSPD1-1036 LBP form UI have been updated still missing some parts --- src/assets/images/Browse.svg | 4 + src/components/CollectionForm/styled.ts | 2 +- src/components/FilePreview/ImagePreview.tsx | 40 ++++ src/components/FilePreview/styleds.tsx | 1 + src/components/Header/HeaderLinks.tsx | 80 ++++--- src/components/Input/index.ts | 2 +- src/pages/AppRoutes.tsx | 4 + src/pages/KYC/common.tsx | 172 ++++++++++++- src/pages/LBP/LbpForm.tsx | 62 +++++ src/pages/LBP/components/Approvals.tsx | 9 + src/pages/LBP/components/Branding.tsx | 55 +++++ src/pages/LBP/components/ProgressBar.tsx | 9 + src/pages/LBP/components/ProjectInfo.tsx | 151 ++++++++++++ src/pages/LBP/components/Tokenomics.tsx | 252 ++++++++++++++++++++ src/utils/routes.ts | 1 + 15 files changed, 801 insertions(+), 43 deletions(-) create mode 100644 src/assets/images/Browse.svg create mode 100644 src/components/FilePreview/ImagePreview.tsx create mode 100644 src/pages/LBP/LbpForm.tsx create mode 100644 src/pages/LBP/components/Approvals.tsx create mode 100644 src/pages/LBP/components/Branding.tsx create mode 100644 src/pages/LBP/components/ProgressBar.tsx create mode 100644 src/pages/LBP/components/ProjectInfo.tsx create mode 100644 src/pages/LBP/components/Tokenomics.tsx diff --git a/src/assets/images/Browse.svg b/src/assets/images/Browse.svg new file mode 100644 index 0000000000..56c2755c39 --- /dev/null +++ b/src/assets/images/Browse.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/CollectionForm/styled.ts b/src/components/CollectionForm/styled.ts index b0d6235335..17754799cd 100644 --- a/src/components/CollectionForm/styled.ts +++ b/src/components/CollectionForm/styled.ts @@ -74,7 +74,7 @@ export const StyledInput = styled(Input)` height: 60px; ` export const StyledTextarea = styled(Textarea)` - ${inputStyles} + margin-bottom: 0; ` export const Row = styled.div` diff --git a/src/components/FilePreview/ImagePreview.tsx b/src/components/FilePreview/ImagePreview.tsx new file mode 100644 index 0000000000..22212c6e82 --- /dev/null +++ b/src/components/FilePreview/ImagePreview.tsx @@ -0,0 +1,40 @@ +import React, { CSSProperties, FC } from 'react'; +import { FileWithPath } from 'react-dropzone'; +import { ButtonText } from 'components/Button'; +import { ReactComponent as TrashNoBorder } from 'assets/images/TrashNoBorder.svg'; +import { Wrapper } from './styleds'; + +interface Props { + file: FileWithPath; + handleDeleteClick: () => void; + style?: CSSProperties; + withBackground?: boolean; + isDisabled?: boolean; + index: number; +} + +export const ImagePreview: FC = ({ + file, + style, + handleDeleteClick, + withBackground = true, + isDisabled = false, + }: Props) => { + return ( + + Preview + {!isDisabled && ( + + { + event.preventDefault(); + handleDeleteClick(); + }} + /> + + )} + + ); +}; + + diff --git a/src/components/FilePreview/styleds.tsx b/src/components/FilePreview/styleds.tsx index e529260fef..7d7f1082ff 100644 --- a/src/components/FilePreview/styleds.tsx +++ b/src/components/FilePreview/styleds.tsx @@ -10,6 +10,7 @@ export const Wrapper = styled(Flex)<{ withBackground: boolean }>` border: 1px solid #e6e6ff; // background-color: ${({ theme, withBackground }) => (withBackground ? theme.bg1 : 'none')}; width: 100%; + position: relative; ` export const StyledPdfImage = styled(PdfImage)` diff --git a/src/components/Header/HeaderLinks.tsx b/src/components/Header/HeaderLinks.tsx index 1f15af37fa..c0b42c642f 100644 --- a/src/components/Header/HeaderLinks.tsx +++ b/src/components/Header/HeaderLinks.tsx @@ -132,40 +132,40 @@ export const HeaderLinks = () => { return ( {/* {isAllowed('/charts') && account && isWhitelisted && ( */} - - Charts - + + Charts + {/* )} */} Launchpad {/* {isAllowed(routes.securityTokens()) && account && chainId && chains.includes(chainId) && isWhitelisted && ( */} - { - return pathname.includes('security-token') - }} - > - Security Tokens - + { + return pathname.includes('security-token') + }} + > + Security Tokens + {/* )} */} {/* {isAllowed('/pool') && account && chainId && chains.includes(chainId) && isWhitelisted && ( */} - - Liquidity Pools - + + Liquidity Pools + {/* )} */} {/* {isAllowed('/swap') && account && chainId && chains.includes(chainId) && isWhitelisted && ( */} - - Swap/Trade - + + Swap/Trade + {/* )} */} {/* {account && chainId && chains.includes(chainId) && isWhitelisted && ( @@ -195,19 +195,19 @@ export const HeaderLinks = () => { )} */} {/* {isAllowed(routes.vesting) && isAllowed(routes.staking) && account && chainId && ( */} - pathname.startsWith('/vesting') || pathname.startsWith('/staking')} - > - } placement={'bottom-start'}> - - Farming - - - - + pathname.startsWith('/vesting') || pathname.startsWith('/staking')} + > + } placement={'bottom-start'}> + + Farming + + + + {/* )} */} {isAllowed(routes.faucet) && account && chainId && chainId === SupportedChainId.KOVAN && isWhitelisted && ( @@ -216,10 +216,14 @@ export const HeaderLinks = () => { )} - {showIssuance && Issuance Dashboard} + {showIssuance && Issuance} {isAdmin && account && chainId && chains.includes(chainId) && isWhitelisted && ( Admin )} + + + LBP + ) } diff --git a/src/components/Input/index.ts b/src/components/Input/index.ts index a6521c655e..2796e86758 100644 --- a/src/components/Input/index.ts +++ b/src/components/Input/index.ts @@ -89,7 +89,7 @@ export const Textarea = styled.textarea` font-weight: 300; font-size: 16px; border-radius: 6px; - border: 1px solid #e6e6ff; + border: 1px solid #E6E6FF; width: 100%; &::-webkit-outer-spin-button, diff --git a/src/pages/AppRoutes.tsx b/src/pages/AppRoutes.tsx index d7f50008bc..786fb8048c 100644 --- a/src/pages/AppRoutes.tsx +++ b/src/pages/AppRoutes.tsx @@ -19,6 +19,7 @@ import AdminSecurityCatalog from 'components/AdminSecurityCatalog' import AdminTransactionsTable from 'components/AdminTransactionsTable' import { AdminKycTable } from 'components/AdminKyc' import { KycReviewModal } from 'components/KycReviewModal' +import LBPForm from './LBP/LbpForm' const Admin = lazy(() => import('pages/Admin')) const Swap = lazy(() => import('pages/Swap')) @@ -199,4 +200,7 @@ export const routeConfigs: RouteMapEntry[] = [ ...onlyOfferManager, }, { path: routes.manageOffer, component: ManageOffer, ...onlyOfferManager }, + + /* LBP routes */ + { path: routes.LBP, component: LBPForm }, ] diff --git a/src/pages/KYC/common.tsx b/src/pages/KYC/common.tsx index 4c60e7bf3b..260ff32c55 100644 --- a/src/pages/KYC/common.tsx +++ b/src/pages/KYC/common.tsx @@ -6,7 +6,7 @@ import { FileWithPath } from 'react-dropzone' import { Input, Textarea } from 'components/Input' import { ButtonGradient, ButtonOutlined, PinnedContentButton } from 'components/Button' -import { TYPE, EllipsisText, MEDIA_WIDTHS } from 'theme' +import { TYPE, EllipsisText, MEDIA_WIDTHS, LinkStyledButton } from 'theme' import { Label } from 'components/Label' import Upload from 'components/Upload' import { FilePreview } from 'components/FilePreview' @@ -15,6 +15,7 @@ import { Select as ReactSelect } from 'components/Select' import { AcceptFiles } from 'components/Upload/types' import { ReactComponent as UploadLogo } from 'assets/images/NewDownloads.svg' +import { ReactComponent as UploadLogoLbp } from 'assets/images/Browse.svg' import { ReactComponent as InfoLogo } from 'assets/images/info-filled.svg' import { ReactComponent as CrossIcon } from 'assets/images/cross.svg' @@ -24,11 +25,13 @@ import { ReactComponent as ThreeIcon } from 'assets/images/three .svg' import { ReactComponent as InvalidFormInputIcon } from 'assets/svg/invalid-form-input-icon.svg' import { Text } from 'rebass' -import { UploaderCard, FormGrid, BeneficialOwnersTableContainer } from './styleds' -import Row from 'components/Row' +import { UploaderCard, FormGrid, BeneficialOwnersTableContainer, ExtraInfoCardCountry } from './styleds' +import Row, { RowCenter } from 'components/Row' import SelfieImage from 'assets/images/selfie.svg' import { alignItems } from 'styled-system' import { isMobile } from 'react-device-detect' +import { ImagePreview } from 'components/FilePreview/ImagePreview' +import { Plus } from 'react-feather' export interface UploaderProps { files: FileWithPath[] @@ -505,6 +508,155 @@ interface ChooseFileTypes { id?: any } +export const UploaderLBP: FC = ({ + id, + title, + subtitle, + files, + required, + error, + handleDeleteClick, + onDrop, + optional = false, + tooltipText, + isDisabled = false, +}: UploaderProps) => { + return ( + + + + {subtitle && {subtitle}} + {files && files.length > 0 ? ( + + {files.map((file: any, index) => ( + { + handleDeleteClick(index) + }} + isDisabled={isDisabled} + style={{ marginRight: index !== files.length - 1 ? 0 : 0 }} + index={0} + /> + ))} + + ) : ( + + + + + + Share Logo + + + PNG, JPG, and SVG files only. + + + Browse + + + + + )} + + {error && ( + + {error} + + )} + + ) +} + +export const UploaderDocs: FC = ({ + id, + title, + subtitle, + files, + required, + error, + handleDeleteClick, + onDrop, + optional = false, + tooltipText, + isDisabled = false, +}: UploaderProps) => { + return ( + + + + {subtitle && {subtitle}} + {files && files.length > 0 && ( + + {files.map((file: any, index) => ( + { + handleDeleteClick(index) + }} + isDisabled={isDisabled} + // style={{ marginRight: index !== files.length - 1 ? 0 : 0 }} + /> + ))} + + )} + {!isDisabled && ( + + + + + + + Add Documents + + + + + + )} + + {error && ( + + {error} + + )} + + ) +} + export const ChooseFile = ({ label, file, onDrop, error, handleDeleteClick, id }: ChooseFileTypes) => { return ( @@ -621,6 +773,17 @@ const StyledUploadLogo = styled(UploadLogo)` `} ` +const StyledUploadLogoLbp = styled(UploadLogoLbp)` + ${({ theme }) => + theme.config.elements?.main && + css` + path { + stroke: ${theme.config.elements?.main}; + fill: none; + } + `} +` + const StyledDescription = styled(TYPE.description3)` color: ${({ theme: { text2 } }) => `${text2}50`}; ul { @@ -757,3 +920,6 @@ export const SelfieUploaderCard = styled.div` height: 720px; } ` +const LinkButton = styled(LinkStyledButton)` + color: #6666ff; +` diff --git a/src/pages/LBP/LbpForm.tsx b/src/pages/LBP/LbpForm.tsx new file mode 100644 index 0000000000..ae64d764fc --- /dev/null +++ b/src/pages/LBP/LbpForm.tsx @@ -0,0 +1,62 @@ +import react from 'react' +import { Trans } from '@lingui/macro' +import Column from 'components/Column' +import { RowStart } from 'components/Row' +import { FormContainer, FormRow } from 'pages/KYC/IndividualKycForm' +import { FormCard, FormGrid } from 'pages/KYC/styleds' +import { isMobile } from 'react-device-detect' +import { TYPE } from 'theme' +import Branding from './components/Branding' +import ProjectInfo from './components/ProjectInfo' +import Tokenomics from './components/Tokenomics' + +export default function LBPForm() { + return ( + + + + Serenity + + + + + + Branding + + + + + + + + + + + Project information + + + + + + + + + + + Tokenomics + + + + + + + + + + ) +} diff --git a/src/pages/LBP/components/Approvals.tsx b/src/pages/LBP/components/Approvals.tsx new file mode 100644 index 0000000000..99246b2e61 --- /dev/null +++ b/src/pages/LBP/components/Approvals.tsx @@ -0,0 +1,9 @@ +import react from 'react' + +export default function Approvals() { + return ( + <> + <>a + + ) +} diff --git a/src/pages/LBP/components/Branding.tsx b/src/pages/LBP/components/Branding.tsx new file mode 100644 index 0000000000..d4860c5953 --- /dev/null +++ b/src/pages/LBP/components/Branding.tsx @@ -0,0 +1,55 @@ +import { MAX_FILE_UPLOAD_SIZE, MAX_FILE_UPLOAD_SIZE_ERROR } from 'constants/constants'; +import { UploaderLBP } from 'pages/KYC/common'; +import { FormGrid } from 'pages/KYC/styleds'; +import React, { useState } from 'react'; +import { useShowError } from 'state/application/hooks'; + +export default function Branding() { + const [values, setValues] = useState({ + LBPLogo: null, + LBPBanner: null + }); + const showError = useShowError(); + + const handleDropImage = (acceptedFile: any, key: string) => { + const file = acceptedFile; + if (file?.size > MAX_FILE_UPLOAD_SIZE) { + showError(MAX_FILE_UPLOAD_SIZE_ERROR); + } else if (values[key]) { + showError("You can only upload one image at a time."); + } else { + setValues({ ...values, [key]: file }); + } + }; + + const handleImageDelete = (key: string) => { + setValues({ ...values, [key]: null }); + }; + + return ( + <> + + { + handleDropImage(file, 'LBPLogo'); + }} + handleDeleteClick={() => { + handleImageDelete('LBPLogo'); + }} + /> + { + handleDropImage(file, 'LBPBanner'); + }} + handleDeleteClick={() => { + handleImageDelete('LBPBanner'); + }} + /> + + + ); +} diff --git a/src/pages/LBP/components/ProgressBar.tsx b/src/pages/LBP/components/ProgressBar.tsx new file mode 100644 index 0000000000..48c578a08f --- /dev/null +++ b/src/pages/LBP/components/ProgressBar.tsx @@ -0,0 +1,9 @@ +import react from 'react' + +export default function ProgressBar() { + return ( + <> + <>a + + ) +} diff --git a/src/pages/LBP/components/ProjectInfo.tsx b/src/pages/LBP/components/ProjectInfo.tsx new file mode 100644 index 0000000000..de2d6352ea --- /dev/null +++ b/src/pages/LBP/components/ProjectInfo.tsx @@ -0,0 +1,151 @@ +import React, { useState, ChangeEvent } from 'react' +import { Box, Flex } from 'rebass' +import { Trans } from '@lingui/macro' +import { Label } from '@rebass/forms' +import { StyledTextarea } from 'components/CollectionForm/styled' +import { TextInput, Uploader, UploaderDocs } from 'pages/KYC/common' +import { LinkStyledButton, TYPE } from 'theme' +import { RowCenter } from 'components/Row' +import { ExtraInfoCardCountry } from 'pages/KYC/styleds' +import { Plus } from 'react-feather' +import styled from 'styled-components' +import { IconButton } from '@material-ui/core' +import { ReactComponent as TrashIcon } from 'assets/images/newDelete.svg' +import { useShowError } from 'state/application/hooks' +import { MAX_FILE_UPLOAD_SIZE } from 'constants/constants' + +// Reusable form array component +const FormArray = ({ label, items, addItem, removeItem, handleChange }: any) => { + return ( + <> + + {items.map((item: string, index: number) => ( + + + ) => handleChange(e.target.value, index)} + style={{ width: '100%' }} + /> + + removeItem(index)} style={{ padding: '0 1rem' }}> + + + + ))} + + + + + Add {label} + + + + + ) +} + +export default function ProjectInfo() { + const [socialLinks, setSocialLinks] = useState(['']) + const [whitepapers, setWhitepapers] = useState(['']) + const [values, setValues] = useState({ + uploadDocs: [], + }) + + const handleDropImage = (acceptedFiles: any, key: string) => { + const files = Array.isArray(acceptedFiles) ? acceptedFiles : [acceptedFiles] + + const filteredFiles = files.filter((file: any) => file.size <= MAX_FILE_UPLOAD_SIZE) + + setValues({ ...values, [key]: [...values[key], ...filteredFiles] }) + } + + const handleImageDelete = (index: number, key: string) => { + const updatedFiles = values[key].filter((_: any, i: number) => i !== index) + setValues({ ...values, [key]: updatedFiles }) + } + + const handleAddItem = (setter: Function) => { + setter((prevItems: string[]) => [...prevItems, '']) + } + + const handleRemoveItem = (index: number, setter: Function) => { + setter((prevItems: string[]) => prevItems.filter((_, i: number) => i !== index)) + } + + const handleChangeItem = (value: string, index: number, setter: Function) => { + setter((prevItems: string[]) => { + const updatedItems = [...prevItems] + updatedItems[index] = value + return updatedItems + }) + } + + return ( + <> + + + + + + + + {/* Social Links */} + handleAddItem(setSocialLinks)} + removeItem={(index: number) => handleRemoveItem(index, setSocialLinks)} + handleChange={(value: string, index: number) => handleChangeItem(value, index, setSocialLinks)} + /> + + {/* Whitepapers */} + handleAddItem(setWhitepapers)} + removeItem={(index: number) => handleRemoveItem(index, setWhitepapers)} + handleChange={(value: string, index: number) => handleChangeItem(value, index, setWhitepapers)} + /> + + + { + handleDropImage(acceptedFiles, 'uploadDocs') + }} + handleDeleteClick={(index: number) => { + handleImageDelete(index, 'uploadDocs') + }} + /> + + ) +} + +const LinkButton = styled(LinkStyledButton)` + color: #6666ff; +` diff --git a/src/pages/LBP/components/Tokenomics.tsx b/src/pages/LBP/components/Tokenomics.tsx new file mode 100644 index 0000000000..7f08fc672a --- /dev/null +++ b/src/pages/LBP/components/Tokenomics.tsx @@ -0,0 +1,252 @@ +import React, { useState } from 'react'; +import styled from 'styled-components'; +import { Trans } from '@lingui/macro'; +import { TextInput } from 'pages/KYC/common'; +import { TYPE } from 'theme'; +import { RowStart } from 'components/Row'; +import { Line } from 'components/Line'; +import { DateInput } from 'components/DateInput'; // Import the DateInput component +import dayjs from 'dayjs'; +import Stack from '@mui/material/Stack'; +import Slider from '@mui/material/Slider'; +import { FormGrid } from 'pages/KYC/styleds'; + +const TokenomicsContainer = styled.div` + width: 100%; + display: flex; + justify-content: space-between; + border: 1px solid #e6e6ff; + background: #f7f7fa; + padding: 12px 18px; + margin-bottom: 10px; +`; + +const TokenomicsItem = styled.div` + margin-bottom: 8px; +`; + +const Select = styled.select` + flex: 1; + display: block; + border: none; + padding: 8px; + margin-right: 8px; +`; + +const Option = styled.option` + padding: 8px; +`; + +const Span = styled.span` + color: #8f8fb2; + font-size: 12px; + padding: 8px; + text-align: center; + border: 1px solid #e6e6ff; + background: #ffffff; + border-radius: 6px; + width: fit-content; + margin: 0 auto; +`; + +const Input = styled.input` + border: none; + padding: 8px; + text-align: right; + background: none; + font-size: 32px; + font-weight: 700; + color: #292933; + max-width: 200px; + width: calc(100% - 48px); + margin-bottom: 10px; + &::placeholder { + font-size: 32px; + color: #bdbddb; + font-weight: 700; + } +`; + +const MaxWrapper = styled.div` + text-align: center; +`; + +const WeightsContainer = styled.div` + width: 100%; + display: flex; + justify-content: space-between; + padding: 12px 18px; + margin-bottom: 10px; +`; +const SpanBal = styled.span` + display: block; + color: #8f8fb2; + font-size: 12px; + padding: 8px; + margin-top: 8px; +` +const Tokenomics = () => { + const [valueStart, setStartValue] = useState(30); + const [valueEnd, setEndValue] = useState(30); + const [valueStartDate, setStartDate] = useState(''); + const [valueEndDate, setEndDate] = useState(''); + + const handleChangeStart = (event: Event, newValue: number | number[]) => { + setStartValue(newValue as number); + }; + + const handleChangeEnd = (event: Event, newValue: number | number[]) => { + setEndValue(newValue as number); + }; + + const handleStartDateChange = (date: Date | null) => { + if (date) { + const newStartDate = dayjs(date).local().format('YYYY-MM-DD'); + setStartDate(newStartDate); + } + }; + + const handleEndDateChange = (date: Date | null) => { + if (date) { + const newEndDate = dayjs(date).local().format('YYYY-MM-DD'); + setEndDate(newEndDate); + } + }; + + return ( + <> + + + + Configure Quantities + + + <> + Share + + + + + Balance: 4,000.00 + + + + + + Max + + + + + + <> + Asset + + + + + Balance: 4,000.00 + + + + + + Max + + + + + + + + + + + Configure Weights + + + <> + Start Weight + + + + + + + Max + + {/* */} + + +
+ + + +
+ + <> + End Weight + + + + + + + Max + + + + +
+ + + +
+ + + + Configure Duration + + + + + + + + + ); +}; + +export default Tokenomics; diff --git a/src/utils/routes.ts b/src/utils/routes.ts index c0cf05fd92..7c4c5921b9 100644 --- a/src/utils/routes.ts +++ b/src/utils/routes.ts @@ -47,6 +47,7 @@ export const routes = { issuanceReport: `/issuance/extract/:issuanceId`, manageOffer: `/issuance/manage/:issuanceId`, newAdmin: '/admin/accreditation', + LBP: '/lbp', //admin urls From 2088a165ff95e1b18fecb52557904f4ed4387bb6 Mon Sep 17 00:00:00 2001 From: Kapil Date: Mon, 1 Apr 2024 13:27:09 +0530 Subject: [PATCH 002/280] IXSPD1-1036 LBP form UI have been updated still missing some parts --- src/pages/LBP/LbpForm.tsx | 41 ++++++++----- src/pages/LBP/components/Approvals.tsx | 10 +++- src/pages/LBP/components/Tokenomics.tsx | 79 +++++++++++++------------ 3 files changed, 76 insertions(+), 54 deletions(-) diff --git a/src/pages/LBP/LbpForm.tsx b/src/pages/LBP/LbpForm.tsx index ae64d764fc..5b154ec397 100644 --- a/src/pages/LBP/LbpForm.tsx +++ b/src/pages/LBP/LbpForm.tsx @@ -9,20 +9,22 @@ import { TYPE } from 'theme' import Branding from './components/Branding' import ProjectInfo from './components/ProjectInfo' import Tokenomics from './components/Tokenomics' +import Approvals from './components/Approvals' export default function LBPForm() { return ( - - - - Serenity - - + + + + + Serenity + + @@ -52,11 +54,22 @@ export default function LBPForm() { - + + + + + + + + Approvals + + + + - - + + ) } diff --git a/src/pages/LBP/components/Approvals.tsx b/src/pages/LBP/components/Approvals.tsx index 99246b2e61..14f8107c20 100644 --- a/src/pages/LBP/components/Approvals.tsx +++ b/src/pages/LBP/components/Approvals.tsx @@ -1,9 +1,13 @@ +import { FormGrid } from 'pages/KYC/styleds' import react from 'react' export default function Approvals() { return ( - <> - <>a - +
+ +
+
+
+
) } diff --git a/src/pages/LBP/components/Tokenomics.tsx b/src/pages/LBP/components/Tokenomics.tsx index 7f08fc672a..3147bf6aa3 100644 --- a/src/pages/LBP/components/Tokenomics.tsx +++ b/src/pages/LBP/components/Tokenomics.tsx @@ -1,15 +1,15 @@ -import React, { useState } from 'react'; -import styled from 'styled-components'; -import { Trans } from '@lingui/macro'; -import { TextInput } from 'pages/KYC/common'; -import { TYPE } from 'theme'; -import { RowStart } from 'components/Row'; -import { Line } from 'components/Line'; -import { DateInput } from 'components/DateInput'; // Import the DateInput component -import dayjs from 'dayjs'; -import Stack from '@mui/material/Stack'; -import Slider from '@mui/material/Slider'; -import { FormGrid } from 'pages/KYC/styleds'; +import React, { useState } from 'react' +import styled from 'styled-components' +import { Trans } from '@lingui/macro' +import { TextInput } from 'pages/KYC/common' +import { TYPE } from 'theme' +import { RowStart } from 'components/Row' +import { Line } from 'components/Line' +import { DateInput } from 'components/DateInput' // Import the DateInput component +import dayjs from 'dayjs' +import Stack from '@mui/material/Stack' +import Slider from '@mui/material/Slider' +import { FormGrid } from 'pages/KYC/styleds' const TokenomicsContainer = styled.div` width: 100%; @@ -19,11 +19,11 @@ const TokenomicsContainer = styled.div` background: #f7f7fa; padding: 12px 18px; margin-bottom: 10px; -`; +` const TokenomicsItem = styled.div` margin-bottom: 8px; -`; +` const Select = styled.select` flex: 1; @@ -31,11 +31,11 @@ const Select = styled.select` border: none; padding: 8px; margin-right: 8px; -`; +` const Option = styled.option` padding: 8px; -`; +` const Span = styled.span` color: #8f8fb2; @@ -47,7 +47,7 @@ const Span = styled.span` border-radius: 6px; width: fit-content; margin: 0 auto; -`; +` const Input = styled.input` border: none; @@ -65,11 +65,11 @@ const Input = styled.input` color: #bdbddb; font-weight: 700; } -`; +` const MaxWrapper = styled.div` text-align: center; -`; +` const WeightsContainer = styled.div` width: 100%; @@ -77,7 +77,7 @@ const WeightsContainer = styled.div` justify-content: space-between; padding: 12px 18px; margin-bottom: 10px; -`; +` const SpanBal = styled.span` display: block; color: #8f8fb2; @@ -86,32 +86,32 @@ const SpanBal = styled.span` margin-top: 8px; ` const Tokenomics = () => { - const [valueStart, setStartValue] = useState(30); - const [valueEnd, setEndValue] = useState(30); - const [valueStartDate, setStartDate] = useState(''); - const [valueEndDate, setEndDate] = useState(''); + const [valueStart, setStartValue] = useState(30) + const [valueEnd, setEndValue] = useState(30) + const [valueStartDate, setStartDate] = useState('') + const [valueEndDate, setEndDate] = useState('') const handleChangeStart = (event: Event, newValue: number | number[]) => { - setStartValue(newValue as number); - }; + setStartValue(newValue as number) + } const handleChangeEnd = (event: Event, newValue: number | number[]) => { - setEndValue(newValue as number); - }; + setEndValue(newValue as number) + } const handleStartDateChange = (date: Date | null) => { if (date) { - const newStartDate = dayjs(date).local().format('YYYY-MM-DD'); - setStartDate(newStartDate); + const newStartDate = dayjs(date).local().format('YYYY-MM-DD') + setStartDate(newStartDate) } - }; + } const handleEndDateChange = (date: Date | null) => { if (date) { - const newEndDate = dayjs(date).local().format('YYYY-MM-DD'); - setEndDate(newEndDate); + const newEndDate = dayjs(date).local().format('YYYY-MM-DD') + setEndDate(newEndDate) } - }; + } return ( <> @@ -245,8 +245,13 @@ const Tokenomics = () => { minDate={new Date()} /> + + + + + - ); -}; + ) +} -export default Tokenomics; +export default Tokenomics From ac72e09ebcf0768486fcbb7c66e28c0d4a8dd4c2 Mon Sep 17 00:00:00 2001 From: Kapil Date: Tue, 2 Apr 2024 09:48:54 +0530 Subject: [PATCH 003/280] IXSPD1-1036 LBP form UI have been updated and values logs and validation fixes some of componenets still missing some parts --- src/pages/KYC/KYCProgressBar.tsx | 2 +- src/pages/KYC/common.tsx | 5 +- src/pages/LBP/LbpForm.tsx | 111 ++++++++++++++++++----- src/pages/LBP/components/Approvals.tsx | 8 +- src/pages/LBP/components/Branding.tsx | 58 +++++++----- src/pages/LBP/components/ProjectInfo.tsx | 63 +++++++++++-- 6 files changed, 191 insertions(+), 56 deletions(-) diff --git a/src/pages/KYC/KYCProgressBar.tsx b/src/pages/KYC/KYCProgressBar.tsx index e9b9caf625..c89abc5bb8 100644 --- a/src/pages/KYC/KYCProgressBar.tsx +++ b/src/pages/KYC/KYCProgressBar.tsx @@ -11,7 +11,7 @@ import { Box } from 'rebass' interface KYCProgressTopic { title: string href: string - passed: boolean + passed?: boolean failed?: boolean } diff --git a/src/pages/KYC/common.tsx b/src/pages/KYC/common.tsx index 260ff32c55..9a9868c4ef 100644 --- a/src/pages/KYC/common.tsx +++ b/src/pages/KYC/common.tsx @@ -1,4 +1,4 @@ -import React, { CSSProperties, FC, HTMLProps } from 'react' +import React, { CSSProperties, ChangeEvent, FC, HTMLProps } from 'react' import { Box, Flex } from 'rebass' import styled, { css } from 'styled-components' import { t, Trans } from '@lingui/macro' @@ -45,6 +45,9 @@ export interface UploaderProps { tooltipText?: string | JSX.Element isDisabled?: boolean id?: any + name?: string; + onChange?: (e: ChangeEvent) => void; + } interface SelectProps { diff --git a/src/pages/LBP/LbpForm.tsx b/src/pages/LBP/LbpForm.tsx index 5b154ec397..8b27a6c78c 100644 --- a/src/pages/LBP/LbpForm.tsx +++ b/src/pages/LBP/LbpForm.tsx @@ -1,53 +1,86 @@ -import react from 'react' +import React, { useState } from 'react' import { Trans } from '@lingui/macro' import Column from 'components/Column' import { RowStart } from 'components/Row' import { FormContainer, FormRow } from 'pages/KYC/IndividualKycForm' -import { FormCard, FormGrid } from 'pages/KYC/styleds' +import { FormCard, StyledStickyBox } from 'pages/KYC/styleds' import { isMobile } from 'react-device-detect' import { TYPE } from 'theme' import Branding from './components/Branding' import ProjectInfo from './components/ProjectInfo' import Tokenomics from './components/Tokenomics' import Approvals from './components/Approvals' +import { KYCProgressBar } from 'pages/KYC/KYCProgressBar' +import { Card } from 'rebass' export default function LBPForm() { + const [formData, setFormData] = useState({ + branding: {}, + projectInfo: {}, + }) + const [canSubmit, setCanSubmit] = useState(false) + + const handleBrandingChange = (brandingData: any) => { + setFormData((prevData) => ({ ...prevData, branding: brandingData })) + updateSubmitButtonState({ ...formData, branding: brandingData, projectInfo: formData.projectInfo }) + } + + const handleProjectInfoChange = (projectInfoData: any) => { + setFormData((prevData) => ({ ...prevData, projectInfo: projectInfoData })) + updateSubmitButtonState({ ...formData, branding: formData.branding, projectInfo: projectInfoData }) + } + + const updateSubmitButtonState = (formData: any) => { + const brandingComplete = !!formData.branding.LBPLogo && !!formData.branding.LBPBanner + const projectInfoComplete = + !!formData.projectInfo.title && + !!formData.projectInfo.description && + !!formData.projectInfo.website && + !!formData.projectInfo.socialLinks && + !!formData.projectInfo.whitepapers && + !!formData.projectInfo.uploadDocs + setCanSubmit(brandingComplete && projectInfoComplete) + } + + const handleSubmit = () => { + console.log(formData) + } + return ( - - - - Serenity - - - + + + Serenity + + + Branding - + - + Project information - + - + Tokenomics @@ -58,18 +91,50 @@ export default function LBPForm() { - + Approvals - + {/* - + */} - - + + +
+ + + + + +
+
+
) } diff --git a/src/pages/LBP/components/Approvals.tsx b/src/pages/LBP/components/Approvals.tsx index 14f8107c20..ed7c4c946f 100644 --- a/src/pages/LBP/components/Approvals.tsx +++ b/src/pages/LBP/components/Approvals.tsx @@ -4,10 +4,10 @@ import react from 'react' export default function Approvals() { return (
- -
-
-
+
+
+
+
) } diff --git a/src/pages/LBP/components/Branding.tsx b/src/pages/LBP/components/Branding.tsx index d4860c5953..677678847d 100644 --- a/src/pages/LBP/components/Branding.tsx +++ b/src/pages/LBP/components/Branding.tsx @@ -1,55 +1,71 @@ -import { MAX_FILE_UPLOAD_SIZE, MAX_FILE_UPLOAD_SIZE_ERROR } from 'constants/constants'; -import { UploaderLBP } from 'pages/KYC/common'; -import { FormGrid } from 'pages/KYC/styleds'; -import React, { useState } from 'react'; -import { useShowError } from 'state/application/hooks'; +import React, { ChangeEvent, useState } from 'react' +import { useShowError } from 'state/application/hooks' +import { MAX_FILE_UPLOAD_SIZE, MAX_FILE_UPLOAD_SIZE_ERROR } from 'constants/constants' +import { UploaderLBP } from 'pages/KYC/common' +import { FormGrid } from 'pages/KYC/styleds' -export default function Branding() { +interface BrandingProps { + onChange: (data: any) => void +} + +export default function Branding({ onChange }: BrandingProps) { const [values, setValues] = useState({ LBPLogo: null, - LBPBanner: null - }); - const showError = useShowError(); + LBPBanner: null, + }) + const showError = useShowError() const handleDropImage = (acceptedFile: any, key: string) => { - const file = acceptedFile; + const file = acceptedFile if (file?.size > MAX_FILE_UPLOAD_SIZE) { - showError(MAX_FILE_UPLOAD_SIZE_ERROR); + showError(MAX_FILE_UPLOAD_SIZE_ERROR) } else if (values[key]) { - showError("You can only upload one image at a time."); + showError('You can only upload one image at a time.') } else { - setValues({ ...values, [key]: file }); + setValues((prevValues: any) => ({ ...prevValues, [key]: file })) + onChange({ ...values, [key]: file }) } - }; + } const handleImageDelete = (key: string) => { - setValues({ ...values, [key]: null }); - }; + setValues((prevValues: any) => ({ ...prevValues, [key]: null })) + onChange({ ...values, [key]: null }) + } + + const handleInputChange = (e: ChangeEvent, name: string) => { + const { value } = e.target + setValues((prevValues: any) => ({ ...prevValues, [name]: value })) + onChange({ ...values, [name]: value }) + } return ( <> handleInputChange(e, 'LBPLogo')} title="" files={values.LBPLogo ? [values.LBPLogo] : []} onDrop={(file) => { - handleDropImage(file, 'LBPLogo'); + handleDropImage(file, 'LBPLogo') }} handleDeleteClick={() => { - handleImageDelete('LBPLogo'); + handleImageDelete('LBPLogo') }} /> handleInputChange(e, 'LBPBanner')} title="" files={values.LBPBanner ? [values.LBPBanner] : []} onDrop={(file) => { - handleDropImage(file, 'LBPBanner'); + handleDropImage(file, 'LBPBanner') }} handleDeleteClick={() => { - handleImageDelete('LBPBanner'); + handleImageDelete('LBPBanner') }} /> - ); + ) } diff --git a/src/pages/LBP/components/ProjectInfo.tsx b/src/pages/LBP/components/ProjectInfo.tsx index de2d6352ea..793313de19 100644 --- a/src/pages/LBP/components/ProjectInfo.tsx +++ b/src/pages/LBP/components/ProjectInfo.tsx @@ -14,6 +14,10 @@ import { ReactComponent as TrashIcon } from 'assets/images/newDelete.svg' import { useShowError } from 'state/application/hooks' import { MAX_FILE_UPLOAD_SIZE } from 'constants/constants' +interface ProjectInfoProps { + onChange: (data: any) => void +} + // Reusable form array component const FormArray = ({ label, items, addItem, removeItem, handleChange }: any) => { return ( @@ -50,13 +54,38 @@ const FormArray = ({ label, items, addItem, removeItem, handleChange }: any) => ) } -export default function ProjectInfo() { +export default function ProjectInfo({ onChange }: ProjectInfoProps) { + const [projectInfoData, setProjectInfoData] = useState({ + title: '', + description: '', + website: '', + socialLinks: [], + whitepapers: [], + uploadDocs: [], + }) const [socialLinks, setSocialLinks] = useState(['']) const [whitepapers, setWhitepapers] = useState(['']) const [values, setValues] = useState({ uploadDocs: [], }) + const handleInputChange = (e: ChangeEvent) => { + const { name, value } = e.target; + setProjectInfoData(prevData => ({ ...prevData, [name]: value })); + + + const updatedData = { + ...projectInfoData, + [name]: value, + socialLinks: socialLinks, + whitepapers: whitepapers, + }; + + onChange(updatedData); + } + + + const handleDropImage = (acceptedFiles: any, key: string) => { const files = Array.isArray(acceptedFiles) ? acceptedFiles : [acceptedFiles] @@ -88,7 +117,14 @@ export default function ProjectInfo() { return ( <> - + - + - + {/* Social Links */} handleAddItem(setSocialLinks)} removeItem={(index: number) => handleRemoveItem(index, setSocialLinks)} handleChange={(value: string, index: number) => handleChangeItem(value, index, setSocialLinks)} @@ -128,7 +176,10 @@ export default function ProjectInfo() { Upload Documents - All documents should be dated within the last 3 months. Type of document format supported is PDF, JPG, and PNG. + + All documents should be dated within the last 3 months. Type of document format supported is PDF, JPG, and + PNG. +
From 79a645725b5b76725f6e3264bdaab6d97aba0fb7 Mon Sep 17 00:00:00 2001 From: Kapil Date: Wed, 3 Apr 2024 01:45:21 +0530 Subject: [PATCH 004/280] Implement LBP form, validation, exclude the chart is done --- src/assets/images/serenity.svg | 9 + src/assets/images/usdcNew.svg | 9 + src/pages/LBP/LbpForm.tsx | 102 +++++---- src/pages/LBP/components/Approvals.tsx | 62 +++++- src/pages/LBP/components/ProjectInfo.tsx | 265 ++++++++++++++++------- src/pages/LBP/components/Tokenomics.tsx | 215 ++++++++++++++---- 6 files changed, 489 insertions(+), 173 deletions(-) create mode 100644 src/assets/images/serenity.svg create mode 100644 src/assets/images/usdcNew.svg diff --git a/src/assets/images/serenity.svg b/src/assets/images/serenity.svg new file mode 100644 index 0000000000..95352f30ed --- /dev/null +++ b/src/assets/images/serenity.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/usdcNew.svg b/src/assets/images/usdcNew.svg new file mode 100644 index 0000000000..ccc6683756 --- /dev/null +++ b/src/assets/images/usdcNew.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/pages/LBP/LbpForm.tsx b/src/pages/LBP/LbpForm.tsx index 8b27a6c78c..492e443696 100644 --- a/src/pages/LBP/LbpForm.tsx +++ b/src/pages/LBP/LbpForm.tsx @@ -1,65 +1,73 @@ -import React, { useState } from 'react' -import { Trans } from '@lingui/macro' -import Column from 'components/Column' -import { RowStart } from 'components/Row' -import { FormContainer, FormRow } from 'pages/KYC/IndividualKycForm' -import { FormCard, StyledStickyBox } from 'pages/KYC/styleds' -import { isMobile } from 'react-device-detect' -import { TYPE } from 'theme' -import Branding from './components/Branding' -import ProjectInfo from './components/ProjectInfo' -import Tokenomics from './components/Tokenomics' -import Approvals from './components/Approvals' -import { KYCProgressBar } from 'pages/KYC/KYCProgressBar' -import { Card } from 'rebass' +import React, { useState, useEffect } from 'react'; +import { Trans } from '@lingui/macro'; +import Column from 'components/Column'; +import { RowStart } from 'components/Row'; +import { FormContainer, FormRow } from 'pages/KYC/IndividualKycForm'; +import { FormCard, StyledStickyBox } from 'pages/KYC/styleds'; +import { isMobile } from 'react-device-detect'; +import { TYPE } from 'theme'; +import Branding from './components/Branding'; +import ProjectInfo from './components/ProjectInfo'; +import Tokenomics from './components/Tokenomics'; +import Approvals from './components/Approvals'; +import { KYCProgressBar } from 'pages/KYC/KYCProgressBar'; +import { Card } from 'rebass'; export default function LBPForm() { const [formData, setFormData] = useState({ branding: {}, projectInfo: {}, - }) - const [canSubmit, setCanSubmit] = useState(false) + tokenomics: {}, + }); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + updateSubmitButtonState(formData); + }, [formData]); const handleBrandingChange = (brandingData: any) => { - setFormData((prevData) => ({ ...prevData, branding: brandingData })) - updateSubmitButtonState({ ...formData, branding: brandingData, projectInfo: formData.projectInfo }) - } + setFormData((prevData) => ({ ...prevData, branding: brandingData })); + }; const handleProjectInfoChange = (projectInfoData: any) => { - setFormData((prevData) => ({ ...prevData, projectInfo: projectInfoData })) - updateSubmitButtonState({ ...formData, branding: formData.branding, projectInfo: projectInfoData }) - } + setFormData((prevData) => ({ ...prevData, projectInfo: projectInfoData })); + }; + + const handleTokenomicsChange = (tokenomicsData: any) => { + setFormData((prevData) => ({ ...prevData, tokenomics: tokenomicsData })); + }; const updateSubmitButtonState = (formData: any) => { - const brandingComplete = !!formData.branding.LBPLogo && !!formData.branding.LBPBanner - const projectInfoComplete = - !!formData.projectInfo.title && - !!formData.projectInfo.description && - !!formData.projectInfo.website && - !!formData.projectInfo.socialLinks && - !!formData.projectInfo.whitepapers && - !!formData.projectInfo.uploadDocs - setCanSubmit(brandingComplete && projectInfoComplete) - } + const isComplete = (data: any) => Object.values(data).every((val) => !!val); + const brandingComplete = isComplete(formData.branding); + const projectInfoComplete = isComplete(formData.projectInfo); + const tokenomicsComplete = isComplete(formData.tokenomics); + const hasSocialLinks = formData.projectInfo.socialLinks?.length > 0; + const hasWhitepapers = formData.projectInfo.whitepapers?.length > 0; + const hasUploadDocs = formData.projectInfo.uploadDocs?.length > 0; + setCanSubmit( + brandingComplete && + projectInfoComplete && + tokenomicsComplete && + hasSocialLinks && + hasWhitepapers && + hasUploadDocs + ); + }; const handleSubmit = () => { - console.log(formData) - } + console.log(formData); + }; return ( - + Serenity - + Branding @@ -87,7 +95,7 @@ export default function LBPForm() { - + @@ -97,9 +105,9 @@ export default function LBPForm() { Approvals - {/* + - */} + @@ -131,10 +139,10 @@ export default function LBPForm() { /> - + {/*
-
+
*/}
- ) + ); } diff --git a/src/pages/LBP/components/Approvals.tsx b/src/pages/LBP/components/Approvals.tsx index ed7c4c946f..c4bab1e418 100644 --- a/src/pages/LBP/components/Approvals.tsx +++ b/src/pages/LBP/components/Approvals.tsx @@ -1,13 +1,57 @@ -import { FormGrid } from 'pages/KYC/styleds' -import react from 'react' +import styled from 'styled-components'; +import React from 'react'; +import { ReactComponent as USDC } from '../../../assets/images/usdcNew.svg'; +import { ReactComponent as Serenity } from '../../../assets/images/serenity.svg'; + +const CardContainer = styled.div` + display: flex; + justify-content: space-between; + @media (max-width: 768px) { + flex-direction: column; + align-items: center; + } +`; + +const Card = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border: 1px solid #E6E6FF; + border-radius: 6px; + width: calc(50% - 10px); + height: 200px; + margin: 5px; + @media (max-width: 768px) { + width: calc(100% - 20px); + max-width: 350px; + } +`; + +const Button = styled.button` + border: 1px solid #E6E6FF; + color: #6666FF; + width: 250px; + height: 48px; + border-radius: 6px; + background-color: #FFFFFF; + cursor: pointer; + font-size: 16px; +`; export default function Approvals() { return ( -
-
-
-
-
-
- ) + + + +

Approve Serenity

+ +
+ + +

Approve USDC

+ +
+
+ ); } diff --git a/src/pages/LBP/components/ProjectInfo.tsx b/src/pages/LBP/components/ProjectInfo.tsx index 793313de19..e96df5b85f 100644 --- a/src/pages/LBP/components/ProjectInfo.tsx +++ b/src/pages/LBP/components/ProjectInfo.tsx @@ -1,25 +1,46 @@ -import React, { useState, ChangeEvent } from 'react' -import { Box, Flex } from 'rebass' -import { Trans } from '@lingui/macro' -import { Label } from '@rebass/forms' -import { StyledTextarea } from 'components/CollectionForm/styled' -import { TextInput, Uploader, UploaderDocs } from 'pages/KYC/common' -import { LinkStyledButton, TYPE } from 'theme' -import { RowCenter } from 'components/Row' -import { ExtraInfoCardCountry } from 'pages/KYC/styleds' -import { Plus } from 'react-feather' -import styled from 'styled-components' -import { IconButton } from '@material-ui/core' -import { ReactComponent as TrashIcon } from 'assets/images/newDelete.svg' -import { useShowError } from 'state/application/hooks' -import { MAX_FILE_UPLOAD_SIZE } from 'constants/constants' +import React, { useState, ChangeEvent } from 'react'; +import { Box, Flex } from 'rebass'; +import { Trans } from '@lingui/macro'; +import { Label } from '@rebass/forms'; +import { StyledTextarea } from 'components/CollectionForm/styled'; +import { TextInput, UploaderDocs } from 'pages/KYC/common'; +import { LinkStyledButton, TYPE } from 'theme'; +import { RowCenter } from 'components/Row'; +import { ExtraInfoCardCountry } from 'pages/KYC/styleds'; +import { Plus } from 'react-feather'; +import styled from 'styled-components'; +import { IconButton } from '@material-ui/core'; +import { ReactComponent as TrashIcon } from 'assets/images/newDelete.svg'; +import { MAX_FILE_UPLOAD_SIZE } from 'constants/constants'; +import { ButtonOutlined, PinnedContentButton } from 'components/Button'; +import RedesignedWideModal from 'components/Modal/RedesignedWideModal'; +import closeIcon from '../../../assets/images/newCross.svg'; +import { color } from 'styled-system'; interface ProjectInfoProps { - onChange: (data: any) => void + onChange: (data: any) => void; } -// Reusable form array component -const FormArray = ({ label, items, addItem, removeItem, handleChange }: any) => { +interface LinkData { + name: string; + url: string; +} + +interface ProjectInfoData { + title: string; + description: string; + website: string; + socialLinks: LinkData[]; + whitepapers: LinkData[]; + uploadDocs: string[]; + [key: string]: any; +} + +const FormArray = ({ label, items, removeItem, handleChange, openModal }: any) => { + const handleInternalChange = (value: string, index: number) => { + handleChange(value, index, label); + }; + return ( <>