diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 007b963b..5327417c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ package="com.yomamobile"> + + + { + console.log('err', err) + throw err + }) + }, + } +} diff --git a/src/assets/Images/index.ts b/src/assets/Images/index.ts deleted file mode 100644 index c384a1f0..00000000 --- a/src/assets/Images/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import BackIcon from './BackIcon.svg' -import BlueTick from './BlueTick.svg' -import FacebookIcon from './FacebookIcon.svg' -import GoogleIcon from './GoogleIcon.svg' -import Message from './Message.svg' -import PurpleQuarter from './PurpleQuarter.svg' -import PurpleSemiCircle from './PurpleSemiCircle.svg' -import RedSemiCircle from './RedSemiCircle.svg' -import WhiteLogo from './WhiteLogo.svg' -import YellowCircleLeft from './YellowCircleLeft.svg' -import YellowCircleRight from './YellowCircleRight.svg' - -export { - RedSemiCircle, - PurpleSemiCircle, - PurpleQuarter, - YellowCircleRight, - YellowCircleLeft, - BlueTick, - Message, - BackIcon, - WhiteLogo, - GoogleIcon, - FacebookIcon, -} diff --git a/src/assets/Fonts/Montserrat-Bold.ttf b/src/assets/fonts/Montserrat-Bold.ttf similarity index 100% rename from src/assets/Fonts/Montserrat-Bold.ttf rename to src/assets/fonts/Montserrat-Bold.ttf diff --git a/src/assets/Fonts/Montserrat-Medium.ttf b/src/assets/fonts/Montserrat-Medium.ttf similarity index 100% rename from src/assets/Fonts/Montserrat-Medium.ttf rename to src/assets/fonts/Montserrat-Medium.ttf diff --git a/src/assets/Fonts/Montserrat-Regular.ttf b/src/assets/fonts/Montserrat-Regular.ttf similarity index 100% rename from src/assets/Fonts/Montserrat-Regular.ttf rename to src/assets/fonts/Montserrat-Regular.ttf diff --git a/src/assets/Fonts/Montserrat-SemiBold.ttf b/src/assets/fonts/Montserrat-SemiBold.ttf similarity index 100% rename from src/assets/Fonts/Montserrat-SemiBold.ttf rename to src/assets/fonts/Montserrat-SemiBold.ttf diff --git a/src/assets/Images/BackIcon.svg b/src/assets/images/BackIcon.svg similarity index 100% rename from src/assets/Images/BackIcon.svg rename to src/assets/images/BackIcon.svg diff --git a/src/assets/images/BlueRightCircle.svg b/src/assets/images/BlueRightCircle.svg new file mode 100644 index 00000000..894715ca --- /dev/null +++ b/src/assets/images/BlueRightCircle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/Images/BlueTick.svg b/src/assets/images/BlueTick.svg similarity index 100% rename from src/assets/Images/BlueTick.svg rename to src/assets/images/BlueTick.svg diff --git a/src/assets/Images/FacebookIcon.svg b/src/assets/images/FacebookIcon.svg similarity index 100% rename from src/assets/Images/FacebookIcon.svg rename to src/assets/images/FacebookIcon.svg diff --git a/src/assets/Images/GoogleIcon.svg b/src/assets/images/GoogleIcon.svg similarity index 100% rename from src/assets/Images/GoogleIcon.svg rename to src/assets/images/GoogleIcon.svg diff --git a/src/assets/images/LightYellowPattern.svg b/src/assets/images/LightYellowPattern.svg new file mode 100644 index 00000000..0cecb621 --- /dev/null +++ b/src/assets/images/LightYellowPattern.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/Images/Message.svg b/src/assets/images/Message.svg similarity index 100% rename from src/assets/Images/Message.svg rename to src/assets/images/Message.svg diff --git a/src/assets/Images/PurpleQuarter.svg b/src/assets/images/PurpleQuarter.svg similarity index 100% rename from src/assets/Images/PurpleQuarter.svg rename to src/assets/images/PurpleQuarter.svg diff --git a/src/assets/Images/PurpleSemiCircle.svg b/src/assets/images/PurpleSemiCircle.svg similarity index 100% rename from src/assets/Images/PurpleSemiCircle.svg rename to src/assets/images/PurpleSemiCircle.svg diff --git a/src/assets/images/RLabsLogo.svg b/src/assets/images/RLabsLogo.svg new file mode 100644 index 00000000..d75dae4c --- /dev/null +++ b/src/assets/images/RLabsLogo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/Images/RedSemiCircle.svg b/src/assets/images/RedSemiCircle.svg similarity index 100% rename from src/assets/Images/RedSemiCircle.svg rename to src/assets/images/RedSemiCircle.svg diff --git a/src/assets/Images/WhiteLogo.svg b/src/assets/images/WhiteLogo.svg similarity index 100% rename from src/assets/Images/WhiteLogo.svg rename to src/assets/images/WhiteLogo.svg diff --git a/src/assets/Images/YellowCircleLeft.svg b/src/assets/images/YellowCircleLeft.svg similarity index 100% rename from src/assets/Images/YellowCircleLeft.svg rename to src/assets/images/YellowCircleLeft.svg diff --git a/src/assets/Images/YellowCircleRight.svg b/src/assets/images/YellowCircleRight.svg similarity index 100% rename from src/assets/Images/YellowCircleRight.svg rename to src/assets/images/YellowCircleRight.svg diff --git a/src/assets/images/icon-back-grey.svg b/src/assets/images/icon-back-grey.svg new file mode 100644 index 00000000..aef47375 --- /dev/null +++ b/src/assets/images/icon-back-grey.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/icon-challenges.svg b/src/assets/images/icon-challenges.svg new file mode 100644 index 00000000..d7969a4c --- /dev/null +++ b/src/assets/images/icon-challenges.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icon-courses.svg b/src/assets/images/icon-courses.svg new file mode 100644 index 00000000..412bf697 --- /dev/null +++ b/src/assets/images/icon-courses.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icon-digital-cv.svg b/src/assets/images/icon-digital-cv.svg new file mode 100644 index 00000000..93c1ca04 --- /dev/null +++ b/src/assets/images/icon-digital-cv.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icon-edit.svg b/src/assets/images/icon-edit.svg new file mode 100644 index 00000000..d6f92181 --- /dev/null +++ b/src/assets/images/icon-edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/icon-profile.svg b/src/assets/images/icon-profile.svg new file mode 100644 index 00000000..d49d26f2 --- /dev/null +++ b/src/assets/images/icon-profile.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/index.ts b/src/assets/images/index.ts new file mode 100644 index 00000000..45077d3c --- /dev/null +++ b/src/assets/images/index.ts @@ -0,0 +1,47 @@ +import BackIcon from './BackIcon.svg' +import BlueRightCircle from './BlueRightCircle.svg' +import BlueTick from './BlueTick.svg' +import FacebookIcon from './FacebookIcon.svg' +import GoogleIcon from './GoogleIcon.svg' +import LightYellowPattern from './LightYellowPattern.svg' +import Message from './Message.svg' +import PurpleQuarter from './PurpleQuarter.svg' +import PurpleSemiCircle from './PurpleSemiCircle.svg' +import RLabsLogo from './RLabsLogo.svg' +import RedSemiCircle from './RedSemiCircle.svg' +import WhiteLogo from './WhiteLogo.svg' +import YellowCircleLeft from './YellowCircleLeft.svg' +import YellowCircleRight from './YellowCircleRight.svg' +import BackIconGrey from './icon-back-grey.svg' +import ChallengesIcon from './icon-challenges.svg' +import CoursesIcon from './icon-courses.svg' +import DigitalCvIcon from './icon-digital-cv.svg' +import EditIcon from './icon-edit.svg' +import ProfileIcon from './icon-profile.svg' +import MarketplaceIcon from './marketplaceIcon.svg' +import ZIcon from './zIcon.svg' + +export { + BackIcon, + BackIconGrey, + BlueRightCircle, + BlueTick, + ChallengesIcon, + CoursesIcon, + DigitalCvIcon, + EditIcon, + FacebookIcon, + GoogleIcon, + LightYellowPattern, + MarketplaceIcon, + Message, + ProfileIcon, + PurpleQuarter, + PurpleSemiCircle, + RedSemiCircle, + RLabsLogo, + WhiteLogo, + YellowCircleLeft, + YellowCircleRight, + ZIcon, +} diff --git a/src/assets/images/marketplaceIcon.svg b/src/assets/images/marketplaceIcon.svg new file mode 100644 index 00000000..e0ed4adf --- /dev/null +++ b/src/assets/images/marketplaceIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/zIcon.svg b/src/assets/images/zIcon.svg new file mode 100644 index 00000000..5490b67f --- /dev/null +++ b/src/assets/images/zIcon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/CustomInput/CustomInput.styles.ts b/src/components/CustomInput/CustomInput.styles.ts new file mode 100644 index 00000000..664f7908 --- /dev/null +++ b/src/components/CustomInput/CustomInput.styles.ts @@ -0,0 +1,22 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' +import { Colors, colors } from 'styles' + +const styles = { + textInputView: { + width: '95%', + alignSelf: 'center', + } as ViewStyle, + label: { + marginLeft: 10, + } as TextStyle, + textInputStyle: { + width: '95%', + alignSelf: 'center', + height: 35, + padding: 0, + borderBottomWidth: 1, + borderColor: `${colors[Colors.menuGrey]}70`, + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/CustomInput/CustomInput.tsx b/src/components/CustomInput/CustomInput.tsx new file mode 100644 index 00000000..32827c3c --- /dev/null +++ b/src/components/CustomInput/CustomInput.tsx @@ -0,0 +1,31 @@ +import Text, { TextAlign } from 'components/Typography' +import React from 'react' +import { TextInput, TextInputProps, View } from 'react-native' +import { colors, Colors } from 'styles' + +import styles from './CustomInput.styles' + +type InputProps = TextInputProps & { + label: string + touched?: boolean + error?: any +} + +const CustomInput = ({ label, touched, error, ...props }: InputProps) => { + return ( + + {label} + + + {touched && error} + + + ) +} + +export default CustomInput diff --git a/src/components/CvCard/CvCard.styles.ts b/src/components/CvCard/CvCard.styles.ts new file mode 100644 index 00000000..f3028da4 --- /dev/null +++ b/src/components/CvCard/CvCard.styles.ts @@ -0,0 +1,50 @@ +import { Dimensions, StyleSheet, ViewStyle } from 'react-native' +import { colors, Colors } from 'styles' + +const { height } = Dimensions.get('window') + +const styles = { + cardView: { + backgroundColor: colors[Colors.white], + width: '97%', + borderRadius: 25, + alignSelf: 'center', + overflow: 'hidden', + paddingVertical: 10, + paddingHorizontal: 20, + marginTop: 10, + height: height / 4, + } as ViewStyle, + certificateCountView: { + height: 25, + width: 25, + maxWidth: 30, + alignItems: 'center', + justifyContent: 'center', + padding: 5, + borderRadius: 12, + marginRight: 10, + } as ViewStyle, + rowView: { + flexDirection: 'row', + alignItems: 'center', + } as ViewStyle, + editIcon: { + elevation: 3, + backgroundColor: colors[Colors.white], + borderRadius: 15, + position: 'absolute', + right: 0, + } as ViewStyle, + dividerLine: { + height: 2, + backgroundColor: colors[Colors.unsavedStyleLightGrey], + marginVertical: 10, + } as ViewStyle, + bodyView: { + height: '70%', + justifyContent: 'center', + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/CvCard/CvCard.tsx b/src/components/CvCard/CvCard.tsx new file mode 100644 index 00000000..a7e4fde5 --- /dev/null +++ b/src/components/CvCard/CvCard.tsx @@ -0,0 +1,53 @@ +import { EditIcon } from 'assets/images' +import Text, { HeaderLevels, TextAlign } from 'components/Typography' +import React from 'react' +import { TouchableOpacity, View } from 'react-native' +import { colors, Colors } from 'styles' + +import styles from './CvCard.styles' + +type Props = { + cardTitle: string + defaultText: string + count?: number + hasCount: boolean + countColor?: Colors + countBackgroundColor?: Colors + onEdit?: () => void +} + +const CvCard = ({ + cardTitle, + defaultText, + count, + hasCount = false, + countColor, + countBackgroundColor, + onEdit, +}: Props) => { + return ( + + + {hasCount ? ( + + + {count} + + + ) : null} + + {cardTitle} + + + + + + + + {defaultText} + + + ) +} + +export default CvCard diff --git a/src/components/DropDown/DropDown.styles.ts b/src/components/DropDown/DropDown.styles.ts index d0ffb5f9..1b4f0485 100644 --- a/src/components/DropDown/DropDown.styles.ts +++ b/src/components/DropDown/DropDown.styles.ts @@ -1,10 +1,14 @@ import { Dimensions, StyleSheet, ViewStyle } from 'react-native' +import { colors, Colors } from 'styles' -const { height, width } = Dimensions.get('window') +const { width } = Dimensions.get('window') const styles = { + container: { + height: 45, + marginTop: 15, + } as ViewStyle, dropDownStyle: { - backgroundColor: 'rgb(243,246,250)', width: width / 1.3, alignSelf: 'center', borderWidth: 0, @@ -14,10 +18,13 @@ const styles = { borderBottomRightRadius: 60, } as ViewStyle, dropDownViewStyle: { - backgroundColor: 'rgb(243,246,250)', + backgroundColor: colors[Colors.white], width: '90%', alignSelf: 'center', } as ViewStyle, + itemStyle: { + justifyContent: 'flex-start', + } as ViewStyle, } export default StyleSheet.create(styles) diff --git a/src/components/DropDown/DropDown.tsx b/src/components/DropDown/DropDown.tsx index f4c1e803..ab60127c 100644 --- a/src/components/DropDown/DropDown.tsx +++ b/src/components/DropDown/DropDown.tsx @@ -1,7 +1,8 @@ +import Text, { TextAlign } from 'components/Typography' import React from 'react' -import { Text, View } from 'react-native' +import { View } from 'react-native' import DropDownPicker, { DropDownPickerProps } from 'react-native-dropdown-picker' -import { TextStyles } from 'styles' +import { Colors, TextStyles } from 'styles' import styles from './DropDown.styles' @@ -14,16 +15,16 @@ const DropDown = ({ touched, error, ...props }: Props) => { return ( - {touched && error} + + {touched && error} + ) } diff --git a/src/components/FirstTimeCard/FirstTimeCard.styles.ts b/src/components/FirstTimeCard/FirstTimeCard.styles.ts new file mode 100644 index 00000000..8d082011 --- /dev/null +++ b/src/components/FirstTimeCard/FirstTimeCard.styles.ts @@ -0,0 +1,60 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' +import { colors, Colors } from 'styles' + +const styles = { + cardView: { + backgroundColor: colors[Colors.primaryYellow], + width: '97%', + borderRadius: 25, + alignSelf: 'center', + overflow: 'hidden', + paddingVertical: 10, + paddingHorizontal: 20, + } as ViewStyle, + bodyText: { + zIndex: 1, + marginTop: 5, + } as TextStyle, + progressBar: { + height: 6, + width: '100%', + alignSelf: 'center', + backgroundColor: colors[Colors.white], + borderRadius: 18, + zIndex: 1, + } as ViewStyle, + innerProgressbar: { + ...StyleSheet.absoluteFillObject, + backgroundColor: colors[Colors.primaryRed], + borderRadius: 18, + } as ViewStyle, + percentText: { + textAlign: 'right', + paddingRight: 10, + zIndex: 1, + paddingVertical: 5, + } as TextStyle, + buttonStyle: { + zIndex: 1, + width: '100%', + alignSelf: 'center', + } as ViewStyle, + blueCircle: { + position: 'absolute', + left: 0, + bottom: 0, + zIndex: 0, + } as ViewStyle, + yellowPattern: { + position: 'absolute', + right: 0, + bottom: 0, + zIndex: 0, + } as ViewStyle, + hostedText: { + flexDirection: 'row', + marginVertical: 10, + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/FirstTimeCard/FirstTimeCard.tsx b/src/components/FirstTimeCard/FirstTimeCard.tsx new file mode 100644 index 00000000..113ee6db --- /dev/null +++ b/src/components/FirstTimeCard/FirstTimeCard.tsx @@ -0,0 +1,65 @@ +import { BlueRightCircle, LightYellowPattern, RLabsLogo } from 'assets/images' +import { ButtonContainer } from 'components' +import Text, { BodyLevels, Bold, FontWeights, HeaderLevels } from 'components/Typography' +import { fontWeights } from 'components/Typography/fontWeights.styles' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { View } from 'react-native' +import { Colors, TextStyles } from 'styles' +import ButtonStyles from 'styles/button.styles' + +import styles from './FirstTimeCard.styles' + +type Props = { + navigation: any +} + +const FirstTimeCard = ({ navigation }: Props) => { + const { t } = useTranslation() + return ( + + + {t('Complete')} + +  {t('your CV')} + + + + {t('Future proof your career and earn')} + 30 ZLTO + {t('by completing our first challenge')}. + + + {t('Hosted by')} + + + + + + + {t('1% complete')} + + ('Let’s do it')} + buttonStyle={[ButtonStyles.largeTertiary3Button, styles.buttonStyle]} + buttonTextStyle={[TextStyles.textWhite, TextStyles.buttonText]} + onPress={() => {}} + /> + + + + + + + + ) +} + +export default FirstTimeCard diff --git a/src/components/HeaderContainer/HeaderContainer.tsx b/src/components/HeaderContainer/HeaderContainer.tsx index a5f5ca12..cedefb9e 100644 --- a/src/components/HeaderContainer/HeaderContainer.tsx +++ b/src/components/HeaderContainer/HeaderContainer.tsx @@ -1,5 +1,5 @@ import { StackActions } from '@react-navigation/native' -import { BackIcon } from 'assets/Images' +import { BackIcon } from 'assets/images' import React, { useEffect } from 'react' import { BackHandler, Text, TouchableOpacity, View } from 'react-native' import { TextStyles } from 'styles' diff --git a/src/components/HomeHeader/HomeHeader.styles.ts b/src/components/HomeHeader/HomeHeader.styles.ts new file mode 100644 index 00000000..2bb297a0 --- /dev/null +++ b/src/components/HomeHeader/HomeHeader.styles.ts @@ -0,0 +1,42 @@ +import { StyleSheet, ViewStyle, Dimensions, ImageStyle } from 'react-native' + +import { colors, Colors } from '../../styles' + +const { width, height } = Dimensions.get('window') + +const styles = { + header: { + height: 50, + backgroundColor: colors[Colors.white], + width: '100%', + alignItems: 'center', + justifyContent: 'space-between', + flexDirection: 'row', + paddingHorizontal: 20, + } as ViewStyle, + profileInnerStyle: { + backgroundColor: colors[Colors.backgroundGrey], + borderRadius: 14, + height: 27, + width: 27, + alignItems: 'center', + justifyContent: 'center', + } as ViewStyle, + backIconView: { + position: 'absolute', + left: 20, + } as ViewStyle, + backIcon: { + height: 25, + } as ImageStyle, + tokensView: { + backgroundColor: `${colors[Colors.primaryYellow]}15`, + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 2, + paddingHorizontal: 10, + borderRadius: 11, + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/HomeHeader/HomeHeader.tsx b/src/components/HomeHeader/HomeHeader.tsx new file mode 100644 index 00000000..db49a813 --- /dev/null +++ b/src/components/HomeHeader/HomeHeader.tsx @@ -0,0 +1,31 @@ +import { ZIcon } from 'assets/images' +import ProfilePhoto from 'components/ProfilePhoto/ProfilePhoto' +import React from 'react' +import { Text, TouchableOpacity, View } from 'react-native' +import { TextStyles } from 'styles' + +import styles from './HomeHeader.styles' + +type Props = { + navigation: any +} + +const HomeHeader = ({ navigation }: Props) => { + return ( + + navigation.navigate('Profile')} + outerRadius={17} + percent={10} + profileInnerStyle={styles.profileInnerStyle} + /> + + + 1000 + + + ) +} + +export default HomeHeader diff --git a/src/components/InfoModal/InfoModal.styles.ts b/src/components/InfoModal/InfoModal.styles.ts new file mode 100644 index 00000000..8201c5aa --- /dev/null +++ b/src/components/InfoModal/InfoModal.styles.ts @@ -0,0 +1,28 @@ +import { StyleSheet, ViewStyle, TextStyle } from 'react-native' + +import { colors, Colors } from '../../styles' + +const styles = { + centeredView: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + marginTop: 22, + } as ViewStyle, + modalView: { + margin: 20, + backgroundColor: colors[Colors.white], + borderRadius: 20, + padding: 35, + alignItems: 'center', + elevation: 5, + } as ViewStyle, + button: { + borderRadius: 20, + padding: 10, + elevation: 2, + backgroundColor: colors[Colors.primaryGreen], + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/InfoModal/InfoModal.tsx b/src/components/InfoModal/InfoModal.tsx new file mode 100644 index 00000000..6ce8501a --- /dev/null +++ b/src/components/InfoModal/InfoModal.tsx @@ -0,0 +1,29 @@ +import Text from 'components/Typography' +import React from 'react' +import { Modal, View, TouchableOpacity } from 'react-native' +import { Colors, TextStyles } from 'styles' + +import styles from './InfoModal.styles' + +interface Props { + visible: boolean + closeModal: () => void + infoText: string +} + +const InfoModal = ({ visible, closeModal, infoText, ...props }: Props) => { + return ( + + + + {infoText} + + Close + + + + + ) +} + +export default InfoModal diff --git a/src/components/Input/Input.styles.ts b/src/components/Input/Input.styles.ts index 479b27e6..bdd1710f 100644 --- a/src/components/Input/Input.styles.ts +++ b/src/components/Input/Input.styles.ts @@ -1,10 +1,11 @@ import { Dimensions, StyleSheet, ViewStyle } from 'react-native' +import { colors, Colors } from 'styles' -const { height, width } = Dimensions.get('window') +const { width } = Dimensions.get('window') const styles = { textInputStyle: { - backgroundColor: 'rgb(243,246,250)', + backgroundColor: colors[Colors.tertiary10], width: width / 1.3, alignSelf: 'center', borderRadius: 60, diff --git a/src/components/LargeHeaderContainer/LargeHeaderContainer.tsx b/src/components/LargeHeaderContainer/LargeHeaderContainer.tsx index 2059151e..f9dc0ff3 100644 --- a/src/components/LargeHeaderContainer/LargeHeaderContainer.tsx +++ b/src/components/LargeHeaderContainer/LargeHeaderContainer.tsx @@ -1,4 +1,4 @@ -import { WhiteLogo } from 'assets/Images' +import { WhiteLogo } from 'assets/images' import React from 'react' import { View, ViewStyle } from 'react-native' import { WithChildren } from 'types/react.types' diff --git a/src/components/NormalHeader/NormalHeader.styles.ts b/src/components/NormalHeader/NormalHeader.styles.ts new file mode 100644 index 00000000..a1d6f4b7 --- /dev/null +++ b/src/components/NormalHeader/NormalHeader.styles.ts @@ -0,0 +1,19 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' + +import { colors, Colors } from '../../styles' + +const styles = { + header: { + height: 50, + backgroundColor: colors[Colors.white], + width: '100%', + alignItems: 'center', + justifyContent: 'space-between', + flexDirection: 'row', + } as ViewStyle, + saveText: { + paddingRight: 20, + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/NormalHeader/NormalHeader.tsx b/src/components/NormalHeader/NormalHeader.tsx new file mode 100644 index 00000000..356804a8 --- /dev/null +++ b/src/components/NormalHeader/NormalHeader.tsx @@ -0,0 +1,43 @@ +import { StackActions } from '@react-navigation/native' +import { BackIconGrey } from 'assets/images' +import Text, { Bold, FontWeights, HeaderLevels } from 'components/Typography' +import React, { useEffect } from 'react' +import { BackHandler, TouchableOpacity, View } from 'react-native' +import { Colors } from 'styles' + +import styles from './NormalHeader.styles' + +type Props = { + navigation: any + headerText: string + onSave?: any +} + +const NormalHeader = ({ navigation, headerText, onSave }: Props) => { + useEffect(() => { + const backHandler = BackHandler.addEventListener('hardwareBackPress', () => { + goBack() + return true + }) + return () => backHandler.remove() + }, []) + + const goBack = () => { + navigation.dispatch(StackActions.pop(1)) + } + return ( + + + + + {headerText} + + + Save + + + + ) +} + +export default NormalHeader diff --git a/src/components/ProfilePhoto/ProfilePhoto.styles.ts b/src/components/ProfilePhoto/ProfilePhoto.styles.ts new file mode 100644 index 00000000..5808a707 --- /dev/null +++ b/src/components/ProfilePhoto/ProfilePhoto.styles.ts @@ -0,0 +1,16 @@ +import { StyleSheet, ViewStyle } from 'react-native' + +import { colors, Colors } from '../../styles' + +const styles = { + editIcon: { + elevation: 3, + backgroundColor: colors[Colors.white], + borderRadius: 15, + position: 'absolute', + right: 0, + bottom: -5, + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/components/ProfilePhoto/ProfilePhoto.tsx b/src/components/ProfilePhoto/ProfilePhoto.tsx new file mode 100644 index 00000000..bf892b92 --- /dev/null +++ b/src/components/ProfilePhoto/ProfilePhoto.tsx @@ -0,0 +1,49 @@ +import { EditIcon, ProfileIcon } from 'assets/images' +import ProgressCircle from 'components/ProgressCircle/ProgressCircle' +import React from 'react' +import { GestureResponderEvent, TouchableOpacity, View, ViewStyle } from 'react-native' +import { colors, Colors } from 'styles' + +import styles from './ProfilePhoto.styles' + +type Props = { + outerRadius: number + percent: number + onPress: (event: GestureResponderEvent) => void + borderWidth: number + profileInnerStyle?: ViewStyle + profileOuterStyle?: ViewStyle + showEditIcon?: boolean +} + +const ProfilePhoto = ({ + outerRadius, + percent, + onPress, + borderWidth, + profileInnerStyle, + profileOuterStyle, + showEditIcon = false, +}: Props) => { + return ( + + + + + + + {showEditIcon ? ( + + + + ) : null} + + ) +} + +export default ProfilePhoto diff --git a/src/components/ProgressCircle/ProgressCircle.styles.ts b/src/components/ProgressCircle/ProgressCircle.styles.ts new file mode 100644 index 00000000..ab55ab98 --- /dev/null +++ b/src/components/ProgressCircle/ProgressCircle.styles.ts @@ -0,0 +1,34 @@ +import { StyleSheet, ViewStyle } from 'react-native' + +const styles = StyleSheet.create({ + circle: { + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + position: 'relative', + } as ViewStyle, + innerCircle: { + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + position: 'relative', + zIndex: 2, + } as ViewStyle, + leftWrap: { + overflow: 'hidden', + position: 'absolute', + top: 0, + zIndex: 1, + } as ViewStyle, + loader: { + borderRadius: 1000, + left: 0, + position: 'absolute', + top: 0, + } as ViewStyle, + rightWrap: { + position: 'absolute', + } as ViewStyle, +}) + +export default StyleSheet.create(styles) diff --git a/src/components/ProgressCircle/ProgressCircle.tsx b/src/components/ProgressCircle/ProgressCircle.tsx new file mode 100644 index 00000000..8f7144f1 --- /dev/null +++ b/src/components/ProgressCircle/ProgressCircle.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import { View } from 'react-native' +import { Colors, colors } from 'styles' +import { WithChildren } from 'types/react.types' + +import styles from './ProgressCircle.styles' + +type Props = WithChildren<{ + backgroundColor?: string + borderWidth?: number + children?: React.ReactNode + color?: string + innerColor?: string + percent?: number + radius: number +}> + +const ProgressCircle = ({ + backgroundColor = `${colors[Colors.menuGrey]}25`, + borderWidth = 1, + children, + color, + innerColor = colors[Colors.white], + percent = 0, + radius, +}: Props) => { + const diameter = 2 * radius + return ( + + + = 50 ? (percent - 50) * 3.6 : 0}deg` }, + { translateX: radius / 2 }, + ], + width: radius, + }, + ]} + /> + + + = 50 ? 180 : percent * 3.6}deg` }, + { translateX: -radius / 2 }, + ], + width: radius, + }, + ]} + /> + + + {children} + + + ) +} + +export default ProgressCircle diff --git a/src/components/SocialLogin/SocialLogin.tsx b/src/components/SocialLogin/SocialLogin.tsx index 89be0551..0b9366b3 100644 --- a/src/components/SocialLogin/SocialLogin.tsx +++ b/src/components/SocialLogin/SocialLogin.tsx @@ -1,5 +1,5 @@ import { GoogleSignin } from '@react-native-google-signin/google-signin' -import { FacebookIcon, GoogleIcon } from 'assets/Images' +import { FacebookIcon, GoogleIcon } from 'assets/images' import React from 'react' import { LoginManager } from 'react-native-fbsdk' import { TextStyles } from 'styles' diff --git a/src/components/SocialRegistration/SocialRegistration.tsx b/src/components/SocialRegistration/SocialRegistration.tsx index 85b89cab..bec6de96 100644 --- a/src/components/SocialRegistration/SocialRegistration.tsx +++ b/src/components/SocialRegistration/SocialRegistration.tsx @@ -1,5 +1,5 @@ import { GoogleSignin, statusCodes } from '@react-native-google-signin/google-signin' -import { FacebookIcon, GoogleIcon } from 'assets/Images' +import { FacebookIcon, GoogleIcon } from 'assets/images' import React from 'react' import { useTranslation } from 'react-i18next' import { LoginManager } from 'react-native-fbsdk' diff --git a/src/components/index.ts b/src/components/index.ts index f7e31524..9951851d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,8 +1,16 @@ import ButtonContainer from './ButtonContainer/ButtonContainer' +import CustomInput from './CustomInput/CustomInput' +import CvCard from './CvCard/CvCard' import DropDown from './DropDown/DropDown' +import FirstTimeCard from './FirstTimeCard/FirstTimeCard' import HeaderContainer from './HeaderContainer/HeaderContainer' +import HomeHeader from './HomeHeader/HomeHeader' +import InfoModal from './InfoModal/InfoModal' import Input from './Input/Input' import LargeHeaderContainer from './LargeHeaderContainer/LargeHeaderContainer' +import NormalHeader from './NormalHeader/NormalHeader' +import ProfilePhoto from './ProfilePhoto/ProfilePhoto' +import ProgressCircle from './ProgressCircle/ProgressCircle' import SocialLogin from './SocialLogin/SocialLogin' import SocialRegistration from './SocialRegistration/SocialRegistration' import Spinner from './Spinner/Spinner' @@ -10,10 +18,18 @@ import ViewContainer from './ViewContainer/ViewContainer' export { ButtonContainer, + CustomInput, + CvCard, DropDown, + FirstTimeCard, HeaderContainer, + HomeHeader, + InfoModal, Input, LargeHeaderContainer, + NormalHeader, + ProfilePhoto, + ProgressCircle, SocialLogin, SocialRegistration, Spinner, diff --git a/src/helpers/helpers.ts b/src/helpers/helpers.ts new file mode 100644 index 00000000..153f54f8 --- /dev/null +++ b/src/helpers/helpers.ts @@ -0,0 +1,8 @@ +export const BASE_URL = 'https://staging.api.yoma.africa/api/v1/' + +// TODO: Static user ID for now +export const USER_ID = '5f258846-6a3b-4b2f-8ccf-b251beac066b' + +// TODO: Static token for now +export const AUTH_TOKEN = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiVXNlciIsInVuaXF1ZV9uYW1lIjoiNWYyNTg4NDYtNmEzYi00YjJmLThjY2YtYjI1MWJlYWMwNjZiIiwibmJmIjoxNjE3ODc0ODc3LCJleHAiOjE2MTc4NzY2NzcsImlhdCI6MTYxNzg3NDg3N30.3UIID33WHJRRHSaSwZXpndHK5xQM_6pNs6chF8DYn7M' diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 3a008068..286d37e4 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -44,6 +44,10 @@ "emailError": "Email must be at least 2 characters", "validEmailError": "Email must be a valid email", "passwordMinCharError": "password must be at least 8 characters", - "passwordRegexError": "Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character" + "passwordRegexError": "Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character", + "myCv": "My Cv", + "courses": "Courses", + "challenges": "Challenges", + "marketplace": "Marketplace" } } diff --git a/src/modules/About/About.styles.ts b/src/modules/About/About.styles.ts new file mode 100644 index 00000000..abb8e6e7 --- /dev/null +++ b/src/modules/About/About.styles.ts @@ -0,0 +1,33 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' +import { Colors, colors } from 'styles' + +const styles = { + container: { + backgroundColor: colors[Colors.unsavedStyleLightGrey], + ...StyleSheet.absoluteFillObject, + } as ViewStyle, + whiteCard: { + backgroundColor: colors[Colors.white], + width: '95%', + borderRadius: 12, + paddingVertical: 5, + elevation: 3, + marginVertical: 10, + alignSelf: 'center', + paddingHorizontal: 15, + flex: 1, + } as ViewStyle, + textInputStyle: { + borderBottomWidth: 1, + width: '100%', + flex: 1, + borderColor: colors[Colors.unsavedStyleLightGrey], + paddingLeft: 0, + textAlignVertical: 'top', + } as ViewStyle, + bottomText: { + marginVertical: 10, + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/modules/About/About.tsx b/src/modules/About/About.tsx new file mode 100644 index 00000000..f6a4fb82 --- /dev/null +++ b/src/modules/About/About.tsx @@ -0,0 +1,79 @@ +import api from 'api' +import { InfoModal, NormalHeader, ViewContainer } from 'components' +import Text, { MetaLevels } from 'components/Typography' +import { USER_ID } from 'helpers/helpers' +import React, { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { TouchableOpacity, View, TextInput } from 'react-native' +import { Colors } from 'styles' + +import styles from './About.styles' + +interface Props { + navigation: any +} + +const About = ({ navigation }: Props) => { + const { t } = useTranslation() + const [summary, setSummary] = useState('') + const [infoModal, setInfoModal] = useState(false) + + useEffect(() => { + const getBiography = async () => { + await api.users + .getById(USER_ID) + .then(async response => { + console.log('response', response) + const user = response.data + setSummary(user.biography || '') + }) + .catch(error => { + console.log('error', error) + }) + } + getBiography() + }, []) + + const updateBiography = async () => { + try { + const response = await api.users.edit(USER_ID, { biography: summary }) + console.log('response', response) + navigation.navigate('Home') + } catch (error) { + console.log('error', error) + } + } + + return ( + + setInfoModal(false)} + infoText={ + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis mauris purus. Quisque malesuada ornare mauris sed feugiat. Cras lectus est, iaculis quis nulla cursus, finibus gravida massa. Donec condimentum porta nisi, eu egestas risus ullamcorper in. In et magna mauris. ' + } + /> + + + {t('Summary')} + { + setSummary(text) + }} + returnKeyType="done" + /> + setInfoModal(true)}> + + {t('Find inspiration on how to write a great profile.')} + + + + + ) +} + +export default About diff --git a/src/modules/About/index.ts b/src/modules/About/index.ts new file mode 100644 index 00000000..dc4b9465 --- /dev/null +++ b/src/modules/About/index.ts @@ -0,0 +1,3 @@ +import About from './About' + +export default About diff --git a/src/modules/App/App.test.tsx b/src/modules/App/App.test.tsx index 48f68161..9a666221 100644 --- a/src/modules/App/App.test.tsx +++ b/src/modules/App/App.test.tsx @@ -13,6 +13,8 @@ jest.mock('react-native-localize', () => ({ })) jest.mock('@react-native-google-signin/google-signin', () => ({})) +jest.mock('rn-fetch-blob', () => ({})) + describe('App', () => { afterEach(cleanup) it('should render correctly', () => { diff --git a/src/modules/AppNavigation/AppNavigation.tsx b/src/modules/AppNavigation/AppNavigation.tsx index 7be84390..0280d28a 100644 --- a/src/modules/AppNavigation/AppNavigation.tsx +++ b/src/modules/AppNavigation/AppNavigation.tsx @@ -2,19 +2,24 @@ import { NavigationContainer } from '@react-navigation/native' import { createStackNavigator } from '@react-navigation/stack' import React from 'react' +import Home from '../Home/Home' import Authentication from './Authentication/Authentication' -import DigitalCv from './DigitalCv/DigitalCv' import linking from './Linking' const Stack = createStackNavigator() const AppNavigation = () => { - const isAuthenticated = false + const isAuthenticated = true return ( - {isAuthenticated && } - {!isAuthenticated && } + + {isAuthenticated ? ( + + ) : ( + + )} + ) } diff --git a/src/modules/AppNavigation/DigitalCv/DigitalCv.tsx b/src/modules/AppNavigation/DigitalCv/DigitalCv.tsx deleted file mode 100644 index 1b4d8667..00000000 --- a/src/modules/AppNavigation/DigitalCv/DigitalCv.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { createStackNavigator } from '@react-navigation/stack' -import DigitalCvHome from 'modules/DigitalCv/DigitalCvHome' -import React from 'react' - -const Stack = createStackNavigator() - -const DigitalCv = () => ( - - - -) - -export default DigitalCv diff --git a/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.styles.ts b/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.styles.ts index a5787701..d5798b2c 100644 --- a/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.styles.ts +++ b/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.styles.ts @@ -20,7 +20,7 @@ const styles = { bottom: 0, } as ViewStyle, whiteCard: { - backgroundColor: '#fff', + backgroundColor: colors[Colors.white], alignSelf: 'center', marginTop: '-20%', width: '90%', diff --git a/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.tsx b/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.tsx index 40bc632f..5ace4051 100644 --- a/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.tsx +++ b/src/modules/Auth/Screens/ForgotPassword/ForgotPassword.tsx @@ -1,4 +1,4 @@ -import { YellowCircleRight, Message } from 'assets/Images' +import { YellowCircleRight, Message } from 'assets/images' import { ViewContainer, LargeHeaderContainer, ButtonContainer } from 'components' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/Auth/Screens/Landing/Landing.tsx b/src/modules/Auth/Screens/Landing/Landing.tsx index fd86e053..e085436f 100644 --- a/src/modules/Auth/Screens/Landing/Landing.tsx +++ b/src/modules/Auth/Screens/Landing/Landing.tsx @@ -1,4 +1,4 @@ -import { RedSemiCircle, WhiteLogo, PurpleSemiCircle } from 'assets/Images' +import { RedSemiCircle, WhiteLogo, PurpleSemiCircle } from 'assets/images' import { ButtonContainer, ViewContainer } from 'components' import React from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/Auth/Screens/Login/Login.styles.ts b/src/modules/Auth/Screens/Login/Login.styles.ts index 2d279c87..4e2e677b 100644 --- a/src/modules/Auth/Screens/Login/Login.styles.ts +++ b/src/modules/Auth/Screens/Login/Login.styles.ts @@ -19,7 +19,7 @@ const styles = { bottom: 0, } as ViewStyle, whiteCard: { - backgroundColor: '#fff', + backgroundColor: colors[Colors.white], alignSelf: 'center', marginTop: '-20%', width: '90%', diff --git a/src/modules/Auth/Screens/Login/Login.tsx b/src/modules/Auth/Screens/Login/Login.tsx index 01da2de8..7e116750 100644 --- a/src/modules/Auth/Screens/Login/Login.tsx +++ b/src/modules/Auth/Screens/Login/Login.tsx @@ -1,4 +1,4 @@ -import { YellowCircleLeft } from 'assets/Images' +import { YellowCircleLeft } from 'assets/images' import { LargeHeaderContainer, SocialRegistration, ViewContainer } from 'components' import React from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/Auth/Screens/Register/Register.styles.ts b/src/modules/Auth/Screens/Register/Register.styles.ts index 717cca7d..e0a08ea4 100644 --- a/src/modules/Auth/Screens/Register/Register.styles.ts +++ b/src/modules/Auth/Screens/Register/Register.styles.ts @@ -19,7 +19,7 @@ const styles = { bottom: 0, } as ViewStyle, whiteCard: { - backgroundColor: '#fff', + backgroundColor: colors[Colors.white], alignSelf: 'center', marginTop: '-20%', width: '90%', diff --git a/src/modules/Auth/Screens/Register/Register.tsx b/src/modules/Auth/Screens/Register/Register.tsx index baad2d62..8c465dcb 100644 --- a/src/modules/Auth/Screens/Register/Register.tsx +++ b/src/modules/Auth/Screens/Register/Register.tsx @@ -1,4 +1,4 @@ -import { PurpleQuarter } from 'assets/Images' +import { PurpleQuarter } from 'assets/images' import { ButtonContainer, LargeHeaderContainer, SocialRegistration, ViewContainer } from 'components' import React from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.styles.ts b/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.styles.ts index 6880e5de..92a6549d 100644 --- a/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.styles.ts +++ b/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.styles.ts @@ -1,5 +1,9 @@ -import { StyleSheet } from 'react-native' +import { StyleSheet, ViewStyle } from 'react-native' -const styles = StyleSheet.create({}) +const styles = StyleSheet.create({ + profileForm: { + width: '100%', + } as ViewStyle, +}) export default styles diff --git a/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.tsx b/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.tsx index 58662cfb..d8a36b9b 100644 --- a/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.tsx +++ b/src/modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.tsx @@ -1,5 +1,5 @@ import api from 'api' -import { BlueTick } from 'assets/Images' +import { BlueTick } from 'assets/images' import { ButtonContainer, DropDown, Input, Spinner } from 'components' import countries from 'constants/countries' import { Formik } from 'formik' diff --git a/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.styles.ts b/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.styles.ts index 29ed9e5e..9f992c1b 100644 --- a/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.styles.ts +++ b/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.styles.ts @@ -12,7 +12,7 @@ const styles = { bottom: 0, } as ViewStyle, whiteCard: { - backgroundColor: '#fff', + backgroundColor: colors[Colors.white], alignSelf: 'center', marginTop: '-30%', width: '90%', diff --git a/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.tsx b/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.tsx index 8ef8cf69..463b2700 100644 --- a/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.tsx +++ b/src/modules/Auth/Screens/RegisterWithEmail/RegisterWithEmail.tsx @@ -1,4 +1,4 @@ -import { YellowCircleRight } from 'assets/Images' +import { YellowCircleRight } from 'assets/images' import { LargeHeaderContainer, ViewContainer } from 'components' import React from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/Auth/Screens/ResetPassword/ResetPassword.styles.ts b/src/modules/Auth/Screens/ResetPassword/ResetPassword.styles.ts index deaa962e..c13d8bde 100644 --- a/src/modules/Auth/Screens/ResetPassword/ResetPassword.styles.ts +++ b/src/modules/Auth/Screens/ResetPassword/ResetPassword.styles.ts @@ -1,4 +1,5 @@ import { StyleSheet, TextStyle, ViewStyle } from 'react-native' +import { Colors, colors } from 'styles' const styles = { container: { @@ -14,7 +15,7 @@ const styles = { bottom: 0, } as ViewStyle, whiteCard: { - backgroundColor: '#fff', + backgroundColor: colors[Colors.white], alignSelf: 'center', marginTop: '-20%', width: '90%', diff --git a/src/modules/Auth/Screens/ResetPassword/ResetPassword.tsx b/src/modules/Auth/Screens/ResetPassword/ResetPassword.tsx index 325f8cee..6f203931 100644 --- a/src/modules/Auth/Screens/ResetPassword/ResetPassword.tsx +++ b/src/modules/Auth/Screens/ResetPassword/ResetPassword.tsx @@ -1,4 +1,4 @@ -import { PurpleQuarter } from 'assets/Images' +import { PurpleQuarter } from 'assets/images' import { LargeHeaderContainer, ViewContainer } from 'components' import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/modules/DigitalCv/DigitalCvHome.styles.ts b/src/modules/Challenges/Challenges.styles.ts similarity index 100% rename from src/modules/DigitalCv/DigitalCvHome.styles.ts rename to src/modules/Challenges/Challenges.styles.ts diff --git a/src/modules/DigitalCv/DigitalCvHome.tsx b/src/modules/Challenges/Challenges.tsx similarity index 65% rename from src/modules/DigitalCv/DigitalCvHome.tsx rename to src/modules/Challenges/Challenges.tsx index 240c2361..0afbcea2 100644 --- a/src/modules/DigitalCv/DigitalCvHome.tsx +++ b/src/modules/Challenges/Challenges.tsx @@ -3,19 +3,19 @@ import { useTranslation } from 'react-i18next' import { Button, Text, View } from 'react-native' import ViewContainer from '../../components/ViewContainer/ViewContainer' -import styles from './DigitalCvHome.styles' +import styles from './Challenges.styles' interface Props { navigation: any } -const DigitalCvHome = ({ navigation }: Props) => { +const Challenges = ({ navigation }: Props) => { const { t } = useTranslation() return ( - {t('signUpPlease')} + {t('Challenges')} ) } -export default DigitalCvHome +export default Challenges diff --git a/src/modules/Challenges/index.ts b/src/modules/Challenges/index.ts new file mode 100644 index 00000000..91ca4311 --- /dev/null +++ b/src/modules/Challenges/index.ts @@ -0,0 +1,3 @@ +import Challenges from './Challenges' + +export default Challenges diff --git a/src/modules/Courses/Courses.styles.ts b/src/modules/Courses/Courses.styles.ts new file mode 100644 index 00000000..fd4ad3a8 --- /dev/null +++ b/src/modules/Courses/Courses.styles.ts @@ -0,0 +1,18 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' + +import { Colors, colors } from '../../styles' + +const styles = { + container: { + backgroundColor: colors[Colors.white], + alignItems: 'center', + justifyContent: 'center', + ...StyleSheet.absoluteFillObject, + } as ViewStyle, + text: { + fontSize: 36, + fontWeight: 'bold', + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/modules/Courses/Courses.tsx b/src/modules/Courses/Courses.tsx new file mode 100644 index 00000000..e92dfbc8 --- /dev/null +++ b/src/modules/Courses/Courses.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { Button, Text, View } from 'react-native' + +import ViewContainer from '../../components/ViewContainer/ViewContainer' +import styles from './Courses.styles' + +interface Props { + navigation: any +} + +const Courses = ({ navigation }: Props) => { + const { t } = useTranslation() + return ( + + {t('Courses')} + + ) +} + +export default Courses diff --git a/src/modules/Courses/index.ts b/src/modules/Courses/index.ts new file mode 100644 index 00000000..0a41a089 --- /dev/null +++ b/src/modules/Courses/index.ts @@ -0,0 +1,3 @@ +import Courses from './Courses' + +export default Courses diff --git a/src/modules/DigitalCv/DigitalCv.styles.ts b/src/modules/DigitalCv/DigitalCv.styles.ts new file mode 100644 index 00000000..200dc373 --- /dev/null +++ b/src/modules/DigitalCv/DigitalCv.styles.ts @@ -0,0 +1,12 @@ +import { StyleSheet, ViewStyle } from 'react-native' +import { Colors, colors } from 'styles' + +const styles = { + container: { + backgroundColor: colors[Colors.unsavedStyleLightGrey], + alignItems: 'center', + ...StyleSheet.absoluteFillObject, + } as ViewStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/modules/DigitalCv/DigitalCv.tsx b/src/modules/DigitalCv/DigitalCv.tsx new file mode 100644 index 00000000..2604d2f8 --- /dev/null +++ b/src/modules/DigitalCv/DigitalCv.tsx @@ -0,0 +1,55 @@ +import { ViewContainer, HomeHeader, FirstTimeCard, CvCard } from 'components' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { ScrollView, Text, View } from 'react-native' +import { Colors, colors, TextStyles } from 'styles' + +import styles from './DigitalCv.styles' + +interface Props { + navigation: any +} + +const DigitalCv = ({ navigation }: Props) => { + const { t } = useTranslation() + return ( + + + + + navigation.navigate('About')} + /> + + + + + + ) +} + +export default DigitalCv diff --git a/src/modules/DigitalCv/index.ts b/src/modules/DigitalCv/index.ts new file mode 100644 index 00000000..bfd628b5 --- /dev/null +++ b/src/modules/DigitalCv/index.ts @@ -0,0 +1,3 @@ +import DigitalCv from './DigitalCv' + +export default DigitalCv diff --git a/src/modules/Home/Home.tsx b/src/modules/Home/Home.tsx new file mode 100644 index 00000000..a8d54bf3 --- /dev/null +++ b/src/modules/Home/Home.tsx @@ -0,0 +1,82 @@ +import { BottomTabBarOptions, createBottomTabNavigator } from '@react-navigation/bottom-tabs' +import { createStackNavigator } from '@react-navigation/stack' +import { DigitalCvIcon, CoursesIcon, ChallengesIcon, MarketplaceIcon } from 'assets/images' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { colors, Colors, FontFamily } from 'styles' +import fontStyles from 'styles/font.styles' + +import About from '../About' +import Challenges from '../Challenges' +import Courses from '../Courses' +import DigitalCv from '../DigitalCv' +import Marketplace from '../Marketplace' +import Profile from '../Profile' + +const Stack = createStackNavigator() +const Tab = createBottomTabNavigator() + +const tabBarOptions: BottomTabBarOptions = { + tabStyle: { + backgroundColor: colors[Colors.primaryPurple], + paddingBottom: 2, + }, + activeTintColor: colors[Colors.white], + inactiveTintColor: `${colors[Colors.white]}38`, + labelStyle: { + fontFamily: fontStyles[FontFamily.semibold], + }, +} + +const HomeTabs = () => { + const { t } = useTranslation() + return ( + + , + }} + /> + , + }} + /> + , + }} + /> + , + }} + /> + + ) +} + +const Home = () => { + return ( + + + + + + + ) +} + +export default Home diff --git a/src/modules/Marketplace/Marketplace.styles.ts b/src/modules/Marketplace/Marketplace.styles.ts new file mode 100644 index 00000000..fd4ad3a8 --- /dev/null +++ b/src/modules/Marketplace/Marketplace.styles.ts @@ -0,0 +1,18 @@ +import { StyleSheet, TextStyle, ViewStyle } from 'react-native' + +import { Colors, colors } from '../../styles' + +const styles = { + container: { + backgroundColor: colors[Colors.white], + alignItems: 'center', + justifyContent: 'center', + ...StyleSheet.absoluteFillObject, + } as ViewStyle, + text: { + fontSize: 36, + fontWeight: 'bold', + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/modules/Marketplace/Marketplace.tsx b/src/modules/Marketplace/Marketplace.tsx new file mode 100644 index 00000000..2a692097 --- /dev/null +++ b/src/modules/Marketplace/Marketplace.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { Button, Text, View } from 'react-native' + +import ViewContainer from '../../components/ViewContainer/ViewContainer' +import styles from './Marketplace.styles' + +interface Props { + navigation: any +} + +const Marketplace = ({ navigation }: Props) => { + const { t } = useTranslation() + return ( + + {t('Marketplace')} + + ) +} + +export default Marketplace diff --git a/src/modules/Marketplace/index.ts b/src/modules/Marketplace/index.ts new file mode 100644 index 00000000..581b39c6 --- /dev/null +++ b/src/modules/Marketplace/index.ts @@ -0,0 +1,3 @@ +import Marketplace from './Marketplace' + +export default Marketplace diff --git a/src/modules/Profile/Profile.styles.ts b/src/modules/Profile/Profile.styles.ts new file mode 100644 index 00000000..8b664b36 --- /dev/null +++ b/src/modules/Profile/Profile.styles.ts @@ -0,0 +1,41 @@ +import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from 'react-native' + +import { Colors, colors } from '../../styles' + +const styles = { + container: { + backgroundColor: colors[Colors.unsavedStyleLightGrey], + ...StyleSheet.absoluteFillObject, + } as ViewStyle, + whiteCard: { + backgroundColor: colors[Colors.white], + width: '95%', + borderRadius: 12, + paddingVertical: 20, + elevation: 3, + alignItems: 'center', + marginTop: 50, + } as ViewStyle, + profileImage: { + height: 70, + width: 70, + borderRadius: 35, + marginTop: -50, + } as ImageStyle, + editIcon: { + elevation: 3, + backgroundColor: colors[Colors.white], + borderRadius: 15, + position: 'absolute', + right: 0, + bottom: -5, + } as ViewStyle, + profileOuterStyle: { + marginTop: -50, + } as ViewStyle, + logout: { + marginVertical: 20, + } as TextStyle, +} + +export default StyleSheet.create(styles) diff --git a/src/modules/Profile/Profile.tsx b/src/modules/Profile/Profile.tsx new file mode 100644 index 00000000..e781fd5d --- /dev/null +++ b/src/modules/Profile/Profile.tsx @@ -0,0 +1,118 @@ +import api from 'api' +import { EditIcon } from 'assets/images' +import { NormalHeader, ProfilePhoto, ViewContainer } from 'components' +import Text, { Bold } from 'components/Typography' +import { USER_ID } from 'helpers/helpers' +import React, { useEffect, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Image, ScrollView, TouchableOpacity, View } from 'react-native' +import ImagePicker from 'react-native-image-crop-picker' +import { Colors } from 'styles' +import { showSimpleMessage } from 'utils/error' + +import styles from './Profile.styles' +import ProfileForm from './ProfileForm/ProfileForm' + +interface Props { + navigation: any +} + +const Profile = ({ navigation }: Props) => { + const [profileImage, setProfileImage] = useState('') + const { t } = useTranslation() + const childRef = useRef() + + useEffect(() => { + getUserData() + }, []) + + const getUserData = async () => { + await api.users + .getById(USER_ID) + .then(async response => { + const userData = response.data + const { photoURL } = userData + setProfileImage(photoURL) + }) + .catch(error => { + console.log('error', error) + showSimpleMessage('danger', 'Error', error) + }) + } + + async function onSubmit(image: any) { + const photo = { + name: 'Photo', + filename: image.path.substring(image.path.lastIndexOf('/') + 1), + type: image.mime, + data: image.data, + } + try { + const response = await api.users.photo.create(USER_ID, photo) + console.log(response) + } catch (error) { + showSimpleMessage('danger', 'Error', error) + } + } + + const captureImage = () => { + ImagePicker.openCamera({ + cropping: true, + includeBase64: true, + freeStyleCropEnabled: true, + forceJpg: true, + mediaType: 'photo', + useFrontCamera: true, + cropperCircleOverlay: true, + compressImageQuality: 0.5, + }) + .then(async image => { + onSubmit(image) + setProfileImage(image.data) + }) + .catch(e => { + console.log('error in image', e) + }) + } + + return ( + + childRef.current.handleSubmit()} /> + + + {profileImage ? ( + + + + + + + ) : ( + + )} + + + + navigation.reset({ + routes: [{ name: 'Authentication' }], + }) + } + > + + {t('Log Out')} + + + + + ) +} + +export default Profile diff --git a/src/modules/Profile/ProfileForm/ProfileForm.styles.ts b/src/modules/Profile/ProfileForm/ProfileForm.styles.ts new file mode 100644 index 00000000..6880e5de --- /dev/null +++ b/src/modules/Profile/ProfileForm/ProfileForm.styles.ts @@ -0,0 +1,5 @@ +import { StyleSheet } from 'react-native' + +const styles = StyleSheet.create({}) + +export default styles diff --git a/src/modules/Profile/ProfileForm/ProfileForm.tsx b/src/modules/Profile/ProfileForm/ProfileForm.tsx new file mode 100644 index 00000000..1dd6dde3 --- /dev/null +++ b/src/modules/Profile/ProfileForm/ProfileForm.tsx @@ -0,0 +1,196 @@ +import api from 'api' +import { DropDown, Spinner } from 'components' +import CustomInput from 'components/CustomInput/CustomInput' +import countries from 'constants/countries' +import { Formik } from 'formik' +import { USER_ID } from 'helpers/helpers' +import styles from 'modules/Auth/Screens/RegisterWithEmail/RegisterForm/RegisterForm.styles' +import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Text, View } from 'react-native' +import { TextStyles } from 'styles' +import { showSimpleMessage } from 'utils/error' +import { nameHasDigitsOrSymbols } from 'utils/regex' +import * as yup from 'yup' + +interface Props { + navigation: any +} + +const ProfileForm = forwardRef(({ navigation }: Props, ref) => { + const { t } = useTranslation() + const [user, setUser] = useState({ + firstName: '', + lastName: '', + countryAlpha2: '', + email: '', + phoneNumber: '', + }) + const formRef = useRef() + const [country, setCountry] = useState('') + const [dropdown, setDropDown] = useState(false) + const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/ + + useImperativeHandle(ref, () => ({ + handleSubmit() { + if (formRef.current) { + formRef.current.handleSubmit() + } + }, + })) + + useEffect(() => { + getUserData() + }, []) + + const getUserData = async () => { + await api.users + .getById(USER_ID) + .then(async response => { + const userData = response.data + const { firstName, lastName, email, countryAlpha2, phoneNumber } = userData + setUser({ firstName, lastName, email, countryAlpha2, phoneNumber }) + setCountry(countryAlpha2) + console.log(countryAlpha2) + }) + .catch(error => { + console.log('error', error) + showSimpleMessage('danger', 'Error', error) + }) + } + + return ( + { + return !nameHasDigitsOrSymbols(value) + }) + .label('First name'), + lastName: yup + .string() + .min(2) + .max(50) + .required(t('required')) + .test('Last name', 'Last name cannot include numbers or symbols', (value: any) => { + return !nameHasDigitsOrSymbols(value) + }) + .label('Last name'), + countryAlpha2: yup.string().required('Required').label('Country'), + email: yup + .string() + .min(2, t('emailError')) + .max(255) + .email(t('validEmailError')) + .required(t('required')) + .label('Email'), + phoneNumber: yup + .string() + .required(t('required')) + .matches(phoneRegExp, 'Phone number is not valid') + .min(10, 'too short') + .max(13, 'too long'), + })} + onSubmit={async (values, actions) => { + console.log('edit values: ', values) + try { + const response = await api.users.edit(USER_ID, values) + console.log('response', response) + navigation.navigate('Home') + } catch (error) { + console.log('error', error) + } + }} + > + {({ handleChange, handleBlur, handleSubmit, values, touched, errors, isSubmitting, setFieldValue }) => { + return ( + + + + + + {dropdown ? ( + ({ + label: c.name, + value: c.code, + }))} + onChangeItem={itemValue => { + handleChange('countryAlpha2') + handleBlur('countryAlpha2') + setFieldValue('countryAlpha2', itemValue.value) + setCountry(itemValue.label) + setDropDown(false) + }} + defaultValue={country} + searchable={true} + searchablePlaceholder="Search for country" + searchablePlaceholderTextColor="gray" + placeholder={t('country')} + touched={touched.countryAlpha2} + error={errors.countryAlpha2} + isVisible={dropdown} + /> + ) : null} + setDropDown(true)} + > + Use current location + + + + + ) + }} + + ) +}) + +export default ProfileForm diff --git a/src/modules/Profile/index.ts b/src/modules/Profile/index.ts new file mode 100644 index 00000000..1c66a66d --- /dev/null +++ b/src/modules/Profile/index.ts @@ -0,0 +1,3 @@ +import Profile from './Profile' + +export default Profile diff --git a/src/styles/colors.styles.ts b/src/styles/colors.styles.ts index fa9bf639..c74bf0a7 100644 --- a/src/styles/colors.styles.ts +++ b/src/styles/colors.styles.ts @@ -14,15 +14,19 @@ const SECONDARY_BLUE = '#72C8ED' const SECONDARY_RED = '#A33232' const SECONDARY_DARK_BLUE = '#162A42' const MENU_GREY = '#959BB4' +const BACKGROUND_GREY = '#F1F4F8' const WHITE = '#FFFFFF' // Not set as a styled color in the designs const UNSAVED_STYLE_LIGHT_GREY = '#E5E5E5' +const UNSAVED_STYLE_LIGHT_BLUE = '#E5F7FD' +const UNSAVED_STYLE_LIGHT_RED = '#FFE4E6' export default { [Colors.fontBlue]: FONT_BLUE, [Colors.unsavedStyleLightGrey]: UNSAVED_STYLE_LIGHT_GREY, [Colors.menuGrey]: MENU_GREY, + [Colors.backgroundGrey]: BACKGROUND_GREY, [Colors.primaryBlue]: PRIMARY_BLUE, [Colors.primaryDarkGrey]: PRIMARY_DARK_GREY, [Colors.primaryGreen]: PRIMARY_GREEN, @@ -36,4 +40,6 @@ export default { [Colors.secondaryPurple]: SECONDARY_PURPLE, [Colors.secondaryRed]: SECONDARY_RED, [Colors.white]: WHITE, + [Colors.unsavedStyleLightBlue]: UNSAVED_STYLE_LIGHT_BLUE, + [Colors.unsavedStyleLightRed]: UNSAVED_STYLE_LIGHT_RED, } diff --git a/src/styles/styles.types.ts b/src/styles/styles.types.ts index 734c872f..9b6889bf 100644 --- a/src/styles/styles.types.ts +++ b/src/styles/styles.types.ts @@ -1,6 +1,7 @@ export enum Colors { fontBlue = 'fontBlue', menuGrey = 'menuGrey', + backgroundGrey = 'backgroundGrey', primaryBlue = 'primaryBlue', primaryDarkGrey = 'primaryDarkGrey', primaryGreen = 'primaryGreen', @@ -15,6 +16,8 @@ export enum Colors { secondaryRed = 'secondaryRed', white = 'white', unsavedStyleLightGrey = 'unsavedStyleLightGrey', + unsavedStyleLightBlue = 'unsavedStyleLightBlue', + unsavedStyleLightRed = 'unsavedStyleLightRed', } export enum FontFamily { diff --git a/src/styles/text.styles.ts b/src/styles/text.styles.ts index ba6d6bf7..122afe14 100644 --- a/src/styles/text.styles.ts +++ b/src/styles/text.styles.ts @@ -23,6 +23,12 @@ const TextStyles = StyleSheet.create({ fontSize: 12, fontFamily: fontStyles[FontFamily.small], } as TextStyle, + boldText: { + fontFamily: fontStyles[FontFamily.bold], + } as TextStyle, + semiBoldText: { + fontFamily: fontStyles[FontFamily.semibold], + } as TextStyle, buttonText: { fontSize: 15, fontFamily: fontStyles[FontFamily.bold], @@ -34,6 +40,9 @@ const TextStyles = StyleSheet.create({ textPrimary: { color: colors[Colors.primaryPurple], } as TextStyle, + textSecondary: { + color: colors[Colors.primaryYellow], + } as TextStyle, textWhite: { color: colors[Colors.white], } as TextStyle,