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(points): Implement Points Home screen #5128

Merged
merged 19 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
28 changes: 28 additions & 0 deletions locales/base/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2216,5 +2216,33 @@
"contactSupport": "Contact Support",
"dismiss": "Dismiss"
}
},
"points": {
"title": "Valora Points",
jophish marked this conversation as resolved.
Show resolved Hide resolved
"activity": "Activity",
"infoCard": {
"title": "More ways to earn points coming soon 🚀",
jophish marked this conversation as resolved.
Show resolved Hide resolved
"body": "We are working on adding more ways to earn points through using the app. Keep checking in for updates."
},
"activitySection": {
"title": "How do I earn points?",
"body": "It's easy! Earn points by simply using the app."
},
"activityCards": {
"createWallet": {
"title": "Create a Valora Wallet"
jophish marked this conversation as resolved.
Show resolved Hide resolved
},
"swap": {
"title": "Swap assets",
"bottomSheet": {
"title": "Swap assets",
"body": "This space will be used to give all the details needed for this. Maybe minimum amount to swap. \n\nEarn 50 points whenever you swap an asset using Valora.",
jophish marked this conversation as resolved.
Show resolved Hide resolved
"cta": "Go to swap"
}
},
"moreComing": {
"title": "More coming soon!"
}
}
}
}
7 changes: 7 additions & 0 deletions src/analytics/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -664,3 +664,10 @@ export enum JumpstartEvents {
jumpstart_claim_error_dismissed = 'jumpstart_claim_error_dismissed',
jumpstart_claim_error_contact_support = 'jumpstart_claim_error_contact_support',
}

export enum PointsEvents {
points_screen_open = 'points_screen_open',
points_screen_back = 'points_screen_back',
points_swap_card_press = 'points_swap_card_press',
jophish marked this conversation as resolved.
Show resolved Hide resolved
points_swap_cta_press = 'points_swap_cta_press',
}
11 changes: 10 additions & 1 deletion src/analytics/Properties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
TransactionEvents,
WalletConnectEvents,
WebViewEvents,
PointsEvents,
} from 'src/analytics/Events'
import {
BackQuizProgress,
Expand Down Expand Up @@ -1553,6 +1554,13 @@ interface JumpstartEventsProperties {
[JumpstartEvents.jumpstart_claim_error_contact_support]: undefined
}

interface PointsEventsProperties {
[PointsEvents.points_screen_open]: undefined
[PointsEvents.points_screen_back]: undefined
[PointsEvents.points_swap_card_press]: undefined
[PointsEvents.points_swap_cta_press]: undefined
}

export type AnalyticsPropertiesList = AppEventsProperties &
HomeEventsProperties &
SettingsEventsProperties &
Expand Down Expand Up @@ -1587,6 +1595,7 @@ export type AnalyticsPropertiesList = AppEventsProperties &
NftsEventsProperties &
BuilderHooksProperties &
DappShortcutsProperties &
TransactionDetailsProperties
TransactionDetailsProperties &
PointsEventsProperties

export type AnalyticsEventType = keyof AnalyticsPropertiesList
7 changes: 7 additions & 0 deletions src/analytics/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
TransactionEvents,
WalletConnectEvents,
WebViewEvents,
PointsEvents,
} from 'src/analytics/Events'

