mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
SELF-1198: PointsInfo screen (#1410)
This commit is contained in:
committed by
GitHub
parent
e71860d7ee
commit
60e1cb3fc5
@@ -8,6 +8,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { Button, Image, Text, View, XStack, YStack, ZStack } from 'tamagui';
|
||||
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
import { HelpCircle } from '@tamagui/lucide-icons';
|
||||
|
||||
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import { PointEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
@@ -75,6 +76,10 @@ const Points: React.FC = () => {
|
||||
}, []),
|
||||
);
|
||||
|
||||
const onHelpButtonPress = () => {
|
||||
navigation.navigate('PointsInfo');
|
||||
};
|
||||
|
||||
//TODO - uncomment after merging - https://github.com/selfxyz/self/pull/1363/
|
||||
// useEffect(() => {
|
||||
// const backupEvent = usePointEventStore
|
||||
@@ -316,6 +321,9 @@ const Points: React.FC = () => {
|
||||
const ListHeader = (
|
||||
<YStack paddingHorizontal={5} gap={20} paddingTop={20}>
|
||||
<YStack style={styles.pointsCard}>
|
||||
<Pressable style={styles.helpButton} onPress={onHelpButtonPress}>
|
||||
<HelpCircle size={32} color={blue600} />
|
||||
</Pressable>
|
||||
<YStack style={styles.pointsCardContent}>
|
||||
<View style={styles.logoContainer}>
|
||||
<LogoInversed width={33} height={33} />
|
||||
@@ -581,6 +589,12 @@ const styles = StyleSheet.create({
|
||||
color: white,
|
||||
textAlign: 'center',
|
||||
},
|
||||
helpButton: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
padding: 12,
|
||||
},
|
||||
});
|
||||
|
||||
export default Points;
|
||||
|
||||
@@ -91,6 +91,15 @@ export const useEarnPointsFlow = ({
|
||||
});
|
||||
}, [hasReferrer, navigation, navigateToPointsProof]);
|
||||
|
||||
const showPointsInfoScreen = useCallback(() => {
|
||||
navigation.navigate('PointsInfo', {
|
||||
showNextButton: true,
|
||||
onNextButtonPress: () => {
|
||||
showPointsDisclosureModal();
|
||||
},
|
||||
});
|
||||
}, [navigation, showPointsDisclosureModal]);
|
||||
|
||||
const handleReferralFlow = useCallback(async () => {
|
||||
if (!referrer) {
|
||||
return;
|
||||
@@ -157,7 +166,7 @@ export const useEarnPointsFlow = ({
|
||||
const hasUserDoneThePointsDisclosure_result =
|
||||
await hasUserDoneThePointsDisclosure();
|
||||
if (!hasUserDoneThePointsDisclosure_result) {
|
||||
showPointsDisclosureModal();
|
||||
showPointsInfoScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,7 +185,7 @@ export const useEarnPointsFlow = ({
|
||||
isReferralConfirmed,
|
||||
navigation,
|
||||
showIdentityVerificationModal,
|
||||
showPointsDisclosureModal,
|
||||
showPointsInfoScreen,
|
||||
handleReferralFlow,
|
||||
],
|
||||
);
|
||||
|
||||
3
app/src/images/icons/checkmark_square.svg
Normal file
3
app/src/images/icons/checkmark_square.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.71289 20.2451C0.589844 19.1318 0.0234375 18.0088 0.0136719 16.876C0.00390625 15.7334 0.555664 14.6006 1.66895 13.4775L13.4902 1.6709C14.6035 0.557617 15.7266 0.00585937 16.8594 0.015625C18.002 0.0253906 19.1348 0.591797 20.2578 1.71484L32.0059 13.4629C33.1289 14.5859 33.6904 15.7188 33.6904 16.8613C33.7002 18.0039 33.1484 19.127 32.0352 20.2305L20.2285 32.0518C19.1152 33.1553 17.9873 33.7021 16.8447 33.6924C15.7119 33.6924 14.584 33.1309 13.4609 32.0078L1.71289 20.2451ZM15.2334 24.083C15.5068 24.083 15.7559 24.0195 15.9805 23.8926C16.2148 23.7656 16.4199 23.5752 16.5957 23.3213L23.4512 12.6279C23.5488 12.4717 23.6367 12.3057 23.7148 12.1299C23.793 11.9443 23.832 11.7686 23.832 11.6025C23.832 11.2217 23.6855 10.9141 23.3926 10.6797C23.1094 10.4453 22.7871 10.3281 22.4258 10.3281C21.9473 10.3281 21.5518 10.582 21.2393 11.0898L15.1748 20.7871L12.3623 17.2129C12.167 16.9688 11.9766 16.7979 11.791 16.7002C11.6055 16.6025 11.3955 16.5537 11.1611 16.5537C10.79 16.5537 10.4727 16.6904 10.209 16.9639C9.95508 17.2275 9.82812 17.5449 9.82812 17.916C9.82812 18.1016 9.8623 18.2822 9.93066 18.458C9.99902 18.6338 10.0967 18.8047 10.2236 18.9707L13.8125 23.3359C14.0273 23.5996 14.2471 23.79 14.4717 23.9072C14.6963 24.0244 14.9502 24.083 15.2334 24.083Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
3
app/src/images/icons/cloud_backup.svg
Normal file
3
app/src/images/icons/cloud_backup.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="38" height="26" viewBox="0 0 38 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M29.2539 26.002H9.00977C7.73047 26.002 6.54395 25.7822 5.4502 25.3428C4.36621 24.9131 3.41406 24.3271 2.59375 23.585C1.77344 22.833 1.13379 21.9639 0.674805 20.9775C0.225586 19.9912 0.000976562 18.9414 0.000976562 17.8281C0.000976562 16.6074 0.220703 15.4844 0.660156 14.459C1.09961 13.4238 1.72461 12.5645 2.53516 11.8809C3.3457 11.1973 4.30762 10.7578 5.4209 10.5625C5.45996 9.53711 5.70898 8.60938 6.16797 7.7793C6.62695 6.93945 7.22266 6.24609 7.95508 5.69922C8.69727 5.14258 9.52246 4.77148 10.4307 4.58594C11.3389 4.39063 12.252 4.41992 13.1699 4.67383C13.7852 3.78516 14.5176 2.98926 15.3672 2.28613C16.2168 1.58301 17.1787 1.02637 18.2529 0.616211C19.3369 0.206055 20.5332 0.000976562 21.8418 0.000976562C23.375 0.000976562 24.8008 0.279297 26.1191 0.835938C27.4375 1.39258 28.5898 2.18359 29.5762 3.20898C30.5723 4.23438 31.3438 5.44043 31.8906 6.82715C32.4473 8.21387 32.7256 9.7373 32.7256 11.3975C33.6924 11.7979 34.5273 12.3545 35.2305 13.0674C35.9336 13.7803 36.4707 14.6006 36.8418 15.5283C37.2129 16.4561 37.3984 17.4375 37.3984 18.4727C37.3984 19.5176 37.1885 20.4941 36.7686 21.4023C36.3584 22.3105 35.7822 23.1113 35.04 23.8047C34.2979 24.4883 33.4287 25.0254 32.4326 25.416C31.4463 25.8066 30.3867 26.002 29.2539 26.002ZM17.6377 19.9961C18.1748 19.9961 18.5947 19.7568 18.8975 19.2783L24.6396 10.0498C24.7178 9.92285 24.791 9.78125 24.8594 9.625C24.9375 9.45898 24.9766 9.28809 24.9766 9.1123C24.9766 8.76074 24.8447 8.46777 24.5811 8.2334C24.3174 7.99902 24.0049 7.88184 23.6436 7.88184C23.1553 7.88184 22.7695 8.12109 22.4863 8.59961L17.5791 16.7588L15.0889 13.5654C14.8057 13.165 14.4346 12.9648 13.9756 12.9648C13.624 12.9648 13.3164 13.0918 13.0527 13.3457C12.7988 13.5898 12.6719 13.9023 12.6719 14.2832C12.6719 14.6055 12.7939 14.9229 13.0381 15.2354L16.3193 19.3076C16.5049 19.542 16.7051 19.7178 16.9199 19.835C17.1348 19.9424 17.374 19.9961 17.6377 19.9961Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
3
app/src/images/icons/push_notifications.svg
Normal file
3
app/src/images/icons/push_notifications.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="35" height="31" viewBox="0 0 35 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.04297 27.3174C6.70508 27.3174 5.51367 27.2051 4.46875 26.9805C3.43359 26.7559 2.54004 26.2676 1.78809 25.5156C1.02637 24.7734 0.538086 23.8848 0.323242 22.8496C0.108398 21.8047 0.000976562 20.6133 0.000976562 19.2754V8.01074C0.000976562 6.68262 0.108398 5.50098 0.323242 4.46582C0.547852 3.43066 1.03613 2.54199 1.78809 1.7998C2.54004 1.03809 3.43359 0.549805 4.46875 0.334961C5.51367 0.110352 6.69531 -0.00195312 8.01367 -0.00195312H19.2783C20.6064 -0.00195312 21.793 0.110352 22.8379 0.334961C23.8828 0.549805 24.7861 1.03809 25.5479 1.7998C26.29 2.54199 26.7686 3.43555 26.9834 4.48047C27.208 5.51563 27.3203 6.70215 27.3203 8.04004V12.8594C26.002 12.8594 24.7617 13.1133 23.5996 13.6211C22.4473 14.1191 21.4268 14.8125 20.5381 15.7012C19.6494 16.5801 18.9561 17.6006 18.458 18.7627C17.96 19.915 17.7109 21.1553 17.7109 22.4834C17.7109 23.3623 17.8232 24.207 18.0479 25.0176C18.2822 25.8379 18.6094 26.6045 19.0293 27.3174H8.04297ZM27.335 30.0273C26.2998 30.0273 25.3281 29.832 24.4199 29.4414C23.5117 29.0508 22.7109 28.5039 22.0176 27.8008C21.3242 27.1074 20.7773 26.3066 20.377 25.3984C19.9863 24.4902 19.791 23.5186 19.791 22.4834C19.791 21.4482 19.9863 20.4766 20.377 19.5684C20.7773 18.6602 21.3242 17.8594 22.0176 17.166C22.7109 16.4629 23.5117 15.916 24.4199 15.5254C25.3281 15.1348 26.2998 14.9395 27.335 14.9395C28.3701 14.9395 29.3418 15.1348 30.25 15.5254C31.1582 15.916 31.959 16.458 32.6523 17.1514C33.3457 17.8447 33.8877 18.6504 34.2783 19.5684C34.6787 20.4766 34.8789 21.4482 34.8789 22.4834C34.8789 23.5088 34.6787 24.4756 34.2783 25.3838C33.8877 26.3018 33.3408 27.1074 32.6377 27.8008C31.9443 28.4941 31.1387 29.0361 30.2207 29.4268C29.3125 29.8271 28.3506 30.0273 27.335 30.0273ZM26.4854 26.5703C26.8662 26.5703 27.1494 26.4385 27.335 26.1748L31.583 20.3447C31.6611 20.2373 31.7148 20.1299 31.7441 20.0225C31.7832 19.915 31.8027 19.8174 31.8027 19.7295C31.8027 19.4365 31.6953 19.1924 31.4805 18.9971C31.2754 18.792 31.0312 18.6895 30.748 18.6895C30.3867 18.6895 30.0938 18.8457 29.8691 19.1582L26.4121 23.9336L24.7129 22.0732C24.625 21.9756 24.5127 21.8975 24.376 21.8389C24.249 21.7803 24.1025 21.751 23.9365 21.751C23.6533 21.751 23.4092 21.8486 23.2041 22.0439C22.999 22.2295 22.8965 22.4785 22.8965 22.791C22.8965 22.918 22.9209 23.0498 22.9697 23.1865C23.0186 23.3135 23.0869 23.4355 23.1748 23.5527L25.6504 26.2188C25.748 26.3359 25.875 26.4238 26.0312 26.4824C26.1875 26.541 26.3389 26.5703 26.4854 26.5703Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -9,6 +9,7 @@ import PointsScreen from '@/components/NavBar/Points';
|
||||
import { PointsNavBar } from '@/components/NavBar/PointsNavBar';
|
||||
import ReferralScreen from '@/screens/app/ReferralScreen';
|
||||
import HomeScreen from '@/screens/home/HomeScreen';
|
||||
import PointsInfoScreen from '@/screens/home/PointsInfoScreen';
|
||||
import ProofHistoryDetailScreen from '@/screens/home/ProofHistoryDetailScreen';
|
||||
import ProofHistoryScreen from '@/screens/home/ProofHistoryScreen';
|
||||
|
||||
@@ -48,6 +49,14 @@ const homeScreens = {
|
||||
title: 'Approval',
|
||||
},
|
||||
},
|
||||
PointsInfo: {
|
||||
screen: PointsInfoScreen,
|
||||
options: {
|
||||
headerBackTitle: 'close',
|
||||
title: 'Self Points',
|
||||
animation: 'slide_from_bottom',
|
||||
} as NativeStackNavigationOptions,
|
||||
},
|
||||
};
|
||||
|
||||
export default homeScreens;
|
||||
|
||||
@@ -78,6 +78,7 @@ export type RootStackParamList = Omit<
|
||||
| 'Modal'
|
||||
| 'MockDataDeepLink'
|
||||
| 'Points'
|
||||
| 'PointsInfo'
|
||||
| 'ProofHistoryDetail'
|
||||
| 'Prove'
|
||||
| 'SaveRecoveryPhrase'
|
||||
@@ -162,6 +163,12 @@ export type RootStackParamList = Omit<
|
||||
testReferralFlow?: boolean;
|
||||
};
|
||||
Points: undefined;
|
||||
PointsInfo:
|
||||
| {
|
||||
showNextButton?: boolean;
|
||||
onNextButtonPress?: () => void;
|
||||
}
|
||||
| undefined;
|
||||
IdDetails: undefined;
|
||||
|
||||
// Onboarding screens
|
||||
|
||||
@@ -35,7 +35,7 @@ import UnverifiedHumanImage from '@/images/unverified_human.png';
|
||||
import type { RootStackParamList } from '@/navigation';
|
||||
import { usePassport } from '@/providers/passportDataProvider';
|
||||
import useUserStore from '@/stores/userStore';
|
||||
import { black, slate50, slate300 } from '@/utils/colors';
|
||||
import { black, blue600, slate50, slate300 } from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
|
||||
const HomeScreen: React.FC = () => {
|
||||
@@ -302,11 +302,12 @@ const HomeScreen: React.FC = () => {
|
||||
testID="earn-points-button"
|
||||
onPress={() => {
|
||||
selfClient.trackEvent(PointEvents.HOME_POINT_EARN_POINTS_OPENED);
|
||||
|
||||
onEarnPointsPress(true);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
color="#2563EB"
|
||||
color={blue600}
|
||||
textAlign="center"
|
||||
fontFamily={dinot}
|
||||
fontSize={18}
|
||||
|
||||
189
app/src/screens/home/PointsInfoScreen.tsx
Normal file
189
app/src/screens/home/PointsInfoScreen.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { ScrollView, Text, View, XStack, YStack } from 'tamagui';
|
||||
import type { StaticScreenProps } from '@react-navigation/native';
|
||||
|
||||
import { PrimaryButton, Title } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
|
||||
import CheckmarkSquareIcon from '@/images/icons/checkmark_square.svg';
|
||||
import CloudBackupIcon from '@/images/icons/cloud_backup.svg';
|
||||
import PushNotificationsIcon from '@/images/icons/push_notifications.svg';
|
||||
import StarIcon from '@/images/icons/star.svg';
|
||||
import Referral from '@/images/referral.png';
|
||||
import { black, slate50, slate500, white } from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
|
||||
type PointsInfoScreenProps = StaticScreenProps<
|
||||
| {
|
||||
showNextButton?: boolean;
|
||||
onNextButtonPress?: () => void;
|
||||
}
|
||||
| undefined
|
||||
>;
|
||||
|
||||
interface EarnPointsItemProps {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
|
||||
const EarnPointsItem = ({ title, description, icon }: EarnPointsItemProps) => {
|
||||
return (
|
||||
<XStack
|
||||
padding={10}
|
||||
backgroundColor={slate50}
|
||||
borderRadius={10}
|
||||
gap={20}
|
||||
alignItems="center"
|
||||
>
|
||||
<View
|
||||
style={styles.iconContainer}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{icon}
|
||||
</View>
|
||||
<YStack gap={4} flex={1}>
|
||||
<Text style={styles.pointsItemTitle}>{title}</Text>
|
||||
<Text style={styles.pointsItemDescription}>{description}</Text>
|
||||
</YStack>
|
||||
</XStack>
|
||||
);
|
||||
};
|
||||
|
||||
const EARN_POINTS_ITEMS = [
|
||||
{
|
||||
title: 'Inviting friends to Self',
|
||||
description:
|
||||
"You'll both receive Self Points after your friend signs their first proof.",
|
||||
icon: <StarIcon width={40} height={40} color={black} />,
|
||||
},
|
||||
{
|
||||
title: 'Signing proof requests',
|
||||
description:
|
||||
'Every successful proof that you sign will reward you with Self Points.',
|
||||
icon: <CheckmarkSquareIcon width={40} height={40} color={black} />,
|
||||
},
|
||||
{
|
||||
title: 'Enabling push notifications',
|
||||
description: 'Instantly earn Self Points by activating push notifications.',
|
||||
icon: <PushNotificationsIcon width={40} height={40} color={black} />,
|
||||
},
|
||||
{
|
||||
title: 'Activate cloud back up',
|
||||
description:
|
||||
'Securely back up your account in settings to earn Self Points instantly.',
|
||||
icon: <CloudBackupIcon width={40} height={40} color={black} />,
|
||||
},
|
||||
];
|
||||
|
||||
const PointsInfoScreen: React.FC<PointsInfoScreenProps> = ({
|
||||
route: { params },
|
||||
}) => {
|
||||
const { showNextButton, onNextButtonPress } = params || {};
|
||||
const { left, right, bottom } = useSafeAreaInsets();
|
||||
|
||||
return (
|
||||
<YStack flex={1} gap={40} paddingBottom={bottom} backgroundColor={white}>
|
||||
<Image
|
||||
source={Referral}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 300,
|
||||
resizeMode: 'cover',
|
||||
}}
|
||||
/>
|
||||
<ScrollView paddingLeft={20 + left} paddingRight={20 + right}>
|
||||
<YStack gap={20}>
|
||||
<YStack gap={2}>
|
||||
<Title>How it works</Title>
|
||||
<Text style={styles.description}>
|
||||
Self Points are rewards you earn for engaging with the Self
|
||||
platform. You can earn Points by:
|
||||
</Text>
|
||||
</YStack>
|
||||
<YStack gap={10}>
|
||||
{EARN_POINTS_ITEMS.map(item => (
|
||||
<EarnPointsItem key={item.title} {...item} />
|
||||
))}
|
||||
</YStack>
|
||||
<YStack gap={2}>
|
||||
<Title>Points are deposited at noon UTC every Sunday</Title>
|
||||
<Text style={styles.description}>
|
||||
To ensure privacy and security on-chain, points are deposited into
|
||||
your wallet every Sunday at noon UTC.
|
||||
</Text>
|
||||
</YStack>
|
||||
<YStack style={styles.instructionsContainer} gap={12}>
|
||||
<Text style={styles.instructionsText}>
|
||||
Any points that you earn during the week will be added to your
|
||||
account on the following Sunday.
|
||||
</Text>
|
||||
<Text style={styles.instructionsText}>
|
||||
You can track your incoming points in the Self app along with the
|
||||
countdown to Self Sunday every week.
|
||||
</Text>
|
||||
</YStack>
|
||||
</YStack>
|
||||
</ScrollView>
|
||||
{showNextButton && (
|
||||
<View paddingTop={20} paddingLeft={20 + left} paddingRight={20 + right}>
|
||||
<PrimaryButton onPress={onNextButtonPress}>Next</PrimaryButton>
|
||||
</View>
|
||||
)}
|
||||
</YStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default PointsInfoScreen;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
description: {
|
||||
fontFamily: dinot,
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
color: black,
|
||||
},
|
||||
instructionsContainer: {
|
||||
fontFamily: dinot,
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
color: slate500,
|
||||
backgroundColor: slate50,
|
||||
paddingVertical: 20,
|
||||
paddingHorizontal: 10,
|
||||
borderRadius: 10,
|
||||
},
|
||||
instructionsText: {
|
||||
fontFamily: dinot,
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
color: slate500,
|
||||
},
|
||||
nextButton: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
iconContainer: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
pointsItemTitle: {
|
||||
fontFamily: dinot,
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
color: black,
|
||||
},
|
||||
pointsItemDescription: {
|
||||
fontFamily: dinot,
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
color: slate500,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user