Skip to content

Commit

Permalink
220 desktop design (#237)
Browse files Browse the repository at this point in the history
* wip: working has stream design

* add: finalize design

* fix: lint

* fix: eslint

* fix: fixed impact button on mobile

* fix: layout difference on collective page

* Update packages/app/src/components/ViewCollective.tsx

* Update packages/app/src/components/ViewCollective.tsx

---------

Co-authored-by: LewisB <[email protected]>
Co-authored-by: Lewis B <[email protected]>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent 754ec05 commit c6934e8
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 134 deletions.
1 change: 0 additions & 1 deletion packages/app/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
// Import the crypto getRandomValues shim (**BEFORE** the shims)
import 'react-native-get-random-values';

Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/CollectiveHomeCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Image, StyleSheet, Text, TouchableOpacity, TouchableOpacityProps, View } from 'react-native';
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

import { InterSemiBold, InterSmall } from '../utils/webFonts';
import useCrossNavigate from '../routes/useCrossNavigate';
Expand Down
10 changes: 8 additions & 2 deletions packages/app/src/components/ImpactButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Image, Text, TouchableOpacity, View, StyleSheet } from 'react-native';
import { Image, Platform, Text, TouchableOpacity, View, StyleSheet } from 'react-native';

import { InterSemiBold } from '../utils/webFonts';
import { Colors } from '../utils/colors';
Expand All @@ -14,7 +14,13 @@ function ImpactButton({ title, onClick }: ImpactButtonProps) {
const { isDesktopView } = useScreenSize();

return (
<TouchableOpacity style={[styles.button, isDesktopView && styles.desktopButton]} onPress={onClick}>
<TouchableOpacity
style={[
styles.button,
isDesktopView && styles.desktopButton,
!isDesktopView ? Platform.select({ web: { position: 'fixed' } }) : {},
]}
onPress={onClick}>
<View style={[styles.buttonContent, isDesktopView && styles.buttonDesktopContent]}>
<Text style={styles.buttonText}>{title}</Text>
<Image source={chevronRight} style={styles.icon} />
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function Layout({ children, breadcrumbPath }: LayoutProps) {
styles.scrollView,
{ ...(!isMobileView && { maxHeight: scrollViewHeight, minHeight: scrollViewHeight }) },
{ paddingBottom: isCollectivePage ? 61 : 0 },
{ paddingHorizontal: isTabletView ? 48 : isMobileView ? 8 : 24 },
{ paddingHorizontal: isTabletView ? 48 : isMobileView ? 0 : isCollectivePage ? 0 : 24 },
];

return (
Expand Down
281 changes: 154 additions & 127 deletions packages/app/src/components/ViewCollective.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { StyleSheet, Text, Image } from 'react-native';
import { Link, View } from 'native-base';
import { StyleSheet, Image } from 'react-native';
import { Link, useBreakpointValue, Text, View, VStack } from 'native-base';
import { useAccount, useEnsName } from 'wagmi';

import RowItem from './RowItem';
Expand All @@ -13,7 +13,7 @@ import { Colors } from '../utils/colors';
import { useScreenSize } from '../theme/hooks';

import { formatTime } from '../lib/formatTime';
import { Collective } from '../models/models';
import { Collective, DonorCollective } from '../models/models';
import { useDonorCollectiveByAddresses, useGetTokenPrice } from '../hooks';
import {
AtIcon,
Expand All @@ -33,11 +33,138 @@ import {
} from '../assets/';
import { calculateGoodDollarAmounts } from '../lib/calculateGoodDollarAmounts';
import FlowingDonationsRowItem from './FlowingDonationsRowItem';
import { defaultInfoLabel, SUBGRAPH_POLL_INTERVAL } from '../models/constants';
import { defaultInfoLabel, GDToken, SUBGRAPH_POLL_INTERVAL } from '../models/constants';
import env from '../lib/env';
import { ActiveStreamCard } from './ActiveStreamCard';
import { WalletDonatedCard } from './WalletCards/WalletDonatedCard';
import { useGetTokenBalance } from '../hooks/useGetTokenBalance';
import { useFlowingBalance } from '../hooks/useFlowingBalance';
import { GoodDollarAmount } from './GoodDollarAmount';
import { styles as walletCardStyles } from '../components/WalletCards/styles';
import { formatFlowRate } from '../lib/formatFlowRate';
import { StopDonationActionButton } from './StopDonationActionButton';

const HasDonatedCard = ({
donorCollective,
tokenPrice,
}: {
donorCollective?: DonorCollective;
tokenPrice?: number;
}) => {
const { address } = useAccount();
const { data: ensName } = useEnsName({ address, chainId: 1 });
const userName = ensName ?? 'This wallet';
const { navigate } = useCrossNavigate();
const isDonating = donorCollective && donorCollective.flowRate !== '0';
const hasDonated = isDonating || (donorCollective && donorCollective.contribution !== '0');
const donorBalance = useGetTokenBalance(GDToken.address, donorCollective?.donor as any);
const secondsLeft = isDonating ? Number(BigInt(donorBalance) / BigInt(donorCollective?.flowRate || 1)) : 0;
const endDate = formatTime(Date.now() / 1000 + secondsLeft);

const { wei: donationsFormatted, usdValue: donationsUsdValue } = useFlowingBalance(
donorCollective?.contribution || '0',
donorCollective?.timestamp || 0, // Timestamp in Subgraph's UTC.
donorCollective?.flowRate || '0',
tokenPrice
);
const container = useBreakpointValue({
base: {
flexDirection: 'column',
borderTopWidth: 1,
borderColor: 'goodGrey.600',
gap: 4,
marginTop: 8,
},
xl: {
gap: 8,
flexDirection: 'row',
borderTopWidth: 1,
borderColor: 'goodGrey.600',
marginTop: 8,
paddingTop: 8,
marginBottom: 8,
justifyContent: 'space-between',
},
});
if (!donorCollective || !hasDonated) return null;
return (
<View width={'100%'}>
<View {...container} flexGrow={1}>
<View flexGrow={0}>
<Image source={SupportImage} style={styles.supportImg} />
<Text style={styles.supportText}>You {isDonating ? 'Support' : 'Supported'} this GoodCollective!!</Text>
</View>

<VStack flexGrow={{ xl: 1, base: 0 }} borderRightWidth={{ xl: 1, base: 0 }} borderColor={'goodGrey.600'}>
<Text style={walletCardStyles.info}>{userName} has donated</Text>
<VStack style={walletCardStyles.row}>
<Text style={walletCardStyles.bold}>G$ </Text>
<GoodDollarAmount
style={walletCardStyles.totalReceived}
lastDigitsProps={{ style: { fontSize: 18, fontWeight: '300', lineHeight: 33 } }}
amount={donationsFormatted || '0'}
/>
</VStack>
<Text style={walletCardStyles.formattedUsd}>= {donationsUsdValue || 0} USD</Text>
{isDonating ? (
<VStack space={1} marginTop={4}>
<Text {...walletCardStyles.description}>Donation Streaming Rate</Text>
<Text {...walletCardStyles.text}>G$ {formatFlowRate(donorCollective.flowRate)} / Monthly</Text>
</VStack>
) : null}
</VStack>
{/* Stream Rate */}

{/* Dates */}
<VStack
display={{ base: isDonating ? 'flex' : 'none', xl: 'flex' }}
justifyContent={'space-between'}
flexGrow={{ xl: 1, base: 0 }}
flexDirection={{ xl: 'column', base: 'row' }}>
{isDonating ? (
<>
<VStack>
<Text {...walletCardStyles.description}>Date Initiated</Text>
<Text {...walletCardStyles.text}>{formatTime(donorCollective.timestamp)}</Text>
</VStack>

<VStack marginTop={{ xl: 4, base: 0 }}>
<Text {...walletCardStyles.description}>Estimated End Date</Text>
<Text {...walletCardStyles.text}>{endDate}</Text>
</VStack>
</>
) : null}
</VStack>

{/* Buttons */}
<View justifyContent={'right'} flexDirection={'column'} flexGrow={1} marginTop={{ xl: 0, base: 4 }}>
{isDonating ? (
<StopDonationActionButton donorCollective={donorCollective} />
) : (
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${donorCollective.collective}`);
}}
/>
)}
<View flex={1} marginTop={{ xl: 0, base: 4 }}>
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
seeType={true}
onPress={() => {
navigate(`/collective/${donorCollective.collective}/donors`);
}}
/>
</View>
</View>
</View>
</View>
);
};
interface ViewCollectiveProps {
collective: Collective;
}
Expand All @@ -63,11 +190,7 @@ function ViewCollective({ collective }: ViewCollectiveProps) {
const infoLabel = collective.ipfs.rewardDescription ?? defaultInfoLabel;

const { address } = useAccount();
const { data: ensName } = useEnsName({ address, chainId: 1 });
const userName = ensName ?? 'This wallet';
const maybeDonorCollective = useDonorCollectiveByAddresses(address ?? '', poolAddress, SUBGRAPH_POLL_INTERVAL);
const isDonating = maybeDonorCollective && maybeDonorCollective.flowRate !== '0';
const hasDonated = isDonating || (maybeDonorCollective && maybeDonorCollective.contribution !== '0');

const { price: tokenPrice } = useGetTokenPrice('G$');

Expand All @@ -76,7 +199,6 @@ function ViewCollective({ collective }: ViewCollectiveProps) {
tokenPrice,
2
);

if (isDesktopView) {
return (
<View style={{ gap: 24, flex: 1 }}>
Expand Down Expand Up @@ -119,66 +241,25 @@ function ViewCollective({ collective }: ViewCollectiveProps) {
<Text style={styles.informationLabel}>{infoLabel}</Text>
</View>

{hasDonated ? (
<View style={styles.collectiveDonateBox}>
{!isDesktopView && (
<>
<Image source={SupportImage} style={styles.supportImg} />
<Text style={styles.supportText}>
You {isDonating ? 'Support' : 'Supported'} this GoodCollective!!
</Text>
</>
)}
<View style={{ gap: 16 }}>
<WalletDonatedCard
donorCollective={maybeDonorCollective}
tokenPrice={tokenPrice || 0}
userName={userName}
/>
{isDonating ? (
<ActiveStreamCard donorCollective={maybeDonorCollective} />
) : (
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${poolAddress}`);
}}
/>
)}{' '}
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
onPress={() => {
navigate(`/collective/${poolAddress}/donors`);
}}
/>
</View>
</View>
) : (
<View style={styles.collectiveDonateBox}>
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${poolAddress}`);
}}
/>
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
onPress={() => {
navigate(`/collective/${poolAddress}/donors`);
}}
/>
</View>
)}
<View style={styles.collectiveDonateBox}>
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${poolAddress}`);
}}
/>
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
onPress={() => {
navigate(`/collective/${poolAddress}/donors`);
}}
/>
</View>
</View>
</View>