/**
Expand Down Expand Up @@ -464,6 +465,12 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
[RewardsEvents.learn_more_pressed]: ``,
[RewardsEvents.claimed_reward]: ``,

// Events related to Valora Points program
[PointsEvents.points_screen_open]: `when Points home screen is opened`,
[PointsEvents.points_screen_back]: `when back button is pressed from Points home screen`,
[PointsEvents.points_swap_card_press]: `when the Swap activity card is pressed from Points home screen`,
[PointsEvents.points_swap_cta_press]: `when the Swap CTA is pressed from bottom sheet`,

// Events related to WalletConnect pairing (technical: opening up the communication channel via QR code or deeplink)
[WalletConnectEvents.wc_pairing_start]: `when WC pairing is started (no UI at this point)`,
[WalletConnectEvents.wc_pairing_success]: `when WC pairing succeeds`,
Expand Down
30 changes: 30 additions & 0 deletions src/components/PointsButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import { StyleProp, ViewStyle } from 'react-native'
import { PointsEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import AttentionIcon from 'src/icons/Attention'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { TopBarIconButton } from 'src/navigator/TopBarButton'

interface Props {
style?: StyleProp<ViewStyle>
size?: number
testID?: string
}

export default function PointsButton({ style, size, testID }: Props) {
const onPress = () => {
ValoraAnalytics.track(PointsEvents.points_screen_open)
navigate(Screens.PointsHome)
}

return (
<TopBarIconButton
testID={testID}
icon={<AttentionIcon size={size} />}
jophish marked this conversation as resolved.
Show resolved Hide resolved
onPress={onPress}
style={style}
/>
)
}
3 changes: 3 additions & 0 deletions src/home/WalletHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { typeScale } from 'src/styles/fonts'
import { Spacing } from 'src/styles/styles'
import TransactionFeed from 'src/transactions/feed/TransactionFeed'
import { hasGrantedContactsPermission } from 'src/utils/contacts'
import PointsButton from 'src/components/PointsButton'

const AnimatedSectionList = Animated.createAnimatedComponent(SectionList)

Expand Down Expand Up @@ -213,8 +214,10 @@ function WalletHome({ navigation, route }: Props) {
const showBetaTag = getFeatureGate(StatsigFeatureGates.SHOW_BETA_TAG)
const topLeftElement = showBetaTag && <BetaTag />

const showPoints = getFeatureGate(StatsigFeatureGates.SHOW_POINTS)
const topRightElements = (
<View style={styles.topRightElementsContainer}>
{showPoints && <PointsButton testID={'WalletHome/PointsButton'} />}
<QrScanButton testID={'WalletHome/QRScanButton'} />
<NotificationBell testID={'WalletHome/NotificationBell'} />
</View>
Expand Down
34 changes: 34 additions & 0 deletions src/icons/Celebration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react'
import colors from 'src/styles/colors'
import Svg, { Path } from 'svgs'

interface Props {
height?: number
width?: number
jophish marked this conversation as resolved.
Show resolved Hide resolved
color?: string
}

export default class Celebration extends React.PureComponent<Props> {
static defaultProps = {
height: 24,
width: 24,
color: colors.black,
}

render() {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
jophish marked this conversation as resolved.
Show resolved Hide resolved
width={this.props.width}
height={this.props.height}
viewBox="0 0 24 24"
fill="none"
>
<Path
fill={this.props.color}
d="M0 21 5 7l9 9-14 5Zm3.3-3.3 7.05-2.5-4.55-4.55-2.5 7.05Zm9.25-6.15L11.5 10.5l5.6-5.6a2.624 2.624 0 0 1 1.925-.8c.75 0 1.392.267 1.925.8l.6.6-1.05 1.05-.6-.6a1.187 1.187 0 0 0-.875-.35c-.35 0-.642.117-.875.35l-5.6 5.6Zm-4-4L7.5 6.5l.6-.6c.233-.233.35-.517.35-.85 0-.333-.117-.617-.35-.85l-.65-.65L8.5 2.5l.65.65c.533.533.8 1.167.8 1.9 0 .733-.267 1.367-.8 1.9l-.6.6Zm2 2L9.5 8.5l3.6-3.6c.233-.233.35-.525.35-.875s-.117-.642-.35-.875l-1.6-1.6L12.55.5l1.6 1.6c.533.533.8 1.175.8 1.925s-.267 1.392-.8 1.925l-3.6 3.6Zm4 4L13.5 12.5l1.6-1.6a2.624 2.624 0 0 1 1.925-.8c.75 0 1.392.267 1.925.8l1.6 1.6-1.05 1.05-1.6-1.6a1.187 1.187 0 0 0-.875-.35c-.35 0-.642.117-.875.35l-1.6 1.6Z"
/>
</Svg>
)
}
}
34 changes: 34 additions & 0 deletions src/icons/CheckmarkWithCircleBorder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react'
Copy link
Collaborator

@kathaypacific kathaypacific Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i lost the original thread but i think you mentioned that we want to create a new icon here because the checkmark is not quite the same as the other checkmark 🫠 i have a couple feelings about this, one of my triggers is stuff that looks the same but slightly different because it's just not clear the value of maintaining extra code for the subtle differences. also subtle differences = inconsistency. i'd encourage us to be gatekeepers of consistency and question designers when we see something that is same same but different, most of the time we're able to keep using existing components (or refresh existing components) - and if the answer is "we absolutely must use this slightly different thing because of reasons XYZ" then at least we feel better about the extra code :)

for this could i request that we check with Kayla if we need to use a new checkmark? and if so, perhaps we can replace the existing checkmark with this one.

i also had a thought that perhaps for these icons they're intended only for the points use case, and maybe we can put the icons in the points folder...i'd be less annoying if this icon wasn't going in the global folder which is already hard to navigate

import colors from 'src/styles/colors'
import Svg, { Path } from 'svgs'

interface Props {
height?: number
width?: number
color?: string
}

export default class CheckmarkWithCircleBorder extends React.PureComponent<Props> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personal opinion here but i always struggle with finding icons in this folder so i've been trying to gatekeep more stuff being added here especially stuff that's more for one-time use. can we use the existing CheckMark icon and draw a circle ourselves? 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC I looked at the existing checkmark and it seemed to be different than the one used in the design on a quick inspection.. might not be a huge deal but it did look different to me

static defaultProps = {
height: 24,
width: 24,
color: colors.black,
}

render() {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
width={this.props.width}
height={this.props.height}
viewBox="0 0 24 24"
fill="none"
>
<Path
fill={this.props.color}
d="M6.067 8.2 4.633 6.767a.632.632 0 0 0-.466-.184.632.632 0 0 0-.467.184.632.632 0 0 0-.183.466c0 .19.06.345.183.467l1.9 1.9a.64.64 0 0 0 .467.2.64.64 0 0 0 .466-.2L10.3 5.833a.632.632 0 0 0 .183-.466.632.632 0 0 0-.183-.467.632.632 0 0 0-.467-.183.632.632 0 0 0-.466.183l-3.3 3.3ZM7 13.667a6.492 6.492 0 0 1-2.6-.525 6.732 6.732 0 0 1-2.117-1.425A6.733 6.733 0 0 1 .858 9.6 6.492 6.492 0 0 1 .333 7c0-.922.175-1.789.525-2.6a6.732 6.732 0 0 1 1.425-2.117c.6-.6 1.306-1.075 2.117-1.425A6.492 6.492 0 0 1 7 .333c.922 0 1.789.175 2.6.525.811.35 1.517.825 2.117 1.425.6.6 1.075 1.306 1.425 2.117.35.811.525 1.678.525 2.6 0 .922-.175 1.789-.525 2.6a6.733 6.733 0 0 1-1.425 2.117c-.6.6-1.306 1.075-2.117 1.425a6.492 6.492 0 0 1-2.6.525Zm0-1.334c1.489 0 2.75-.516 3.783-1.55C11.817 9.75 12.333 8.49 12.333 7c0-1.489-.516-2.75-1.55-3.783C9.75 2.183 8.49 1.667 7 1.667c-1.489 0-2.75.516-3.783 1.55C2.183 4.25 1.667 5.51 1.667 7c0 1.489.516 2.75 1.55 3.783C4.25 11.817 5.51 12.333 7 12.333Z"
/>
</Svg>
)
}
}
34 changes: 34 additions & 0 deletions src/icons/Rocket.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react'
import colors from 'src/styles/colors'
import Svg, { Path } from 'svgs'

interface Props {
height?: number
width?: number
color?: string
}

export default class Rocket extends React.PureComponent<Props> {
static defaultProps = {
height: 24,
width: 24,
color: colors.black,
}

render() {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
width={this.props.width}
height={this.props.height}
viewBox="0 0 24 24"
fill="none"
>
<Path
fill={this.props.color}
d="m3.65 8.025 1.95.825c.233-.467.475-.917.725-1.35.25-.433.525-.867.825-1.3l-1.4-.275-2.1 2.1ZM7.2 10.1l2.85 2.825c.7-.267 1.45-.675 2.25-1.225s1.55-1.175 2.25-1.875a13.455 13.455 0 0 0 2.738-3.887c.658-1.425.945-2.738.862-3.938-1.2-.083-2.517.204-3.95.863A13.4 13.4 0 0 0 10.3 5.6c-.7.7-1.325 1.45-1.875 2.25S7.467 9.4 7.2 10.1Zm4.45-1.625a1.92 1.92 0 0 1-.575-1.412c0-.559.192-1.03.575-1.413.383-.383.858-.575 1.425-.575.567 0 1.042.192 1.425.575.383.383.575.854.575 1.413a1.92 1.92 0 0 1-.575 1.412c-.383.383-.858.575-1.425.575-.567 0-1.042-.192-1.425-.575Zm.475 8.025 2.1-2.1-.275-1.4c-.433.3-.867.57-1.3.813-.433.241-.883.479-1.35.712l.825 1.975ZM19.95.175c.317 2.017.12 3.98-.587 5.888-.709 1.908-1.93 3.729-3.663 5.462L16.2 14c.067.333.05.658-.05.975-.1.317-.267.592-.5.825l-4.2 4.2-2.1-4.925L5.075 10.8.15 8.7l4.175-4.2c.233-.233.512-.4.837-.5.325-.1.655-.117.988-.05l2.475.5c1.733-1.733 3.55-2.958 5.45-3.675 1.9-.717 3.858-.917 5.875-.6Zm-18.025 13.8c.583-.583 1.296-.88 2.137-.887.842-.009 1.555.279 2.138.862s.87 1.296.862 2.138c-.008.841-.304 1.554-.887 2.137-.417.417-1.113.775-2.088 1.075-.975.3-2.32.567-4.037.8.233-1.717.5-3.062.8-4.037.3-.975.658-1.671 1.075-2.088Zm1.425 1.4c-.167.167-.333.47-.5.913a6.463 6.463 0 0 0-.35 1.337c.45-.067.896-.18 1.337-.337.442-.159.746-.321.913-.488.2-.2.308-.442.325-.725a.907.907 0 0 0-.275-.725.946.946 0 0 0-.725-.287 1.033 1.033 0 0 0-.725.312Z"
/>
</Svg>
)
}
}
34 changes: 34 additions & 0 deletions src/icons/SwapArrows.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react'
import colors from 'src/styles/colors'
import Svg, { Path } from 'svgs'

interface Props {
height?: number
width?: number
color?: string
}

export default class SwapArrows extends React.PureComponent<Props> {
static defaultProps = {
height: 24,
width: 24,
color: colors.black,
}

render() {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
width={this.props.width}
height={this.props.height}
viewBox="0 0 24 24"
fill="none"
>
<Path
fill={this.props.color}
d="M11.722 15.567v.5h2.624l-3.235 3.227-3.235-3.227H10.5v-7.79h1.222v7.29ZM3.833 4.433v-.5H1.21L4.444.706 7.68 3.933H5.056v7.79H3.833v-7.29Z"
/>
</Svg>
)
}
}
11 changes: 11 additions & 0 deletions src/navigator/Navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ import VerificationStartScreen from 'src/verify/VerificationStartScreen'
import WalletConnectSessionsScreen from 'src/walletConnect/screens/Sessions'
import WalletConnectRequest from 'src/walletConnect/screens/WalletConnectRequest'
import WebViewScreen from 'src/webview/WebViewScreen'
import PointsHome from 'src/points/PointsHome'

const TAG = 'Navigator'

Expand Down Expand Up @@ -560,6 +561,15 @@ const assetScreens = (Navigator: typeof Stack) => (
</>
)

const pointsScreens = (Navigator: typeof Stack) => (
<>
<Navigator.Screen
name={Screens.PointsHome}
component={PointsHome}
options={PointsHome.navigationOptions}
/>
</>
)
const mapStateToProps = (state: RootState) => {
return {
choseToRestoreAccount: state.account.choseToRestoreAccount,
Expand Down Expand Up @@ -628,6 +638,7 @@ export function MainStackScreen() {
{swapScreens(Stack)}
{nftScreens(Stack)}
{assetScreens(Stack)}
{pointsScreens(Stack)}
</Stack.Navigator>
)
}
Expand Down
1 change: 1 addition & 0 deletions src/navigator/Screens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export enum Screens {
OnboardingSuccessScreen = 'OnboardingSuccessScreen',
PincodeEnter = 'PincodeEnter',
PincodeSet = 'PincodeSet',
PointsHome = 'PointsHome',
Profile = 'Profile',
ProfileMenu = 'ProfileMenu',
ProtectWallet = 'ProtectWallet',
Expand Down
1 change: 1 addition & 0 deletions src/navigator/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export type StackParamList = {
showGuidedOnboarding?: boolean
}
| undefined
[Screens.PointsHome]: undefined
[Screens.ProtectWallet]: undefined
[Screens.OnboardingRecoveryPhrase]: undefined
[Screens.Profile]: undefined
Expand Down
Loading
Loading