Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sajal/gys-8621-add-modal-before-contribute-flow-for-projects-in-an-active #1623

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/components/molecules/AuthModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ import {
} from '../../utils'
import { Caption } from '../typography'

interface IAuthModal {
isOpen: boolean
onClose: () => void
export type AuthModalAdditionalprops = {
title?: string
description?: string
showTwitter?: boolean
Expand All @@ -41,6 +39,10 @@ interface IAuthModal {
showGithub?: boolean
privateRoute?: boolean
}
type AuthModalProps = {
isOpen: boolean
onClose: () => void
} & AuthModalAdditionalprops

const ConnectAccounts = ({
onClose,
Expand Down Expand Up @@ -107,7 +109,7 @@ const ConnectAccounts = ({
)
}

export const AuthModal = (authModalProps: IAuthModal) => {
export const AuthModal = (authModalProps: AuthModalProps) => {
const { t } = useTranslation()
const isMobile = useMobileMode()
const {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/navigation/platformNavBar/PlatformNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { ProfileNav } from './profileNav/ProfileNav'

export const PlatformNavBar = () => {
const { isLoggedIn, logout, queryCurrentUser } = useAuthContext()
const { loginIsOpen, loginOnClose } = useAuthModal()
const { loginIsOpen, loginOnClose, loginModalAdditionalProps } = useAuthModal()

const isMobileMode = useMobileMode()

Expand Down Expand Up @@ -122,6 +122,7 @@ export const PlatformNavBar = () => {
onLoginAlertModalClose()
emailPromptOnOpen()
}}
{...loginModalAdditionalProps}
/>
<EmailPromptModal isOpen={emailPromptIsOpen} onClose={emailPromptOnClose} />
</HStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const LoggedOutModal = ({ isOpen, onClose }: UseModalProps) => {
<ModalBody>
<Text>{t('Please log back in with your profile, or press continue if want to stay anonymous.')}</Text>
<Box display="flex" justifyContent="space-between" paddingTop="20px">
<Button variant="solid" colorScheme="primary1" width="50%" mx={1} onClick={loginOnOpen}>
<Button variant="solid" colorScheme="primary1" width="50%" mx={1} onClick={() => loginOnOpen()}>
{t('Login')}
</Button>
<Button variant="soft" colorScheme="neutral1" width="50%" mx={1} onClick={onClose}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export const LoginButton = (props: ButtonProps) => {
const { loginOnOpen } = useAuthModal()
const { t } = useTranslation()
return (
<Button size={{ base: 'md', lg: 'lg' }} variant="outline" colorScheme="primary1" onClick={loginOnOpen} {...props}>
<Button
size={{ base: 'md', lg: 'lg' }}
variant="outline"
colorScheme="primary1"
onClick={() => loginOnOpen()}
{...props}
>
{t('Sign in')}
</Button>
)
Expand Down
53 changes: 53 additions & 0 deletions src/modules/project/API/useProjectGrantApplicationsAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useAtom, useSetAtom } from 'jotai'
import { useEffect } from 'react'

import { ProjectGrantApplicationsWhereInputEnum, useProjectGrantApplicationsLazyQuery } from '../../../types'
import { useProjectAtom } from '../hooks/useProjectAtom'
import { initialProjectGrantApplicationsLoadAtom, partialUpdateProjectAtom } from '../state/projectAtom'

/**
* Query project grant applications for project context
* @param load - Load project grant applications on mount
*/
export const useProjectGrantApplicationsAPI = (load?: boolean) => {
const partialUpdateProject = useSetAtom(partialUpdateProjectAtom)
const [initialProjectGrantApplicationsLoad, setInitialProjectGrantApplicationsLoad] = useAtom(
initialProjectGrantApplicationsLoadAtom,
)

const { project, loading } = useProjectAtom()

const [queryProjectGrantApplications, queryProjectGrantApplicationsOptions] = useProjectGrantApplicationsLazyQuery({
variables: {
where: { id: project.id },
input: {
where: {
grantStatus: ProjectGrantApplicationsWhereInputEnum.FundingOpen,
},
},
},
fetchPolicy: 'cache-first',

onCompleted(data) {
if (!data.projectGet) {
return
}

partialUpdateProject(data.projectGet)
setInitialProjectGrantApplicationsLoad(true)
},
})

useEffect(() => {
if (project.id && !loading && load && !initialProjectGrantApplicationsLoad) {
queryProjectGrantApplications()
}
}, [project.id, loading, load, queryProjectGrantApplications, initialProjectGrantApplicationsLoad])

return {
queryProjectGrantApplications: {
execute: queryProjectGrantApplications,
...queryProjectGrantApplicationsOptions,
},
}
}
18 changes: 18 additions & 0 deletions src/modules/project/graphql/fragments/grantFragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { gql } from '@apollo/client'

export const FRAGMENT_PROJECT_GRANT_APPLICANT = gql`
fragment ProjectGrantApplicant on GrantApplicant {
id
status
grant {
... on CommunityVoteGrant {
id
votingSystem
type
name
title
status
}
}
}
`
12 changes: 12 additions & 0 deletions src/modules/project/graphql/queries/projectQuery.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { gql } from '@apollo/client'

import { FRAGMENT_PROJECT_GRANT_APPLICANT } from '../fragments/grantFragment'
import {
FRAGMENT_PROJECT_HEADER_SUMMARY,
FRAGMENT_PROJECT_PAGE_BODY,
Expand All @@ -25,6 +26,17 @@ export const QUERY_PROJECT_PAGE_DETAILS = gql`
}
`

export const QUERY_PROJECT_GRANT_APPLICATION = gql`
${FRAGMENT_PROJECT_GRANT_APPLICANT}
query ProjectGrantApplications($where: UniqueProjectQueryInput!, $input: ProjectGrantApplicationsInput) {
projectGet(where: $where) {
grantApplications(input: $input) {
...ProjectGrantApplicant
}
}
}
`

export const QUERY_PROJECT_HEADER_SUMMARY = gql`
${FRAGMENT_PROJECT_HEADER_SUMMARY}
query ProjectPageHeaderSummary($where: UniqueProjectQueryInput!) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const FundingDetailsUserComment = () => {
{'Funding anonymously. '}
<Box
as="span"
onClick={loginOnOpen}
onClick={() => loginOnOpen()}
color="primary.600"
fontWeight="bold"
_hover={{ cursor: 'pointer' }}
Expand All @@ -93,7 +93,7 @@ export const FundingDetailsUserComment = () => {
<Box zIndex="10" position="absolute" left={2} top={2}>
{isAnonymous || !user ? (
<Tooltip shouldWrapChildren label={t('Funding anonymously. Click to login')}>
<AvatarElement borderRadius="50%" noLink onClick={loginOnOpen} avatarOnly />
<AvatarElement borderRadius="50%" noLink onClick={() => loginOnOpen()} avatarOnly />
</Tooltip>
) : (
<Tooltip shouldWrapChildren label={`${t('Funding as')} ${user.username}. ${t('Click to logout')}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { Button, ButtonProps } from '@chakra-ui/react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'

import { useProjectGrantApplicationsAPI } from '@/modules/project/API/useProjectGrantApplicationsAPI'
import { getPath } from '@/shared/constants'
import { useModal } from '@/shared/hooks'
import { VotingInfoModal } from '@/shared/molecules/VotingInfoModal'
import { CommunityVoteGrant, GrantStatusEnum, VotingSystem } from '@/types'

import { isActive } from '../../../../../../../utils'
import { useProjectAtom } from '../../../../../hooks/useProjectAtom'
Expand All @@ -12,24 +16,55 @@ export const ContributeButton = (props: ButtonProps) => {

const navigate = useNavigate()

const votingInfoModal = useModal()

const { queryProjectGrantApplications } = useProjectGrantApplicationsAPI(true)

const { project } = useProjectAtom()

if (!project) {
return null
}

const communityVotingGrant =
project?.grantApplications &&
project.grantApplications.length > 0 &&
(project.grantApplications.find(
(application) =>
application.grant.__typename === 'CommunityVoteGrant' &&
application.grant.status === GrantStatusEnum.FundingOpen,
)?.grant as CommunityVoteGrant)

const isStepVoting = communityVotingGrant ? communityVotingGrant.votingSystem === VotingSystem.StepLog_10 : false

const isFundingDisabled = !isActive(project.status)

return (
<Button
size="lg"
variant="solid"
colorScheme="primary1"
isDisabled={isFundingDisabled}
onClick={() => navigate(getPath('projectFunding', project.name))}
{...props}
>
{t('Contribute')}
</Button>
<>
{communityVotingGrant && isStepVoting && (
<VotingInfoModal
{...votingInfoModal}
modalTitle={t('Project is part of a voting grant')}
grantName={communityVotingGrant.title}
votingSystem={VotingSystem.StepLog_10}
project={project}
/>
)}
<Button
size="lg"
variant="solid"
colorScheme="primary1"
isDisabled={isFundingDisabled}
onClick={() =>
communityVotingGrant && isStepVoting
? votingInfoModal.onOpen()
: navigate(getPath('projectFunding', project.name))
}
isLoading={queryProjectGrantApplications.loading}
{...props}
>
{t('Contribute')}
</Button>
</>
)
}
15 changes: 13 additions & 2 deletions src/modules/project/state/projectAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { useCallback } from 'react'
import { toInt } from '@/utils'

import { authUserAtom } from '../../../pages/auth/state'
import { ProjectHeaderSummaryFragment, ProjectPageBodyFragment, ProjectPageDetailsFragment } from '../../../types'
import {
ProjectGrantApplicantFragment,
ProjectHeaderSummaryFragment,
ProjectPageBodyFragment,
ProjectPageDetailsFragment,
} from '../../../types'
import { resetRewardsAtom } from '../pages1/projectDashboard/views/sales/state/rewardsAtom'
import { affiliateAtomReset } from './affiliateAtom'
import { contributionAtomReset } from './contributionsAtom'
Expand All @@ -14,7 +19,9 @@ import { projectFormAtomReset } from './projectFormAtom'
import { rewardsAtomReset } from './rewardsAtom'
import { walletAtomReset } from './walletAtom'

export type ProjectState = ProjectPageBodyFragment & ProjectHeaderSummaryFragment & ProjectPageDetailsFragment
export type ProjectState = ProjectPageBodyFragment &
ProjectHeaderSummaryFragment &
ProjectPageDetailsFragment & { grantApplications?: ProjectGrantApplicantFragment[] }

/** Project atom is the root project store */
export const projectAtom = atom<ProjectState>({} as ProjectState)
Expand Down Expand Up @@ -81,11 +88,15 @@ export const projectOwnerAtom = atom((get) => {
/** Initial load for project details, set to true after loaded */
export const initialProjectDetailsLoadAtom = atom(false)

/** Initial load for project grant applications, set to true after loaded */
export const initialProjectGrantApplicationsLoadAtom = atom(false)

/** Reset all real-atoms in this file to it's initial State */
export const projectAtomReset = atom(null, (get, set) => {
set(projectAtom, {} as ProjectState)
set(projectLoadingAtom, true)
set(initialProjectDetailsLoadAtom, false)
set(initialProjectGrantApplicationsLoadAtom, false)
})

export const useProjectReset = () => {
Expand Down
22 changes: 17 additions & 5 deletions src/pages/auth/hooks/useAuthModal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { useAtom } from 'jotai'
import { useAtom, useSetAtom } from 'jotai'

import { isLoginModalOpenAtom } from '../state'
import { AuthModalAdditionalprops } from '@/components/molecules'

import { isLoginModalOpenAtom, loginModalAdditionalPropsAtom, resetLoginModalAdditionalPropsAtom } from '../state'

export const useAuthModal = () => {
const [loginIsOpen, setLoginIsOpen] = useAtom(isLoginModalOpenAtom)
const [loginModalAdditionalProps, setLoginModalAdditionalProps] = useAtom(loginModalAdditionalPropsAtom)
const resetLoginModalAdditionalProps = useSetAtom(resetLoginModalAdditionalPropsAtom)

const loginOnOpen = () => setLoginIsOpen(true)
const loginOnOpen = (props?: AuthModalAdditionalprops) => {
setLoginIsOpen(true)
if (props) {
setLoginModalAdditionalProps(props)
}
}

const loginOnClose = () => setLoginIsOpen(false)
const loginOnClose = () => {
setLoginIsOpen(false)
resetLoginModalAdditionalProps()
}

return { loginIsOpen, loginOnOpen, loginOnClose }
return { loginIsOpen, loginOnOpen, loginOnClose, loginModalAdditionalProps }
}
22 changes: 22 additions & 0 deletions src/pages/auth/state/authAtom.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { atom, useAtomValue } from 'jotai'
import { atomWithStorage } from 'jotai/utils'

import { AuthModalAdditionalprops } from '@/components/molecules'

import { Project, UserMeFragment } from '../../../types'
import { ExternalAccountType, SocialAccountType } from '../type'

Expand All @@ -15,6 +17,18 @@ export const defaultUser: UserMeFragment = {
hasSocialAccount: false,
}

export const defaultLoginAdditionalProps: AuthModalAdditionalprops = {
title: '',
description: '',
showTwitter: true,
showNostr: true,
showLightning: true,
showFacebook: true,
showGoogle: true,
showGithub: true,
privateRoute: false,
}

/** Primary user that is logged in */
export const authUserAtom = atom<UserMeFragment>(defaultUser)

Expand All @@ -31,5 +45,13 @@ export const useFollowedProjectsValue = () => useAtomValue(followedProjectsAtom)
/** Used to open login modal from any place */
export const isLoginModalOpenAtom = atom<boolean>(false)

/** Additional props for the login modal */
export const loginModalAdditionalPropsAtom = atom<AuthModalAdditionalprops>(defaultLoginAdditionalProps)

/** Reset the additional props for the login modal */
export const resetLoginModalAdditionalPropsAtom = atom(null, (_get, set) => {
set(loginModalAdditionalPropsAtom, defaultLoginAdditionalProps)
})

/** Login method used by the current User */
export const loginMethodAtom = atomWithStorage<ExternalAccountType | SocialAccountType | ''>('loginMethod', '')
Loading
Loading