From 2d0066016ce96ea9a083bcfd477f0ed60e00752b Mon Sep 17 00:00:00 2001 From: Fran Date: Fri, 30 Jun 2023 17:26:39 -0300 Subject: [PATCH] feat: updated funding flow (#1023) * feat: shipping information * feat: rewards shipping --- .../projectDisplay/ActivityBrief.tsx | 12 +- src/config/theme/theme.ts | 16 ++ src/defaults/projectReward.ts | 3 + src/graphql/fragments/project.ts | 1 + src/graphql/mutations/project.ts | 8 +- src/hooks/useFundingFormState.tsx | 19 ++ .../components/ContributionInfoBox.tsx | 0 .../components/ContributionShippingBox.tsx | 33 +++ .../components/CreatorEmailButton.tsx | 37 +++ .../components/CreatorEmailContentButton.tsx | 101 ++++++++ .../components/FundingFormUserInfoSection.tsx | 67 +++++ .../components/ProjectFundingSummaryCard.tsx | 119 +++++++++ .../components/SuccessImageComponent.tsx | 40 +-- .../projectActivityPanel/index.tsx | 21 +- .../ProjectFundingSelectionFormScreen.tsx | 222 ++++------------- .../screens/SuccessScreen.tsx | 38 +-- .../components/RewardAdditionModal.tsx | 140 ++++++----- .../projectMainBody/components/index.ts | 2 +- src/translations/English.json | 27 +- src/types/generated/graphql.ts | 232 +++++++++++------- 20 files changed, 732 insertions(+), 406 deletions(-) rename src/pages/projectView/{projectMainBody => projectActivityPanel}/components/ContributionInfoBox.tsx (100%) create mode 100644 src/pages/projectView/projectActivityPanel/components/ContributionShippingBox.tsx create mode 100644 src/pages/projectView/projectActivityPanel/components/CreatorEmailButton.tsx create mode 100644 src/pages/projectView/projectActivityPanel/components/CreatorEmailContentButton.tsx create mode 100644 src/pages/projectView/projectActivityPanel/components/FundingFormUserInfoSection.tsx create mode 100644 src/pages/projectView/projectActivityPanel/components/ProjectFundingSummaryCard.tsx diff --git a/src/components/molecules/projectDisplay/ActivityBrief.tsx b/src/components/molecules/projectDisplay/ActivityBrief.tsx index fc2cdbd70..bb8514149 100644 --- a/src/components/molecules/projectDisplay/ActivityBrief.tsx +++ b/src/components/molecules/projectDisplay/ActivityBrief.tsx @@ -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' @@ -203,9 +203,11 @@ export const ActivityBrief = ({ size="lg" variant="transparent" > - {t('Supporters')} + {loading || latestFunders.length ? ( + {t('Supporters')} + ) : null} - {latestFunders.length > 0 + {!loading ? latestFunders.map((funder) => { return ( ({ + color: `${colorScheme}.400`, + control: { + _checked: { + color: `${colorScheme}.400`, + }, + }, + }), + }, + defaultProps: { + variant: 'primary', + colorScheme: 'primary', + }, + }, Radio: { variants: { primary: ({ colorScheme = 'primary' }: StyleFunctionProps) => ({ diff --git a/src/defaults/projectReward.ts b/src/defaults/projectReward.ts index afeadfa09..0d565bfb0 100644 --- a/src/defaults/projectReward.ts +++ b/src/defaults/projectReward.ts @@ -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, } diff --git a/src/graphql/fragments/project.ts b/src/graphql/fragments/project.ts index 26d60d628..35dddc80e 100644 --- a/src/graphql/fragments/project.ts +++ b/src/graphql/fragments/project.ts @@ -66,6 +66,7 @@ export const FRAGMENT_PROJECT_REWARD_FOR_CREATE_UPDATE = gql` deleted stock sold + hasShipping } ` diff --git a/src/graphql/mutations/project.ts b/src/graphql/mutations/project.ts index f8995d4da..8374605af 100644 --- a/src/graphql/mutations/project.ts +++ b/src/graphql/mutations/project.ts @@ -65,8 +65,8 @@ 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 } } @@ -74,8 +74,8 @@ export const MUTATION_CREATE_PROJECT_REWARD = gql` 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 } } diff --git a/src/hooks/useFundingFormState.tsx b/src/hooks/useFundingFormState.tsx index 2278bba9d..6cf1dc909 100644 --- a/src/hooks/useFundingFormState.tsx +++ b/src/hooks/useFundingFormState.tsx @@ -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, @@ -89,6 +91,7 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => { rewardsCost: 0, totalAmount: current.donationAmount, })) + setNeedsShipping(false) }, []) const updateReward = useCallback( @@ -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 @@ -142,8 +149,18 @@ 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, @@ -151,5 +168,7 @@ export const useFundingFormState = ({ rewards }: UseFundStateProps) => { updateReward, resetForm, resetRewards, + needsShipping, + hasSelectedRewards, } } diff --git a/src/pages/projectView/projectMainBody/components/ContributionInfoBox.tsx b/src/pages/projectView/projectActivityPanel/components/ContributionInfoBox.tsx similarity index 100% rename from src/pages/projectView/projectMainBody/components/ContributionInfoBox.tsx rename to src/pages/projectView/projectActivityPanel/components/ContributionInfoBox.tsx diff --git a/src/pages/projectView/projectActivityPanel/components/ContributionShippingBox.tsx b/src/pages/projectView/projectActivityPanel/components/ContributionShippingBox.tsx new file mode 100644 index 000000000..57a84c3bd --- /dev/null +++ b/src/pages/projectView/projectActivityPanel/components/ContributionShippingBox.tsx @@ -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 ( + + {t('Shipping')} + + {t( + "To receive the selected items, you need to send your shipping details to the creator's email.", + )} + + + + + + ) +} diff --git a/src/pages/projectView/projectActivityPanel/components/CreatorEmailButton.tsx b/src/pages/projectView/projectActivityPanel/components/CreatorEmailButton.tsx new file mode 100644 index 000000000..2cef5e797 --- /dev/null +++ b/src/pages/projectView/projectActivityPanel/components/CreatorEmailButton.tsx @@ -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 ( + + ) +} diff --git a/src/pages/projectView/projectActivityPanel/components/CreatorEmailContentButton.tsx b/src/pages/projectView/projectActivityPanel/components/CreatorEmailContentButton.tsx new file mode 100644 index 000000000..4a820eda4 --- /dev/null +++ b/src/pages/projectView/projectActivityPanel/components/CreatorEmailContentButton.tsx @@ -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(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 ( + + + + {t('Hi,\nI just purchased the following items on Geyser:')}{' '} + + {rewardEntries.map(([key, value], index) => { + const reward = rewards.find(({ id }) => id === key) + if (reward) { + return ( + + {reward.name} x{value} + {index < rewardEntries.length - 1 ? ', ' : ''} + + ) + } + })} + + + + {t('This is my reference code:')} + + + {fundingTx.uuid} + + + {t('I’d like it to be shipped to the following address:')} + + + {'<'} + {t('ADD RECEIVING POSTAL ADDRESS')} + {'>'} + + + + {t('Cheers,')} + + + + + ) +} diff --git a/src/pages/projectView/projectActivityPanel/components/FundingFormUserInfoSection.tsx b/src/pages/projectView/projectActivityPanel/components/FundingFormUserInfoSection.tsx new file mode 100644 index 000000000..328f3d87c --- /dev/null +++ b/src/pages/projectView/projectActivityPanel/components/FundingFormUserInfoSection.tsx @@ -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 +} + +export const FundingFormUserInfoSection = ({ onBackClick }: Props) => { + const { t } = useTranslation() + const { + fundForm: { + setState, + setTarget, + needsShipping, + state: { comment, email }, + }, + } = useProjectContext() + return ( + + + + {t('Final details')} + + + + + + + {needsShipping ? ( + <> + + + + + + ) : null} + + ) +} diff --git a/src/pages/projectView/projectActivityPanel/components/ProjectFundingSummaryCard.tsx b/src/pages/projectView/projectActivityPanel/components/ProjectFundingSummaryCard.tsx new file mode 100644 index 000000000..7f0d1a60e --- /dev/null +++ b/src/pages/projectView/projectActivityPanel/components/ProjectFundingSummaryCard.tsx @@ -0,0 +1,119 @@ +import { Button, HStack, Text, VStack } from '@chakra-ui/react' +import { FormEventHandler, forwardRef } from 'react' + +import { BoltIcon } from '../../../../components/icons' +import { SatoshiAmount, SectionTitle } from '../../../../components/ui' +import { useProjectContext } from '../../../../context' +import { useFundCalc } from '../../../../helpers' + +type Props = { + onSubmit: () => void +} + +export const ProjectFundingSummaryCard = forwardRef( + ({ onSubmit }, ref) => { + const { fundForm, project } = useProjectContext() + + const { state: formState, hasSelectedRewards } = fundForm + + const { getTotalAmount } = useFundCalc(formState) + + const name = project ? project.name : '' + const rewards = project ? project.rewards : [] + const hasRewards = rewards.length > 0 + + const handleSubmit: FormEventHandler = (e) => { + e.preventDefault() + e.stopPropagation() + onSubmit() + } + + return ( +
+ + + {hasRewards && hasSelectedRewards ? ( + + + Rewards + + + {formState.rewardsByIDAndCount && + Object.entries(formState.rewardsByIDAndCount).map( + ([key, value]) => { + const reward = rewards.find(({ id }) => id === key) + if (reward) { + return ( + + {value}x {reward.name} + + ) + } + }, + )} + + + ) : null} + + + Total + + + + {getTotalAmount('sats', name)} + + + + {`($${getTotalAmount('dollar', name)})`} + + + + + + + +
+ ) + }, +) diff --git a/src/pages/projectView/projectActivityPanel/components/SuccessImageComponent.tsx b/src/pages/projectView/projectActivityPanel/components/SuccessImageComponent.tsx index d0eb68b2c..aac3721dc 100644 --- a/src/pages/projectView/projectActivityPanel/components/SuccessImageComponent.tsx +++ b/src/pages/projectView/projectActivityPanel/components/SuccessImageComponent.tsx @@ -10,7 +10,7 @@ import { import * as htmlToImage from 'html-to-image' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { BiCopy, BiDownload } from 'react-icons/bi' +import { BiCopy } from 'react-icons/bi' import { HiOutlineCheck } from 'react-icons/hi' import { Body2, H3 } from '../../../../components/typography' @@ -37,22 +37,6 @@ export const SuccessImageComponent = ({ return null } - const handleDownload = async () => { - try { - const dataUrl = await getDataUrl() - const link = document.createElement('a') - link.download = `share-contribution-to-${project.name}.png` - link.href = dataUrl - link.click() - } catch (error) { - toast({ - status: 'error', - title: 'Failed to download image', - description: 'Please try again', - }) - } - } - const handleCopy = async () => { try { const dataUrl = await getDataUrl() @@ -156,9 +140,14 @@ export const SuccessImageComponent = ({ - + - - - diff --git a/src/pages/projectView/projectActivityPanel/index.tsx b/src/pages/projectView/projectActivityPanel/index.tsx index cea5b12e6..7dcd5292d 100644 --- a/src/pages/projectView/projectActivityPanel/index.tsx +++ b/src/pages/projectView/projectActivityPanel/index.tsx @@ -15,7 +15,6 @@ import { RewardFundingInput, } from '../../../types' import { toInt, useMobileMode } from '../../../utils' -import { truthyFilter } from '../../../utils/array' import { InfoPageSkeleton, ProjectFundingInitialInfoScreen } from './screens' import { ProjectFundingQRScreen, @@ -42,13 +41,11 @@ export const ProjectActivityPanel = ({ resourceType, resourceId }: Props) => { const { mobileView, setMobileView, project, fundingFlow, fundForm } = useProjectContext() - // required for knowing the rewards and the funds const { state: formState, - setTarget, setState: setFormState, - updateReward, resetForm, + hasSelectedRewards, } = fundForm const { @@ -133,11 +130,7 @@ export const ProjectActivityPanel = ({ resourceType, resourceId }: Props) => { }, } - if ( - state.rewardsByIDAndCount && - Object.entries(state.rewardsByIDAndCount).length > 0 && - rewardsByIDAndCount - ) { + if (hasSelectedRewards && rewardsByIDAndCount) { const rewardsArray = Object.keys(rewardsByIDAndCount).map((key) => ({ id: toInt(key), quantity: rewardsByIDAndCount[key as keyof ProjectReward], @@ -177,15 +170,9 @@ export const ProjectActivityPanel = ({ resourceType, resourceId }: Props) => { case fundingStages.form: return ( ) @@ -227,7 +214,7 @@ export const ProjectActivityPanel = ({ resourceType, resourceId }: Props) => { marginTop={isMobile ? '0px' : '20px'} height="calc(100% - 20px)" borderTopLeftRadius={isMobile ? 'initial' : '8px'} - overflow="hidden" + overflowX="hidden" borderTop={isMobile ? 'none' : '2px solid'} borderLeft="2px solid" borderColor="neutral.200" diff --git a/src/pages/projectView/projectActivityPanel/screens/ProjectFundingSelectionFormScreen.tsx b/src/pages/projectView/projectActivityPanel/screens/ProjectFundingSelectionFormScreen.tsx index 2c2f862dc..9717f2b47 100644 --- a/src/pages/projectView/projectActivityPanel/screens/ProjectFundingSelectionFormScreen.tsx +++ b/src/pages/projectView/projectActivityPanel/screens/ProjectFundingSelectionFormScreen.tsx @@ -1,78 +1,74 @@ -import { - Box, - Button, - CloseButton, - Divider, - HStack, - Text, - VStack, -} from '@chakra-ui/react' -import { useRef } from 'react' -import { useTranslation } from 'react-i18next' +import { Box, CloseButton, Divider, VStack } from '@chakra-ui/react' +import { useRef, useState } from 'react' -import { BoltIcon } from '../../../../components/icons' -import { - SatoshiAmount, - SectionTitle, - TextInputBox, -} from '../../../../components/ui' import { MAX_FUNDING_AMOUNT_USD } from '../../../../constants' -import { useFundCalc } from '../../../../helpers' -import { IFundForm } from '../../../../hooks' -import { IProjectType } from '../../../../interfaces' -import { ProjectRewardForCreateUpdateFragment } from '../../../../types' -import { useNotification } from '../../../../utils' -import { ProjectFundingFormCommentField } from '../../projectMainBody/components' -import { FundingFormSection } from '../components' +import { useProjectContext } from '../../../../context' +import { useFundCalc } from '../../../../helpers/fundingCalculation' +import { ProjectRewardForCreateUpdateFragment } from '../../../../types/generated/graphql' +import { useMobileMode, useNotification } from '../../../../utils' +import { FundingFormSection } from '../components/FundingFormSection' +import { FundingFormUserInfoSection } from '../components/FundingFormUserInfoSection' +import { ProjectFundingSummaryCard } from '../components/ProjectFundingSummaryCard' type Props = { - isMobile?: boolean handleCloseButton: () => void - formState: IFundForm - setTarget: (_: any) => void - updateReward: any - setFormState: any handleFund: () => void - type: IProjectType rewards?: ProjectRewardForCreateUpdateFragment[] name: string } export const ProjectFundingSelectionFormScreen = ({ - isMobile, handleCloseButton, handleFund, - formState, - setTarget, - setFormState, - updateReward, rewards, name, }: Props) => { - const { t } = useTranslation() - const { getTotalAmount } = useFundCalc(formState) + const isMobile = useMobileMode() + const summaryCardRef = useRef(null) + + const [step, setStep] = useState<'contribution' | 'info'>('contribution') + + const { + fundForm: { state: formState, needsShipping }, + } = useProjectContext() + const { getTotalAmount } = useFundCalc(formState) const { toast } = useNotification() - const commentContainerRef = useRef(null) const hasRewards = rewards && rewards.length > 0 - const hasSelectedRewards = - formState.rewardsByIDAndCount && - Object.entries(formState.rewardsByIDAndCount).length > 0 - const submit = () => { - const valid = validateFundingAmount() - if (valid) { - handleFund() + const handleSubmit = { + contribution() { + const valid = validateFundingAmount() + if (valid) { + setStep('info') + } + }, + info() { + const valid = validateFundingUserInfo() + if (valid) { + handleFund() + } + }, + } + + const validateFundingUserInfo = () => { + if (needsShipping && !formState.email) { + toast({ + title: 'Email is a required field when donating for a reward.', + description: 'Please enter an email.', + status: 'error', + }) + return false } + + return true } const validateFundingAmount = () => { if (getTotalAmount('dollar', name) >= MAX_FUNDING_AMOUNT_USD) { toast({ - title: `${t('Payment above')} ${MAX_FUNDING_AMOUNT_USD} ${t( - 'is not allowed at the moment.', - )}`, + title: `Payment above ${MAX_FUNDING_AMOUNT_USD} is not allowed at the moment.`, description: 'Please update the amount, or contact us for donating a higher amount.', status: 'error', @@ -89,15 +85,6 @@ export const ProjectFundingSelectionFormScreen = ({ return false } - if (formState.rewardsCost && !formState.email) { - toast({ - title: 'Email is a required field when donating for a reward.', - description: 'Please enter an email.', - status: 'error', - }) - return false - } - return true } @@ -110,8 +97,8 @@ export const ProjectFundingSelectionFormScreen = ({ alignItems="flex-start" backgroundColor="neutral.0" marginBottom={ - isMobile && commentContainerRef.current - ? `${commentContainerRef.current.offsetHeight}px` + isMobile && summaryCardRef.current + ? `${summaryCardRef.current.offsetHeight}px` : undefined } > @@ -127,7 +114,13 @@ export const ProjectFundingSelectionFormScreen = ({ )} - + {step === 'contribution' ? ( + + ) : ( + setStep('contribution')} + /> + )} )} - - - {t('Comment')} - - - - {formState.rewardsCost && ( - - - - )} - - - - {hasRewards && hasSelectedRewards ? ( - - - {t('Rewards')} - - - {formState.rewardsByIDAndCount && - Object.entries(formState.rewardsByIDAndCount).map( - ([key, value]) => { - const reward = rewards.find(({ id }) => id === key) - if (reward) { - return ( - - {value}x {reward.name} - - ) - } - }, - )} - - - ) : null} - - - {t('Total')} - - - - {getTotalAmount('sats', name)} - - - - {`($${getTotalAmount('dollar', name)})`} - - - - - - - + ) diff --git a/src/pages/projectView/projectActivityPanel/screens/SuccessScreen.tsx b/src/pages/projectView/projectActivityPanel/screens/SuccessScreen.tsx index bc431f547..9da51684e 100644 --- a/src/pages/projectView/projectActivityPanel/screens/SuccessScreen.tsx +++ b/src/pages/projectView/projectActivityPanel/screens/SuccessScreen.tsx @@ -3,8 +3,6 @@ import { Button, CloseButton, VStack } from '@chakra-ui/react' import { useEffect, useState } from 'react' import ReactConfetti from 'react-confetti' import { useTranslation } from 'react-i18next' -import { BiCopyAlt } from 'react-icons/bi' -import { HiOutlineSpeakerphone } from 'react-icons/hi' import { Link } from 'react-router-dom' import { getPath } from '../../../../constants' @@ -19,12 +17,12 @@ import { ProjectFragment, UserBadge, } from '../../../../types' -import { copyTextToClipboard } from '../../../../utils' import { ContributionInfoBox, ContributionInfoBoxVersion, } from '../../projectMainBody/components' import { SuccessImageComponent } from '../components' +import { ContributionShippingBox } from '../components/ContributionShippingBox' type Props = { fundingState: IFundForm @@ -44,11 +42,6 @@ export const SuccessScreen = ({ const { getTotalAmount } = useFundCalc(fundingState) - const shareProjectWithFriends = () => { - copyTextToClipboard(window.location.href) - setCopy(true) - } - const { data } = useQuery<{ userBadges: UserBadge[] }>(QUERY_USER_BADGES, { variables: { input: { where: { fundingTxId: fundingTx.id } } }, }) @@ -78,7 +71,6 @@ export const SuccessScreen = ({ width="100%" height={{ base: 'calc(100vh - 115px)', lg: '100%' }} overflowX="hidden" - overflowY={{ base: 'auto', lg: 'hidden' }} position="relative" backgroundColor="primary.400" alignItems="center" @@ -100,33 +92,17 @@ export const SuccessScreen = ({ currentBadge={currentBadge} fundingTx={fundingTx} /> - - {fundingTx.funder.user?.id && currentBadge && ( - - )} + {fundingTx.funder.user?.id && currentBadge && ( - + )} + + ) diff --git a/src/pages/projectView/projectMainBody/components/RewardAdditionModal.tsx b/src/pages/projectView/projectMainBody/components/RewardAdditionModal.tsx index eb9fb8eb7..4778fd81d 100644 --- a/src/pages/projectView/projectMainBody/components/RewardAdditionModal.tsx +++ b/src/pages/projectView/projectMainBody/components/RewardAdditionModal.tsx @@ -1,5 +1,6 @@ import { - HStack, + Button, + Checkbox, Input, InputGroup, InputLeftAddon, @@ -7,31 +8,28 @@ import { VStack, } from '@chakra-ui/react' import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' import { BiDollar } from 'react-icons/bi' import { SatoshiIconTilted } from '../../../../components/icons' import { Modal } from '../../../../components/layouts/Modal' import { FileUpload } from '../../../../components/molecules' import { Body2 } from '../../../../components/typography' -import { - ButtonComponent, - ImageWithReload, - TextArea, - TextInputBox, - UploadBox, -} from '../../../../components/ui' +import { TextArea, TextInputBox, UploadBox } from '../../../../components/ui' import { ProjectRewardValidations } from '../../../../constants/validations' import { defaultProjectReward } from '../../../../defaults' +import { FieldContainer } from '../../../../forms/components/FieldContainer' import { CreateProjectRewardInput, ProjectFragment, ProjectRewardForCreateUpdateFragment, RewardCurrency, UpdateProjectRewardInput, - useCreateProjectRewardMutation, - useUpdateProjectRewardMutation, + useProjectRewardCreateMutation, + useProjectRewardUpdateMutation, } from '../../../../types/generated/graphql' import { commaFormatted, toInt, useNotification } from '../../../../utils' +import { CreatorEmailButton } from '../../projectActivityPanel/components/CreatorEmailButton' type Props = { isOpen: boolean @@ -55,8 +53,11 @@ export const RewardAdditionModal = ({ project, props, }: Props) => { + const { t } = useTranslation() const { toast } = useNotification() + const ownerEmail = project.owners[0]?.user.email || '' + const [formCostDollarValue, setFormCostDollarValue] = useState( defaultProjectReward.cost / 100, ) @@ -67,9 +68,9 @@ export const RewardAdditionModal = ({ const [formError, setFormError] = useState({}) const [createReward, { loading: createRewardLoading }] = - useCreateProjectRewardMutation({ + useProjectRewardCreateMutation({ onCompleted(data) { - onSubmit(data.createProjectReward, false) + onSubmit(data.projectRewardCreate, false) onClose() }, onError(error) { @@ -82,14 +83,14 @@ export const RewardAdditionModal = ({ }) const [updateReward, { loading: updateRewardLoading }] = - useUpdateProjectRewardMutation({ - onCompleted({ updateProjectReward }) { + useProjectRewardUpdateMutation({ + onCompleted(data) { toast({ title: 'Successfully updated!', - description: `Reward ${updateProjectReward.name} was successfully updated`, + description: `Reward ${data.projectRewardUpdate.name} was successfully updated`, status: 'success', }) - onSubmit(updateProjectReward, true) + onSubmit(data.projectRewardUpdate, true) onClose() }, onError(error) { @@ -110,6 +111,7 @@ export const RewardAdditionModal = ({ image: reward.image || undefined, name: reward.name, stock: reward.stock || undefined, + hasShipping: reward.hasShipping, } } @@ -122,6 +124,7 @@ export const RewardAdditionModal = ({ image: reward.image || undefined, name: reward.name, stock: reward.stock || undefined, + hasShipping: reward.hasShipping, } } @@ -186,6 +189,14 @@ export const RewardAdditionModal = ({ setReward((current) => ({ ...current, image: url })) } + const handleDeleteThumbnail = () => { + setReward((current) => ({ ...current, image: null })) + } + + const handleShipping = (event: React.ChangeEvent) => { + setReward((current) => ({ ...current, hasShipping: event.target.checked })) + } + const validateReward = () => { const errors: any = {} let isValid = true @@ -234,6 +245,9 @@ export const RewardAdditionModal = ({ return ( @@ -245,21 +259,9 @@ export const RewardAdditionModal = ({ } - isOpen={isOpen} - onClose={onClose} > - - - Name + + - + - - Description +