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

feat: add my contributions tab to user profile #1148

Merged
merged 2 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions src/graphql/queries/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const QUERY_USER_PROFILE = gql`
description
createdAt
status
thumbnailImage
}
}
ownerOf {
Expand Down
83 changes: 83 additions & 0 deletions src/pages/profile/views/profileTabs/ProfileContributions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'

import { Box, HStack, VStack, Link } from '@chakra-ui/react'

import type { User, UserProjectContribution } from '../../../../types'
import { getPath } from '../../../../constants'
import { H3 } from '../../../../components/typography'
import { ImageWithReload, SatoshiAmount } from '../../../../components/ui'
import { ProfileTabLayout } from '../../components'

function contributionAmount(c: UserProjectContribution) {
if (c.funder) {
return c.funder.amountFunded ?? 0
}
return 0
}

interface ContributionSummaryProps {
title: string
url: string
imageSrc: string
amount: number
}

const ContributionSummary = ({
title,
url,
amount,
imageSrc,
}: ContributionSummaryProps) => {
return (
<HStack spacing={2}>
<Box width="75px" height="66px">
<ImageWithReload
width="100%"
height="100%"
objectFit="cover"
src={imageSrc}
alt={`${title}-header-image`}
borderRadius="8px"
/>
</Box>
<VStack align="flex-start">
<Link href={url} textDecoration="none">
<H3>{title}</H3>
</Link>
<SatoshiAmount color="primary.800" fontSize="2xl" fontWeight="bold">
{amount}
</SatoshiAmount>
</VStack>
</HStack>
)
}

export const ProfileContributions = ({
userProfile,
}: {
userProfile: User
}) => {
const { t } = useTranslation()
const contributions = useMemo(() => {
const contributions = [...userProfile.contributions]
contributions.sort(
(a: UserProjectContribution, b: UserProjectContribution) =>
contributionAmount(b) - contributionAmount(a),
)
return contributions
}, [userProfile])
return (
<ProfileTabLayout title={t('My contributions')}>
{contributions.map((c: UserProjectContribution) => (
<ContributionSummary
key={c.project.id}
title={c.project.name}
imageSrc={c.project.thumbnailImage || ''}
verbiricha marked this conversation as resolved.
Show resolved Hide resolved
url={getPath('project', c.project.name)}
amount={contributionAmount(c)}
/>
))}
</ProfileTabLayout>
)
}
15 changes: 14 additions & 1 deletion src/pages/profile/views/profileTabs/ProfileTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { User } from '../../../../types'
import { ProfileActivity } from './ProfileActivity'
import { ProfileFollowed } from './ProfileFollowed'
import { ProfileProjects } from './ProfileProjects'
import { ProfileContributions } from './ProfileContributions'

export const ProfileTabs = ({
userProfile,
Expand All @@ -23,6 +24,14 @@ export const ProfileTabs = ({
[userProfile],
)

const contributionsTab = useMemo(
() => ({
title: 'My contributions',
Component: () => <ProfileContributions userProfile={userProfile} />,
}),
[userProfile],
)

const projectsTab = useMemo(
() => ({
title: 'Projects',
Expand Down Expand Up @@ -52,8 +61,12 @@ export const ProfileTabs = ({
return [activityTab]
}

if (isViewingOwnProfile) {
tabs.push(contributionsTab)
}

if (userProfile.ownerOf?.length > 0 || isViewingOwnProfile) {
tabs = [projectsTab, ...tabs]
tabs.unshift(projectsTab)
}

if (userProfile.projectFollows?.length) {
Expand Down
101 changes: 51 additions & 50 deletions src/translations/English.json
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,9 @@
"Select region": "Select region",
"You must write a project story.": "You must write a project story.",
"Project story should be shorter than": "Project story should be shorter than",
"Project story should be shorter than 4000 characters.":"Project story should be shorter than 4000 characters.",
"Geyser is sponsoring 10M Sats to support bitcoin films, but it’s the community who decides who wins the grant. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.":"Geyser is sponsoring 10M Sats to support bitcoin films, but it’s the community who decides who wins the grant. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.",
"This grant support video-game developers that have integrated or want to integrate bitcoin and lightning in their platforms. The aim is to celebrate and showcase the power of lightning micropayments to the use case of gaming. Yes, Bitcoin makes gaming fun and rewarding!\n\nThis is a community-voting grant where the community grant fund distribution by voting. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.":"This grant support video-game developers that have integrated or want to integrate bitcoin and lightning in their platforms. The aim is to celebrate and showcase the power of lightning micropayments to the use case of gaming. Yes, Bitcoin makes gaming fun and rewarding!\n\nThis is a community-voting grant where the community grant fund distribution by voting. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.",
"Project story should be shorter than 4000 characters.": "Project story should be shorter than 4000 characters.",
"Geyser is sponsoring 10M Sats to support bitcoin films, but it’s the community who decides who wins the grant. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.": "Geyser is sponsoring 10M Sats to support bitcoin films, but it’s the community who decides who wins the grant. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.",
"This grant support video-game developers that have integrated or want to integrate bitcoin and lightning in their platforms. The aim is to celebrate and showcase the power of lightning micropayments to the use case of gaming. Yes, Bitcoin makes gaming fun and rewarding!\n\nThis is a community-voting grant where the community grant fund distribution by voting. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.": "This grant support video-game developers that have integrated or want to integrate bitcoin and lightning in their platforms. The aim is to celebrate and showcase the power of lightning micropayments to the use case of gaming. Yes, Bitcoin makes gaming fun and rewarding!\n\nThis is a community-voting grant where the community grant fund distribution by voting. Vote with your Sats! 1 Sat = 1 vote. Grant funds will be distributed proportionally to the number of votes received while the grant is active.",
"Includes Shipping": "Includes Shipping",
"Shipping": "Shipping",
"Public comment": "Public comment",
Expand Down Expand Up @@ -587,7 +587,7 @@
"The owner of this badge contributed to 10 different Geyser projects.": "The owner of this badge contributed to 10 different Geyser projects.",
"The owner of this badge contributed to 50 different Geyser projects.": "The owner of this badge contributed to 50 different Geyser projects.",
"The owner of this badge contributed to 100 different Geyser projects.": "The owner of this badge contributed to 100 different Geyser projects.",
"The owner of this badge is a Geyser open-source contributor. Without you Geyser would be a lot less.":"The owner of this badge is a Geyser open-source contributor. Without you Geyser would be a lot less.",
"The owner of this badge is a Geyser open-source contributor. Without you Geyser would be a lot less.": "The owner of this badge is a Geyser open-source contributor. Without you Geyser would be a lot less.",
"The owner of this badge was a guest on The Geyser Podcast.": "The owner of this badge was a guest on The Geyser Podcast.",
"The first 100 projects on Geyser receive this badge for being early believers of our mission.": "The first 100 projects on Geyser receive this badge for being early believers of our mission.",
"The owner of this badge won the Geyser Grant Round 1 for doing great work for the Bitcoin ecosystem.": "The owner of this badge won the Geyser Grant Round 1 for doing great work for the Bitcoin ecosystem.",
Expand Down Expand Up @@ -626,50 +626,51 @@
"Failed to update email.": "Failed to update email.",
"Failed to verify email.": "Failed to verify email.",
"Your email": "Your email",
"The project wallet can only be changed by the project creator with a verified email, for security reasons. You can verify your email in the Profile page’s Settings.":"The project wallet can only be changed by the project creator with a verified email, for security reasons. You can verify your email in the Profile page’s Settings.",
"Wallet updated successfully!":"Wallet updated successfully!",
"Failed to update wallet.":"Failed to update wallet.",
"Failed to login with email":"Failed to login with email",
"You can update your wallet securely by using the One Time Password sent to your verified email.":"You can update your wallet securely by using the One Time Password sent to your verified email.",
"This email is where you will receive important project notifications":"This email is where you will receive important project notifications",
"Verify email":"Verify email",
"This email has not been verified":"This email has not been verified",
"You can update your email securely by using One Time Password sent to your last verfied email.":"You can update your email securely by using One Time Password sent to your last verfied email.",
"Delete profile":"Delete profile",
"Failed to delete profile":"Failed to delete profile",
"Settings":"Settings",
"Delete your profile permanently from Geyser.":"Delete your profile permanently from Geyser.",
"Verify your email to secure your account and be able to edit project wallet information. This email will be used to notify you on important project and wallet updates.":"Verify your email to secure your account and be able to edit project wallet information. This email will be used to notify you on important project and wallet updates.",
"To delete your profile permanently from Geyser.":"To delete your profile permanently from Geyser.",
"Your profile has been deleted.":"Your profile has been deleted.",
"Profile has been deleted":"Profile has been deleted",
"Type '{{textToConfirm}}' and confirm":"Type '{{textToConfirm}}' and confirm",
"Close":"Close",
"Check your SPAM folder for the email.":"Check your SPAM folder for the email.",
"As a project creator, you cannot delete your profile":"As a project creator, you cannot delete your profile",
"Successfully updated user email":"Successfully updated user email",
"Email verification successfull!":"Email verification successfull!",
"Copy lightning invoice":"Copy lightning invoice",
"Copy onchain address":"Copy onchain address",
"Update available":"Update available",
"There is a newer version of the app available":"There is a newer version of the app available",
"Would you like to reload the page to get the latest update?":"Would you like to reload the page to get the latest update?",
"Supporters":"Supporters",
"There's a new version of Geyser!":"There's a new version of Geyser!",
"Restart the app to load the new version":"Restart the app to load the new version",
"Not now":"Not now",
"Restart app":"Restart app",
"Add row above":"Add row above",
"Add row below":"Add row below",
"Add column left":"Add column left",
"Add column right":"Add column right",
"Remove column":"Remove column",
"Remove row":"Remove row",
"Insert video":"Insert video",
"Insert":"Insert",
"Must be a valid twitter URL":"Must be a valid twitter URL",
"URL is required":"URL is required",
"Insert tweet":"Insert tweet",
"Failed to insert tweet":"Failed to insert tweet",
"Funding as anonymous. <1>Click here</1> to connect profile to contribution":"Funding as anonymous. <1>Click here</1> to connect profile to contribution"
"The project wallet can only be changed by the project creator with a verified email, for security reasons. You can verify your email in the Profile page’s Settings.": "The project wallet can only be changed by the project creator with a verified email, for security reasons. You can verify your email in the Profile page’s Settings.",
"Wallet updated successfully!": "Wallet updated successfully!",
"Failed to update wallet.": "Failed to update wallet.",
"Failed to login with email": "Failed to login with email",
"You can update your wallet securely by using the One Time Password sent to your verified email.": "You can update your wallet securely by using the One Time Password sent to your verified email.",
"This email is where you will receive important project notifications": "This email is where you will receive important project notifications",
"Verify email": "Verify email",
"This email has not been verified": "This email has not been verified",
"You can update your email securely by using One Time Password sent to your last verfied email.": "You can update your email securely by using One Time Password sent to your last verfied email.",
"Delete profile": "Delete profile",
"Failed to delete profile": "Failed to delete profile",
"Settings": "Settings",
"Delete your profile permanently from Geyser.": "Delete your profile permanently from Geyser.",
"Verify your email to secure your account and be able to edit project wallet information. This email will be used to notify you on important project and wallet updates.": "Verify your email to secure your account and be able to edit project wallet information. This email will be used to notify you on important project and wallet updates.",
"To delete your profile permanently from Geyser.": "To delete your profile permanently from Geyser.",
"Your profile has been deleted.": "Your profile has been deleted.",
"Profile has been deleted": "Profile has been deleted",
"Type '{{textToConfirm}}' and confirm": "Type '{{textToConfirm}}' and confirm",
"Close": "Close",
"Check your SPAM folder for the email.": "Check your SPAM folder for the email.",
"As a project creator, you cannot delete your profile": "As a project creator, you cannot delete your profile",
"Successfully updated user email": "Successfully updated user email",
"Email verification successfull!": "Email verification successfull!",
"Copy lightning invoice": "Copy lightning invoice",
"Copy onchain address": "Copy onchain address",
"Update available": "Update available",
"There is a newer version of the app available": "There is a newer version of the app available",
"Would you like to reload the page to get the latest update?": "Would you like to reload the page to get the latest update?",
"Supporters": "Supporters",
"There's a new version of Geyser!": "There's a new version of Geyser!",
"Restart the app to load the new version": "Restart the app to load the new version",
"Not now": "Not now",
"Restart app": "Restart app",
"Add row above": "Add row above",
"Add row below": "Add row below",
"Add column left": "Add column left",
"Add column right": "Add column right",
"Remove column": "Remove column",
"Remove row": "Remove row",
"Insert video": "Insert video",
"Insert": "Insert",
"Must be a valid twitter URL": "Must be a valid twitter URL",
"URL is required": "URL is required",
"Insert tweet": "Insert tweet",
"Failed to insert tweet": "Failed to insert tweet",
"Funding as anonymous. <1>Click here</1> to connect profile to contribution": "Funding as anonymous. <1>Click here</1> to connect profile to contribution",
"My contributions": "My contributions"
}
103 changes: 2 additions & 101 deletions src/types/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4571,16 +4571,6 @@ export type ProjectFragment = {
}>
}

export type ProjectFundersFragment = {
__typename?: 'Funder'
id: any
amountFunded?: number | null
confirmed: boolean
confirmedAt?: any | null
timesFunded?: number | null
user?: ({ __typename?: 'User' } & UserForAvatarFragment) | null
}

export type UserMeFragment = {
__typename?: 'User'
id: any
Expand Down Expand Up @@ -5484,19 +5474,6 @@ export type ProjectByNameOrIdQuery = {
projectGet?: ({ __typename?: 'Project' } & ProjectFragment) | null
}

export type ProjectFundingDataQueryVariables = Exact<{
where: UniqueProjectQueryInput
input?: InputMaybe<ProjectEntriesGetInput>
}>

export type ProjectFundingDataQuery = {
__typename?: 'Query'
projectGet?: {
__typename?: 'Project'
funders: Array<{ __typename?: 'Funder' } & ProjectFundersFragment>
} | null
}

export type ProjectsQueryVariables = Exact<{
input?: InputMaybe<ProjectsGetQueryInput>
}>
Expand Down Expand Up @@ -5805,6 +5782,7 @@ export type UserProfileQuery = {
description?: any | null
createdAt: string
status?: ProjectStatus | null
thumbnailImage?: string | null
}
}>
ownerOf: Array<{
Expand Down Expand Up @@ -6144,19 +6122,6 @@ export const ProjectFragmentDoc = gql`
${UserForAvatarFragmentDoc}
${EntryForProjectFragmentDoc}
`
export const ProjectFundersFragmentDoc = gql`
fragment projectFunders on Funder {
id
user {
...UserForAvatar
}
amountFunded
confirmed
confirmedAt
timesFunded
}
${UserForAvatarFragmentDoc}
`
export const FunderWithUserFragmentDoc = gql`
fragment FunderWithUser on Funder {
amountFunded
Expand Down Expand Up @@ -9148,71 +9113,6 @@ export type ProjectByNameOrIdQueryResult = Apollo.QueryResult<
ProjectByNameOrIdQuery,
ProjectByNameOrIdQueryVariables
>
export const ProjectFundingDataDocument = gql`
query ProjectFundingData(
$where: UniqueProjectQueryInput!
$input: ProjectEntriesGetInput
) {
projectGet(where: $where) {
funders {
...projectFunders
}
}
}
${ProjectFundersFragmentDoc}
`

/**
* __useProjectFundingDataQuery__
*
* To run a query within a React component, call `useProjectFundingDataQuery` and pass it any options that fit your needs.
* When your component renders, `useProjectFundingDataQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useProjectFundingDataQuery({
* variables: {
* where: // value for 'where'
* input: // value for 'input'
* },
* });
*/
export function useProjectFundingDataQuery(
baseOptions: Apollo.QueryHookOptions<
ProjectFundingDataQuery,
ProjectFundingDataQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions }
return Apollo.useQuery<
ProjectFundingDataQuery,
ProjectFundingDataQueryVariables
>(ProjectFundingDataDocument, options)
}
export function useProjectFundingDataLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProjectFundingDataQuery,
ProjectFundingDataQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions }
return Apollo.useLazyQuery<
ProjectFundingDataQuery,
ProjectFundingDataQueryVariables
>(ProjectFundingDataDocument, options)
}
export type ProjectFundingDataQueryHookResult = ReturnType<
typeof useProjectFundingDataQuery
>
export type ProjectFundingDataLazyQueryHookResult = ReturnType<
typeof useProjectFundingDataLazyQuery
>
export type ProjectFundingDataQueryResult = Apollo.QueryResult<
ProjectFundingDataQuery,
ProjectFundingDataQueryVariables
>
export const ProjectsDocument = gql`
query Projects($input: ProjectsGetQueryInput) {
projects(input: $input) {
Expand Down Expand Up @@ -10192,6 +10092,7 @@ export const UserProfileDocument = gql`
description
createdAt
status
thumbnailImage
}
}
ownerOf {
Expand Down
Loading