Expand Down Expand Up @@ -215,6 +296,7 @@ function ViewCollective({ collective }: ViewCollectiveProps) {
/>
</View>
</View>
<HasDonatedCard donorCollective={maybeDonorCollective} tokenPrice={tokenPrice} />
</View>

<View style={styles.collectiveDesktopActions}>
Expand Down Expand Up @@ -301,62 +383,7 @@ function ViewCollective({ collective }: ViewCollectiveProps) {
currency={collective.rewardToken}
/>
</View>

{hasDonated ? (
<View style={{ gap: 24 }}>
<Image source={SupportImage} style={styles.supportImg} />
<Text style={styles.supportText}>You {isDonating ? 'Support' : 'Supported'} this GoodCollective!!</Text>
<View style={{ gap: 16 }}>
<WalletDonatedCard
donorCollective={maybeDonorCollective}
tokenPrice={tokenPrice || 0}
userName={userName}
/>
{isDonating ? (
<ActiveStreamCard donorCollective={maybeDonorCollective} />
) : (
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${poolAddress}`);
}}
/>
)}
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
onPress={() => {
navigate(`/collective/${poolAddress}/donors`);
}}
/>
</View>
</View>
) : (
<View style={{ gap: 16 }}>
<RoundedButton
title="Donate"
backgroundColor={Colors.green[100]}
color={Colors.green[200]}
seeType={false}
onPress={() => {
navigate(`/donate/${poolAddress}`);
}}
/>
<RoundedButton
title="See all donors"
backgroundColor={Colors.purple[100]}
color={Colors.purple[200]}
fontSize={18}
onPress={() => {
navigate(`/collective/${poolAddress}/donors`);
}}
/>
</View>
)}
<HasDonatedCard donorCollective={maybeDonorCollective} tokenPrice={tokenPrice} />
</View>

<View style={[styles.container]}>
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/hooks/useFetchFullName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function useFetchFullNames(addresses: string[]): any {

const hashedAddresses = Object.keys(addressToHashMapping);

const { data, error } = useMongoDbQuery<UserProfilesResponse>(findProfiles, {
const { data } = useMongoDbQuery<UserProfilesResponse>(findProfiles, {
variables: {
query: {
index: { walletAddress: { hash_in: hashedAddresses } },
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/theme/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const nbTheme = extendTheme({
300: '#CCCCCC',
400: '#B0B0B0',
500: '#1F2937',
600: '#5A5A5A',
600: '#D4D4D4',
},
goodPurple: {
100: '#E2EAFF',
Expand Down

0 comments on commit c6934e8

Please sign in to comment.