Skip to content

Commit

Permalink
feat: updated funding flow (#1023)
Browse files Browse the repository at this point in the history
* feat: shipping information

* feat: rewards shipping
  • Loading branch information
jfrader committed Jun 30, 2023
1 parent 858d998 commit 2d00660
Show file tree
Hide file tree
Showing 20 changed files with 732 additions and 406 deletions.
12 changes: 7 additions & 5 deletions src/components/molecules/projectDisplay/ActivityBrief.tsx
Expand Up @@ -9,16 +9,16 @@ import {
VStack,
} from '@chakra-ui/react'
import { useEffect, useMemo, useState } from 'react'
import { AiOutlineEllipsis } from 'react-icons/ai'
import { useTranslation } from 'react-i18next'
import { AiOutlineEllipsis } from 'react-icons/ai'

import { ExternalAccountType } from '../../../pages/auth'
import { Countdown } from "../../../pages/projectView/projectActivityPanel/components"
import { Countdown } from '../../../pages/projectView/projectActivityPanel/components'
import {
FunderWithUserFragment,
ProjectFragment,
ProjectMilestone,
} from "../../../types"
} from '../../../types'
import { isActive } from '../../../utils'
import { getProjectBalance } from '../../../utils/helpers'
import { SatoshiAmount } from '../../ui'
Expand Down Expand Up @@ -203,9 +203,11 @@ export const ActivityBrief = ({
size="lg"
variant="transparent"
>
<Text fontWeight={500}>{t('Supporters')}</Text>
{loading || latestFunders.length ? (
<Text fontWeight={500}>{t('Supporters')}</Text>
) : null}
<HStack ml={1} spacing={0} alignItems="start">
{latestFunders.length > 0
{!loading
? latestFunders.map((funder) => {
return (
<UserAvatar
Expand Down
16 changes: 16 additions & 0 deletions src/config/theme/theme.ts
Expand Up @@ -183,6 +183,22 @@ export const theme = {
},
},
},
Checkbox: {
variants: {
primary: ({ colorScheme = 'primary' }: StyleFunctionProps) => ({
color: `${colorScheme}.400`,
control: {
_checked: {
color: `${colorScheme}.400`,
},
},
}),
},
defaultProps: {
variant: 'primary',
colorScheme: 'primary',
},
},
Radio: {
variants: {
primary: ({ colorScheme = 'primary' }: StyleFunctionProps) => ({
Expand Down
3 changes: 3 additions & 0 deletions src/defaults/projectReward.ts
Expand Up @@ -9,5 +9,8 @@ export const defaultProjectReward: ProjectReward = {
deleted: false,
stock: 0,
sold: 0,
hasShipping: false,
createdAt: new Date(),
updatedAt: new Date(),
project: {} as Project,
}
1 change: 1 addition & 0 deletions src/graphql/fragments/project.ts
Expand Up @@ -66,6 +66,7 @@ export const FRAGMENT_PROJECT_REWARD_FOR_CREATE_UPDATE = gql`
deleted
stock
sold
hasShipping
}
`

Expand Down
8 changes: 4 additions & 4 deletions src/graphql/mutations/project.ts
Expand Up @@ -65,17 +65,17 @@ export const MUTATION_UPDATE_PROJECT = gql`

export const MUTATION_CREATE_PROJECT_REWARD = gql`
${FRAGMENT_PROJECT_REWARD_FOR_CREATE_UPDATE}
mutation CreateProjectReward($input: CreateProjectRewardInput!) {
createProjectReward(input: $input) {
mutation ProjectRewardCreate($input: CreateProjectRewardInput!) {
projectRewardCreate(input: $input) {
...ProjectRewardForCreateUpdate
}
}
`

export const MUTATION_UPDATE_PROJECT_REWARD = gql`
${FRAGMENT_PROJECT_REWARD_FOR_CREATE_UPDATE}
mutation UpdateProjectReward($input: UpdateProjectRewardInput!) {
updateProjectReward(input: $input) {
mutation ProjectRewardUpdate($input: UpdateProjectRewardInput!) {
projectRewardUpdate(input: $input) {
...ProjectRewardForCreateUpdate
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/hooks/useFundingFormState.tsx
Expand Up @@ -45,6 +45,8 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => {
const { user, isAnonymous } = useContext(AuthContext)
const { getUSDCentsAmount } = useBTCConverter()

const [needsShipping, setNeedsShipping] = useState(false)

const initialState: IFundForm = useMemo(
() => ({
donationAmount: 0,
Expand Down Expand Up @@ -89,6 +91,7 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => {
rewardsCost: 0,
totalAmount: current.donationAmount,
}))
setNeedsShipping(false)
}, [])

const updateReward = useCallback(
Expand All @@ -113,6 +116,10 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => {
)

if (reward && reward.id) {
if (reward.hasShipping) {
setNeedsShipping((current) => current || reward.hasShipping)
}

const rewardMultiplier = newRewardsCountInfo[rewardID.toString()]
if (!rewardMultiplier) {
return 0
Expand Down Expand Up @@ -142,14 +149,26 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => {

const resetForm = useCallback(() => {
_setState(initialState)
setNeedsShipping(false)
}, [initialState])

const hasSelectedRewards = useMemo(
() =>
Boolean(
state.rewardsByIDAndCount &&
Object.keys(state.rewardsByIDAndCount).length > 0,
),
[state.rewardsByIDAndCount],
)

return {
state,
setTarget,
setState,
updateReward,
resetForm,
resetRewards,
needsShipping,
hasSelectedRewards,
}
}
@@ -0,0 +1,33 @@
import { Text, VStack } from '@chakra-ui/react'
import { useTranslation } from 'react-i18next'

import { useProjectContext } from '../../../../context'
import { CreatorEmailButton } from './CreatorEmailButton'
import { CreatorEmailContentButton } from './CreatorEmailContentButton'

export const ContributionShippingBox = () => {
const { t } = useTranslation()
const { project } = useProjectContext()
const ownerEmail = project?.owners[0]?.user.email || ''
return (
<VStack
padding={2}
width={'full'}
borderRadius="8px"
backgroundColor="primary.100"
spacing={2}
justify="flex-start"
alignItems="flex-start"
>
<Text variant="body1">{t('Shipping')}</Text>
<Text>
{t(
"To receive the selected items, you need to send your shipping details to the creator's email.",
)}
</Text>

<CreatorEmailButton email={ownerEmail} />
<CreatorEmailContentButton />
</VStack>
)
}
@@ -0,0 +1,37 @@
import { CopyIcon } from '@chakra-ui/icons'
import { Box, Button, ButtonProps } from '@chakra-ui/react'
import { useState } from 'react'

import { copyTextToClipboard } from '../../../../utils'

export const CreatorEmailButton = ({
email,
...props
}: { email: string } & ButtonProps) => {
const [isEmailCopied, setEmailCopied] = useState(false)

const handleCopyEmail = () => {
copyTextToClipboard(email)

setEmailCopied(true)
setTimeout(() => {
setEmailCopied(false)
}, 1000)
}

return (
<Button
w="100%"
justifyContent="start"
isActive={isEmailCopied}
onClick={handleCopyEmail}
variant="secondary"
rightIcon={<CopyIcon />}
{...props}
>
<Box as="span" flexGrow={1} textAlign="left">
{email}
</Box>
</Button>
)
}
@@ -0,0 +1,101 @@
import { CopyIcon } from '@chakra-ui/icons'
import { HStack, StackProps, Text, VStack } from '@chakra-ui/react'
import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'

import { useProjectContext } from '../../../../context'
import { copyTextToClipboard } from '../../../../utils'

export const CreatorEmailContentButton = ({ ...props }: StackProps) => {
const { t } = useTranslation()
const [isCopied, setCopied] = useState(false)

const ref = useRef<HTMLDivElement>(null)

const {
project,
fundingFlow: { fundingTx },
fundForm: { state },
} = useProjectContext()

const handleCopyContent = () => {
const content = ref.current?.innerText || ''
copyTextToClipboard(content)

if (content) {
setCopied(true)
setTimeout(() => {
setCopied(false)
}, 1000)
}
}

const rewards = project ? project.rewards : []

const rewardEntries = state.rewardsByIDAndCount
? Object.entries(state.rewardsByIDAndCount)
: []

if (!fundingTx) {
return null
}

return (
<HStack
w="100%"
ref={ref}
px={2}
py={4}
justifyContent="start"
alignItems="center"
maxHeight="auto"
height="auto"
cursor="pointer"
border="2px solid"
borderRadius="8px"
_hover={{ borderColor: 'primary.400' }}
bg={isCopied ? 'primary.100' : 'neutral.0'}
borderColor={isCopied ? 'primary.400' : 'neutral.200'}
onClick={handleCopyContent}
{...props}
>
<VStack flexGrow={1} textAlign="left" alignItems="start">
<Text display="block" variant="caption">
{t('Hi,\nI just purchased the following items on Geyser:')}{' '}
<b>
{rewardEntries.map(([key, value], index) => {
const reward = rewards.find(({ id }) => id === key)
if (reward) {
return (
<span key={key}>
{reward.name} x{value}
{index < rewardEntries.length - 1 ? ', ' : ''}
</span>
)
}
})}
</b>
</Text>
<Text display="block" variant="caption">
{t('This is my reference code:')}
</Text>
<Text display="block" variant="caption" fontWeight="bold">
{fundingTx.uuid}
</Text>
<Text display="block" variant="caption">
{t('I’d like it to be shipped to the following address:')}
</Text>
<Text display="block" variant="caption" fontWeight="bold">
{'<'}
{t('ADD RECEIVING POSTAL ADDRESS')}
{'>'}
</Text>

<Text display="block" variant="caption">
{t('Cheers,')}
</Text>
</VStack>
<CopyIcon />
</HStack>
)
}
@@ -0,0 +1,67 @@
import { ArrowBackIcon } from '@chakra-ui/icons'
import { Button, HStack, Input, VStack } from '@chakra-ui/react'
import { MouseEventHandler } from 'react'
import { useTranslation } from 'react-i18next'

import { SectionTitle } from '../../../../components/ui'
import { useProjectContext } from '../../../../context'
import { FieldContainer } from '../../../../forms/components/FieldContainer'
import { ProjectFundingFormCommentField } from '../../projectMainBody/components'

type Props = {
onBackClick: MouseEventHandler<HTMLButtonElement>
}

export const FundingFormUserInfoSection = ({ onBackClick }: Props) => {
const { t } = useTranslation()
const {
fundForm: {
setState,
setTarget,
needsShipping,
state: { comment, email },
},
} = useProjectContext()
return (
<VStack alignItems="start" width="100%" spacing={5}>
<HStack>
<Button onClick={onBackClick} variant="transparent">
<ArrowBackIcon />
</Button>
<SectionTitle>{t('Final details')}</SectionTitle>
</HStack>

<FieldContainer title={t('Public comment')}>
<ProjectFundingFormCommentField
comment={comment}
setTarget={setTarget}
setFormState={setState}
width="full"
/>
</FieldContainer>

{needsShipping ? (
<>
<FieldContainer
title="Your email"
subtitle="The seller may want to reach out."
>
<Input
type="email"
name="email"
placeholder="funderemail@gmail.com"
value={email}
onChange={setTarget}
/>
</FieldContainer>
<FieldContainer
title={t('Shipping')}
subtitle={t(
"To receive the selected items, you will need to send your shipping details to the creator's email. Which will be revealed in the success screen.",
)}
/>
</>
) : null}
</VStack>
)
}

0 comments on commit 2d00660

Please sign in to comment.