From b304ea208f55561af67020ca5be97c855b766519 Mon Sep 17 00:00:00 2001 From: saml33 Date: Thu, 21 Jul 2022 14:50:56 +1000 Subject: [PATCH] start onboarding flow --- components/account/AccountActions.tsx | 7 +- components/forms/Input.tsx | 23 ++-- components/forms/Label.tsx | 5 + components/forms/Select.tsx | 86 +++++++++++++++ components/modals/DepositModal.tsx | 8 +- components/modals/IntroModal.tsx | 12 +++ components/modals/UserSetupModal.tsx | 127 +++++++++++++++++++++++ components/modals/WithdrawModal.tsx | 8 +- components/shared/Button.tsx | 25 +++-- components/shared/InlineNotification.tsx | 56 ++++++++++ components/shared/Modal.tsx | 27 +++-- components/swap/JupiterRoutes.tsx | 5 +- components/swap/RouteFeeInfo.tsx | 4 +- components/swap/Swap.tsx | 3 +- components/swap/SwapTokenChart.tsx | 6 +- pages/index.tsx | 26 ++++- public/locales/en/common.json | 2 +- styles/globals.css | 35 ++++++- types/modal.ts | 4 + utils/profile.ts | 11 ++ 20 files changed, 420 insertions(+), 60 deletions(-) create mode 100644 components/forms/Label.tsx create mode 100644 components/forms/Select.tsx create mode 100644 components/modals/IntroModal.tsx create mode 100644 components/modals/UserSetupModal.tsx create mode 100644 components/shared/InlineNotification.tsx create mode 100644 types/modal.ts create mode 100644 utils/profile.ts diff --git a/components/account/AccountActions.tsx b/components/account/AccountActions.tsx index 79a7053c..e180701a 100644 --- a/components/account/AccountActions.tsx +++ b/components/account/AccountActions.tsx @@ -30,13 +30,18 @@ const AccountActions = () => { return ( <>
- diff --git a/components/forms/Input.tsx b/components/forms/Input.tsx index 20e7b9ee..dc6573f6 100644 --- a/components/forms/Input.tsx +++ b/components/forms/Input.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, forwardRef, ReactNode } from 'react' +import { ChangeEvent, forwardRef } from 'react' interface InputProps { type: string @@ -34,14 +34,14 @@ const Input = forwardRef((props, ref) => {
) : null} ((props, ref) => { }) export default Input - -interface LabelProps { - children: ReactNode - className?: string -} - -export const Label = ({ children, className }: LabelProps) => ( - -) diff --git a/components/forms/Label.tsx b/components/forms/Label.tsx new file mode 100644 index 00000000..bd4c9017 --- /dev/null +++ b/components/forms/Label.tsx @@ -0,0 +1,5 @@ +const Label = ({ text }: { text: string }) => ( +

{text}

+) + +export default Label diff --git a/components/forms/Select.tsx b/components/forms/Select.tsx new file mode 100644 index 00000000..8b691925 --- /dev/null +++ b/components/forms/Select.tsx @@ -0,0 +1,86 @@ +import { Listbox } from '@headlessui/react' +import { ChevronDownIcon } from '@heroicons/react/solid' +import { ReactNode } from 'react' + +interface SelectProps { + value: string | ReactNode + onChange: (x: string) => void + children: ReactNode + className?: string + dropdownPanelClassName?: string + placeholder?: string + disabled?: boolean +} + +const Select = ({ + value, + onChange, + children, + className, + dropdownPanelClassName, + placeholder = 'Select', + disabled = false, +}: SelectProps) => { + return ( +
+ + {({ open }) => ( + <> + +
+ {value ? ( + value + ) : ( + {placeholder} + )} + +
+
+ {open ? ( + + {children} + + ) : null} + + )} +
+
+ ) +} + +interface OptionProps { + value: string + children: string | ReactNode + className?: string +} + +const Option = ({ value, children, className }: OptionProps) => { + return ( + + {({ selected }) => ( +
+ {children} +
+ )} +
+ ) +} + +Select.Option = Option + +export default Select diff --git a/components/modals/DepositModal.tsx b/components/modals/DepositModal.tsx index b6a1e08d..d5589568 100644 --- a/components/modals/DepositModal.tsx +++ b/components/modals/DepositModal.tsx @@ -1,17 +1,13 @@ import React, { useState } from 'react' import mangoStore from '../../store/state' +import { ModalProps } from '../../types/modal' import { notify } from '../../utils/notifications' import Button from '../shared/Button' import Loading from '../shared/Loading' import Modal from '../shared/Modal' -type DepositModalProps = { - isOpen: boolean - onClose: () => void -} - -function DepositModal({ isOpen, onClose }: DepositModalProps) { +function DepositModal({ isOpen, onClose }: ModalProps) { const [inputAmount, setInputAmount] = useState('') const [submitting, setSubmitting] = useState(false) const [selectedToken, setSelectedToken] = useState('USDC') diff --git a/components/modals/IntroModal.tsx b/components/modals/IntroModal.tsx new file mode 100644 index 00000000..696b0162 --- /dev/null +++ b/components/modals/IntroModal.tsx @@ -0,0 +1,12 @@ +import { ModalProps } from '../../types/modal' +import Modal from '../shared/Modal' + +const IntroModal = ({ isOpen, onClose }: ModalProps) => { + return ( + +
Hi
+
+ ) +} + +export default IntroModal diff --git a/components/modals/UserSetupModal.tsx b/components/modals/UserSetupModal.tsx new file mode 100644 index 00000000..83c74708 --- /dev/null +++ b/components/modals/UserSetupModal.tsx @@ -0,0 +1,127 @@ +import { Transition } from '@headlessui/react' +import { useTranslation } from 'next-i18next' +import { ChangeEvent, useState } from 'react' +import { ModalProps } from '../../types/modal' +import { PROFILE_CATEGORIES } from '../../utils/profile' +import Input from '../forms/Input' +import Label from '../forms/Label' +import Select from '../forms/Select' +import Button, { LinkButton } from '../shared/Button' +import InlineNotification from '../shared/InlineNotification' +import Modal from '../shared/Modal' +import useLocalStorageState from '../../hooks/useLocalStorageState' + +export const SKIP_ACCOUNT_SETUP_KEY = 'skipAccountSetup' + +const UserSetupModal = ({ isOpen, onClose }: ModalProps) => { + const { t } = useTranslation() + const [profileName, setProfileName] = useState('') + const [accountName, setAccountName] = useState('') + const [profileCategory, setProfileCategory] = useState('') + const [showAccountSetup, setShowAccountSetup] = useState(false) + const [, setSkipAccountSetup] = useLocalStorageState(SKIP_ACCOUNT_SETUP_KEY) + + const handleSaveProfile = () => { + // save profile details to db... + + setShowAccountSetup(true) + } + + const handleUserSetup = () => { + // create account + } + + const handleSkipAccountSetup = () => { + setSkipAccountSetup(true) + onClose() + } + + return ( + + <> +
+

Create Profile

+

+ This is your Mango Identity and is used on our leaderboard and chat +

+
+
+
+
+
+
+ + setShowAccountSetup(true)}> + I'll do this later + +
+ + +
+
+
+

Account Setup

+

You need a Mango Account to get started

+
+
+ {/* Not sure if we need to name the first account or if every users first account should have the same name "Main Account" or something similar */} +
+ +
+
+ + handleSkipAccountSetup()}> + I'll do this later + +
+
+
+
+ ) +} + +export default UserSetupModal diff --git a/components/modals/WithdrawModal.tsx b/components/modals/WithdrawModal.tsx index a401d789..70768df0 100644 --- a/components/modals/WithdrawModal.tsx +++ b/components/modals/WithdrawModal.tsx @@ -1,17 +1,13 @@ import { useState } from 'react' import mangoStore from '../../store/state' +import { ModalProps } from '../../types/modal' import { notify } from '../../utils/notifications' import Button from '../shared/Button' import Loading from '../shared/Loading' import Modal from '../shared/Modal' -type WithdrawModalProps = { - isOpen: boolean - onClose: () => void -} - -function WithdrawModal({ isOpen, onClose }: WithdrawModalProps) { +function WithdrawModal({ isOpen, onClose }: ModalProps) { const [inputAmount, setInputAmount] = useState('') const [submitting, setSubmitting] = useState(false) const [selectedToken, setSelectedToken] = useState('USDC') diff --git a/components/shared/Button.tsx b/components/shared/Button.tsx index 2edb0acc..f6eca3f3 100644 --- a/components/shared/Button.tsx +++ b/components/shared/Button.tsx @@ -1,6 +1,6 @@ import { FunctionComponent, ReactNode } from 'react' -interface ButtonProps { +interface AllButtonProps { onClick?: (e?: React.MouseEvent) => void disabled?: boolean className?: string @@ -8,21 +8,34 @@ interface ButtonProps { children?: ReactNode } -const Button: FunctionComponent = ({ +interface ButtonProps { + size?: 'large' | 'medium' | 'small' +} + +type ButtonCombinedProps = AllButtonProps & ButtonProps + +const Button: FunctionComponent = ({ children, onClick, disabled = false, className, secondary, + size = 'medium', ...props }) => { return ( + ) : null} {title} {children} diff --git a/components/swap/JupiterRoutes.tsx b/components/swap/JupiterRoutes.tsx index 50650817..c34590d9 100644 --- a/components/swap/JupiterRoutes.tsx +++ b/components/swap/JupiterRoutes.tsx @@ -110,10 +110,7 @@ const JupiterRoutes = ({ ) : null}
- diff --git a/components/swap/RouteFeeInfo.tsx b/components/swap/RouteFeeInfo.tsx index df10780f..1335cb00 100644 --- a/components/swap/RouteFeeInfo.tsx +++ b/components/swap/RouteFeeInfo.tsx @@ -49,7 +49,7 @@ const RouteFeeInfo = ({

{t('trade:review-trade')}

-
+ {/*

{t('liquidity')}

-
+
*/} {amountOut && amountIn ? (

{t('trade:rate')}

diff --git a/components/swap/Swap.tsx b/components/swap/Swap.tsx index bc5cc8aa..94862442 100644 --- a/components/swap/Swap.tsx +++ b/components/swap/Swap.tsx @@ -343,10 +343,11 @@ const Swap = () => { ) : null}