From 7e7dd5244e8d26485ad7950a89c04c98c4fef83f Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 11 Mar 2019 21:00:02 +0400 Subject: Initial commit/ --- frontend/app/app.js | 92 ++++ frontend/app/assets/fonts/Righteous-Regular.ttf | Bin 0 -> 43104 bytes frontend/app/assets/fonts/Roboto-Bold.ttf | Bin 0 -> 170760 bytes frontend/app/assets/fonts/Roboto-Light.ttf | Bin 0 -> 170420 bytes frontend/app/assets/fonts/Roboto-Medium.ttf | Bin 0 -> 172064 bytes frontend/app/assets/fonts/Roboto-Regular.ttf | Bin 0 -> 171676 bytes frontend/app/assets/fonts/fontawesome.ttf | Bin 0 -> 165548 bytes frontend/app/assets/fonts/icomoon.ttf | Bin 0 -> 5264 bytes frontend/app/assets/icons.js | 30 ++ frontend/app/assets/icons/americanExpressIcon.png | Bin 0 -> 3369 bytes .../app/assets/icons/americanExpressIcon@2x.png | Bin 0 -> 3807 bytes .../app/assets/icons/americanExpressIcon@3x.png | Bin 0 -> 13534 bytes frontend/app/assets/icons/iconPlus.png | Bin 0 -> 1092 bytes frontend/app/assets/icons/iconPlus@2x.png | Bin 0 -> 1234 bytes frontend/app/assets/icons/iconPlus@3x.png | Bin 0 -> 1573 bytes frontend/app/assets/icons/masterCardIcon.png | Bin 0 -> 1848 bytes frontend/app/assets/icons/masterCardIcon@2x.png | Bin 0 -> 2099 bytes frontend/app/assets/icons/masterCardIcon@3x.png | Bin 0 -> 4529 bytes frontend/app/assets/icons/sendIcon.png | Bin 0 -> 1028 bytes frontend/app/assets/icons/sendIcon@2x.png | Bin 0 -> 1114 bytes frontend/app/assets/icons/sendIcon@3x.png | Bin 0 -> 1263 bytes frontend/app/assets/icons/visaIcon.png | Bin 0 -> 1941 bytes frontend/app/assets/icons/visaIcon@2x.png | Bin 0 -> 2348 bytes frontend/app/assets/icons/visaIcon@3x.png | Bin 0 -> 6361 bytes frontend/app/assets/images/backgroundLoginV1.png | Bin 0 -> 53121 bytes .../app/assets/images/backgroundLoginV1@2x.png | Bin 0 -> 146973 bytes .../app/assets/images/backgroundLoginV1@3x.png | Bin 0 -> 134625 bytes .../assets/images/backgroundLoginV1DarkTheme.png | Bin 0 -> 43948 bytes .../images/backgroundLoginV1DarkTheme@2x.png | Bin 0 -> 43624 bytes .../images/backgroundLoginV1DarkTheme@3x.png | Bin 0 -> 181568 bytes frontend/app/assets/images/darkThemeImage.png | Bin 0 -> 57195 bytes frontend/app/assets/images/darkThemeImage@2x.png | Bin 0 -> 172221 bytes frontend/app/assets/images/darkThemeImage@3x.png | Bin 0 -> 358655 bytes frontend/app/assets/images/icon.png | Bin 0 -> 517561 bytes frontend/app/assets/images/install/mt86plus | Bin 0 -> 182704 bytes frontend/app/assets/images/kittenImage.png | Bin 0 -> 69327 bytes frontend/app/assets/images/kittenImage@2x.png | Bin 0 -> 192707 bytes frontend/app/assets/images/kittenImage@3x.png | Bin 0 -> 276065 bytes frontend/app/assets/images/kittenImageDark.png | Bin 0 -> 48418 bytes frontend/app/assets/images/kittenImageDark@2x.png | Bin 0 -> 92372 bytes frontend/app/assets/images/kittenImageDark@3x.png | Bin 0 -> 210723 bytes frontend/app/assets/images/lightThemeImage.png | Bin 0 -> 47829 bytes frontend/app/assets/images/lightThemeImage@2x.png | Bin 0 -> 147848 bytes frontend/app/assets/images/lightThemeImage@3x.png | Bin 0 -> 293174 bytes frontend/app/assets/images/logo.png | Bin 0 -> 8477 bytes frontend/app/assets/images/logo@2x.png | Bin 0 -> 24361 bytes frontend/app/assets/images/logo@3x.png | Bin 0 -> 43568 bytes frontend/app/assets/images/logoDark.png | Bin 0 -> 5275 bytes frontend/app/assets/images/logoDark@2x.png | Bin 0 -> 12288 bytes frontend/app/assets/images/logoDark@3x.png | Bin 0 -> 28623 bytes frontend/app/assets/images/screensImage.png | Bin 0 -> 40333 bytes frontend/app/assets/images/screensImage@2x.png | Bin 0 -> 128814 bytes frontend/app/assets/images/screensImage@3x.png | Bin 0 -> 232133 bytes frontend/app/assets/images/screensImageDark.png | Bin 0 -> 112650 bytes frontend/app/assets/images/screensImageDark@2x.png | Bin 0 -> 294449 bytes frontend/app/assets/images/screensImageDark@3x.png | Bin 0 -> 632534 bytes frontend/app/assets/images/smallLogo.png | Bin 0 -> 2321 bytes frontend/app/assets/images/smallLogo@2x.png | Bin 0 -> 6690 bytes frontend/app/assets/images/smallLogo@3x.png | Bin 0 -> 11905 bytes frontend/app/assets/images/smallLogoDark.png | Bin 0 -> 2458 bytes frontend/app/assets/images/smallLogoDark@2x.png | Bin 0 -> 4761 bytes frontend/app/assets/images/smallLogoDark@3x.png | Bin 0 -> 10103 bytes frontend/app/assets/images/splashBack.png | Bin 0 -> 112149 bytes frontend/app/assets/images/splashBack@2x.png | Bin 0 -> 412782 bytes frontend/app/assets/images/splashBack@3x.png | Bin 0 -> 656967 bytes frontend/app/components/avatar/index.js | 66 +++ frontend/app/components/avatar/types.js | 49 ++ frontend/app/components/cardInput.js | 67 +++ frontend/app/components/charts/areaChart.js | 120 +++++ .../app/components/charts/areaSmoothedChart.js | 118 +++++ frontend/app/components/charts/doughnutChart.js | 125 ++++++ frontend/app/components/charts/index.js | 4 + frontend/app/components/charts/progessChart.js | 96 ++++ frontend/app/components/ellipsis.js | 30 ++ frontend/app/components/findFriends.js | 64 +++ frontend/app/components/gallery.js | 78 ++++ frontend/app/components/gradientButton/index.js | 45 ++ frontend/app/components/gradientButton/types.js | 48 ++ frontend/app/components/index.js | 14 + frontend/app/components/navBar.js | 145 ++++++ frontend/app/components/paginationIndicator.js | 49 ++ frontend/app/components/passwordTextInput.js | 47 ++ frontend/app/components/picker/datePicker.js | 103 +++++ frontend/app/components/picker/index.js | 1 + frontend/app/components/progressBar.js | 63 +++ frontend/app/components/socialBar/index.js | 61 +++ frontend/app/components/socialBar/types.js | 43 ++ frontend/app/components/socialSetting.js | 66 +++ frontend/app/components/switch/index.android.js | 171 +++++++ frontend/app/components/switch/index.ios.js | 36 ++ frontend/app/components/switch/types.js | 35 ++ frontend/app/components/walkthrough.js | 63 +++ frontend/app/config/analytics.js | 7 + frontend/app/config/appConstants.js | 7 + frontend/app/config/bootstrap.js | 492 +++++++++++++++++++++ frontend/app/config/darkTheme.js | 209 +++++++++ frontend/app/config/navigation/propTypes.js | 15 + frontend/app/config/navigation/routes.js | 269 +++++++++++ frontend/app/config/navigation/routesBuilder.js | 62 +++ frontend/app/config/navigation/transitions.js | 59 +++ frontend/app/config/theme.js | 210 +++++++++ frontend/app/data/dataGenerator.js | 45 ++ frontend/app/data/img/Image1.png | Bin 0 -> 1364956 bytes frontend/app/data/img/Image10.png | Bin 0 -> 1373683 bytes frontend/app/data/img/Image11.png | Bin 0 -> 1634438 bytes frontend/app/data/img/Image12.png | Bin 0 -> 1586933 bytes frontend/app/data/img/Image2.png | Bin 0 -> 1554760 bytes frontend/app/data/img/Image3.png | Bin 0 -> 1762312 bytes frontend/app/data/img/Image4.png | Bin 0 -> 1043931 bytes frontend/app/data/img/Image5.png | Bin 0 -> 1474852 bytes frontend/app/data/img/Image6.png | Bin 0 -> 1307144 bytes frontend/app/data/img/Image7.png | Bin 0 -> 1925115 bytes frontend/app/data/img/Image8.png | Bin 0 -> 1399177 bytes frontend/app/data/img/Image9.png | Bin 0 -> 732000 bytes frontend/app/data/img/avatars/Image1.png | Bin 0 -> 221949 bytes frontend/app/data/img/avatars/Image10.png | Bin 0 -> 264326 bytes frontend/app/data/img/avatars/Image11.png | Bin 0 -> 211892 bytes frontend/app/data/img/avatars/Image12.png | Bin 0 -> 195780 bytes frontend/app/data/img/avatars/Image2.png | Bin 0 -> 198751 bytes frontend/app/data/img/avatars/Image3.png | Bin 0 -> 206014 bytes frontend/app/data/img/avatars/Image4.png | Bin 0 -> 148659 bytes frontend/app/data/img/avatars/Image5.png | Bin 0 -> 188015 bytes frontend/app/data/img/avatars/Image6.png | Bin 0 -> 187966 bytes frontend/app/data/img/avatars/Image7.png | Bin 0 -> 167809 bytes frontend/app/data/img/avatars/Image8.png | Bin 0 -> 188909 bytes frontend/app/data/img/avatars/Image9.png | Bin 0 -> 187464 bytes frontend/app/data/img/photo1.png | Bin 0 -> 1604075 bytes frontend/app/data/img/photo17.png | Bin 0 -> 761786 bytes frontend/app/data/img/photo18.png | Bin 0 -> 763599 bytes frontend/app/data/img/photo19.png | Bin 0 -> 673692 bytes frontend/app/data/img/photo2.png | Bin 0 -> 563966 bytes frontend/app/data/img/photo20.png | Bin 0 -> 801144 bytes frontend/app/data/img/photo3.png | Bin 0 -> 434811 bytes frontend/app/data/img/photo32.jpg | Bin 0 -> 38005 bytes frontend/app/data/img/photo4.png | Bin 0 -> 732549 bytes frontend/app/data/img/photo45.png | Bin 0 -> 142446 bytes frontend/app/data/img/photo46.png | Bin 0 -> 90263 bytes frontend/app/data/img/photo47.png | Bin 0 -> 130838 bytes frontend/app/data/img/photo48.png | Bin 0 -> 172662 bytes frontend/app/data/img/photo49.png | Bin 0 -> 183762 bytes frontend/app/data/img/photo5.png | Bin 0 -> 851007 bytes frontend/app/data/img/photo6.png | Bin 0 -> 1020990 bytes frontend/app/data/index.js | 52 +++ frontend/app/data/raw/articles.js | 173 ++++++++ frontend/app/data/raw/cards.js | 40 ++ frontend/app/data/raw/conversations.js | 85 ++++ frontend/app/data/raw/notifications.js | 59 +++ frontend/app/data/raw/users.js | 194 ++++++++ frontend/app/screens/articles/article.js | 94 ++++ frontend/app/screens/articles/articles1.js | 74 ++++ frontend/app/screens/articles/articles2.js | 84 ++++ frontend/app/screens/articles/articles3.js | 81 ++++ frontend/app/screens/articles/articles4.js | 78 ++++ frontend/app/screens/articles/blogposts.js | 88 ++++ frontend/app/screens/articles/index.js | 6 + frontend/app/screens/dashboard/dashboard.js | 117 +++++ frontend/app/screens/dashboard/index.js | 1 + frontend/app/screens/eCommerce/addToCardForm.js | 138 ++++++ frontend/app/screens/eCommerce/cards.js | 242 ++++++++++ frontend/app/screens/eCommerce/index.js | 2 + frontend/app/screens/index.js | 11 + frontend/app/screens/login/index.js | 4 + frontend/app/screens/login/login1.js | 129 ++++++ frontend/app/screens/login/login2.js | 127 ++++++ frontend/app/screens/login/passwordRecovery.js | 83 ++++ frontend/app/screens/login/signUp.js | 110 +++++ frontend/app/screens/menu/categoryMenu.js | 77 ++++ frontend/app/screens/menu/index.js | 2 + frontend/app/screens/menu/menus.js | 114 +++++ frontend/app/screens/messaging/chat.js | 214 +++++++++ frontend/app/screens/messaging/chatList.js | 147 ++++++ frontend/app/screens/messaging/comments.js | 98 ++++ frontend/app/screens/messaging/index.js | 3 + frontend/app/screens/navigation/grid.js | 70 +++ frontend/app/screens/navigation/grid2.js | 82 ++++ frontend/app/screens/navigation/index.js | 4 + frontend/app/screens/navigation/list.js | 73 +++ frontend/app/screens/navigation/sideMenu.js | 113 +++++ frontend/app/screens/other/index.js | 2 + frontend/app/screens/other/settings.js | 176 ++++++++ frontend/app/screens/other/splash.js | 108 +++++ frontend/app/screens/social/contacts.js | 124 ++++++ frontend/app/screens/social/feed.js | 73 +++ frontend/app/screens/social/index.js | 7 + frontend/app/screens/social/notifications.js | 98 ++++ frontend/app/screens/social/profile1.js | 104 +++++ frontend/app/screens/social/profile2.js | 108 +++++ frontend/app/screens/social/profile3.js | 96 ++++ frontend/app/screens/social/profileSettings.js | 200 +++++++++ frontend/app/screens/theme/index.js | 1 + frontend/app/screens/theme/themes.js | 77 ++++ frontend/app/screens/walkthroughs/index.js | 1 + frontend/app/screens/walkthroughs/walkthrough1.js | 40 ++ frontend/app/screens/walkthroughs/walkthrough2.js | 46 ++ .../app/screens/walkthroughs/walkthroughScreen.js | 61 +++ frontend/app/utils/scale.js | 13 + frontend/app/utils/textUtils.js | 5 + 197 files changed, 7713 insertions(+) create mode 100644 frontend/app/app.js create mode 100755 frontend/app/assets/fonts/Righteous-Regular.ttf create mode 100755 frontend/app/assets/fonts/Roboto-Bold.ttf create mode 100755 frontend/app/assets/fonts/Roboto-Light.ttf create mode 100755 frontend/app/assets/fonts/Roboto-Medium.ttf create mode 100755 frontend/app/assets/fonts/Roboto-Regular.ttf create mode 100644 frontend/app/assets/fonts/fontawesome.ttf create mode 100755 frontend/app/assets/fonts/icomoon.ttf create mode 100644 frontend/app/assets/icons.js create mode 100644 frontend/app/assets/icons/americanExpressIcon.png create mode 100644 frontend/app/assets/icons/americanExpressIcon@2x.png create mode 100644 frontend/app/assets/icons/americanExpressIcon@3x.png create mode 100644 frontend/app/assets/icons/iconPlus.png create mode 100644 frontend/app/assets/icons/iconPlus@2x.png create mode 100644 frontend/app/assets/icons/iconPlus@3x.png create mode 100644 frontend/app/assets/icons/masterCardIcon.png create mode 100644 frontend/app/assets/icons/masterCardIcon@2x.png create mode 100644 frontend/app/assets/icons/masterCardIcon@3x.png create mode 100644 frontend/app/assets/icons/sendIcon.png create mode 100644 frontend/app/assets/icons/sendIcon@2x.png create mode 100644 frontend/app/assets/icons/sendIcon@3x.png create mode 100644 frontend/app/assets/icons/visaIcon.png create mode 100644 frontend/app/assets/icons/visaIcon@2x.png create mode 100644 frontend/app/assets/icons/visaIcon@3x.png create mode 100644 frontend/app/assets/images/backgroundLoginV1.png create mode 100644 frontend/app/assets/images/backgroundLoginV1@2x.png create mode 100644 frontend/app/assets/images/backgroundLoginV1@3x.png create mode 100644 frontend/app/assets/images/backgroundLoginV1DarkTheme.png create mode 100644 frontend/app/assets/images/backgroundLoginV1DarkTheme@2x.png create mode 100644 frontend/app/assets/images/backgroundLoginV1DarkTheme@3x.png create mode 100644 frontend/app/assets/images/darkThemeImage.png create mode 100644 frontend/app/assets/images/darkThemeImage@2x.png create mode 100644 frontend/app/assets/images/darkThemeImage@3x.png create mode 100644 frontend/app/assets/images/icon.png create mode 100644 frontend/app/assets/images/install/mt86plus create mode 100644 frontend/app/assets/images/kittenImage.png create mode 100644 frontend/app/assets/images/kittenImage@2x.png create mode 100644 frontend/app/assets/images/kittenImage@3x.png create mode 100644 frontend/app/assets/images/kittenImageDark.png create mode 100644 frontend/app/assets/images/kittenImageDark@2x.png create mode 100644 frontend/app/assets/images/kittenImageDark@3x.png create mode 100644 frontend/app/assets/images/lightThemeImage.png create mode 100644 frontend/app/assets/images/lightThemeImage@2x.png create mode 100644 frontend/app/assets/images/lightThemeImage@3x.png create mode 100644 frontend/app/assets/images/logo.png create mode 100644 frontend/app/assets/images/logo@2x.png create mode 100644 frontend/app/assets/images/logo@3x.png create mode 100644 frontend/app/assets/images/logoDark.png create mode 100644 frontend/app/assets/images/logoDark@2x.png create mode 100644 frontend/app/assets/images/logoDark@3x.png create mode 100644 frontend/app/assets/images/screensImage.png create mode 100644 frontend/app/assets/images/screensImage@2x.png create mode 100644 frontend/app/assets/images/screensImage@3x.png create mode 100644 frontend/app/assets/images/screensImageDark.png create mode 100644 frontend/app/assets/images/screensImageDark@2x.png create mode 100644 frontend/app/assets/images/screensImageDark@3x.png create mode 100644 frontend/app/assets/images/smallLogo.png create mode 100644 frontend/app/assets/images/smallLogo@2x.png create mode 100644 frontend/app/assets/images/smallLogo@3x.png create mode 100644 frontend/app/assets/images/smallLogoDark.png create mode 100644 frontend/app/assets/images/smallLogoDark@2x.png create mode 100644 frontend/app/assets/images/smallLogoDark@3x.png create mode 100644 frontend/app/assets/images/splashBack.png create mode 100644 frontend/app/assets/images/splashBack@2x.png create mode 100644 frontend/app/assets/images/splashBack@3x.png create mode 100644 frontend/app/components/avatar/index.js create mode 100644 frontend/app/components/avatar/types.js create mode 100644 frontend/app/components/cardInput.js create mode 100644 frontend/app/components/charts/areaChart.js create mode 100644 frontend/app/components/charts/areaSmoothedChart.js create mode 100644 frontend/app/components/charts/doughnutChart.js create mode 100644 frontend/app/components/charts/index.js create mode 100644 frontend/app/components/charts/progessChart.js create mode 100644 frontend/app/components/ellipsis.js create mode 100644 frontend/app/components/findFriends.js create mode 100644 frontend/app/components/gallery.js create mode 100644 frontend/app/components/gradientButton/index.js create mode 100644 frontend/app/components/gradientButton/types.js create mode 100644 frontend/app/components/index.js create mode 100644 frontend/app/components/navBar.js create mode 100644 frontend/app/components/paginationIndicator.js create mode 100644 frontend/app/components/passwordTextInput.js create mode 100644 frontend/app/components/picker/datePicker.js create mode 100644 frontend/app/components/picker/index.js create mode 100644 frontend/app/components/progressBar.js create mode 100644 frontend/app/components/socialBar/index.js create mode 100644 frontend/app/components/socialBar/types.js create mode 100644 frontend/app/components/socialSetting.js create mode 100644 frontend/app/components/switch/index.android.js create mode 100644 frontend/app/components/switch/index.ios.js create mode 100644 frontend/app/components/switch/types.js create mode 100644 frontend/app/components/walkthrough.js create mode 100644 frontend/app/config/analytics.js create mode 100644 frontend/app/config/appConstants.js create mode 100644 frontend/app/config/bootstrap.js create mode 100644 frontend/app/config/darkTheme.js create mode 100644 frontend/app/config/navigation/propTypes.js create mode 100644 frontend/app/config/navigation/routes.js create mode 100644 frontend/app/config/navigation/routesBuilder.js create mode 100644 frontend/app/config/navigation/transitions.js create mode 100644 frontend/app/config/theme.js create mode 100644 frontend/app/data/dataGenerator.js create mode 100755 frontend/app/data/img/Image1.png create mode 100755 frontend/app/data/img/Image10.png create mode 100755 frontend/app/data/img/Image11.png create mode 100755 frontend/app/data/img/Image12.png create mode 100755 frontend/app/data/img/Image2.png create mode 100755 frontend/app/data/img/Image3.png create mode 100755 frontend/app/data/img/Image4.png create mode 100755 frontend/app/data/img/Image5.png create mode 100755 frontend/app/data/img/Image6.png create mode 100755 frontend/app/data/img/Image7.png create mode 100755 frontend/app/data/img/Image8.png create mode 100755 frontend/app/data/img/Image9.png create mode 100755 frontend/app/data/img/avatars/Image1.png create mode 100755 frontend/app/data/img/avatars/Image10.png create mode 100755 frontend/app/data/img/avatars/Image11.png create mode 100755 frontend/app/data/img/avatars/Image12.png create mode 100755 frontend/app/data/img/avatars/Image2.png create mode 100755 frontend/app/data/img/avatars/Image3.png create mode 100755 frontend/app/data/img/avatars/Image4.png create mode 100755 frontend/app/data/img/avatars/Image5.png create mode 100755 frontend/app/data/img/avatars/Image6.png create mode 100755 frontend/app/data/img/avatars/Image7.png create mode 100755 frontend/app/data/img/avatars/Image8.png create mode 100755 frontend/app/data/img/avatars/Image9.png create mode 100644 frontend/app/data/img/photo1.png create mode 100644 frontend/app/data/img/photo17.png create mode 100644 frontend/app/data/img/photo18.png create mode 100644 frontend/app/data/img/photo19.png create mode 100644 frontend/app/data/img/photo2.png create mode 100644 frontend/app/data/img/photo20.png create mode 100644 frontend/app/data/img/photo3.png create mode 100644 frontend/app/data/img/photo32.jpg create mode 100644 frontend/app/data/img/photo4.png create mode 100644 frontend/app/data/img/photo45.png create mode 100644 frontend/app/data/img/photo46.png create mode 100644 frontend/app/data/img/photo47.png create mode 100644 frontend/app/data/img/photo48.png create mode 100644 frontend/app/data/img/photo49.png create mode 100644 frontend/app/data/img/photo5.png create mode 100644 frontend/app/data/img/photo6.png create mode 100644 frontend/app/data/index.js create mode 100644 frontend/app/data/raw/articles.js create mode 100644 frontend/app/data/raw/cards.js create mode 100644 frontend/app/data/raw/conversations.js create mode 100644 frontend/app/data/raw/notifications.js create mode 100644 frontend/app/data/raw/users.js create mode 100644 frontend/app/screens/articles/article.js create mode 100644 frontend/app/screens/articles/articles1.js create mode 100644 frontend/app/screens/articles/articles2.js create mode 100644 frontend/app/screens/articles/articles3.js create mode 100644 frontend/app/screens/articles/articles4.js create mode 100644 frontend/app/screens/articles/blogposts.js create mode 100644 frontend/app/screens/articles/index.js create mode 100644 frontend/app/screens/dashboard/dashboard.js create mode 100644 frontend/app/screens/dashboard/index.js create mode 100644 frontend/app/screens/eCommerce/addToCardForm.js create mode 100644 frontend/app/screens/eCommerce/cards.js create mode 100644 frontend/app/screens/eCommerce/index.js create mode 100644 frontend/app/screens/index.js create mode 100644 frontend/app/screens/login/index.js create mode 100644 frontend/app/screens/login/login1.js create mode 100644 frontend/app/screens/login/login2.js create mode 100644 frontend/app/screens/login/passwordRecovery.js create mode 100644 frontend/app/screens/login/signUp.js create mode 100644 frontend/app/screens/menu/categoryMenu.js create mode 100644 frontend/app/screens/menu/index.js create mode 100644 frontend/app/screens/menu/menus.js create mode 100644 frontend/app/screens/messaging/chat.js create mode 100644 frontend/app/screens/messaging/chatList.js create mode 100644 frontend/app/screens/messaging/comments.js create mode 100644 frontend/app/screens/messaging/index.js create mode 100644 frontend/app/screens/navigation/grid.js create mode 100644 frontend/app/screens/navigation/grid2.js create mode 100644 frontend/app/screens/navigation/index.js create mode 100644 frontend/app/screens/navigation/list.js create mode 100644 frontend/app/screens/navigation/sideMenu.js create mode 100644 frontend/app/screens/other/index.js create mode 100644 frontend/app/screens/other/settings.js create mode 100644 frontend/app/screens/other/splash.js create mode 100644 frontend/app/screens/social/contacts.js create mode 100644 frontend/app/screens/social/feed.js create mode 100644 frontend/app/screens/social/index.js create mode 100644 frontend/app/screens/social/notifications.js create mode 100644 frontend/app/screens/social/profile1.js create mode 100644 frontend/app/screens/social/profile2.js create mode 100644 frontend/app/screens/social/profile3.js create mode 100644 frontend/app/screens/social/profileSettings.js create mode 100644 frontend/app/screens/theme/index.js create mode 100644 frontend/app/screens/theme/themes.js create mode 100644 frontend/app/screens/walkthroughs/index.js create mode 100644 frontend/app/screens/walkthroughs/walkthrough1.js create mode 100644 frontend/app/screens/walkthroughs/walkthrough2.js create mode 100644 frontend/app/screens/walkthroughs/walkthroughScreen.js create mode 100644 frontend/app/utils/scale.js create mode 100644 frontend/app/utils/textUtils.js (limited to 'frontend/app') diff --git a/frontend/app/app.js b/frontend/app/app.js new file mode 100644 index 0000000..f469e15 --- /dev/null +++ b/frontend/app/app.js @@ -0,0 +1,92 @@ +import React from 'react'; +import { View } from 'react-native'; +import { + AppLoading, + Font, +} from 'expo'; +import { + createDrawerNavigator, + createStackNavigator, +} from 'react-navigation'; +import { withRkTheme } from 'react-native-ui-kitten'; +import { AppRoutes } from './config/navigation/routesBuilder'; +import * as Screens from './screens'; +import { bootstrap } from './config/bootstrap'; +import track from './config/analytics'; +import { data } from './data'; + +bootstrap(); +data.populateData(); + +const KittenApp = createStackNavigator({ + First: { + screen: Screens.SplashScreen, + }, + Home: { + screen: createDrawerNavigator( + { + ...AppRoutes, + }, + { + contentComponent: (props) => { + const SideMenu = withRkTheme(Screens.SideMenu); + return ; + }, + }, + ), + }, +}, { + headerMode: 'none', +}); + +export default class App extends React.Component { + state = { + isLoaded: false, + }; + + componentWillMount() { + this.loadAssets(); + } + + onNavigationStateChange = (previous, current) => { + const screen = { + current: this.getCurrentRouteName(current), + previous: this.getCurrentRouteName(previous), + }; + if (screen.previous !== screen.current) { + track(screen.current); + } + }; + + getCurrentRouteName = (navigation) => { + const route = navigation.routes[navigation.index]; + return route.routes ? this.getCurrentRouteName(route) : route.routeName; + }; + + loadAssets = async () => { + await Font.loadAsync({ + fontawesome: require('./assets/fonts/fontawesome.ttf'), + icomoon: require('./assets/fonts/icomoon.ttf'), + 'Righteous-Regular': require('./assets/fonts/Righteous-Regular.ttf'), + 'Roboto-Bold': require('./assets/fonts/Roboto-Bold.ttf'), + 'Roboto-Medium': require('./assets/fonts/Roboto-Medium.ttf'), + 'Roboto-Regular': require('./assets/fonts/Roboto-Regular.ttf'), + 'Roboto-Light': require('./assets/fonts/Roboto-Light.ttf'), + }); + this.setState({ isLoaded: true }); + }; + + renderLoading = () => ( + + ); + + renderApp = () => ( + + + + ); + + render = () => (this.state.isLoaded ? this.renderApp() : this.renderLoading()); +} + +Expo.registerRootComponent(App); diff --git a/frontend/app/assets/fonts/Righteous-Regular.ttf b/frontend/app/assets/fonts/Righteous-Regular.ttf new file mode 100755 index 0000000..07fc0b4 Binary files /dev/null and b/frontend/app/assets/fonts/Righteous-Regular.ttf differ diff --git a/frontend/app/assets/fonts/Roboto-Bold.ttf b/frontend/app/assets/fonts/Roboto-Bold.ttf new file mode 100755 index 0000000..d3f01ad Binary files /dev/null and b/frontend/app/assets/fonts/Roboto-Bold.ttf differ diff --git a/frontend/app/assets/fonts/Roboto-Light.ttf b/frontend/app/assets/fonts/Roboto-Light.ttf new file mode 100755 index 0000000..219063a Binary files /dev/null and b/frontend/app/assets/fonts/Roboto-Light.ttf differ diff --git a/frontend/app/assets/fonts/Roboto-Medium.ttf b/frontend/app/assets/fonts/Roboto-Medium.ttf new file mode 100755 index 0000000..1a7f3b0 Binary files /dev/null and b/frontend/app/assets/fonts/Roboto-Medium.ttf differ diff --git a/frontend/app/assets/fonts/Roboto-Regular.ttf b/frontend/app/assets/fonts/Roboto-Regular.ttf new file mode 100755 index 0000000..2c97eea Binary files /dev/null and b/frontend/app/assets/fonts/Roboto-Regular.ttf differ diff --git a/frontend/app/assets/fonts/fontawesome.ttf b/frontend/app/assets/fonts/fontawesome.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/frontend/app/assets/fonts/fontawesome.ttf differ diff --git a/frontend/app/assets/fonts/icomoon.ttf b/frontend/app/assets/fonts/icomoon.ttf new file mode 100755 index 0000000..8a05f73 Binary files /dev/null and b/frontend/app/assets/fonts/icomoon.ttf differ diff --git a/frontend/app/assets/icons.js b/frontend/app/assets/icons.js new file mode 100644 index 0000000..59871f8 --- /dev/null +++ b/frontend/app/assets/icons.js @@ -0,0 +1,30 @@ +export const FontIcons = { + login: '', + navigation: '', + article: '', + profile: '', + mail: '', + dashboard: '', + mobile: '', + other: '', + theme: '', + card: '', + addToCardForm: '', +}; + +export const FontAwesome = { + heart: String.fromCharCode(61444), + comment: String.fromCharCode(61669), + user: String.fromCharCode(62144), + twitter: String.fromCharCode(61593), + google: String.fromCharCode(61856), + facebook: String.fromCharCode(61594), + plus: String.fromCharCode(61543), + search: String.fromCharCode(61442), + smile: String.fromCharCode(61720), + chevronRight: String.fromCharCode(61524), + chevronLeft: String.fromCharCode(61700), + bars: String.fromCharCode(61641), + slashEye: String.fromCharCode(61552), + github: String.fromCharCode(61595), +}; diff --git a/frontend/app/assets/icons/americanExpressIcon.png b/frontend/app/assets/icons/americanExpressIcon.png new file mode 100644 index 0000000..7d69723 Binary files /dev/null and b/frontend/app/assets/icons/americanExpressIcon.png differ diff --git a/frontend/app/assets/icons/americanExpressIcon@2x.png b/frontend/app/assets/icons/americanExpressIcon@2x.png new file mode 100644 index 0000000..767407a Binary files /dev/null and b/frontend/app/assets/icons/americanExpressIcon@2x.png differ diff --git a/frontend/app/assets/icons/americanExpressIcon@3x.png b/frontend/app/assets/icons/americanExpressIcon@3x.png new file mode 100644 index 0000000..08426e5 Binary files /dev/null and b/frontend/app/assets/icons/americanExpressIcon@3x.png differ diff --git a/frontend/app/assets/icons/iconPlus.png b/frontend/app/assets/icons/iconPlus.png new file mode 100644 index 0000000..acc2bee Binary files /dev/null and b/frontend/app/assets/icons/iconPlus.png differ diff --git a/frontend/app/assets/icons/iconPlus@2x.png b/frontend/app/assets/icons/iconPlus@2x.png new file mode 100644 index 0000000..47e42bf Binary files /dev/null and b/frontend/app/assets/icons/iconPlus@2x.png differ diff --git a/frontend/app/assets/icons/iconPlus@3x.png b/frontend/app/assets/icons/iconPlus@3x.png new file mode 100644 index 0000000..9e81cb7 Binary files /dev/null and b/frontend/app/assets/icons/iconPlus@3x.png differ diff --git a/frontend/app/assets/icons/masterCardIcon.png b/frontend/app/assets/icons/masterCardIcon.png new file mode 100644 index 0000000..32d0cf0 Binary files /dev/null and b/frontend/app/assets/icons/masterCardIcon.png differ diff --git a/frontend/app/assets/icons/masterCardIcon@2x.png b/frontend/app/assets/icons/masterCardIcon@2x.png new file mode 100644 index 0000000..abbae18 Binary files /dev/null and b/frontend/app/assets/icons/masterCardIcon@2x.png differ diff --git a/frontend/app/assets/icons/masterCardIcon@3x.png b/frontend/app/assets/icons/masterCardIcon@3x.png new file mode 100644 index 0000000..f2656c0 Binary files /dev/null and b/frontend/app/assets/icons/masterCardIcon@3x.png differ diff --git a/frontend/app/assets/icons/sendIcon.png b/frontend/app/assets/icons/sendIcon.png new file mode 100644 index 0000000..59e98a1 Binary files /dev/null and b/frontend/app/assets/icons/sendIcon.png differ diff --git a/frontend/app/assets/icons/sendIcon@2x.png b/frontend/app/assets/icons/sendIcon@2x.png new file mode 100644 index 0000000..ccd42b6 Binary files /dev/null and b/frontend/app/assets/icons/sendIcon@2x.png differ diff --git a/frontend/app/assets/icons/sendIcon@3x.png b/frontend/app/assets/icons/sendIcon@3x.png new file mode 100644 index 0000000..0f51420 Binary files /dev/null and b/frontend/app/assets/icons/sendIcon@3x.png differ diff --git a/frontend/app/assets/icons/visaIcon.png b/frontend/app/assets/icons/visaIcon.png new file mode 100644 index 0000000..89b74da Binary files /dev/null and b/frontend/app/assets/icons/visaIcon.png differ diff --git a/frontend/app/assets/icons/visaIcon@2x.png b/frontend/app/assets/icons/visaIcon@2x.png new file mode 100644 index 0000000..2fd239c Binary files /dev/null and b/frontend/app/assets/icons/visaIcon@2x.png differ diff --git a/frontend/app/assets/icons/visaIcon@3x.png b/frontend/app/assets/icons/visaIcon@3x.png new file mode 100644 index 0000000..014fd20 Binary files /dev/null and b/frontend/app/assets/icons/visaIcon@3x.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1.png b/frontend/app/assets/images/backgroundLoginV1.png new file mode 100644 index 0000000..fadd9c1 Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1@2x.png b/frontend/app/assets/images/backgroundLoginV1@2x.png new file mode 100644 index 0000000..97ed4c8 Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1@2x.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1@3x.png b/frontend/app/assets/images/backgroundLoginV1@3x.png new file mode 100644 index 0000000..fce0f0d Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1@3x.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1DarkTheme.png b/frontend/app/assets/images/backgroundLoginV1DarkTheme.png new file mode 100644 index 0000000..bde640e Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1DarkTheme.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1DarkTheme@2x.png b/frontend/app/assets/images/backgroundLoginV1DarkTheme@2x.png new file mode 100644 index 0000000..2779ff4 Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1DarkTheme@2x.png differ diff --git a/frontend/app/assets/images/backgroundLoginV1DarkTheme@3x.png b/frontend/app/assets/images/backgroundLoginV1DarkTheme@3x.png new file mode 100644 index 0000000..25b7678 Binary files /dev/null and b/frontend/app/assets/images/backgroundLoginV1DarkTheme@3x.png differ diff --git a/frontend/app/assets/images/darkThemeImage.png b/frontend/app/assets/images/darkThemeImage.png new file mode 100644 index 0000000..22a8aad Binary files /dev/null and b/frontend/app/assets/images/darkThemeImage.png differ diff --git a/frontend/app/assets/images/darkThemeImage@2x.png b/frontend/app/assets/images/darkThemeImage@2x.png new file mode 100644 index 0000000..5fd83c8 Binary files /dev/null and b/frontend/app/assets/images/darkThemeImage@2x.png differ diff --git a/frontend/app/assets/images/darkThemeImage@3x.png b/frontend/app/assets/images/darkThemeImage@3x.png new file mode 100644 index 0000000..97476a8 Binary files /dev/null and b/frontend/app/assets/images/darkThemeImage@3x.png differ diff --git a/frontend/app/assets/images/icon.png b/frontend/app/assets/images/icon.png new file mode 100644 index 0000000..69d250e Binary files /dev/null and b/frontend/app/assets/images/icon.png differ diff --git a/frontend/app/assets/images/install/mt86plus b/frontend/app/assets/images/install/mt86plus new file mode 100644 index 0000000..9ad8027 Binary files /dev/null and b/frontend/app/assets/images/install/mt86plus differ diff --git a/frontend/app/assets/images/kittenImage.png b/frontend/app/assets/images/kittenImage.png new file mode 100644 index 0000000..f69ba83 Binary files /dev/null and b/frontend/app/assets/images/kittenImage.png differ diff --git a/frontend/app/assets/images/kittenImage@2x.png b/frontend/app/assets/images/kittenImage@2x.png new file mode 100644 index 0000000..1603f06 Binary files /dev/null and b/frontend/app/assets/images/kittenImage@2x.png differ diff --git a/frontend/app/assets/images/kittenImage@3x.png b/frontend/app/assets/images/kittenImage@3x.png new file mode 100644 index 0000000..3e42333 Binary files /dev/null and b/frontend/app/assets/images/kittenImage@3x.png differ diff --git a/frontend/app/assets/images/kittenImageDark.png b/frontend/app/assets/images/kittenImageDark.png new file mode 100644 index 0000000..7dab278 Binary files /dev/null and b/frontend/app/assets/images/kittenImageDark.png differ diff --git a/frontend/app/assets/images/kittenImageDark@2x.png b/frontend/app/assets/images/kittenImageDark@2x.png new file mode 100644 index 0000000..9b154fe Binary files /dev/null and b/frontend/app/assets/images/kittenImageDark@2x.png differ diff --git a/frontend/app/assets/images/kittenImageDark@3x.png b/frontend/app/assets/images/kittenImageDark@3x.png new file mode 100644 index 0000000..98e2dab Binary files /dev/null and b/frontend/app/assets/images/kittenImageDark@3x.png differ diff --git a/frontend/app/assets/images/lightThemeImage.png b/frontend/app/assets/images/lightThemeImage.png new file mode 100644 index 0000000..36e8202 Binary files /dev/null and b/frontend/app/assets/images/lightThemeImage.png differ diff --git a/frontend/app/assets/images/lightThemeImage@2x.png b/frontend/app/assets/images/lightThemeImage@2x.png new file mode 100644 index 0000000..cc103fd Binary files /dev/null and b/frontend/app/assets/images/lightThemeImage@2x.png differ diff --git a/frontend/app/assets/images/lightThemeImage@3x.png b/frontend/app/assets/images/lightThemeImage@3x.png new file mode 100644 index 0000000..f743a07 Binary files /dev/null and b/frontend/app/assets/images/lightThemeImage@3x.png differ diff --git a/frontend/app/assets/images/logo.png b/frontend/app/assets/images/logo.png new file mode 100644 index 0000000..c671367 Binary files /dev/null and b/frontend/app/assets/images/logo.png differ diff --git a/frontend/app/assets/images/logo@2x.png b/frontend/app/assets/images/logo@2x.png new file mode 100644 index 0000000..9597747 Binary files /dev/null and b/frontend/app/assets/images/logo@2x.png differ diff --git a/frontend/app/assets/images/logo@3x.png b/frontend/app/assets/images/logo@3x.png new file mode 100644 index 0000000..e1fc224 Binary files /dev/null and b/frontend/app/assets/images/logo@3x.png differ diff --git a/frontend/app/assets/images/logoDark.png b/frontend/app/assets/images/logoDark.png new file mode 100644 index 0000000..744a239 Binary files /dev/null and b/frontend/app/assets/images/logoDark.png differ diff --git a/frontend/app/assets/images/logoDark@2x.png b/frontend/app/assets/images/logoDark@2x.png new file mode 100644 index 0000000..93e62f8 Binary files /dev/null and b/frontend/app/assets/images/logoDark@2x.png differ diff --git a/frontend/app/assets/images/logoDark@3x.png b/frontend/app/assets/images/logoDark@3x.png new file mode 100644 index 0000000..9de7bd5 Binary files /dev/null and b/frontend/app/assets/images/logoDark@3x.png differ diff --git a/frontend/app/assets/images/screensImage.png b/frontend/app/assets/images/screensImage.png new file mode 100644 index 0000000..4e672c6 Binary files /dev/null and b/frontend/app/assets/images/screensImage.png differ diff --git a/frontend/app/assets/images/screensImage@2x.png b/frontend/app/assets/images/screensImage@2x.png new file mode 100644 index 0000000..a1adefc Binary files /dev/null and b/frontend/app/assets/images/screensImage@2x.png differ diff --git a/frontend/app/assets/images/screensImage@3x.png b/frontend/app/assets/images/screensImage@3x.png new file mode 100644 index 0000000..c7c40cf Binary files /dev/null and b/frontend/app/assets/images/screensImage@3x.png differ diff --git a/frontend/app/assets/images/screensImageDark.png b/frontend/app/assets/images/screensImageDark.png new file mode 100644 index 0000000..1e4290d Binary files /dev/null and b/frontend/app/assets/images/screensImageDark.png differ diff --git a/frontend/app/assets/images/screensImageDark@2x.png b/frontend/app/assets/images/screensImageDark@2x.png new file mode 100644 index 0000000..d60ef34 Binary files /dev/null and b/frontend/app/assets/images/screensImageDark@2x.png differ diff --git a/frontend/app/assets/images/screensImageDark@3x.png b/frontend/app/assets/images/screensImageDark@3x.png new file mode 100644 index 0000000..7b6c2e9 Binary files /dev/null and b/frontend/app/assets/images/screensImageDark@3x.png differ diff --git a/frontend/app/assets/images/smallLogo.png b/frontend/app/assets/images/smallLogo.png new file mode 100644 index 0000000..934203f Binary files /dev/null and b/frontend/app/assets/images/smallLogo.png differ diff --git a/frontend/app/assets/images/smallLogo@2x.png b/frontend/app/assets/images/smallLogo@2x.png new file mode 100644 index 0000000..2256c76 Binary files /dev/null and b/frontend/app/assets/images/smallLogo@2x.png differ diff --git a/frontend/app/assets/images/smallLogo@3x.png b/frontend/app/assets/images/smallLogo@3x.png new file mode 100644 index 0000000..6b23ffa Binary files /dev/null and b/frontend/app/assets/images/smallLogo@3x.png differ diff --git a/frontend/app/assets/images/smallLogoDark.png b/frontend/app/assets/images/smallLogoDark.png new file mode 100644 index 0000000..2809ba7 Binary files /dev/null and b/frontend/app/assets/images/smallLogoDark.png differ diff --git a/frontend/app/assets/images/smallLogoDark@2x.png b/frontend/app/assets/images/smallLogoDark@2x.png new file mode 100644 index 0000000..769e6b5 Binary files /dev/null and b/frontend/app/assets/images/smallLogoDark@2x.png differ diff --git a/frontend/app/assets/images/smallLogoDark@3x.png b/frontend/app/assets/images/smallLogoDark@3x.png new file mode 100644 index 0000000..5af69c3 Binary files /dev/null and b/frontend/app/assets/images/smallLogoDark@3x.png differ diff --git a/frontend/app/assets/images/splashBack.png b/frontend/app/assets/images/splashBack.png new file mode 100644 index 0000000..f79f8e0 Binary files /dev/null and b/frontend/app/assets/images/splashBack.png differ diff --git a/frontend/app/assets/images/splashBack@2x.png b/frontend/app/assets/images/splashBack@2x.png new file mode 100644 index 0000000..c9dfe1f Binary files /dev/null and b/frontend/app/assets/images/splashBack@2x.png differ diff --git a/frontend/app/assets/images/splashBack@3x.png b/frontend/app/assets/images/splashBack@3x.png new file mode 100644 index 0000000..d163eca Binary files /dev/null and b/frontend/app/assets/images/splashBack@3x.png differ diff --git a/frontend/app/components/avatar/index.js b/frontend/app/components/avatar/index.js new file mode 100644 index 0000000..b01800a --- /dev/null +++ b/frontend/app/components/avatar/index.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { + Image, + View, +} from 'react-native'; +import { + RkComponent, + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../../assets/icons'; + +export class Avatar extends RkComponent { + componentName = 'Avatar'; + typeMapping = { + container: {}, + image: {}, + badge: {}, + badgeText: {}, + }; + + getBadgeStyle = (badgeProps) => { + switch (badgeProps) { + case 'like': + return { + symbol: FontAwesome.heart, + backgroundColor: RkTheme.current.colors.badge.likeBackground, + color: RkTheme.current.colors.badge.likeForeground, + }; + case 'follow': + return { + symbol: FontAwesome.plus, + backgroundColor: RkTheme.current.colors.badge.plusBackground, + color: RkTheme.current.colors.badge.plusForeground, + }; + default: return {}; + } + }; + + renderImg = (styles) => ( + + + { this.props.badge && this.renderBadge(styles.badge)} + + ); + + renderBadge = (style, textStyle) => { + const badgeStyle = this.getBadgeStyle(this.props.badge); + return ( + + + {badgeStyle.symbol} + + + ); + }; + + render() { + const { container, ...other } = this.defineStyles(); + return ( + + {this.renderImg(other)} + + ); + } +} diff --git a/frontend/app/components/avatar/types.js b/frontend/app/components/avatar/types.js new file mode 100644 index 0000000..2d732d8 --- /dev/null +++ b/frontend/app/components/avatar/types.js @@ -0,0 +1,49 @@ +export const AvatarTypes = () => ({ + _base: { + container: { + alignItems: 'center', + flexDirection: 'row', + }, + image: { + width: 40, + height: 40, + }, + badge: { + width: 15, + height: 15, + borderRadius: 7.5, + alignItems: 'center', + justifyContent: 'center', + position: 'absolute', + bottom: -2, + right: -2, + }, + badgeText: { + backgroundColor: 'transparent', + fontSize: 9, + }, + }, + big: { + image: { + width: 110, + height: 110, + borderRadius: 55, + marginBottom: 19, + }, + container: { + flexDirection: 'column', + }, + }, + small: { + image: { + width: 32, + height: 32, + borderRadius: 16, + }, + }, + circle: { + image: { + borderRadius: 20, + }, + }, +}); diff --git a/frontend/app/components/cardInput.js b/frontend/app/components/cardInput.js new file mode 100644 index 0000000..b286d56 --- /dev/null +++ b/frontend/app/components/cardInput.js @@ -0,0 +1,67 @@ +import React from 'react'; +import { + RkButton, + RkTextInput, + RkText, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../assets/icons'; + +export class CardInput extends React.Component { + state = { + hidden: true, + cardNumber: '', + }; + + formatCreditNumber = (number, isHidden) => ( + isHidden + ? number.replace(/\D/g, '') + : number.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim() + ); + + onInputLabelPressed = () => { + this.setState({ + hidden: !this.state.hidden, + cardNumber: this.formatCreditNumber(this.state.cardNumber, !this.state.hidden), + }); + }; + + onInputChanged = (text) => { + this.setState({ + cardNumber: this.formatCreditNumber(text, this.state.hidden), + }); + }; + + renderInputLabel = () => ( + + {FontAwesome.slashEye} + + ); + + render = () => ( + + ); +} + +let styles = RkStyleSheet.create({ + icon: { + fontSize: 24, + }, + button: { + right: 17, + }, +}); diff --git a/frontend/app/components/charts/areaChart.js b/frontend/app/components/charts/areaChart.js new file mode 100644 index 0000000..be40960 --- /dev/null +++ b/frontend/app/components/charts/areaChart.js @@ -0,0 +1,120 @@ +import React from 'react'; +import { + View, + Dimensions, +} from 'react-native'; +import { + RkComponent, + RkTheme, + RkText, +} from 'react-native-ui-kitten'; + +import { + VictoryChart, + VictoryAxis, + VictoryArea, + VictoryScatter, + VictoryGroup, +} from 'victory-native'; + + +export class AreaChart extends RkComponent { + state = { + data: [ + { x: 1, y: 1 }, + { x: 2, y: 2 }, + { x: 3, y: 1 }, + { x: 4, y: 2 }, + { x: 5, y: 3 }, + { x: 6, y: 3 }, + { x: 7, y: 4 }, + { x: 8, y: 3 }, + { x: 9, y: 2 }, + { x: 10, y: 4 }, + ], + }; + + componentWillMount() { + this.size = Dimensions.get('window').width; + } + + componentDidMount() { + this.setStateInterval = setInterval(() => { + let positive = Math.random() > 0.5; + let newValue = this.state.data[this.state.data.length - 1].y; + if (newValue > 3) { + positive = false; + } else if (newValue < 2) { + positive = true; + } + newValue = positive ? newValue + 1 : newValue - 1; + const newData = this.state.data.map((d, i) => ({ + x: d.x, + y: i === this.state.data.length - 1 ? newValue : this.state.data[i + 1].y, + })); + this.setState({ + data: newData, + }); + }, 3000); + } + + componentWillUnmount() { + clearInterval(this.setStateInterval); + } + + render = () => ( + + REAL TIME VISITORS + + + + + + + + + + ); +} diff --git a/frontend/app/components/charts/areaSmoothedChart.js b/frontend/app/components/charts/areaSmoothedChart.js new file mode 100644 index 0000000..54ca435 --- /dev/null +++ b/frontend/app/components/charts/areaSmoothedChart.js @@ -0,0 +1,118 @@ +import React from 'react'; +import { + View, + Dimensions, +} from 'react-native'; +import { + RkComponent, + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import { + VictoryChart, + VictoryAxis, + VictoryArea, +} from 'victory-native'; + +export class AreaSmoothedChart extends RkComponent { + state = { + data: [ + [ + { x: 1, y: 1.0, key: 0 }, + { x: 2, y: 1.5, key: 1 }, + { x: 3, y: 1.0, key: 2 }, + { x: 4, y: 0.5, key: 3 }, + { x: 5, y: 1.0, key: 4 }, + { x: 6, y: 2.0, key: 5 }, + { x: 7, y: 2.5, key: 6 }, + ], + [ + { x: 1, y: 1.5, key: 0 }, + { x: 2, y: 2.0, key: 1 }, + { x: 3, y: 1.5, key: 2 }, + { x: 4, y: 0.8, key: 3 }, + { x: 5, y: 1.5, key: 4 }, + { x: 6, y: 2.6, key: 5 }, + { x: 7, y: 3.3, key: 6 }, + ], + [ + { x: 1, y: 2.0, key: 0 }, + { x: 2, y: 2.5, key: 1 }, + { x: 3, y: 2.0, key: 2 }, + { x: 4, y: 1.1, key: 3 }, + { x: 5, y: 2.0, key: 4 }, + { x: 6, y: 3.2, key: 5 }, + { x: 7, y: 4.0, key: 6 }, + ], + [ + { x: 1, y: 2.5, key: 0 }, + { x: 2, y: 3.0, key: 1 }, + { x: 3, y: 2.5, key: 2 }, + { x: 4, y: 1.4, key: 3 }, + { x: 5, y: 2.5, key: 4 }, + { x: 6, y: 3.7, key: 5 }, + { x: 7, y: 4.7, key: 6 }, + ], + ], + }; + colors = RkTheme.current.colors.charts.followersArea; + + componentWillMount() { + this.size = Dimensions.get('window').width; + } + + renderChartAreas = () => this.state.data.reverse().map((area, index) => ( + + )); + + render = () => ( + + NEW FOLLOWERS + + + + {this.renderChartAreas()} + + + ) +} diff --git a/frontend/app/components/charts/doughnutChart.js b/frontend/app/components/charts/doughnutChart.js new file mode 100644 index 0000000..5b67ba7 --- /dev/null +++ b/frontend/app/components/charts/doughnutChart.js @@ -0,0 +1,125 @@ +import React from 'react'; +import { View } from 'react-native'; +import { + RkComponent, + RkText, + RkTheme, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { VictoryPie } from 'victory-native'; +import { Svg, Text as SvgText } from 'react-native-svg'; +import { scale } from '../../utils/scale'; + +export class DoughnutChart extends RkComponent { + state = { + selected: 0, + data: [ + { + x: 1, + y: 240, + title: '24%', + name: 'Likes', + color: RkTheme.current.colors.charts.doughnut[0], + }, + { + x: 2, + y: 270, + title: '27%', + name: 'Comments', + color: RkTheme.current.colors.charts.doughnut[1], + }, + { + x: 3, + y: 170, + title: '17%', + name: 'Shares', + color: RkTheme.current.colors.charts.doughnut[2], + }, + { + x: 4, + y: 320, + title: '32%', + name: 'People', + color: RkTheme.current.colors.charts.doughnut[3], + }, + ], + }; + size = 300; + fontSize = 40; + + computeColors = () => this.state.data.map(i => i.color); + + onPeopleChartPressed = (event, props) => { + this.setState({ + selected: props.index, + }); + }; + + renderMarkdown = () => this.state.data.map(this.renderMarkdownItem); + + renderMarkdownItem = (item) => ( + + + {item.name} + + ); + + render = () => ( + + AUDIENCE OVERVIEW + + + + + {this.state.data[this.state.selected].title} + + + + + {this.renderMarkdown()} + + + ); +} + +const styles = RkStyleSheet.create(() => ({ + legendContainer: { + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'space-around', + }, + legendItem: { + flexDirection: 'row', + alignItems: 'center', + }, + itemBadge: { + width: 10, + height: 10, + borderRadius: 5, + marginRight: 5, + }, +})); diff --git a/frontend/app/components/charts/index.js b/frontend/app/components/charts/index.js new file mode 100644 index 0000000..c4438e8 --- /dev/null +++ b/frontend/app/components/charts/index.js @@ -0,0 +1,4 @@ +export * from './progessChart'; +export * from './doughnutChart'; +export * from './areaChart'; +export * from './areaSmoothedChart'; diff --git a/frontend/app/components/charts/progessChart.js b/frontend/app/components/charts/progessChart.js new file mode 100644 index 0000000..bd70dcf --- /dev/null +++ b/frontend/app/components/charts/progessChart.js @@ -0,0 +1,96 @@ +import React from 'react'; +import { View } from 'react-native'; +import { + RkComponent, + RkText, + RkTheme, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { VictoryPie } from 'victory-native'; +import { Svg, Text as SvgText } from 'react-native-svg'; +import { scale } from '../../utils/scale'; + +export class ProgressChart extends RkComponent { + state = { + percents: 72, + }; + size = 120; + fontSize = 25; + + componentDidMount() { + this.setStateInterval = setInterval(this.updatePercent, 1500); + } + + componentWillUnmount() { + clearInterval(this.setStateInterval); + } + + updatePercent = () => { + let positive = Math.random() > 0.5; + if (this.state.percents > 95) { + positive = false; + } else if (this.state.percents < 60) { + positive = true; + } + this.setState({ + percents: positive ? this.state.percents + 1 : this.state.percents - 1, + }); + }; + + getChartData = () => [ + { x: 1, y: this.state.percents }, + { x: 2, y: 100 - this.state.percents }, + ]; + + onChartFill = (data) => { + const themeColor = RkTheme.current.colors.charts.followersProgress; + return data.x === 1 ? themeColor : 'transparent'; + }; + + render = () => ( + + FOLLOWERS + + + + + {`${this.state.percents}%`} + + + + REACH + 1 500 356 + +6 per day in average + + + + ); +} + +const styles = RkStyleSheet.create(() => ({ + chartContainer: { + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'center', + marginTop: 10, + }, +})); diff --git a/frontend/app/components/ellipsis.js b/frontend/app/components/ellipsis.js new file mode 100644 index 0000000..1cdcae1 --- /dev/null +++ b/frontend/app/components/ellipsis.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { View } from 'react-native'; +import { RkStyleSheet } from 'react-native-ui-kitten'; + +export class Ellipsis extends React.Component { + render() { + return ( + + + + + + ); + } +} + +let styles = RkStyleSheet.create(theme => ({ + container: { + flexDirection: 'row', + marginHorizontal: 5, + marginVertical: 10, + }, + dot: { + height: 5.5, + width: 5.5, + borderRadius: 3, + backgroundColor: theme.colors.text.base, + marginHorizontal: 2.5, + }, +})); diff --git a/frontend/app/components/findFriends.js b/frontend/app/components/findFriends.js new file mode 100644 index 0000000..0e54034 --- /dev/null +++ b/frontend/app/components/findFriends.js @@ -0,0 +1,64 @@ +import React from 'react'; +import { + StyleSheet, + TouchableOpacity, + View, + ViewPropTypes, +} from 'react-native'; +import { + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import PropTypes from 'prop-types'; +import { FontAwesome } from '../assets/icons'; + +export class FindFriends extends React.Component { + static propTypes = { + selected: PropTypes.bool, + color: PropTypes.string, + icon: PropTypes.node.isRequired, + text: PropTypes.string.isRequired, + onPress: PropTypes.func, + style: ViewPropTypes.style, + }; + static defaultProps = { + selected: false, + color: RkTheme.current.colors.text.base, + onPress: (() => null), + style: {}, + }; + + render = () => { + const color = this.props.selected ? this.props.color : RkTheme.current.colors.disabled; + return ( + + + + {this.props.icon} + {`Find Friends With ${this.props.text}`} + + {FontAwesome.chevronRight} + + + ); + }; +} + +let styles = StyleSheet.create({ + wrapper: { + flex: 1, + }, + container: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingVertical: 18, + }, + text: { + flexDirection: 'row', + }, + icon: { + width: 35, + }, +}); diff --git a/frontend/app/components/gallery.js b/frontend/app/components/gallery.js new file mode 100644 index 0000000..bcc57ea --- /dev/null +++ b/frontend/app/components/gallery.js @@ -0,0 +1,78 @@ +import React from 'react'; +import { + View, + FlatList, + Dimensions, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkButton, + RkModalImg, +} from 'react-native-ui-kitten'; +import PropTypes from 'prop-types'; +import { Ellipsis } from './ellipsis'; +import { SocialBar } from './socialBar'; + +export class Gallery extends React.Component { + static propTypes = { + items: PropTypes.arrayOf(PropTypes.node).isRequired, + }; + + constructor(props) { + super(props); + const itemSize = (Dimensions.get('window').width - 12) / 3; + this.state = { + data: this.props.items, + itemSize, + }; + } + + extractItemKey = (index) => `${index}`; + + renderHeader = (options) => ( + + Close + {`${options.pageNumber}/${options.totalPages}`} + + + + + ); + + renderFooter = () => ( + + ); + + renderItem = ({ index }) => ( + + ); + + render = () => ( + + + + ); +} + +const styles = StyleSheet.create({ + images: { + flexDirection: 'row', + paddingHorizontal: 0.5, + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + }, +}); diff --git a/frontend/app/components/gradientButton/index.js b/frontend/app/components/gradientButton/index.js new file mode 100644 index 0000000..92ebd79 --- /dev/null +++ b/frontend/app/components/gradientButton/index.js @@ -0,0 +1,45 @@ +import React from 'react'; +import { LinearGradient } from 'expo'; +import { + RkButton, + RkText, + RkComponent, +} from 'react-native-ui-kitten'; + +export class GradientButton extends RkComponent { + componentName = 'GradientButton'; + typeMapping = { + button: {}, + gradient: {}, + text: {}, + }; + + renderContent = (textStyle) => { + const hasText = this.props.text === undefined; + return hasText ? this.props.children : this.renderText(textStyle); + }; + + renderText = (textStyle) => ( + {this.props.text} + ); + + render() { + const { button, gradient, text: textStyle } = this.defineStyles(); + const { style, rkType, ...restProps } = this.props; + const colors = this.props.colors || this.extractNonStyleValue(gradient, 'colors'); + return ( + + + {this.renderContent(textStyle)} + + + ); + } +} diff --git a/frontend/app/components/gradientButton/types.js b/frontend/app/components/gradientButton/types.js new file mode 100644 index 0000000..62bcf22 --- /dev/null +++ b/frontend/app/components/gradientButton/types.js @@ -0,0 +1,48 @@ +import { scaleVertical } from '../../utils/scale'; + +export const GradientButtonTypes = (theme) => ({ + _base: { + button: { + alignItems: 'stretch', + paddingVertical: 0, + paddingHorizontal: 0, + height: scaleVertical(40), + borderRadius: 20, + }, + gradient: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + borderRadius: 20, + colors: theme.colors.gradients.base, + }, + text: { + backgroundColor: 'transparent', + color: theme.colors.text.inverse, + }, + }, + large: { + button: { + alignSelf: 'stretch', + height: scaleVertical(56), + borderRadius: 28, + }, + gradient: { + borderRadius: 28, + }, + }, + statItem: { + button: { + flex: 1, + borderRadius: 5, + marginHorizontal: 10, + height: null, + alignSelf: 'auto', + }, + gradient: { + flex: 1, + borderRadius: 5, + padding: 10, + }, + }, +}); diff --git a/frontend/app/components/index.js b/frontend/app/components/index.js new file mode 100644 index 0000000..786a99b --- /dev/null +++ b/frontend/app/components/index.js @@ -0,0 +1,14 @@ +export * from './avatar'; +export * from './gradientButton'; +export * from './charts'; +export * from './socialBar'; +export * from './switch/index'; +export * from './ellipsis'; +export * from './gallery'; +export * from './socialSetting'; +export * from './findFriends'; +export * from './progressBar'; +export * from './navBar'; +export * from './paginationIndicator'; +export * from './passwordTextInput'; +export * from './cardInput'; diff --git a/frontend/app/components/navBar.js b/frontend/app/components/navBar.js new file mode 100644 index 0000000..2947209 --- /dev/null +++ b/frontend/app/components/navBar.js @@ -0,0 +1,145 @@ +import React from 'react'; +import { + StyleSheet, + View, +} from 'react-native'; +import { DrawerActions } from 'react-navigation'; +import PropTypes from 'prop-types'; +import _ from 'lodash'; +import { RkText, RkButton, RkStyleSheet } from 'react-native-ui-kitten'; +import { FontAwesome } from '../assets/icons'; +import { UIConstants } from '../config/appConstants'; +import NavigationType from '../config/navigation/propTypes'; + +export class NavBar extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + headerProps: PropTypes.shape().isRequired, + }; + + onNavigationLeftMenuButtonPressed = () => { + this.props.navigation.dispatch(DrawerActions.openDrawer()); + }; + + onNavigationLeftBackButtonPressed = () => { + this.props.navigation.goBack(); + }; + + renderTitleItem = (title, options) => { + const isCustom = options !== undefined; + return isCustom ? this.renderCustomTitleItem(options) : this.renderNavigationTitleItem(title); + }; + + renderLeftItem = (options) => { + const isCustom = options !== undefined; + return isCustom ? this.renderCustomLeftItem(options) : this.renderNavigationLeftItem(); + }; + + renderRightItem = (options) => { + const isCustom = options !== undefined; + return isCustom ? this.renderCustomRightItem(options) : this.renderNavigationRightItem(); + }; + + renderNavigationTitleItem = (title) => ( + + {title} + + ); + + renderNavigationLeftBackItem = () => ( + + {FontAwesome.chevronLeft} + + ); + + renderNavigationLeftMenuItem = () => ( + + {FontAwesome.bars} + + ); + + renderNavigationLeftItemContent = (sceneIndex) => { + const isFirstScene = sceneIndex === 0; + return isFirstScene ? this.renderNavigationLeftMenuItem() : this.renderNavigationLeftBackItem(); + }; + + renderNavigationLeftItem = () => { + const sceneIndex = _.findIndex(this.props.headerProps.scenes, { isActive: true }); + return ( + + {this.renderNavigationLeftItemContent(sceneIndex)} + + ); + }; + + renderNavigationRightItem = () => undefined; + + renderCustomTitleItem = (options) => ( + + {options} + + ); + + renderCustomLeftItem = (options) => ( + {options} + ); + + renderCustomRightItem = (options) => ( + {options} + ); + + render() { + const { options } = this.props.headerProps.scene.descriptor; + return ( + + + {this.renderTitleItem(options.title, options.headerTitle)} + {this.renderLeftItem(options.headerLeft)} + {this.renderRightItem(options.headerRight)} + + + ); + } +} + +const styles = RkStyleSheet.create(theme => ({ + layout: { + backgroundColor: theme.colors.screen.base, + paddingTop: UIConstants.StatusbarHeight, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: theme.colors.border.base, + }, + container: { + flexDirection: 'row', + height: UIConstants.AppbarHeight, + + }, + left: { + position: 'absolute', + top: 0, + bottom: 0, + justifyContent: 'center', + }, + right: { + position: 'absolute', + right: 0, + top: 0, + bottom: 0, + justifyContent: 'center', + }, + title: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'center', + alignItems: 'center', + }, + menu: { + width: 40, + }, +})); diff --git a/frontend/app/components/paginationIndicator.js b/frontend/app/components/paginationIndicator.js new file mode 100644 index 0000000..6a043d0 --- /dev/null +++ b/frontend/app/components/paginationIndicator.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { View } from 'react-native'; +import { RkStyleSheet } from 'react-native-ui-kitten'; +import PropTypes from 'prop-types'; + +export class PaginationIndicator extends React.Component { + static propTypes = { + current: PropTypes.number, + length: PropTypes.number.isRequired, + }; + static defaultProps = { + current: 0, + }; + + renderIndicatorItem = (index, selected) => ( + + ); + + renderIndicators = () => { + const indicators = []; + for (let i = 0; i < this.props.length; i += 1) { + indicators.push(this.renderIndicatorItem(i, i === this.props.current)); + } + return indicators; + }; + + render = () => ( + + {this.renderIndicators()} + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + flexDirection: 'row', + }, + base: { + width: 8, + height: 8, + borderRadius: 5, + borderColor: theme.colors.brand, + borderWidth: 1, + marginHorizontal: 5, + }, + selected: { + backgroundColor: theme.colors.brand, + }, +})); diff --git a/frontend/app/components/passwordTextInput.js b/frontend/app/components/passwordTextInput.js new file mode 100644 index 0000000..5590caf --- /dev/null +++ b/frontend/app/components/passwordTextInput.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { + RkButton, + RkTextInput, + RkText, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../assets/icons'; + +export class PasswordTextInput extends React.Component { + state = { + hidden: true, + }; + + onInputLabelPressed = () => { + this.setState({ hidden: !this.state.hidden }); + }; + + renderInputLabel = () => ( + + {FontAwesome.slashEye} + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create({ + icon: { + fontSize: 24, + }, + button: { + right: 17, + }, +}); diff --git a/frontend/app/components/picker/datePicker.js b/frontend/app/components/picker/datePicker.js new file mode 100644 index 0000000..4225613 --- /dev/null +++ b/frontend/app/components/picker/datePicker.js @@ -0,0 +1,103 @@ +import React from 'react'; +import { RkPicker } from 'react-native-ui-kitten'; + +export const DatePart = Object.freeze({ YEAR: 1, MONTH: 2, DAY: 3 }); + +export class DatePicker extends React.Component { + componentName = 'DatePicker'; + + state = { + data: { + days: DatePicker.generateArrayFromRange(1, 31), + years: DatePicker.generateArrayFromRange(2000, 2030), + months: [ + { key: 1, value: 'Jun' }, { key: 2, value: 'Feb' }, + { key: 3, value: 'Mar' }, { key: 4, value: 'Apr' }, + { key: 5, value: 'May' }, { key: 6, value: 'Jun' }, + { key: 7, value: 'Jul' }, { key: 8, value: 'Aug' }, + { key: 9, value: 'Sep' }, { key: 10, value: 'Oct' }, + { key: 11, value: 'Nov' }, { key: 12, value: 'Dec' }, + ], + }, + }; + + onDatePickerConfirm = (date) => { + let resultDate = {}; + if (this.props.customDateParts) { + let i = 0; + if (this.props.customDateParts.includes(DatePart.MONTH)) { + resultDate.month = date[i += 1]; + } + if (this.props.customDateParts.includes(DatePart.DAY)) { + resultDate.day = date[i += 1]; + } + if (this.props.customDateParts.includes(DatePart.YEAR)) { + resultDate.year = date[i]; + } + } else { + resultDate = { month: date[0], day: date[1], year: date[2] }; + } + this.props.onConfirm(resultDate); + }; + + static generateArrayFromRange(start, finish) { + return Array(...Array((finish - start) + 1)).map((_, i) => start + i); + } + + findElementByKey(key, array) { + let element = array[0]; + array.forEach((value) => { + if (value.key === key) element = value; + }); + return element; + } + + render() { + const { + onConfirm, + selectedYear, + selectedMonth, + selectedDay, + customDateParts, + ...props + } = this.props; + + let data = [this.state.data.months, this.state.data.days, this.state.data.years]; + let selectedOptions = [ + this.findElementByKey(selectedMonth, this.state.data.months), + selectedDay || 1, + selectedYear || 2000, + ]; + if (customDateParts) { + selectedOptions = []; + data = []; + if (customDateParts.includes(DatePart.MONTH)) { + data.push(this.state.data.months); + selectedOptions.push(this.findElementByKey(selectedMonth, this.state.data.months)); + } + if (customDateParts.includes(DatePart.DAY)) { + data.push(this.state.data.days); + selectedOptions.push(selectedDay || 1); + } + if (customDateParts.includes(DatePart.YEAR)) { + data.push(this.state.data.years); + selectedOptions.push(selectedYear || 2000); + } + } + return ( + + ); + } +} diff --git a/frontend/app/components/picker/index.js b/frontend/app/components/picker/index.js new file mode 100644 index 0000000..6d1605a --- /dev/null +++ b/frontend/app/components/picker/index.js @@ -0,0 +1 @@ +export * from './datePicker'; diff --git a/frontend/app/components/progressBar.js b/frontend/app/components/progressBar.js new file mode 100644 index 0000000..dd3a3a1 --- /dev/null +++ b/frontend/app/components/progressBar.js @@ -0,0 +1,63 @@ +import React from 'react'; +import { + StyleSheet, + View, + Animated, + Easing, + ViewPropTypes, +} from 'react-native'; +import PropTypes from 'prop-types'; +import { RkTheme } from 'react-native-ui-kitten'; + +export class ProgressBar extends React.Component { + static propTypes = { + width: PropTypes.number.isRequired, + progress: PropTypes.number, + color: PropTypes.string, + style: ViewPropTypes.style, + }; + static defaultProps = { + progress: 0, + color: RkTheme.current.colors.accent, + style: {}, + }; + + state = { + progress: new Animated.Value(0), + }; + + componentDidUpdate(prevProps) { + if (this.props.progress >= 0 && this.props.progress !== prevProps.progress) { + this.animate(this.props.progress); + } + } + + animate = (endValue) => { + Animated.timing(this.state.progress, { + easing: Easing.inOut(Easing.ease), + duration: 500, + toValue: endValue, + }).start(); + }; + + render() { + const width = this.state.progress.interpolate({ + inputRange: [0, 1], + outputRange: [0, this.props.width], + }); + return ( + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + height: 3, + }, + value: { + height: 3, + }, +}); diff --git a/frontend/app/components/socialBar/index.js b/frontend/app/components/socialBar/index.js new file mode 100644 index 0000000..5cf3fc2 --- /dev/null +++ b/frontend/app/components/socialBar/index.js @@ -0,0 +1,61 @@ +import React from 'react'; +import { View } from 'react-native'; +import { + RkText, + RkButton, + RkComponent, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../../assets/icons'; + +export class SocialBar extends RkComponent { + componentName = 'SocialBar'; + typeMapping = { + container: {}, + section: {}, + icon: {}, + label: {}, + }; + static data = { + comments: '26', + is_solved: "Doesn't solved", + }; + + constructor(props) { + super(props); + this.state = { + comments: this.props.comments, + is_solved: this.props.is_solved || SocialBar.data.is_solved, + }; + } + + + onCommentButtonPressed = () => { + }; + + + render() { + const { + container, section, icon, label, + } = this.defineStyles(); + + const comments = this.state.comments + (this.props.showLabel ? ' Comments' : ''); + const is_solved = this.state.is_solved + (this.props.showLabel ? '' : ''); + + return ( + + + + {FontAwesome.comment} + {comments} + + + + + {FontAwesome.slashEye} + {is_solved} + + + + ); + } +} diff --git a/frontend/app/components/socialBar/types.js b/frontend/app/components/socialBar/types.js new file mode 100644 index 0000000..3aa638d --- /dev/null +++ b/frontend/app/components/socialBar/types.js @@ -0,0 +1,43 @@ +export const SocialBarTypes = (theme) => ({ + _base: { + container: { + justifyContent: 'center', + alignItems: 'center', + flexDirection: 'row', + flex: 1, + }, + section: { + justifyContent: 'center', + flexDirection: 'row', + flex: 1, + }, + icon: { + fontSize: 20, + }, + label: { + marginLeft: 8, + alignSelf: 'flex-end', + }, + }, + leftAligned: { + section: { + alignItems: 'flex-start', + justifyContent: 'flex-start', + }, + label: { + color: theme.colors.text.inverse, + }, + icon: { + color: theme.colors.text.inverse, + }, + }, + space: { + container: { + justifyContent: 'space-between', + paddingHorizontal: 10, + }, + section: { + flex: -1, + }, + }, +}); diff --git a/frontend/app/components/socialSetting.js b/frontend/app/components/socialSetting.js new file mode 100644 index 0000000..1c2f2a3 --- /dev/null +++ b/frontend/app/components/socialSetting.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { + View, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import PropTypes from 'prop-types'; +import { RkSwitch } from './switch/index'; + +export class SocialSetting extends React.Component { + static propTypes = { + name: PropTypes.string.isRequired, + icon: PropTypes.node.isRequired, + selected: PropTypes.bool, + tintColor: PropTypes.string, + }; + static defaultProps = { + selected: true, + tintColor: RkTheme.current.colors.accent, + }; + + constructor(props) { + super(props); + this.state = { + selected: this.props.selected, + }; + } + + onSwitchValueChanged = (value) => { + this.setState({ selected: value }); + }; + + render() { + const color = this.state.selected ? this.props.tintColor : RkTheme.current.colors.disabled; + return ( + + + {this.props.icon} + {this.props.name} + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + flex: 1, + justifyContent: 'space-between', + alignItems: 'center', + paddingVertical: 14, + }, + left: { + flexDirection: 'row', + alignItems: 'center', + }, + icon: { + width: 35, + alignItems: 'center', + }, +}); diff --git a/frontend/app/components/switch/index.android.js b/frontend/app/components/switch/index.android.js new file mode 100644 index 0000000..2750545 --- /dev/null +++ b/frontend/app/components/switch/index.android.js @@ -0,0 +1,171 @@ +/* + * + * This is modified version of https://github.com/poberwong/react-native-switch-pro + * Copyright (c) 2016 PoberWong + * + */ +import React from 'react'; +import { + Animated, + Easing, + PanResponder, +} from 'react-native'; +import { RkComponent } from 'react-native-ui-kitten'; + +const width = 52; +const height = 32; +const animationDuration = 200; +const offLeftValue = -2; +const onLeftValue = 20; + +export class RkSwitch extends RkComponent { + componentName = 'RkSwitch'; + typeMapping = { + container: { + onColor: 'onColor', + offColor: 'offColor', + }, + thumb: {}, + }; + selectedType = 'selected'; + + constructor(props) { + super(props); + this.offset = width - height; + this.handlerSize = height; + this.state = { + name: this.props.name, + value: this.props.value, + toggleable: true, + alignItems: this.props.value ? 'flex-end' : 'flex-start', + left: this.props.value ? onLeftValue : offLeftValue, + handlerAnimation: new Animated.Value(this.handlerSize), + switchAnimation: new Animated.Value(this.props.value ? -1 : 1), + }; + } + + componentWillReceiveProps(nextProps) { + const { value } = this.state; + if (nextProps === this.props) { + return; + } + if (typeof nextProps.value !== 'undefined' && nextProps.value !== value) { + this.toggleSwitch(true); + } + } + + componentWillMount() { + this.panResponder = PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onStartShouldSetPanResponderCapture: () => true, + onMoveShouldSetPanResponder: () => true, + onMoveShouldSetPanResponderCapture: () => true, + onPanResponderTerminationRequest: () => true, + onPanResponderGrant: this.onPanResponderGrant, + onPanResponderMove: this.onPanResponderMove, + onPanResponderRelease: this.onPanResponderRelease, + }); + } + + onPanResponderGrant = () => { + this.animateHandler(height * 0.9); + }; + + onPanResponderMove = (evt, gestureState) => { + const { value } = this.state; + + this.setState({ + toggleable: value ? (gestureState.dx < 10) : (gestureState.dx > -10), + }); + }; + + onPanResponderRelease = () => { + const { toggleable } = this.state; + const { disabled, onValueChange } = this.props; + + if (toggleable && !disabled) { + if (onValueChange) { + this.toggleSwitch(onValueChange); + } + } + }; + + toggleSwitch = (result, callback = () => null) => { + const { value, switchAnimation } = this.state; + const toValue = !value; + + this.animateHandler(this.handlerSize); + + this.animateSwitch(toValue, () => { + callback(toValue); + this.setState({ + value: toValue, + left: toValue ? onLeftValue : offLeftValue, + }); + switchAnimation.setValue(toValue ? -1 : 1); + }); + }; + + animateSwitch = (value, callback = () => null) => { + const { switchAnimation } = this.state; + + Animated.timing( + switchAnimation, + { + toValue: value ? this.offset : -this.offset, + duration: animationDuration, + easing: Easing.linear, + }, + ).start(callback); + }; + + animateHandler = (value, callback = () => null) => { + const { handlerAnimation } = this.state; + + Animated.timing( + handlerAnimation, + { + toValue: value, + duration: animationDuration, + easing: Easing.linear, + }, + ).start(callback); + }; + + render() { + const { + switchAnimation, handlerAnimation, left, value, + } = this.state; + const { + style, + ...rest + } = this.props; + + const type = value ? this.selectedType : ''; + const { container, thumb } = this.defineStyles(type); + const onColor = this.extractNonStyleValue(container, 'onColor'); + const offColor = this.extractNonStyleValue(container, 'offColor'); + + const interpolatedBackgroundColor = switchAnimation.interpolate({ + inputRange: value ? [-this.offset, -1] : [1, this.offset], + outputRange: [offColor, onColor], + }); + + return ( + + + + ); + } +} diff --git a/frontend/app/components/switch/index.ios.js b/frontend/app/components/switch/index.ios.js new file mode 100644 index 0000000..068cbfb --- /dev/null +++ b/frontend/app/components/switch/index.ios.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { Switch } from 'react-native'; +import { RkComponent } from 'react-native-ui-kitten'; + + +export class RkSwitch extends RkComponent { + componentName = 'RkSwitch'; + typeMapping = { + container: { + onColor: 'onColor', + offColor: 'offColor', + }, + main: {}, + }; + selectedType = 'selected'; + + constructor(props) { + super(props); + this.onChange = this.props.onValueChange ? + this.props.onValueChange + : () => true; + } + + render() { + const { container } = this.defineStyles(); + const onColor = this.extractNonStyleValue(container, 'onColor'); + return ( + this.onChange(value)} + onTintColor={onColor} + /> + ); + } +} diff --git a/frontend/app/components/switch/types.js b/frontend/app/components/switch/types.js new file mode 100644 index 0000000..96b116e --- /dev/null +++ b/frontend/app/components/switch/types.js @@ -0,0 +1,35 @@ +export const SwitchTypes = (theme) => ({ + _base: { + container: { + width: 52, + height: 32, + overflow: 'hidden', + justifyContent: 'center', + borderRadius: 16, + borderWidth: 1, + borderColor: theme.colors.border.secondary, + onColor: theme.colors.primary, + offColor: { + android: theme.colors.screen.base, + ios: theme.colors.border.base, + }, + }, + thumb: { + position: 'absolute', + height: 32, + width: 32, + borderWidth: 1, + borderColor: theme.colors.border.secondary, + backgroundColor: theme.colors.screen.base, + borderRadius: 16, + }, + }, + selected: { + thumb: { + borderColor: theme.colors.primary, + }, + container: { + borderColor: theme.colors.primary, + }, + }, +}); diff --git a/frontend/app/components/walkthrough.js b/frontend/app/components/walkthrough.js new file mode 100644 index 0000000..7fdb247 --- /dev/null +++ b/frontend/app/components/walkthrough.js @@ -0,0 +1,63 @@ +import React from 'react'; +import { + View, + FlatList, + Dimensions, + StyleSheet, +} from 'react-native'; +import PropTypes from 'prop-types'; + +export class Walkthrough extends React.Component { + static propTypes = { + children: PropTypes.arrayOf(PropTypes.element).isRequired, + onChanged: PropTypes.func, + }; + static defaultProps = { + onChanged: (() => null), + }; + + constructor(props) { + super(props); + this.itemWidth = Dimensions.get('window').width; + } + + extractItemKey = (item) => `${this.props.children.indexOf(item)}`; + + onScrollEnd = (e) => { + const { contentOffset } = e.nativeEvent; + const viewSize = e.nativeEvent.layoutMeasurement; + const pageNum = Math.floor(contentOffset.x / viewSize.width); + this.props.onChanged(pageNum); + }; + + renderItem = ({ item }) => ( + + {item} + + ); + + render = () => ( + null} + showsHorizontalScrollIndicator={false} + showsVerticalScrollIndicator={false} + directionalLockEnabled + renderItem={this.renderItem} + /> + ); +} + +const styles = StyleSheet.create({ + list: { + flex: 1, + }, + item: { + flex: 1, + }, +}); diff --git a/frontend/app/config/analytics.js b/frontend/app/config/analytics.js new file mode 100644 index 0000000..6e48218 --- /dev/null +++ b/frontend/app/config/analytics.js @@ -0,0 +1,7 @@ +import { Analytics, PageHit } from 'expo-analytics'; + +const analytics = new Analytics('UA-112172761-2'); + +const track = screen => analytics.hit(new PageHit(screen)); + +export default track; diff --git a/frontend/app/config/appConstants.js b/frontend/app/config/appConstants.js new file mode 100644 index 0000000..a120915 --- /dev/null +++ b/frontend/app/config/appConstants.js @@ -0,0 +1,7 @@ +import { Platform } from 'react-native'; + +export class UIConstants { + static AppbarHeight = Platform.OS === 'ios' ? 44 : 56; + static StatusbarHeight = Platform.OS === 'ios' ? 20 : 0; + static HeaderHeight = UIConstants.AppbarHeight + UIConstants.StatusbarHeight; +} diff --git a/frontend/app/config/bootstrap.js b/frontend/app/config/bootstrap.js new file mode 100644 index 0000000..58fe84f --- /dev/null +++ b/frontend/app/config/bootstrap.js @@ -0,0 +1,492 @@ +import { + StatusBar, + StyleSheet, +} from 'react-native'; +import { RkTheme } from 'react-native-ui-kitten'; +import { KittenTheme } from './theme'; +import { AvatarTypes } from '../components/avatar/types'; +import { GradientButtonTypes } from '../components/gradientButton/types'; +import { SwitchTypes } from '../components/switch/types'; +import { SocialBarTypes } from '../components/socialBar/types'; +import { scale, scaleVertical } from '../utils/scale'; + +export const bootstrap = () => { + RkTheme.setTheme(KittenTheme, null); + + /* + RkText types + */ + + RkTheme.setType('RkText', 'basic', { + fontFamily: theme => theme.fonts.family.bold, + backgroundColor: 'transparent', + }); + + RkTheme.setType('RkText', 'regular', { + fontFamily: theme => theme.fonts.family.regular, + }); + + RkTheme.setType('RkText', 'light', { + fontFamily: theme => theme.fonts.family.light, + }); + + RkTheme.setType('RkText', 'logo', { + fontFamily: theme => theme.fonts.family.logo, + }); + + RkTheme.setType('RkText', 'moon', { + fontFamily: 'icomoon', + }); + + RkTheme.setType('RkText', 'awesome', { + fontFamily: 'fontawesome', + }); + + RkTheme.setType('RkText', 'hero', { + fontSize: scale(33), + }); + + RkTheme.setType('RkText', 'menuIcon', { + fontSize: 44, + }); + + // all font sizes + Object.keys(RkTheme.current.fonts.sizes).forEach(key => { + RkTheme.setType('RkText', key, { + fontSize: theme => theme.fonts.sizes[key], + }); + }); + + // all text colors + Object.keys(RkTheme.current.colors.text).forEach(key => { + RkTheme.setType('RkText', `${key}Color`, { + color: theme => theme.colors.text[key], + }); + }); + + // all text line heights + Object.keys(RkTheme.current.fonts.lineHeights).forEach(key => { + RkTheme.setType('RkText', `${key}Line`, { + text: { lineHeight: theme => theme.fonts.lineHeights[key] }, + }); + }); + + // theme text styles + RkTheme.setType('RkText', 'header1', { + fontSize: theme => theme.fonts.sizes.h1, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'header2', { + fontSize: theme => theme.fonts.sizes.h2, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'header3', { + fontSize: theme => theme.fonts.sizes.h3, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'header4', { + fontSize: theme => theme.fonts.sizes.h4, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'header5', { + fontSize: theme => theme.fonts.sizes.h5, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'header6', { + fontSize: theme => theme.fonts.sizes.h6, + fontFamily: theme => theme.fonts.family.bold, + }); + RkTheme.setType('RkText', 'secondary1', { + fontSize: theme => theme.fonts.sizes.s1, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'secondary2', { + fontSize: theme => theme.fonts.sizes.s2, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'secondary3', { + fontSize: theme => theme.fonts.sizes.s3, + fontFamily: theme => theme.fonts.family.regular, + }); + RkTheme.setType('RkText', 'secondary4', { + fontSize: theme => theme.fonts.sizes.s4, + fontFamily: theme => theme.fonts.family.regular, + }); + RkTheme.setType('RkText', 'secondary5', { + fontSize: theme => theme.fonts.sizes.s5, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'secondary6', { + fontSize: theme => theme.fonts.sizes.s6, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'secondary7', { + fontSize: theme => theme.fonts.sizes.s7, + fontFamily: theme => theme.fonts.family.regular, + }); + RkTheme.setType('RkText', 'primary1', { + fontSize: theme => theme.fonts.sizes.p1, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'primary2', { + fontSize: theme => theme.fonts.sizes.p2, + fontFamily: theme => theme.fonts.family.regular, + }); + RkTheme.setType('RkText', 'primary3', { + fontSize: theme => theme.fonts.sizes.p3, + fontFamily: theme => theme.fonts.family.light, + }); + RkTheme.setType('RkText', 'primary4', { + fontSize: theme => theme.fonts.sizes.p4, + fontFamily: theme => theme.fonts.family.regular, + }); + + RkTheme.setType('RkText', 'center', { + text: { + textAlign: 'center', + }, + }); + + RkTheme.setType('RkText', 'chat', { + color: theme => theme.colors.chat.text, + }); + /* + RkButton types + */ + + RkTheme.setType('RkButton', 'basic', { + container: { + alignSelf: 'auto', + }, + }); + + RkTheme.setType('RkButton', 'square', { + borderRadius: 3, + backgroundColor: theme => theme.colors.button.back, + container: { + flexDirection: 'column', + margin: 8, + }, + }); + + RkTheme.setType('RkButton', 'tile', { + borderRadius: 0, + backgroundColor: 'transparent', + borderWidth: 0.5, + borderColor: theme => theme.colors.border.base, + container: { + flexDirection: 'column', + }, + }); + + RkTheme.setType('RkButton', 'link', { + color: theme => theme.colors.primary, + }); + + RkTheme.setType('RkButton', 'contrast', { + color: theme => theme.colors.text.base, + }); + + RkTheme.setType('RkButton', 'icon', { + height: scale(56), + width: scale(56), + borderColor: theme => theme.colors.border.base, + backgroundColor: theme => theme.colors.control.background, + borderWidth: 1, + }); + + RkTheme.setType('RkButton', 'highlight', { + backgroundColor: theme => theme.colors.button.highlight, + }); + + RkTheme.setType('RkButton', 'social', { + height: scale(62), + width: scale(62), + borderRadius: scale(31), + borderColor: theme => theme.colors.border.accent, + borderWidth: 1, + backgroundColor: theme => theme.colors.control.background, + }); + /* + RkModalImg types + */ + + RkTheme.setType('RkModalImg', 'basic', { + img: { + margin: 1.5, + }, + modal: { + backgroundColor: theme => theme.colors.screen.base, + }, + footer: { + backgroundColor: theme => theme.colors.screen.base, + height: 50, + }, + header: { + backgroundColor: theme => theme.colors.screen.base, + paddingBottom: 6, + }, + }); + + /* + RkTextInput + */ + + RkTheme.setType('RkTextInput', 'basic', { + input: { + fontFamily: theme => theme.fonts.family.bold, + }, + color: theme => theme.colors.text.base, + backgroundColor: theme => theme.colors.control.background, + labelColor: theme => theme.colors.input.label, + placeholderTextColor: theme => theme.colors.input.placeholder, + }); + + RkTheme.setType('RkTextInput', 'rounded', { + fontSize: theme => theme.fonts.sizes.h6, + borderWidth: 1, + underlineWidth: 1, + placeholderTextColor: theme => theme.colors.input.text, + input: { + marginVertical: { + ios: scaleVertical(15), + android: scaleVertical(4), + }, + }, + }); + + + RkTheme.setType('RkTextInput', 'right', { + input: { + textAlign: 'right', + marginTop: { + ios: scaleVertical(18), + android: scaleVertical(11), + }, + }, + label: { + fontFamily: theme => theme.fonts.family.light, + }, + container: { + marginVertical: 4, + }, + backgroundColor: 'transparent', + labelFontSize: theme => theme.fonts.sizes.small, + }); + + RkTheme.setType('RkTextInput', 'row', { + input: { + marginVertical: 0, + marginHorizontal: 0, + marginTop: 0, + paddingTop: { + ios: 2, + android: 0, + }, + paddingBottom: 0, + textAlignVertical: 'center', + includeFontPadding: false, + fontFamily: theme => theme.fonts.family.light, + fontSize: theme => theme.fonts.sizes.small, + }, + container: { + flex: 1, + backgroundColor: theme => theme.colors.input.background, + marginVertical: 0, + borderRadius: 20, + paddingHorizontal: 16, + }, + + }); + + RkTheme.setType('RkTextInput', 'iconRight', { + label: { + position: 'absolute', + right: 0, + }, + input: { + marginRight: scale(46), + }, + }); + + RkTheme.setType('RkTextInput', 'sticker', { + input: { + marginHorizontal: 14, + }, + container: { + justifyContent: 'center', + paddingHorizontal: 0, + }, + label: { + position: 'absolute', + right: 0, + }, + }); + + /* + RkCard types + */ + + RkTheme.setType('RkCard', 'basic', { + container: { + borderRadius: 3, + backgroundColor: theme => theme.colors.control.background, + }, + header: { + justifyContent: 'flex-start', + paddingVertical: 14, + }, + content: { + padding: 16, + }, + footer: { + paddingBottom: 20, + paddingTop: 7.5, + paddingHorizontal: 0, + }, + }); + + RkTheme.setType('RkCard', 'backImg', { + container: { + borderWidth: 0, + borderRadius: 0, + }, + img: { + height: 225, + }, + imgOverlay: { + height: 225, + backgroundColor: 'transparent', + }, + content: { + paddingHorizontal: 14, + }, + footer: { + paddingTop: 15, + paddingBottom: 0, + paddingVertical: 7.5, + paddingHorizontal: 0, + }, + }); + + + RkTheme.setType('RkCard', 'imgBlock', { + img: { + height: 235, + }, + header: { + padding: 0, + paddingVertical: 13, + paddingHorizontal: 16, + }, + imgOverlay: { + height: -1, + }, + footer: { + paddingTop: 18, + paddingBottom: 15, + paddingVertical: 0, + paddingHorizontal: 0, + }, + }); + + RkTheme.setType('RkCard', 'horizontal', { + container: { + flexDirection: 'row', + height: 110, + }, + content: { + flex: 1, + }, + img: { + height: null, + flex: -1, + width: 120, + }, + }); + + RkTheme.setType('RkCard', 'blog', { + header: { + paddingHorizontal: 16, + paddingVertical: 0, + paddingTop: 16, + }, + content: { + padding: 0, + paddingVertical: 0, + paddingTop: 12, + }, + footer: { + paddingHorizontal: 16, + paddingTop: 15, + paddingBottom: 16, + alignItems: 'center', + }, + }); + + RkTheme.setType('RkCard', 'article', { + container: { + borderWidth: 0, + backgroundColor: 'transparent', + }, + header: { + paddingVertical: 0, + paddingTop: 20, + paddingBottom: 16, + justifyContent: 'space-between', + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: theme => theme.colors.border.base, + }, + content: { + padding: 16, + borderBottomWidth: 1, + borderColor: theme => theme.colors.border.base, + }, + footer: { + paddingHorizontal: 14, + paddingTop: 15, + paddingBottom: 16, + alignItems: 'center', + }, + }); + + RkTheme.setType('RkCard', 'credit', { + container: { + borderWidth: 0, + borderRadius: 7, + }, + header: { + justifyContent: 'space-between', + paddingHorizontal: 14, + alignItems: 'center', + paddingBottom: scaleVertical(46), + }, + content: { + alignItems: 'center', + paddingVertical: 0, + }, + footer: { + paddingBottom: scaleVertical(14), + paddingTop: scaleVertical(16), + paddingHorizontal: 14, + alignItems: 'flex-end', + }, + }); + + RkTheme.setType('RkPicker', 'highlight', { + highlightBorderTopColor: theme => theme.colors.border.highlight, + highlightBorderBottomColor: theme => theme.colors.border.highlight, + windowBorderColor: theme => theme.colors.border.highlight, + }); + + /* + Register components + */ + + RkTheme.registerComponent('Avatar', AvatarTypes); + RkTheme.registerComponent('GradientButton', GradientButtonTypes); + RkTheme.registerComponent('RkSwitch', SwitchTypes); + RkTheme.registerComponent('SocialBar', SocialBarTypes); + + StatusBar.setBarStyle('dark-content', true); +}; diff --git a/frontend/app/config/darkTheme.js b/frontend/app/config/darkTheme.js new file mode 100644 index 0000000..4461dcb --- /dev/null +++ b/frontend/app/config/darkTheme.js @@ -0,0 +1,209 @@ +const Colors = { + accent: '#ffffff', + primary: '#ffffff', + success: '#3bd555', + disabled: '#686894', + danger: '#f53d56', + + foreground: '#ffffff', + alterForeground: '#acacd2', + inverseForeground: '#ffffff', + secondaryForeground: '#bcbcbc', + hintForeground: '#969696', + fadedForeground: '#ffffffdd', + + boldBackground: '#090f3f', + background: '#0a1142', + alterBackground: '#12194d', + overlayBackground: '#00000057', + neutralBackground: '#2f396b', + fadedBackground: '#28305a', + brandBackground: '#6b35e4', + + border: '#080e36', + + twitter: '#ffffff', + google: '#ffffff', + facebook: '#ffffff', + + gradientBaseBegin: '#6b35e4', + gradientBaseEnd: '#6b35e4', + gradientVisaBegin: '#63e2ff', + gradientVisaEnd: '#712ec3', + gradientMasterBegin: '#febb5b', + gradientMasterEnd: '#f24645', + gradientAxpBegin: '#42e695', + gradientAxpEnd: '#3bb2bb', + highlight: '#acacd2', + + faded: '#e5e5e5', + icon: '#c2c2c2', + neutral: '#f2f2f2', + + info: '#2942ff', + warning: '#feb401', + + doughnutFirst: '#d500f9', + doughnutSecond: '#7c4dff', + doughnutThird: '#40c4ff', + doughnutFourth: '#2962ff', + + followersProgress: '#d500f9', + + followersFirst: '#2942ff', + followersSecond: '#1b2ba6', + followersThird: '#081c6e', + followersFourth: '#09103f', + + chartsAreaStroke: '#2942ff', + chartsAreaFill: '#0d1238', +}; + +const Fonts = { + light: 'Roboto-Light', + regular: 'Roboto-Regular', + bold: 'Roboto-Medium', + logo: 'Righteous-Regular', +}; + +const FontBaseValue = 18; + +export const DarkKittenTheme = { + name: 'dark', + colors: { + accent: Colors.accent, + primary: Colors.primary, + disabled: Colors.disabled, + twitter: Colors.twitter, + google: Colors.google, + facebook: Colors.facebook, + brand: Colors.brandBackground, + info: Colors.info, + infoActive: Colors.info, + text: { + base: Colors.foreground, + secondary: Colors.foreground, + accent: Colors.accent, + inverse: Colors.inverseForeground, + hint: Colors.alterForeground, + }, + screen: { + base: Colors.background, + alter: Colors.alterBackground, + scroll: Colors.background, + bold: Colors.boldBackground, + overlay: Colors.overlayBackground, + }, + button: { + back: Colors.alterBackground, + underlay: Colors.neutralBackground, + highlight: Colors.brandBackground, + }, + input: { + text: Colors.alterForeground, + background: Colors.alterBackground, + label: Colors.alterForeground, + placeholder: Colors.alterForeground, + }, + border: { + base: Colors.border, + accent: Colors.alterBackground, + secondary: Colors.secondaryForeground, + highlight: Colors.highlight, + }, + control: { + background: Colors.alterBackground, + }, + badge: { + likeBackground: Colors.foreground, + likeForeground: Colors.danger, + plusBackground: Colors.foreground, + plusForeground: Colors.success, + }, + chat: { + messageInBackground: Colors.fadedBackground, + messageOutBackground: Colors.neutralBackground, + text: Colors.fadedForeground, + }, + gradients: { + base: [ + Colors.gradientBaseBegin, + Colors.gradientBaseEnd, + ], + visa: [ + Colors.gradientVisaBegin, + Colors.gradientVisaEnd, + ], + mastercard: [ + Colors.gradientMasterBegin, + Colors.gradientMasterEnd, + ], + axp: [ + Colors.gradientAxpBegin, + Colors.gradientAxpEnd, + ], + }, + dashboard: { + stars: Colors.alterBackground, + tweets: Colors.alterBackground, + likes: Colors.alterBackground, + }, + charts: { + followersProgress: Colors.followersProgress, + doughnut: [ + Colors.doughnutFirst, + Colors.doughnutSecond, + Colors.doughnutThird, + Colors.doughnutFourth, + ], + followersArea: [ + Colors.followersFirst, + Colors.followersSecond, + Colors.followersThird, + Colors.followersFourth, + ], + area: { + stroke: Colors.chartsAreaStroke, + fill: Colors.chartsAreaFill, + }, + }, + }, + fonts: { + sizes: { + h0: 32, + h1: 26, + h2: 24, + h3: 20, + h4: 18, + h5: 16, + h6: 15, + p1: 16, + p2: 15, + p3: 15, + p4: 13, + s1: 15, + s2: 14, + s3: 14, + s4: 12, + s5: 12, + s6: 13, + s7: 10, + base: FontBaseValue, + small: FontBaseValue * 0.8, + medium: FontBaseValue, + large: FontBaseValue * 1.2, + xlarge: FontBaseValue / 0.75, + xxlarge: FontBaseValue * 1.6, + }, + lineHeights: { + medium: 18, + big: 24, + }, + family: { + regular: Fonts.regular, + light: Fonts.light, + bold: Fonts.bold, + logo: Fonts.logo, + }, + }, +}; diff --git a/frontend/app/config/navigation/propTypes.js b/frontend/app/config/navigation/propTypes.js new file mode 100644 index 0000000..a7c6ffc --- /dev/null +++ b/frontend/app/config/navigation/propTypes.js @@ -0,0 +1,15 @@ +import PropTypes from 'prop-types'; + +const shape = (propShape) => PropTypes.shape(propShape); + +const functionTypes = { + goBack: PropTypes.func, + navigate: PropTypes.func, +}; + +const NavigationType = shape({ + goBack: functionTypes.goBack.isRequired, + navigate: functionTypes.navigate.isRequired, +}); + +export default NavigationType; diff --git a/frontend/app/config/navigation/routes.js b/frontend/app/config/navigation/routes.js new file mode 100644 index 0000000..6a75312 --- /dev/null +++ b/frontend/app/config/navigation/routes.js @@ -0,0 +1,269 @@ +import _ from 'lodash'; +import {FontIcons} from '../../assets/icons'; +import * as Screens from '../../screens/index'; + +export const MainRoutes = [ + { + id: 'LoginMenu', + title: 'Auth', + icon: FontIcons.login, + screen: Screens.LoginMenu, + children: [ + { + id: 'Login1', + title: 'Login V1', + screen: Screens.LoginV1, + children: [], + }, + { + id: 'Login2', + title: 'Login V2', + screen: Screens.LoginV2, + children: [], + }, + { + id: 'SignUp', + title: 'Sign Up', + screen: Screens.SignUp, + children: [], + }, + { + id: 'password', + title: 'Password Recovery', + screen: Screens.PasswordRecovery, + children: [], + }, + ], + }, + { + id: 'SocialMenu', + title: 'Social', + icon: FontIcons.profile, + screen: Screens.SocialMenu, + children: [ + { + id: 'ProfileV1', + title: 'User Profile V1', + screen: Screens.ProfileV1, + children: [], + }, + { + id: 'ProfileV2', + title: 'User Profile V2', + screen: Screens.ProfileV2, + children: [], + }, + { + id: 'ProfileV3', + title: 'User Profile V3', + screen: Screens.ProfileV3, + children: [], + }, + { + id: 'ProfileSettings', + title: 'Profile Settings', + screen: Screens.ProfileSettings, + children: [], + }, + { + id: 'Notifications', + title: 'Notifications', + screen: Screens.Notifications, + children: [], + }, + { + id: 'Contacts', + title: 'Contacts', + screen: Screens.Contacts, + children: [], + }, + { + id: 'Feed', + title: 'Feed', + screen: Screens.Feed, + children: [], + }, + ], + }, + { + id: 'ArticlesMenu', + title: 'Articles', + icon: FontIcons.article, + screen: Screens.ArticleMenu, + children: [ + { + id: 'Articles1', + title: 'Article List V1', + screen: Screens.Articles1, + children: [], + }, + { + id: 'Articles2', + title: 'Article List V2', + screen: Screens.Articles2, + children: [], + }, + { + id: 'Articles3', + title: 'Article List V3', + screen: Screens.Articles3, + children: [], + }, + { + id: 'Articles4', + title: 'Article List V4', + screen: Screens.Articles4, + children: [], + }, + { + id: 'Blogposts', + title: 'Blogposts', + screen: Screens.Blogposts, + children: [], + }, + { + id: 'Article', + title: 'Article View', + screen: Screens.Article, + children: [], + }, + ], + }, + { + id: 'MessagingMenu', + title: 'Messaging', + icon: FontIcons.mail, + screen: Screens.MessagingMenu, + children: [ + { + id: 'Chat', + title: 'Chat', + screen: Screens.Chat, + children: [], + }, + { + id: 'ChatList', + title: 'Chat List', + screen: Screens.ChatList, + children: [], + }, + { + id: 'Comments', + title: 'Comments', + screen: Screens.Comments, + children: [], + }, + ], + }, + { + id: 'DashboardsMenu', + title: 'Dashboards', + icon: FontIcons.dashboard, + screen: Screens.DashboardMenu, + children: [{ + id: 'Dashboard', + title: 'Dashboard', + screen: Screens.Dashboard, + children: [], + }], + }, + { + id: 'WalkthroughMenu', + title: 'Walkthroughs', + icon: FontIcons.mobile, + screen: Screens.WalkthroughMenu, + children: [{ + id: 'Walkthrough', + title: 'Walkthrough', + screen: Screens.WalkthroughScreen, + children: [], + }], + }, + { + id: 'EcommerceMenu', + title: 'Ecommerce', + icon: FontIcons.card, + screen: Screens.EcommerceMenu, + children: [ + { + id: 'Cards', + title: 'Cards', + icon: FontIcons.card, + screen: Screens.Cards, + children: [], + }, + { + id: 'AddProblem', + title: 'Add Card Form', + icon: FontIcons.addToCardForm, + screen: Screens.AddToCardForm, + children: [], + }, + + ], + }, + { + id: 'NavigationMenu', + icon: FontIcons.navigation, + title: 'Navigation', + screen: Screens.NavigationMenu, + children: [ + { + id: 'GridV1', + title: 'Grid Menu V1', + screen: Screens.GridV1, + children: [], + }, + { + id: 'GridV2', + title: 'Grid Menu V2', + screen: Screens.GridV2, + children: [], + }, + { + id: 'List', + title: 'List Menu', + screen: Screens.ListMenu, + children: [], + }, + { + id: 'Side', + title: 'Side Menu', + action: 'DrawerOpen', + screen: Screens.SideMenu, + children: [], + }, + ], + }, + { + id: 'OtherMenu', + title: 'Other', + icon: FontIcons.other, + screen: Screens.OtherMenu, + children: [ + { + id: 'Settings', + title: 'Settings', + screen: Screens.Settings, + children: [], + }, + ], + }, + { + id: 'Themes', + title: 'Themes', + icon: FontIcons.theme, + screen: Screens.Themes, + children: [], + }, +]; + +const menuRoutes = _.cloneDeep(MainRoutes); +menuRoutes.unshift({ + id: 'Walkthrough', + title: 'Walkthrough', + screen: Screens.WalkthroughScreen, + children: [], +}); + +export const MenuRoutes = menuRoutes; diff --git a/frontend/app/config/navigation/routesBuilder.js b/frontend/app/config/navigation/routesBuilder.js new file mode 100644 index 0000000..157a958 --- /dev/null +++ b/frontend/app/config/navigation/routesBuilder.js @@ -0,0 +1,62 @@ +import React from 'react'; +import _ from 'lodash'; +import { createStackNavigator } from 'react-navigation'; +import { withRkTheme } from 'react-native-ui-kitten'; +import { NavBar } from '../../components/index'; +import transition from './transitions'; +import { + MainRoutes, + MenuRoutes, +} from './routes'; + +const main = {}; +const flatRoutes = {}; + +const routeMapping = (route) => ({ + screen: withRkTheme(route.screen), + title: route.title, +}); + +(MenuRoutes).forEach(route => { + flatRoutes[route.id] = routeMapping(route); + main[route.id] = routeMapping(route); + route.children.forEach(nestedRoute => { + flatRoutes[nestedRoute.id] = routeMapping(nestedRoute); + }); +}); + +const renderHeader = (navigation, props) => { + const ThemedNavigationBar = withRkTheme(NavBar); + return ( + + ); +}; + +const DrawerRoutes = Object.keys(main).reduce((routes, name) => { + const rawRoutes = routes; + rawRoutes[name] = { + name, + screen: createStackNavigator(flatRoutes, { + initialRouteName: name, + headerMode: 'screen', + cardStyle: { backgroundColor: 'transparent' }, + transitionConfig: transition, + navigationOptions: ({ navigation }) => ({ + gesturesEnabled: false, + header: (props) => renderHeader(navigation, props), + }), + }), + }; + return rawRoutes; +}, {}); + +export const AppRoutes = DrawerRoutes; +export const LoginRoutes = _.find(MainRoutes, { id: 'LoginMenu' }).children; +export const NavigationRoutes = _.find(MainRoutes, { id: 'NavigationMenu' }).children; +export const SocialRoutes = _.find(MainRoutes, { id: 'SocialMenu' }).children; +export const ArticleRoutes = _.find(MainRoutes, { id: 'ArticlesMenu' }).children; +export const MessagingRoutes = _.find(MainRoutes, { id: 'MessagingMenu' }).children; +export const DashboardRoutes = _.find(MainRoutes, { id: 'DashboardsMenu' }).children; +export const WalkthroughRoutes = _.find(MainRoutes, { id: 'WalkthroughMenu' }).children; +export const EcommerceRoutes = _.find(MainRoutes, { id: 'EcommerceMenu' }).children; +export const OtherRoutes = _.find(MainRoutes, { id: 'OtherMenu' }).children; diff --git a/frontend/app/config/navigation/transitions.js b/frontend/app/config/navigation/transitions.js new file mode 100644 index 0000000..ff3d2fa --- /dev/null +++ b/frontend/app/config/navigation/transitions.js @@ -0,0 +1,59 @@ +import { + Dimensions, + Platform, +} from 'react-native'; + +const { width } = Dimensions.get('window'); + +const IosTransition = (index, position) => { + const inputRange = [index - 1, index, index + 0.99, index + 1]; + const outputRange = [width, 0, -10, -10]; + + const translateY = 0; + const translateX = position.interpolate({ + inputRange, + outputRange, + }); + + const opacity = position.interpolate({ + inputRange, + outputRange: [0, 1, 1, 0], + }); + return { + opacity, + transform: [{ translateX }, { translateY }], + }; +}; + +const DroidTransition = (index, position) => { + const inputRange = [index - 1, index, index + 0.99, index + 1]; + + const opacity = position.interpolate({ + inputRange, + outputRange: [0, 1, 1, 0], + }); + + const translateX = 0; + const translateY = position.interpolate({ + inputRange, + outputRange: [50, 0, 0, 0], + }); + + return { + opacity, + transform: [{ translateX }, { translateY }], + }; +}; + +function transition() { + return { + screenInterpolator: (sceneProps) => { + const { position, scene } = sceneProps; + const { index } = scene; + if (Platform.OS === 'ios') { return IosTransition(index, position); } + return DroidTransition(index, position); + }, + }; +} + +export default transition; diff --git a/frontend/app/config/theme.js b/frontend/app/config/theme.js new file mode 100644 index 0000000..b3f4225 --- /dev/null +++ b/frontend/app/config/theme.js @@ -0,0 +1,210 @@ +import { scale } from '../utils/scale'; + +const Colors = { + accent: '#5c9b3a', + primary: '#f64e59', + success: '#3bd555', + disabled: '#cacaca', + + foreground: '#212121', + alterForeground: '#707070', + inverseForeground: '#ffffff', + secondaryForeground: '#bcbcbc', + hintForeground: '#969696', + highlight: '#bcbcbc', + + background: '#ffffff', + alterBackground: '#f2f2f2', + overlayBackground: '#00000057', + neutralBackground: '#f2f2f2', + fadedBackground: '#e5e5e5', + + border: '#f2f2f2', + + twitter: '#41abe1', + google: '#e94335', + facebook: '#3b5998', + + gradientBaseBegin: '#69b338', + gradientBaseEnd: '#0d712a', + gradientVisaBegin: '#63e2ff', + gradientVisaEnd: '#712ec3', + gradientMasterBegin: '#febb5b', + gradientMasterEnd: '#f24645', + gradientAxpBegin: '#42e695', + gradientAxpEnd: '#3bb2bb', + + faded: '#e5e5e5', + icon: '#c2c2c2', + neutral: '#f2f2f2', + + info: '#19bfe5', + warning: '#feb401', + danger: '#ed1c4d', + + starsStat: '#2ab5fa', + tweetsStat: '#ffc61c', + likesStat: '#5468ff', + + doughnutFirst: '#8a98ff', + doughnutSecond: '#ffd146', + doughnutThird: '#c2d521', + doughnutFourth: '#ff6b5c', + + followersProgress: '#c2d521', + + followersFirst: '#b3e5fc', + followersSecond: '#81d4fa', + followersThird: '#4fc3f7', + followersFourth: '#42a5f5', + + chartsAreaStroke: '#097fe5', + chartsAreaFill: '#d6ecff', +}; + +const Fonts = { + light: 'Roboto-Light', + regular: 'Roboto-Regular', + bold: 'Roboto-Medium', + logo: 'Righteous-Regular', +}; + +const FontBaseValue = scale(18); + +export const KittenTheme = { + name: 'light', + colors: { + accent: Colors.accent, + primary: Colors.primary, + disabled: Colors.disabled, + twitter: Colors.twitter, + google: Colors.google, + facebook: Colors.facebook, + brand: Colors.accent, + text: { + base: Colors.foreground, + secondary: Colors.secondaryForeground, + accent: Colors.accent, + inverse: Colors.inverseForeground, + hint: Colors.alterForeground, + }, + input: { + text: Colors.alterForeground, + background: Colors.background, + label: Colors.secondaryForeground, + placeholder: Colors.secondaryForeground, + }, + screen: { + base: Colors.background, + alter: Colors.alterBackground, + scroll: Colors.alterBackground, + bold: Colors.alterBackground, + overlay: Colors.overlayBackground, + }, + button: { + back: Colors.background, + underlay: Colors.neutralBackground, + highlight: Colors.primary, + }, + border: { + base: Colors.border, + accent: Colors.accent, + secondary: Colors.secondaryForeground, + highlight: Colors.highlight, + }, + control: { + background: Colors.background, + }, + badge: { + likeBackground: Colors.primary, + likeForeground: Colors.inverseForeground, + plusBackground: Colors.success, + plusForeground: Colors.inverseForeground, + }, + chat: { + messageInBackground: Colors.neutralBackground, + messageOutBackground: Colors.fadedBackground, + text: Colors.foreground, + }, + gradients: { + base: [ + Colors.gradientBaseBegin, + Colors.gradientBaseEnd, + ], + visa: [ + Colors.gradientVisaBegin, + Colors.gradientVisaEnd, + ], + mastercard: [ + Colors.gradientMasterBegin, + Colors.gradientMasterEnd, + ], + axp: [ + Colors.gradientAxpBegin, + Colors.gradientAxpEnd, + ], + }, + dashboard: { + stars: Colors.starsStat, + tweets: Colors.tweetsStat, + likes: Colors.likesStat, + }, + charts: { + followersProgress: Colors.followersProgress, + doughnut: [ + Colors.doughnutFirst, + Colors.doughnutSecond, + Colors.doughnutThird, + Colors.doughnutFourth, + ], + followersArea: [ + Colors.followersFirst, + Colors.followersSecond, + Colors.followersThird, + Colors.followersFourth, + ], + area: { + stroke: Colors.chartsAreaStroke, + fill: Colors.chartsAreaFill, + }, + }, + }, + fonts: { + sizes: { + h0: scale(32), + h1: scale(26), + h2: scale(24), + h3: scale(20), + h4: scale(18), + h5: scale(16), + h6: scale(15), + p1: scale(16), + p2: scale(15), + p3: scale(15), + p4: scale(13), + s1: scale(15), + s2: scale(13), + s3: scale(13), + s4: scale(12), + s5: scale(12), + s6: scale(13), + s7: scale(10), + base: FontBaseValue, + small: FontBaseValue * 0.8, + medium: FontBaseValue, + large: FontBaseValue * 1.2, + xlarge: FontBaseValue / 0.75, + xxlarge: FontBaseValue * 1.6, + }, + lineHeights: { + medium: 18, + big: 24, + }, + family: { + regular: Fonts.regular, + light: Fonts.light, + bold: Fonts.bold, + logo: Fonts.logo, + }, + }, +}; diff --git a/frontend/app/data/dataGenerator.js b/frontend/app/data/dataGenerator.js new file mode 100644 index 0000000..1a171cf --- /dev/null +++ b/frontend/app/data/dataGenerator.js @@ -0,0 +1,45 @@ +import _ from 'lodash'; +import users from './raw/users'; +import articles from './raw/articles'; +import notifications from './raw/notifications'; +import conversations from './raw/conversations'; + +const populateArticles = () => { + articles.forEach(article => { + const userArticle = article; + const userId = articles.indexOf(article) % users.length; + userArticle.user = _.find(users, x => x.id === userId) || users[0]; + userArticle.comments.map(comment => { + const userComment = comment; + const commentUserId = article.comments.indexOf(comment) % users.length; + userComment.user = _.find(users, x => x.id === commentUserId) || users[0]; + return userComment; + }); + return userArticle; + }); +}; + +const populateNotifications = () => { + notifications.map(notification => { + const userNotification = notification; + const userId = notifications.indexOf(notification) % users.length; + userNotification.user = _.find(users, x => x.id === userId) || users[0]; + return userNotification; + }); +}; + +const populateConversations = () => { + conversations.map(conversation => { + const userConversation = conversation; + userConversation.withUser = _.find(users, x => x.id === conversation.withUserId) || users[0]; + return userConversation; + }); +}; + +const populate = () => { + populateArticles(); + populateNotifications(); + populateConversations(); +}; + +export default populate; diff --git a/frontend/app/data/img/Image1.png b/frontend/app/data/img/Image1.png new file mode 100755 index 0000000..51a7b11 Binary files /dev/null and b/frontend/app/data/img/Image1.png differ diff --git a/frontend/app/data/img/Image10.png b/frontend/app/data/img/Image10.png new file mode 100755 index 0000000..1d5a19b Binary files /dev/null and b/frontend/app/data/img/Image10.png differ diff --git a/frontend/app/data/img/Image11.png b/frontend/app/data/img/Image11.png new file mode 100755 index 0000000..a604b67 Binary files /dev/null and b/frontend/app/data/img/Image11.png differ diff --git a/frontend/app/data/img/Image12.png b/frontend/app/data/img/Image12.png new file mode 100755 index 0000000..8883ccf Binary files /dev/null and b/frontend/app/data/img/Image12.png differ diff --git a/frontend/app/data/img/Image2.png b/frontend/app/data/img/Image2.png new file mode 100755 index 0000000..0774f0a Binary files /dev/null and b/frontend/app/data/img/Image2.png differ diff --git a/frontend/app/data/img/Image3.png b/frontend/app/data/img/Image3.png new file mode 100755 index 0000000..3451fe3 Binary files /dev/null and b/frontend/app/data/img/Image3.png differ diff --git a/frontend/app/data/img/Image4.png b/frontend/app/data/img/Image4.png new file mode 100755 index 0000000..2cc648c Binary files /dev/null and b/frontend/app/data/img/Image4.png differ diff --git a/frontend/app/data/img/Image5.png b/frontend/app/data/img/Image5.png new file mode 100755 index 0000000..b407820 Binary files /dev/null and b/frontend/app/data/img/Image5.png differ diff --git a/frontend/app/data/img/Image6.png b/frontend/app/data/img/Image6.png new file mode 100755 index 0000000..886ad46 Binary files /dev/null and b/frontend/app/data/img/Image6.png differ diff --git a/frontend/app/data/img/Image7.png b/frontend/app/data/img/Image7.png new file mode 100755 index 0000000..c4ed0be Binary files /dev/null and b/frontend/app/data/img/Image7.png differ diff --git a/frontend/app/data/img/Image8.png b/frontend/app/data/img/Image8.png new file mode 100755 index 0000000..e9e67b1 Binary files /dev/null and b/frontend/app/data/img/Image8.png differ diff --git a/frontend/app/data/img/Image9.png b/frontend/app/data/img/Image9.png new file mode 100755 index 0000000..fd5112a Binary files /dev/null and b/frontend/app/data/img/Image9.png differ diff --git a/frontend/app/data/img/avatars/Image1.png b/frontend/app/data/img/avatars/Image1.png new file mode 100755 index 0000000..7e3754a Binary files /dev/null and b/frontend/app/data/img/avatars/Image1.png differ diff --git a/frontend/app/data/img/avatars/Image10.png b/frontend/app/data/img/avatars/Image10.png new file mode 100755 index 0000000..2b5c16d Binary files /dev/null and b/frontend/app/data/img/avatars/Image10.png differ diff --git a/frontend/app/data/img/avatars/Image11.png b/frontend/app/data/img/avatars/Image11.png new file mode 100755 index 0000000..3907308 Binary files /dev/null and b/frontend/app/data/img/avatars/Image11.png differ diff --git a/frontend/app/data/img/avatars/Image12.png b/frontend/app/data/img/avatars/Image12.png new file mode 100755 index 0000000..5429eeb Binary files /dev/null and b/frontend/app/data/img/avatars/Image12.png differ diff --git a/frontend/app/data/img/avatars/Image2.png b/frontend/app/data/img/avatars/Image2.png new file mode 100755 index 0000000..fb2123b Binary files /dev/null and b/frontend/app/data/img/avatars/Image2.png differ diff --git a/frontend/app/data/img/avatars/Image3.png b/frontend/app/data/img/avatars/Image3.png new file mode 100755 index 0000000..823e5e1 Binary files /dev/null and b/frontend/app/data/img/avatars/Image3.png differ diff --git a/frontend/app/data/img/avatars/Image4.png b/frontend/app/data/img/avatars/Image4.png new file mode 100755 index 0000000..86b24ba Binary files /dev/null and b/frontend/app/data/img/avatars/Image4.png differ diff --git a/frontend/app/data/img/avatars/Image5.png b/frontend/app/data/img/avatars/Image5.png new file mode 100755 index 0000000..508f7ab Binary files /dev/null and b/frontend/app/data/img/avatars/Image5.png differ diff --git a/frontend/app/data/img/avatars/Image6.png b/frontend/app/data/img/avatars/Image6.png new file mode 100755 index 0000000..d08e3d0 Binary files /dev/null and b/frontend/app/data/img/avatars/Image6.png differ diff --git a/frontend/app/data/img/avatars/Image7.png b/frontend/app/data/img/avatars/Image7.png new file mode 100755 index 0000000..30330de Binary files /dev/null and b/frontend/app/data/img/avatars/Image7.png differ diff --git a/frontend/app/data/img/avatars/Image8.png b/frontend/app/data/img/avatars/Image8.png new file mode 100755 index 0000000..840aab5 Binary files /dev/null and b/frontend/app/data/img/avatars/Image8.png differ diff --git a/frontend/app/data/img/avatars/Image9.png b/frontend/app/data/img/avatars/Image9.png new file mode 100755 index 0000000..d111f6d Binary files /dev/null and b/frontend/app/data/img/avatars/Image9.png differ diff --git a/frontend/app/data/img/photo1.png b/frontend/app/data/img/photo1.png new file mode 100644 index 0000000..a49e452 Binary files /dev/null and b/frontend/app/data/img/photo1.png differ diff --git a/frontend/app/data/img/photo17.png b/frontend/app/data/img/photo17.png new file mode 100644 index 0000000..2575aef Binary files /dev/null and b/frontend/app/data/img/photo17.png differ diff --git a/frontend/app/data/img/photo18.png b/frontend/app/data/img/photo18.png new file mode 100644 index 0000000..2f4d60f Binary files /dev/null and b/frontend/app/data/img/photo18.png differ diff --git a/frontend/app/data/img/photo19.png b/frontend/app/data/img/photo19.png new file mode 100644 index 0000000..a893ed0 Binary files /dev/null and b/frontend/app/data/img/photo19.png differ diff --git a/frontend/app/data/img/photo2.png b/frontend/app/data/img/photo2.png new file mode 100644 index 0000000..96cbcee Binary files /dev/null and b/frontend/app/data/img/photo2.png differ diff --git a/frontend/app/data/img/photo20.png b/frontend/app/data/img/photo20.png new file mode 100644 index 0000000..8c10cf2 Binary files /dev/null and b/frontend/app/data/img/photo20.png differ diff --git a/frontend/app/data/img/photo3.png b/frontend/app/data/img/photo3.png new file mode 100644 index 0000000..7197a4a Binary files /dev/null and b/frontend/app/data/img/photo3.png differ diff --git a/frontend/app/data/img/photo32.jpg b/frontend/app/data/img/photo32.jpg new file mode 100644 index 0000000..6237110 Binary files /dev/null and b/frontend/app/data/img/photo32.jpg differ diff --git a/frontend/app/data/img/photo4.png b/frontend/app/data/img/photo4.png new file mode 100644 index 0000000..59d901b Binary files /dev/null and b/frontend/app/data/img/photo4.png differ diff --git a/frontend/app/data/img/photo45.png b/frontend/app/data/img/photo45.png new file mode 100644 index 0000000..f403555 Binary files /dev/null and b/frontend/app/data/img/photo45.png differ diff --git a/frontend/app/data/img/photo46.png b/frontend/app/data/img/photo46.png new file mode 100644 index 0000000..2c9ae21 Binary files /dev/null and b/frontend/app/data/img/photo46.png differ diff --git a/frontend/app/data/img/photo47.png b/frontend/app/data/img/photo47.png new file mode 100644 index 0000000..4fc232b Binary files /dev/null and b/frontend/app/data/img/photo47.png differ diff --git a/frontend/app/data/img/photo48.png b/frontend/app/data/img/photo48.png new file mode 100644 index 0000000..881c554 Binary files /dev/null and b/frontend/app/data/img/photo48.png differ diff --git a/frontend/app/data/img/photo49.png b/frontend/app/data/img/photo49.png new file mode 100644 index 0000000..db0f107 Binary files /dev/null and b/frontend/app/data/img/photo49.png differ diff --git a/frontend/app/data/img/photo5.png b/frontend/app/data/img/photo5.png new file mode 100644 index 0000000..ba61c08 Binary files /dev/null and b/frontend/app/data/img/photo5.png differ diff --git a/frontend/app/data/img/photo6.png b/frontend/app/data/img/photo6.png new file mode 100644 index 0000000..8c93751 Binary files /dev/null and b/frontend/app/data/img/photo6.png differ diff --git a/frontend/app/data/index.js b/frontend/app/data/index.js new file mode 100644 index 0000000..2c5abb0 --- /dev/null +++ b/frontend/app/data/index.js @@ -0,0 +1,52 @@ +import _ from 'lodash'; +import populate from './dataGenerator'; +import users from './raw/users'; +import articles from './raw/articles'; +import notifications from './raw/notifications'; +import conversations from './raw/conversations'; +import cards from './raw/cards'; + +class DataProvider { + getUser(id = 1) { + return _.find(users, x => x.id === id); + } + + getUsers() { + return users; + } + + getNotifications() { + return notifications; + } + + getArticles(type = 'article') { + return _.filter(articles, x => x.type === type); + } + + getArticle(id) { + return _.find(articles, x => x.id === id); + } + + + getConversation(userId = 1) { + return _.find(conversations, x => x.withUser.id === userId); + } + + getChatList() { + return conversations; + } + + getComments(postId = 1) { + return this.getArticle(postId).comments; + } + + getCards() { + return cards; + } + + populateData() { + populate(); + } +} + +export const data = new DataProvider(); diff --git a/frontend/app/data/raw/articles.js b/frontend/app/data/raw/articles.js new file mode 100644 index 0000000..38bff3b --- /dev/null +++ b/frontend/app/data/raw/articles.js @@ -0,0 +1,173 @@ +const articles = [{ + id: 1, + photo: require('../img/photo1.png'), + type: 'article', + time: -300, + header: 'Plants Of Our Nature', + text: 'Ferns are a very old group of plants. They first appeared on Earth in the middle Devonian Era about 360 million years ago, just before the Carboniferous Era. Most of the modern fern families we see today first appeared in the Late Cretaceous about 45 or 50 million years ago – during the age of the dinosaurs!', + comments: [{ + id: 1, + text: 'Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis. Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', + time: 0, + }, { + id: 2, + text: 'Quisque ut erat. Curabitur gravida nisi at nibh.', + time: -311, + }, { + id: 3, + text: 'Etiam pretium iaculis justo. In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus. Nulla ut erat id mauris vulputate elementum.', + time: -622, + }, { + id: 4, + text: 'In est risus, auctor sed, tristique in, tempus sit amet, sem.', + time: -933, + }, { + id: 5, + text: 'In hac habitasse platea dictumst.', + time: -1244, + }, { + id: 6, + text: 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', + time: -1555, + }, { + id: 7, + text: 'Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.', + time: -1866, + }, { + id: 8, + text: 'Duis mattis egestas metus. Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', + time: -2177, + }], +}, { + id: 2, + photo: require('../img/photo2.png'), + type: 'article', + time: -1373, + header: 'Balloon Trip', + text: 'Mostly it’s about hot air - for without that balloons are just big empty bags with baskets on the bottom. ' + + 'The Montgolfier brothers had great hopes when they made the first manned flight. ' + + 'They thought balloons would take off as an available means of commercial flight. ' + + 'Instead, they have remained the province of sport, adventure and enjoyment. ' + + 'Modern balloons are a lot more sophisticated than their ancestors, ' + + 'but they still retain the essential characteristics which makes them so attractive. ' + + 'A plane is claustrophobic and very noisy. Balloons are so gentle and majestic and silent when the burner’s not working.', + comments: [], +}, { + id: 3, + photo: require('../img/photo3.png'), + type: 'article', + time: -2446, + header: 'Sea World', + text: 'The worlds oceans cover two thirds of our planet. As we take a dive from the rocks or paddle out from the beach, we are entering a place which is teeming with marine life. ' + + 'From fish to crabs to octopuses or even sea creatures that have not yet been discovered, the oceans and its coastlines are an amazing and interesting foray of water wildlife.', + comments: [], +}, { + id: 4, + photo: require('../img/photo4.png'), + type: 'article', + time: -3519, + header: 'Flowers', + text: 'Flowers did not always exist; they first appeared 140 million years ago. Before that, ferns and cone bearing trees dominated the earth. ' + + 'Several centuries ago in Holland, tulips were more valuable than gold. ' + + 'Broccoli is actually a flower. Some plants such as orchids do not need soil to grow-they get all of their nutrients from the air.', + comments: [], +}, { + id: 5, + photo: require('../img/photo5.png'), + type: 'article', + time: -4592, + header: 'Birds Of Our Planet', + text: 'Birds have feathers, wings, lay eggs and are warm blooded. There are around 10000 different species of birds worldwide. ' + + 'The Ostrich is the largest bird in the world. It also lays the largest eggs and has the fastest maximum running speed (97 kph). ' + + 'Scientists believe that birds evolved from theropod dinosaurs. Birds have hollow bones which help them fly. ' + + 'Some bird species are intelligent enough to create and use tools.', + comments: [], +}, { + id: 6, + photo: require('../img/photo6.png'), + type: 'article', + time: -5665, + header: 'Mountains', + text: 'Mountains make up about one-fifth of the world\'s landscape, and provide homes to at least one-tenth of the world\'s people. ' + + 'The tallest known mountain in the solar system is Olympus Mons, located on Mars. ' + + 'There are mountains under the surface of the sea! ' + + 'Mountains occur more often in oceans than on land; some islands are the peaks of mountains coming out of the water.', + comments: [], +}, { + id: 7, + photo: require('../img/photo45.png'), + type: 'fact', + time: -5665, + header: 'Smile and Frown', + text: 'It takes 17 muscles to smile and 43 to frown.', + comments: [], +}, { + id: 8, + photo: require('../img/photo46.png'), + type: 'fact', + time: -8373, + header: 'Interesting Fact', + text: 'Dolphins sleep with one eye open.', + comments: [], +}, { + id: 9, + photo: require('../img/photo47.png'), + type: 'fact', + time: -565, + header: 'Elephant', + text: 'Elephant is one of the few mammals that can\'t jump.', + comments: [], +}, { + id: 10, + photo: require('../img/photo48.png'), + type: 'fact', + time: -52365, + header: 'Cold Water', + text: 'Cold water weighs less than hot water.', + comments: [], +}, { + id: 11, + photo: require('../img/photo49.png'), + type: 'fact', + time: -1295, + header: 'Our Eyes', + text: 'You blink over 10,000,000 times a year.', + comments: [], +}, { + id: 12, + photo: require('../img/photo17.png'), + type: 'post', + time: -300, + title: 'My Little Kitten', + text: 'I have got a cat. Her name is Matilda. She is quite old for a cat. She is eleven years old. Matilda is very' + + ' fluffy. Her back is black and her belly and chest are white. She also has a black muzzle with long white whiskers. ' + + 'Her legs and paws are white. Matilda has big eyes. Her eyes are light green, but they become yellow in bright sunlight. I love my cat.', + comments: [], +}, { + id: 13, + photo: require('../img/photo18.png'), + type: 'post', + time: -1373, + header: 'Interesting Fact', + text: 'One chef prepared a delicious cake with apples and named it in honor of his beloved Charlotte.', + comments: [], +}, { + id: 14, + photo: require('../img/photo19.png'), + type: 'post', + time: -2446, + header: 'Music In Our Life', + text: 'The scientists say that they can define your character if they know what music you like.', + comments: [], +}, { + id: 15, + photo: require('../img/photo20.png'), + type: 'post', + time: -3519, + header: 'Exciting Adventure', + text: 'My trip to Spain last summer. I think that it was the most interesting trip in my life.', + comments: [], +}, +]; + +export default articles; diff --git a/frontend/app/data/raw/cards.js b/frontend/app/data/raw/cards.js new file mode 100644 index 0000000..7533e89 --- /dev/null +++ b/frontend/app/data/raw/cards.js @@ -0,0 +1,40 @@ +const cards = + [{ + id: 1, + name: 'Cindee Seton', + bank: 'CitiBank', + amount: 440, + date: '07/19', + cardNo: '3538********8699', + type: 'visa', + currency: 'usd', + }, { + id: 2, + name: 'Cindee Seton', + bank: 'CitiBank', + amount: 1740, + date: '07/19', + cardNo: '5602********1161', + type: 'mastercard', + currency: 'eur', + }, { + id: 3, + name: 'Cindee Seton', + bank: 'CitiBank', + amount: 2120, + date: '09/24', + cardNo: '3379********5427', + type: 'axp', + currency: 'usd', + }, { + id: 4, + name: 'Cindee Seton', + bank: 'CitiBank', + amount: 3150, + date: '02/21', + cardNo: '4911********8396', + type: 'visa', + currency: 'eur', + }]; + +export default cards; diff --git a/frontend/app/data/raw/conversations.js b/frontend/app/data/raw/conversations.js new file mode 100644 index 0000000..2e778e7 --- /dev/null +++ b/frontend/app/data/raw/conversations.js @@ -0,0 +1,85 @@ +export const Conversations = [ + { + withUserId: 1, + messages: [ + { + id: 0, + type: 'out', + time: -300, + text: 'Hey, how’ve you been?', + }, + { + id: 1, + time: -240, + type: 'in', + text: 'Yeah, not bad, actually I finally got a call back from that job that I interviewed for, and guess what? I got it!', + }, + { + id: 2, + time: -230, + type: 'out', + text: 'Awesome! Yeah, well done, that’s really great to hear. Do you start right away?', + }, + { + id: 3, + time: -100, + type: 'out', + text: 'Well, uhm yes and no, I go in for training tomorrow, but I don’t really start until next week. ' + + 'Do you have some time this weekend, maybe we could get together?', + }, + { + id: 4, + time: -45, + type: 'in', + text: 'I’ve got a lot planned this weekend, just running around, doing loads of stuff, but Friday’s pretty open.', + }, + { + id: 5, + time: -5, + type: 'out', + text: 'That works pretty well for me!', + }], + }, + { + withUserId: 5, + messages: [ + { + id: 0, + type: 'out', + time: -300, + text: 'I have no idea what to buy for Mary for her birthday.', + }, + { + id: 1, + time: -240, + type: 'in', + text: 'Me, neither! Would you like to go in and buy her a gift together?', + }, + { + id: 2, + time: -100, + type: 'out', + text: 'If I remember right, she likes music, skiing, and reading', + }, + { + id: 3, + time: -45, + type: 'out', + text: 'You know, maybe we could get her some concert tickets. Who would know her favorite groups?', + }, + { + id: 4, + time: -25, + type: 'in', + text: 'Her roommate, Malia, might know what her favorite groups are.', + }, + { + id: 5, + time: -5, + type: 'out', + text: 'Cool! Let\'s give Malia a call and ask her for her help right now', + }], + }, +]; + +export default Conversations; diff --git a/frontend/app/data/raw/notifications.js b/frontend/app/data/raw/notifications.js new file mode 100644 index 0000000..967bec0 --- /dev/null +++ b/frontend/app/data/raw/notifications.js @@ -0,0 +1,59 @@ +const notifications = [ + { + id: 1, + type: 'follow', + description: 'liked profile page for Dribbble App Design Concept', + time: -1, + }, { + id: 2, + type: 'like', + description: 'liked a photo on your album', + time: -271, + attach: require('../img/Image8.png'), + }, { + id: 3, + type: 'like', + description: 'liked a photo on your album', + time: -541, + attach: require('../img/Image8.png'), + }, { + id: 4, + type: 'like', + description: 'liked profile page for Dribbble App Design Concept', + time: -811, + }, { + id: 5, + type: 'like', + description: 'liked profile page for Dribbble App Design Concept', + time: -1081, + }, { + id: 6, + type: 'follow', + description: 'followed you UI/UX Designer and Interaction Designer', + time: -1351, + }, { + id: 7, + type: 'follow', + description: 'liked a photo on your album', + time: -1621, + attach: require('../img/Image8.png'), + }, { + id: 8, + type: 'follow', + description: 'followed you iOS Developer and Graphic Designer', + time: -1891, + }, { + id: 9, + type: 'follow', + description: 'liked profile page for Dribbble App Design Concept', + time: -2161, + }, { + id: 10, + type: 'like', + description: 'liked a photo on your album', + time: -2431, + attach: require('../img/Image8.png'), + }, +]; + +export default notifications; diff --git a/frontend/app/data/raw/users.js b/frontend/app/data/raw/users.js new file mode 100644 index 0000000..d7e651a --- /dev/null +++ b/frontend/app/data/raw/users.js @@ -0,0 +1,194 @@ +const images = [ + require('../img/Image10.png'), + require('../img/Image11.png'), + require('../img/Image2.png'), + require('../img/Image3.png'), + require('../img/Image4.png'), + require('../img/Image1.png'), + require('../img/Image12.png'), + require('../img/Image8.png'), + require('../img/Image6.png'), + require('../img/Image9.png'), + require('../img/Image5.png'), + require('../img/Image7.png'), +]; + +const users = [{ + id: 1, + firstName: 'Helen', + lastName: 'Gilbert', + phone: '+1 415 670 90 34', + country: 'Belarus', + email: 'h.gilbert@akveo.com', + password: '123456', + newPassword: '12345678', + confirmPassword: '12345678', + photo: require('../img/avatars/Image9.png'), + postCount: 86, + followersCount: 22102, + followingCount: 536, + images, + +}, +{ + id: 2, + firstName: 'Emilie', + lastName: 'McDiarmid', + email: 'emcdiarmid1@yale.edu', + country: 'China', + password: 'YyKgJ8A3b4b', + newPassword: 'DpCRPYW7Fgy', + confirmPassword: 'DpCRPYW7Fgy', + postCount: 95, + phone: '86-(261)670-4133', + followingCount: 975, + followersCount: 1703, + images, + photo: require('../img/avatars/Image1.png'), +}, +{ + id: 3, + firstName: 'Sandra', + lastName: 'Paver', + email: 'spaver2@ox.ac.uk', + country: 'Greece', + password: '0BCeHRlt84Zo', + newPassword: '61BaifSE20w', + confirmPassword: '61BaifSE20w', + postCount: 60, + phone: '30-(524)246-5851', + followingCount: 736, + followersCount: 1534, + images, + photo: require('../img/avatars/Image3.png'), +}, +{ + id: 4, + firstName: 'Nancy', + lastName: 'O\'Crevan', + email: 'nocrevan3@zimbio.com', + country: 'China', + password: 'W0NxvHo2C', + newPassword: 'vj4ueTKK', + confirmPassword: 'vj4ueTKK', + postCount: 78, + phone: '86-(499)721-5796', + followingCount: 86, + followersCount: 3303, + images, + photo: require('../img/avatars/Image4.png'), +}, +{ + id: 5, + firstName: 'Clayton', + lastName: 'O\'Mullaney', + email: 'cmullaney4@tripadvisor.com', + country: 'Philippines', + password: 'ZlzECwoN', + newPassword: 'N9l5KLpBW', + confirmPassword: 'N9l5KLpBW', + postCount: 37, + phone: '63-(210)188-9126', + followingCount: 745, + followersCount: 2703, + images, + photo: require('../img/avatars/Image5.png'), +}, +{ + id: 6, + firstName: 'Carlee', + lastName: 'Aubry', + email: 'caubry5@nytimes.com', + country: 'China', + password: 'jUIz9PNbU', + newPassword: 'nJRP3MdIh4U', + confirmPassword: 'nJRP3MdIh4U', + postCount: 89, + phone: '86-(939)186-9659', + followingCount: 444, + followersCount: 8432, + images, + photo: require('../img/avatars/Image6.png'), +}, +{ + id: 7, + firstName: 'Patrick', + lastName: 'Holden', + email: 'p.holden6@woothemes.com', + country: 'Indonesia', + password: 'inOEsoAlnh', + newPassword: '60z2bgL', + confirmPassword: '60z2bgL', + postCount: 48, + phone: '62-(373)613-7229', + followingCount: 731, + followersCount: 18230, + images, + photo: require('../img/avatars/Image7.png'), +}, +{ + id: 8, + firstName: 'Edward', + lastName: 'Storton', + email: 'estorton7@google.ca', + country: 'Nigeria', + password: 'e1H56GRP', + newPassword: 't2a1FbI8oCo', + confirmPassword: 't2a1FbI8oCo', + postCount: 100, + phone: '234-(135)610-8989', + followingCount: 667, + followersCount: 4234, + images, + photo: require('../img/avatars/Image8.png'), +}, +{ + id: 9, + firstName: 'Carole', + lastName: 'Blundon', + email: 'cblundon8@google.pl', + country: 'United States', + password: 't9xI6skPz', + newPassword: 'y84Jquaxg8', + confirmPassword: 'y84Jquaxg8', + postCount: 74, + phone: '1-(913)904-8423', + followingCount: 750, + followersCount: 1032, + images, + photo: require('../img/avatars/Image10.png'), +}, +{ + id: 10, + firstName: 'Bryce', + lastName: 'Curle', + email: 'bcurled@paginegialle.it', + country: 'Indonesia', + password: 'ACCsjlPq', + newPassword: 'm05jBM1S88', + confirmPassword: 'm05jBM1S88', + postCount: 54, + phone: '62-(688)911-5487', + followingCount: 343, + followersCount: 3721, + images, + photo: require('../img/avatars/Image11.png'), +}, +{ + id: 11, + firstName: 'Babara', + lastName: 'Greasty', + email: 'bgreastya@netlog.com', + country: 'Russia', + password: '0SuOdS8XQK', + newPassword: 'f49mZd49eGHm', + confirmPassword: 'f49mZd49eGHm', + postCount: 58, + phone: '7-(121)282-0448', + followingCount: 165, + followersCount: 5433, + images, + photo: require('../img/avatars/Image12.png'), +}]; + +export default users; diff --git a/frontend/app/screens/articles/article.js b/frontend/app/screens/articles/article.js new file mode 100644 index 0000000..059ab44 --- /dev/null +++ b/frontend/app/screens/articles/article.js @@ -0,0 +1,94 @@ +import React from 'react'; +import axios from 'axios'; + + +import { + ScrollView, + Image, + View, + TouchableOpacity, +} from 'react-native'; +import { + RkCard, + RkText, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { + Avatar, + SocialBar, +} from '../../components'; +import NavigationType from '../../config/navigation/propTypes'; + + +export class Article extends React.Component { + state = { + article: {}, + mounted: false, + }; + + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Current problem'.toUpperCase(), + }; + + + componentWillMount() { + const articleId = this.props.navigation.getParam('id', 1); + console.log(articleId); + + axios.get(`http://192.168.1.43:8000/api/articles/${articleId}`) + .then(res => { + this.setState({ + article: res.data, + mounted: true, + }); + console.log(this.state.article); + }); + } + + render() { + if (this.state.mounted) { + return ( + + + + + + {this.state.article.title} + + + + + + + {this.state.article.text} + + + + + + + + + ); + } + return null; + } +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + title: { + marginBottom: 5, + }, +})); diff --git a/frontend/app/screens/articles/articles1.js b/frontend/app/screens/articles/articles1.js new file mode 100644 index 0000000..47049b4 --- /dev/null +++ b/frontend/app/screens/articles/articles1.js @@ -0,0 +1,74 @@ +import React from 'react'; +import { + FlatList, + Image, + View, + TouchableOpacity, +} from 'react-native'; +import { + RkText, + RkCard, RkStyleSheet, +} from 'react-native-ui-kitten'; +import { SocialBar } from '../../components'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class Articles1 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Article List'.toUpperCase(), + }; + + state = { + data: data.getArticles(), + }; + + extractItemKey = (item) => `${item.id}`; + + onItemPressed = ({ item }) => { + this.props.navigation.navigate('Article', { id: item.id }); + }; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + + + {item.header} + {moment().add(item.time, 'seconds').fromNow()} + + + + + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + overlay: { + justifyContent: 'flex-end', + }, + footer: { + width: 240, + }, +})); diff --git a/frontend/app/screens/articles/articles2.js b/frontend/app/screens/articles/articles2.js new file mode 100644 index 0000000..0d48812 --- /dev/null +++ b/frontend/app/screens/articles/articles2.js @@ -0,0 +1,84 @@ +import React from 'react'; +import { + FlatList, + Image, + View, + TouchableOpacity, +} from 'react-native'; +import { + RkText, + RkCard, RkStyleSheet, +} from 'react-native-ui-kitten'; +import axios from 'axios'; +import { SocialBar } from '../../components'; +import NavigationType from '../../config/navigation/propTypes'; + + +export class Articles2 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Problems List'.toUpperCase(), + }; + + state = { + articles: [], + }; + + componentDidMount() { + axios.get('http://192.168.1.43:8000/api/articles') + .then(res => { + this.setState({ + articles: res.data, + }); + + }); + } + + extractItemKey = (item) => `${item.id}`; + + onItemPressed = (item) => { + this.props.navigation.navigate('Article', { id: item.id }); + }; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + + + {item.title} + + + + + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.scroll, + paddingVertical: 8, + paddingHorizontal: 14, + }, + card: { + marginVertical: 8, + }, + time: { + marginTop: 5, + }, +})); diff --git a/frontend/app/screens/articles/articles3.js b/frontend/app/screens/articles/articles3.js new file mode 100644 index 0000000..e5eda4e --- /dev/null +++ b/frontend/app/screens/articles/articles3.js @@ -0,0 +1,81 @@ +import React from 'react'; +import { + FlatList, + Image, + View, + TouchableOpacity, +} from 'react-native'; +import { + RkText, + RkCard, RkStyleSheet, +} from 'react-native-ui-kitten'; +import { SocialBar } from '../../components'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class Articles3 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Article List'.toUpperCase(), + }; + + state = { + data: data.getArticles(), + }; + + extractItemKey = (item) => `${item.id}`; + + onItemPressed = ({ item }) => { + this.props.navigation.navigate('Article', { id: item.id }); + }; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + + + {item.header} + {moment().add(item.time, 'seconds').fromNow()} + + + + + + + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.scroll, + paddingHorizontal: 14, + paddingVertical: 8, + }, + card: { + marginVertical: 8, + }, + footer: { + paddingTop: 16, + }, + time: { + marginTop: 5, + }, +})); diff --git a/frontend/app/screens/articles/articles4.js b/frontend/app/screens/articles/articles4.js new file mode 100644 index 0000000..1f08ba1 --- /dev/null +++ b/frontend/app/screens/articles/articles4.js @@ -0,0 +1,78 @@ +import React from 'react'; +import { + FlatList, + Image, + View, + TouchableOpacity, +} from 'react-native'; +import { + RkText, + RkCard, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { SocialBar } from '../../components'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + + +export class Articles4 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Article List'.toUpperCase(), + }; + + state = { + data: data.getArticles(), + }; + + extractItemKey = (item) => `${item.id}`; + + renderItem = ({ item }) => ( + this.props.navigation.navigate('Article', { id: item.id })}> + + + + {item.header} + + {`${item.user.firstName} ${item.user.lastName}`} + + {item.text} + + + + + + + ); + + render = () => ( + + + + ); +} + + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.scroll, + paddingVertical: 8, + paddingHorizontal: 14, + }, + card: { + marginVertical: 8, + }, + post: { + marginTop: 13, + }, +})); diff --git a/frontend/app/screens/articles/blogposts.js b/frontend/app/screens/articles/blogposts.js new file mode 100644 index 0000000..3ce4565 --- /dev/null +++ b/frontend/app/screens/articles/blogposts.js @@ -0,0 +1,88 @@ +import React from 'react'; +import { + FlatList, + View, + Image, + TouchableOpacity, +} from 'react-native'; +import { + RkCard, RkStyleSheet, + RkText, +} from 'react-native-ui-kitten'; +import { Avatar } from '../../components'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class Blogposts extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Blogposts'.toUpperCase(), + }; + + state = { + data: data.getArticles('post'), + }; + + extractItemKey = (item) => `${item.id}`; + + onItemPressed = (item) => { + this.props.navigation.navigate('Article', { id: item.id }); + }; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + + + {item.title} + + + + {item.text} + + + + + + {`${item.user.firstName} ${item.user.lastName}`} + + {moment().add(item.time, 'seconds').fromNow()} + + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.scroll, + paddingVertical: 8, + paddingHorizontal: 14, + }, + card: { + marginVertical: 8, + }, + userInfo: { + flexDirection: 'row', + alignItems: 'center', + }, + avatar: { + marginRight: 17, + }, +})); diff --git a/frontend/app/screens/articles/index.js b/frontend/app/screens/articles/index.js new file mode 100644 index 0000000..115d2ac --- /dev/null +++ b/frontend/app/screens/articles/index.js @@ -0,0 +1,6 @@ +export * from './articles1'; +export * from './articles2'; +export * from './articles3'; +export * from './articles4'; +export * from './blogposts'; +export * from './article'; diff --git a/frontend/app/screens/dashboard/dashboard.js b/frontend/app/screens/dashboard/dashboard.js new file mode 100644 index 0000000..06c8d6a --- /dev/null +++ b/frontend/app/screens/dashboard/dashboard.js @@ -0,0 +1,117 @@ +import React from 'react'; +import { + View, + ScrollView, +} from 'react-native'; +import { + RkText, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../../assets/icons'; +import { + ProgressChart, + DoughnutChart, + AreaChart, + AreaSmoothedChart, +} from '../../components/'; + +export class Dashboard extends React.Component { + static navigationOptions = { + title: 'Dashboard'.toUpperCase(), + }; + + state = { + data: { + statItems: [ + { + name: 'Stars', + value: '4,512', + icon: 'github', + background: RkTheme.current.colors.dashboard.stars, + }, + { + name: 'Tweets', + value: '2,256', + icon: 'twitter', + background: RkTheme.current.colors.dashboard.tweets, + }, + { + name: 'Likes', + value: '1,124', + icon: 'facebook', + background: RkTheme.current.colors.dashboard.likes, + }, + ], + }, + }; + + renderStatItem = (item) => ( + + + {item.value} + {item.name} + + {FontAwesome[item.icon]} + + ); + + render = () => { + const chartBackgroundStyle = { backgroundColor: RkTheme.current.colors.control.background }; + return ( + + + {this.state.data.statItems.map(this.renderStatItem)} + + + + + + + + + + + + + + + ); + }; +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + backgroundColor: theme.colors.screen.scroll, + paddingHorizontal: 15, + }, + statItems: { + flexDirection: 'row', + justifyContent: 'space-between', + marginVertical: 15, + }, + statItemContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + borderRadius: 3, + paddingHorizontal: 10, + paddingVertical: 10, + }, + statItemIcon: { + alignSelf: 'center', + marginLeft: 10, + color: 'white', + }, + statItemValue: { + color: 'white', + }, + statItemName: { + color: 'white', + }, + chartBlock: { + padding: 15, + marginBottom: 15, + justifyContent: 'center', + }, +})); + diff --git a/frontend/app/screens/dashboard/index.js b/frontend/app/screens/dashboard/index.js new file mode 100644 index 0000000..b58b6c9 --- /dev/null +++ b/frontend/app/screens/dashboard/index.js @@ -0,0 +1 @@ +export * from './dashboard'; diff --git a/frontend/app/screens/eCommerce/addToCardForm.js b/frontend/app/screens/eCommerce/addToCardForm.js new file mode 100644 index 0000000..5d41885 --- /dev/null +++ b/frontend/app/screens/eCommerce/addToCardForm.js @@ -0,0 +1,138 @@ +import React from 'react'; +import axios from 'axios'; +import { + View, + Keyboard, +} from 'react-native'; +import { + RkText, + RkTextInput, + RkStyleSheet, + RkAvoidKeyboard, +} from 'react-native-ui-kitten'; +import { GradientButton } from '../../components/'; +import { PasswordTextInput } from '../../components/passwordTextInput'; + +import { scale } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +export class AddToCardForm extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Add Card'.toUpperCase(), + }; + + state = { + name: '', + email: '', + problem: '', + + }; + + + onAddButtonPressed = () => { + axios.post('http://192.168.1.43:8000/api/articles/', { + title: this.state.problem.split(' ').slice(0, 5), + text: this.state.problem, + + }) + this.props.navigation.goBack(); + }; + + render = () => ( + true} + onResponderRelease={() => Keyboard.dismiss()}> + + + + + + + Your name + + this.setState({ name })} + value={this.state.name} + /> + + + + + Your e-mail + + this.setState({ email })} + value={this.state.email} + /> + + + + + Describe eco-problem + + this.setState({ problem })} + value={this.state.problem} + /> + + + + + + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + padding: 15, + flex: 1, + backgroundColor: theme.colors.screen.base, + }, + content: { + marginTop: 10, + }, + formContent: { + justifyContent: 'space-between', + flexDirection: 'column', + flex: 1, + }, + textRow: { + marginLeft: 20, + }, + expireDateBlock: { + justifyContent: 'space-between', + flexDirection: 'row', + }, + expireDateInput: { + flex: 0.48, + marginVertical: 10, + }, + expireDateInnerInput: { + textAlign: 'center', + }, + expireDateDelimiter: { + flex: 0.04, + }, + balloon: { + maxWidth: scale(250), + padding: 15, + borderRadius: 100, + borderWidth: 0.5, + borderColor: theme.colors.border.solid, + }, +})); diff --git a/frontend/app/screens/eCommerce/cards.js b/frontend/app/screens/eCommerce/cards.js new file mode 100644 index 0000000..c22c30d --- /dev/null +++ b/frontend/app/screens/eCommerce/cards.js @@ -0,0 +1,242 @@ +import React from 'react'; +import { + FlatList, + View, + Image, + TouchableOpacity, + Modal, +} from 'react-native'; +import { + RkText, + RkCard, + RkButton, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; +import { LinearGradient } from 'expo'; +import { data } from '../../data'; +import { PasswordTextInput } from '../../components/passwordTextInput'; +import { UIConstants } from '../../config/appConstants'; +import { scaleVertical } from '../../utils/scale'; + +export class Cards extends React.Component { + static navigationOptions = { + title: 'Cards'.toUpperCase(), + }; + + state = { + data: data.getCards(), + modalVisible: false, + }; + + getCardStyle = (type) => { + switch (type) { + case 'visa': + return { + gradient: RkTheme.current.colors.gradients.visa, + icon: require('../../assets/icons/visaIcon.png'), + }; + case 'mastercard': + return { + gradient: RkTheme.current.colors.gradients.mastercard, + icon: require('../../assets/icons/masterCardIcon.png'), + }; + case 'axp': + return { + gradient: RkTheme.current.colors.gradients.axp, + icon: require('../../assets/icons/americanExpressIcon.png'), + }; + default: return {}; + } + }; + + formatCurrency = (amount, currency) => { + switch (currency) { + case 'usd': + return `$${amount}`; + case 'eur': + return `€${amount}`; + default: return ''; + } + }; + + prepareCardNo = (cardNo) => { + const re = /\*+/; + const parts = cardNo.split(re); + return { + firstPart: parts[0], + lastPart: parts[1], + }; + }; + + renderFooter = () => ( + + + + + + ); + + setModalVisible = (visible) => { + this.setState({ modalVisible: visible }); + }; + + onItemPressed = () => { + this.setModalVisible(true); + }; + + extractItemKey = (item) => `${item.id}`; + + renderItem = ({ item }) => { + const { gradient, icon } = this.getCardStyle(item.type); + const { firstPart, lastPart } = this.prepareCardNo(item.cardNo); + + return ( + + + + + {item.bank} + + + + + {firstPart} + * * * * + * * * * + {lastPart} + + {item.date} + + + + {item.currency.toUpperCase()} + {item.name.toUpperCase()} + + {this.formatCurrency(item.amount, item.currency)} + + + + + + ); + }; + + render = () => ( + + + this.setModalVisible(false)} + visible={this.state.modalVisible}> + + + + Enter security code + + + + this.setModalVisible(false)} + style={styles.popupButton} + rkType='clear'> + CANCEL + + + this.setModalVisible(false)} + style={styles.popupButton} + rkType='clear'> + OK + + + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + list: { + marginHorizontal: 16, + }, + card: { + marginVertical: 8, + }, + background: { + borderRadius: 7, + }, + cardNoContainer: { + flexDirection: 'row', + }, + cardNo: { + marginHorizontal: 8, + }, + cardPlaceholder: { + paddingTop: 4, + }, + date: { + marginTop: scaleVertical(20), + }, + footer: { + marginTop: 8, + marginBottom: scaleVertical(16), + alignItems: 'center', + }, + button: { + height: 56, + width: 56, + }, + popup: { + backgroundColor: theme.colors.screen.base, + marginTop: scaleVertical(70), + marginHorizontal: 37, + borderRadius: 7, + }, + popupOverlay: { + backgroundColor: theme.colors.screen.overlay, + flex: 1, + marginTop: UIConstants.HeaderHeight, + }, + popupContent: { + alignItems: 'center', + margin: 16, + }, + popupHeader: { + marginBottom: scaleVertical(45), + }, + popupButtons: { + marginTop: 15, + flexDirection: 'row', + borderTopWidth: 1, + borderColor: theme.colors.border.base, + }, + popupButton: { + flex: 1, + marginVertical: 16, + }, + separator: { + backgroundColor: theme.colors.border.base, + width: 1, + }, +})); diff --git a/frontend/app/screens/eCommerce/index.js b/frontend/app/screens/eCommerce/index.js new file mode 100644 index 0000000..7658d81 --- /dev/null +++ b/frontend/app/screens/eCommerce/index.js @@ -0,0 +1,2 @@ +export * from './cards'; +export * from './addToCardForm'; diff --git a/frontend/app/screens/index.js b/frontend/app/screens/index.js new file mode 100644 index 0000000..b7ce1cb --- /dev/null +++ b/frontend/app/screens/index.js @@ -0,0 +1,11 @@ +export * from './navigation'; +export * from './menu'; +export * from './other'; +export * from './dashboard'; +export * from './social'; +export * from './articles'; +export * from './messaging'; +export * from './login'; +export * from './walkthroughs'; +export * from './eCommerce'; +export * from './theme'; diff --git a/frontend/app/screens/login/index.js b/frontend/app/screens/login/index.js new file mode 100644 index 0000000..b0b1cd1 --- /dev/null +++ b/frontend/app/screens/login/index.js @@ -0,0 +1,4 @@ +export * from './login1'; +export * from './login2'; +export * from './signUp'; +export * from './passwordRecovery'; diff --git a/frontend/app/screens/login/login1.js b/frontend/app/screens/login/login1.js new file mode 100644 index 0000000..73e97d5 --- /dev/null +++ b/frontend/app/screens/login/login1.js @@ -0,0 +1,129 @@ +import React from 'react'; +import { + View, + Image, + Dimensions, + Keyboard, +} from 'react-native'; +import { + RkButton, + RkText, + RkTextInput, + RkAvoidKeyboard, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../../assets/icons'; +import { GradientButton } from '../../components/gradientButton'; +import { scaleModerate, scaleVertical } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +export class LoginV1 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + header: null, + }; + + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/backgroundLoginV1.png') : require('../../assets/images/backgroundLoginV1DarkTheme.png') + ); + + renderImage = () => { + const screenSize = Dimensions.get('window'); + const imageSize = { + width: screenSize.width, + height: screenSize.height - scaleModerate(375, 1), + }; + return ( + + ); + }; + + onLoginButtonPressed = () => { + this.props.navigation.goBack(); + }; + + onSignUpButtonPressed = () => { + this.props.navigation.navigate('SignUp'); + }; + + render = () => ( + true} + onResponderRelease={() => Keyboard.dismiss()} + style={styles.screen}> + {this.renderImage()} + + + + {FontAwesome.twitter} + + + {FontAwesome.google} + + + {FontAwesome.facebook} + + + + + + + + Don’t have an account? + + Sign up now + + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + flex: 1, + alignItems: 'center', + backgroundColor: theme.colors.screen.base, + }, + image: { + resizeMode: 'cover', + marginBottom: scaleVertical(10), + }, + container: { + paddingHorizontal: 17, + paddingBottom: scaleVertical(22), + alignItems: 'center', + flex: -1, + }, + footer: { + justifyContent: 'flex-end', + flex: 1, + }, + buttons: { + flexDirection: 'row', + marginBottom: scaleVertical(24), + }, + button: { + marginHorizontal: 14, + }, + save: { + marginVertical: 9, + }, + textRow: { + justifyContent: 'center', + flexDirection: 'row', + }, +})); diff --git a/frontend/app/screens/login/login2.js b/frontend/app/screens/login/login2.js new file mode 100644 index 0000000..c211190 --- /dev/null +++ b/frontend/app/screens/login/login2.js @@ -0,0 +1,127 @@ +import React from 'react'; +import { + View, + Image, + Keyboard, +} from 'react-native'; +import { + RkButton, + RkText, + RkTextInput, + RkAvoidKeyboard, + RkTheme, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { FontAwesome } from '../../assets/icons'; +import { GradientButton } from '../../components/gradientButton'; +import { scaleVertical } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +export class LoginV2 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + header: null, + }; + + onLoginButtonPressed = () => { + this.props.navigation.goBack(); + }; + + onSignUpButtonPressed = () => { + this.props.navigation.navigate('SignUp'); + }; + + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/logo.png') : require('../../assets/images/logoDark.png') + ); + + renderImage = () => ( + + ); + + render = () => ( + true} + onResponderRelease={() => Keyboard.dismiss()}> + + {this.renderImage()} + React Native + UI Kitten + + + + + + + + + + {FontAwesome.twitter} + + + {FontAwesome.google} + + + {FontAwesome.facebook} + + + + + Don’t have an account? + + Sign up now + + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + padding: scaleVertical(16), + flex: 1, + justifyContent: 'space-between', + backgroundColor: theme.colors.screen.base, + }, + image: { + height: scaleVertical(77), + resizeMode: 'contain', + }, + header: { + paddingBottom: scaleVertical(10), + alignItems: 'center', + justifyContent: 'center', + flex: 1, + }, + content: { + justifyContent: 'space-between', + }, + save: { + marginVertical: 20, + }, + buttons: { + flexDirection: 'row', + marginBottom: scaleVertical(24), + marginHorizontal: 24, + justifyContent: 'space-around', + }, + textRow: { + flexDirection: 'row', + justifyContent: 'center', + }, + button: { + borderColor: theme.colors.border.solid, + }, + footer: {}, +})); diff --git a/frontend/app/screens/login/passwordRecovery.js b/frontend/app/screens/login/passwordRecovery.js new file mode 100644 index 0000000..b383e4c --- /dev/null +++ b/frontend/app/screens/login/passwordRecovery.js @@ -0,0 +1,83 @@ +import React from 'react'; +import { + View, + Image, + Keyboard, +} from 'react-native'; +import { + RkStyleSheet, + RkText, + RkTextInput, + RkTheme, +} from 'react-native-ui-kitten'; +import { GradientButton } from '../../components/'; +import { scaleVertical } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +export class PasswordRecovery extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + header: null, + }; + + onSendButtonPressed = () => { + this.props.navigation.goBack(); + }; + + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/logo.png') : require('../../assets/images/logoDark.png') + ); + + renderImage = () => ( + + ); + + render = () => ( + true} + onResponderRelease={() => Keyboard.dismiss()}> + + {this.renderImage()} + Password Recovery + + + + + Enter your email below to receive your password reset instructions + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + flex: 1, + paddingHorizontal: 16, + paddingVertical: scaleVertical(24), + justifyContent: 'space-between', + backgroundColor: theme.colors.screen.base, + }, + header: { + alignItems: 'center', + }, + image: { + marginVertical: scaleVertical(27), + height: scaleVertical(77), + resizeMode: 'contain', + }, + content: { + alignItems: 'center', + }, +})); diff --git a/frontend/app/screens/login/signUp.js b/frontend/app/screens/login/signUp.js new file mode 100644 index 0000000..5c7965e --- /dev/null +++ b/frontend/app/screens/login/signUp.js @@ -0,0 +1,110 @@ +import React from 'react'; +import { + View, + Image, + Keyboard, +} from 'react-native'; +import { + RkButton, + RkText, + RkTextInput, + RkStyleSheet, + RkTheme, + RkAvoidKeyboard, +} from 'react-native-ui-kitten'; +import { GradientButton } from '../../components/'; +import { scaleVertical } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +export class SignUp extends React.Component { + static navigationOptions = { + header: null, + }; + static propTypes = { + navigation: NavigationType.isRequired, + }; + + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/logo.png') : require('../../assets/images/logoDark.png') + ); + + renderImage = () => ( + + ); + + onSignUpButtonPressed = () => { + this.props.navigation.goBack(); + }; + + onSignInButtonPressed = () => { + this.props.navigation.navigate('Login1'); + }; + + render = () => ( + true} + onResponderRelease={() => Keyboard.dismiss()}> + + {this.renderImage()} + Registration + + + + + + + + + + + + Already have an account? + + Sign in now + + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + padding: 16, + flex: 1, + justifyContent: 'space-around', + backgroundColor: theme.colors.screen.base, + }, + image: { + marginBottom: 10, + height: scaleVertical(77), + resizeMode: 'contain', + }, + content: { + justifyContent: 'space-between', + }, + save: { + marginVertical: 20, + }, + buttons: { + flexDirection: 'row', + marginBottom: 24, + marginHorizontal: 24, + justifyContent: 'space-around', + }, + footer: { + justifyContent: 'flex-end', + }, + textRow: { + flexDirection: 'row', + justifyContent: 'center', + }, +})); diff --git a/frontend/app/screens/menu/categoryMenu.js b/frontend/app/screens/menu/categoryMenu.js new file mode 100644 index 0000000..6ed6400 --- /dev/null +++ b/frontend/app/screens/menu/categoryMenu.js @@ -0,0 +1,77 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { + TouchableHighlight, + View, + FlatList, + StyleSheet, +} from 'react-native'; +import { + RkStyleSheet, + RkTheme, + RkText, +} from 'react-native-ui-kitten'; +import NavigationType from '../../config/navigation/propTypes'; + +export class CategoryMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + items: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.string.isRequired, + })).isRequired, + }; + + onItemPressed = (item) => { + const url = item.action || item.id; + this.props.navigation.navigate(url); + }; + + extractItemKey = (item) => item.id; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + {item.title} + + + ); + + renderPlaceholder = () => ( + + Coming Soon... + + ); + + renderList = () => ( + + ); + + render = () => (this.props.items.length === 0 ? this.renderPlaceholder() : this.renderList()); +} + +const styles = RkStyleSheet.create(theme => ({ + item: { + paddingVertical: 32.5, + paddingHorizontal: 16.5, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + }, + list: { + backgroundColor: theme.colors.screen.base, + }, + emptyContainer: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: theme.colors.screen.base, + }, +})); diff --git a/frontend/app/screens/menu/index.js b/frontend/app/screens/menu/index.js new file mode 100644 index 0000000..4bea133 --- /dev/null +++ b/frontend/app/screens/menu/index.js @@ -0,0 +1,2 @@ +export * from './categoryMenu'; +export * from './menus'; diff --git a/frontend/app/screens/menu/menus.js b/frontend/app/screens/menu/menus.js new file mode 100644 index 0000000..8cd8ff2 --- /dev/null +++ b/frontend/app/screens/menu/menus.js @@ -0,0 +1,114 @@ +/* eslint-disable react/no-multi-comp */ +import React from 'react'; + +import { CategoryMenu } from './categoryMenu'; +import * as Routes from '../../config/navigation/routesBuilder'; +import NavigationType from '../../config/navigation/propTypes'; + +export class LoginMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Login'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class NavigationMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Navigation'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class SocialMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Social'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class ArticleMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Articles'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class MessagingMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Messaging'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class DashboardMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Dashboards'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class WalkthroughMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Walkthrough'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class EcommerceMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Ecommerce'.toUpperCase(), + }; + render = () => ( + + ); +} + +export class OtherMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Other'.toUpperCase(), + }; + render = () => ( + + ); +} diff --git a/frontend/app/screens/messaging/chat.js b/frontend/app/screens/messaging/chat.js new file mode 100644 index 0000000..c6b0b5e --- /dev/null +++ b/frontend/app/screens/messaging/chat.js @@ -0,0 +1,214 @@ +import React from 'react'; +import { + FlatList, + View, + Platform, + Image, + TouchableOpacity, + Keyboard, + InteractionManager, +} from 'react-native'; +import { + RkButton, + RkText, + RkTextInput, + RkAvoidKeyboard, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; +import _ from 'lodash'; +import { FontAwesome } from '../../assets/icons'; +import { data } from '../../data'; +import { Avatar } from '../../components/avatar'; +import { scale } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class Chat extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = ({ navigation }) => { + const userId = navigation.state.params ? navigation.state.params.userId : undefined; + const user = data.getUser(userId); + return ({ + headerTitle: Chat.renderNavigationTitle(navigation, user), + headerRight: Chat.renderNavigationAvatar(navigation, user), + }); + }; + + constructor(props) { + super(props); + const userId = this.props.navigation.getParam('userId', undefined); + this.state = { + data: data.getConversation(userId), + }; + } + + componentDidMount() { + InteractionManager.runAfterInteractions(() => { + this.listRef.scrollToEnd(); + }); + } + + setListRef = (ref) => { + this.listRef = ref; + }; + + extractItemKey = (item) => `${item.id}`; + + scrollToEnd = () => { + if (Platform.OS === 'ios') { + this.listRef.scrollToEnd(); + } else { + _.delay(this.listRef.scrollToEnd, 100); + } + }; + + onInputChanged = (text) => { + this.setState({ message: text }); + }; + + onSendButtonPressed = () => { + if (!this.state.message) { + return; + } + this.state.data.messages.push({ + id: this.state.data.messages.length, time: 0, type: 'out', text: this.state.message, + }); + this.setState({ message: '' }); + this.scrollToEnd(true); + }; + + static onNavigationTitlePressed = (navigation, user) => { + navigation.navigate('ProfileV1', { id: user.id }); + }; + + static onNavigationAvatarPressed = (navigation, user) => { + navigation.navigate('ProfileV1', { id: user.id }); + }; + + static renderNavigationTitle = (navigation, user) => ( + Chat.onNavigationTitlePressed(navigation, user)}> + + {`${user.firstName} ${user.lastName}`} + Online + + + ); + + static renderNavigationAvatar = (navigation, user) => ( + Chat.onNavigationAvatarPressed(navigation, user)}> + + + ); + + renderDate = (date) => ( + + {moment().add(date, 'seconds').format('LT')} + + ); + + renderItem = ({ item }) => { + const isIncoming = item.type === 'in'; + const backgroundColor = isIncoming + ? RkTheme.current.colors.chat.messageInBackground + : RkTheme.current.colors.chat.messageOutBackground; + const itemStyle = isIncoming ? styles.itemIn : styles.itemOut; + + return ( + + {!isIncoming && this.renderDate(item.time)} + + {item.text} + + {isIncoming && this.renderDate(item.time)} + + ); + }; + + render = () => ( + + + + + {FontAwesome.plus} + + + + + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + header: { + alignItems: 'center', + }, + avatar: { + marginRight: 16, + }, + container: { + flex: 1, + backgroundColor: theme.colors.screen.base, + }, + list: { + paddingHorizontal: 17, + }, + footer: { + flexDirection: 'row', + minHeight: 60, + padding: 10, + backgroundColor: theme.colors.screen.alter, + }, + item: { + marginVertical: 14, + flex: 1, + flexDirection: 'row', + }, + itemIn: {}, + itemOut: { + alignSelf: 'flex-end', + }, + balloon: { + maxWidth: scale(250), + paddingHorizontal: 15, + paddingTop: 10, + paddingBottom: 15, + borderRadius: 20, + }, + time: { + alignSelf: 'flex-end', + margin: 15, + }, + plus: { + paddingVertical: 10, + paddingHorizontal: 10, + marginRight: 7, + }, + send: { + width: 40, + height: 40, + marginLeft: 10, + }, +})); diff --git a/frontend/app/screens/messaging/chatList.js b/frontend/app/screens/messaging/chatList.js new file mode 100644 index 0000000..36cde5c --- /dev/null +++ b/frontend/app/screens/messaging/chatList.js @@ -0,0 +1,147 @@ +import React from 'react'; +import { + FlatList, + View, + StyleSheet, + TouchableOpacity, +} from 'react-native'; +import _ from 'lodash'; +import { + RkStyleSheet, + RkText, + RkTextInput, +} from 'react-native-ui-kitten'; +import { Avatar } from '../../components'; +import { FontAwesome } from '../../assets/icons'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class ChatList extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Chats List'.toUpperCase(), + }; + + state = { + data: { + original: data.getChatList(), + filtered: data.getChatList(), + }, + }; + + extractItemKey = (item) => `${item.withUser.id}`; + + onInputChanged = (event) => { + const pattern = new RegExp(event.nativeEvent.text, 'i'); + const chats = _.filter(this.state.data.original, chat => { + const filterResult = { + firstName: chat.withUser.firstName.search(pattern), + lastName: chat.withUser.lastName.search(pattern), + }; + return filterResult.firstName !== -1 || filterResult.lastName !== -1 ? chat : undefined; + }); + this.setState({ + data: { + original: this.state.data.original, + filtered: chats, + }, + }); + }; + + onItemPressed = (item) => { + const navigationParams = { userId: item.withUser.id }; + this.props.navigation.navigate('Chat', navigationParams); + }; + + renderSeparator = () => ( + + ); + + renderInputLabel = () => ( + {FontAwesome.search} + ); + + renderHeader = () => ( + + + + ); + + renderItem = ({ item }) => { + const last = item.messages[item.messages.length - 1]; + return ( + this.onItemPressed(item)}> + + + + + {`${item.withUser.firstName} ${item.withUser.lastName}`} + + {moment().add(last.time, 'seconds').format('LT')} + + + + {last.text} + + + + + ); + }; + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + searchContainer: { + backgroundColor: theme.colors.screen.bold, + paddingHorizontal: 16, + paddingVertical: 10, + height: 60, + alignItems: 'center', + }, + container: { + paddingLeft: 19, + paddingRight: 16, + paddingBottom: 12, + paddingTop: 7, + flexDirection: 'row', + }, + content: { + marginLeft: 16, + flex: 1, + }, + contentHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 6, + }, + separator: { + height: StyleSheet.hairlineWidth, + backgroundColor: theme.colors.border.base, + }, +})); diff --git a/frontend/app/screens/messaging/comments.js b/frontend/app/screens/messaging/comments.js new file mode 100644 index 0000000..3b772c5 --- /dev/null +++ b/frontend/app/screens/messaging/comments.js @@ -0,0 +1,98 @@ +import React from 'react'; +import { + FlatList, + View, + StyleSheet, + TouchableOpacity, +} from 'react-native'; +import { + RkStyleSheet, + RkText, +} from 'react-native-ui-kitten'; +import { Avatar } from '../../components'; +import { data } from '../../data'; +import NavigationType from '../../config/navigation/propTypes'; + +const moment = require('moment'); + +export class Comments extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Comments'.toUpperCase(), + }; + + constructor(props) { + super(props); + const postId = this.props.navigation.getParam('postId', undefined); + this.state = { + data: data.getComments(postId), + }; + } + + extractItemKey = (item) => `${item.id}`; + + onItemPressed = (item) => { + const navigationParams = { id: item.user.id }; + this.props.navigation.navigate('ProfileV1', navigationParams); + }; + + renderSeparator = () => ( + + ); + + renderItem = ({ item }) => ( + + this.onItemPressed(item)}> + + + + + {`${item.user.firstName} ${item.user.lastName}`} + + {moment().add(item.time, 'seconds').format('LT')} + + + {item.text} + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + container: { + paddingLeft: 19, + paddingRight: 16, + paddingVertical: 12, + flexDirection: 'row', + alignItems: 'flex-start', + }, + content: { + marginLeft: 16, + flex: 1, + }, + contentHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 6, + }, + separator: { + height: StyleSheet.hairlineWidth, + backgroundColor: theme.colors.border.base, + }, +})); diff --git a/frontend/app/screens/messaging/index.js b/frontend/app/screens/messaging/index.js new file mode 100644 index 0000000..0d39244 --- /dev/null +++ b/frontend/app/screens/messaging/index.js @@ -0,0 +1,3 @@ +export * from './chat'; +export * from './chatList'; +export * from './comments'; diff --git a/frontend/app/screens/navigation/grid.js b/frontend/app/screens/navigation/grid.js new file mode 100644 index 0000000..7fbe404 --- /dev/null +++ b/frontend/app/screens/navigation/grid.js @@ -0,0 +1,70 @@ +import React from 'react'; +import { + ScrollView, + Dimensions, +} from 'react-native'; +import { + RkButton, RkStyleSheet, + RkText, +} from 'react-native-ui-kitten'; +import { MainRoutes } from '../../config/navigation/routes'; +import NavigationType from '../../config/navigation/propTypes'; + +const paddingValue = 8; + +export class GridV1 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Grid Menu'.toUpperCase(), + }; + + constructor(props) { + super(props); + const screenWidth = Dimensions.get('window').width; + this.itemSize = { + width: (screenWidth - (paddingValue * 6)) / 2, + height: (screenWidth - (paddingValue * 6)) / 2, + }; + } + + onItemPressed = (item) => { + this.props.navigation.navigate(item.id); + }; + + renderItems = () => MainRoutes.map(route => ( + this.onItemPressed(route)}> + + {route.icon} + + {route.title} + + )); + + render = () => ( + + {this.renderItems()} + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.scroll, + padding: paddingValue, + }, + rootContainer: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + icon: { + marginBottom: 16, + }, +})); diff --git a/frontend/app/screens/navigation/grid2.js b/frontend/app/screens/navigation/grid2.js new file mode 100644 index 0000000..8773e02 --- /dev/null +++ b/frontend/app/screens/navigation/grid2.js @@ -0,0 +1,82 @@ +import React from 'react'; +import { + ScrollView, + View, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkButton, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { MainRoutes } from '../../config/navigation/routes'; +import NavigationType from '../../config/navigation/propTypes'; + +export class GridV2 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Grid Menu'.toUpperCase(), + }; + + state = { + dimensions: undefined, + }; + + onContainerLayout = (event) => { + if (this.state.height) { + return; + } + const dimensions = event.nativeEvent.layout; + this.setState({ dimensions }); + }; + + renderItems = () => MainRoutes.map(this.renderItem); + + renderItem = (item) => ( + this.onItemPressed(item)}> + + {item.icon} + + {item.title} + + ); + + onItemPressed = (item) => { + this.props.navigation.navigate(item.id); + }; + + render() { + const items = this.state.dimensions === undefined ? : this.renderItems(); + return ( + + {items} + + ); + } +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + rootContainer: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + empty: { + borderWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + }, + icon: { + marginBottom: 16, + }, +})); diff --git a/frontend/app/screens/navigation/index.js b/frontend/app/screens/navigation/index.js new file mode 100644 index 0000000..3f5229f --- /dev/null +++ b/frontend/app/screens/navigation/index.js @@ -0,0 +1,4 @@ +export * from './grid2'; +export * from './grid'; +export * from './sideMenu'; +export * from './list'; diff --git a/frontend/app/screens/navigation/list.js b/frontend/app/screens/navigation/list.js new file mode 100644 index 0000000..33c52ba --- /dev/null +++ b/frontend/app/screens/navigation/list.js @@ -0,0 +1,73 @@ +import React from 'react'; +import { + FlatList, + TouchableOpacity, + View, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { MainRoutes } from '../../config/navigation/routes'; +import NavigationType from '../../config/navigation/propTypes'; + +export class ListMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'List Menu'.toUpperCase(), + }; + + onItemPressed = (item) => { + this.props.navigation.navigate(item.id); + }; + + extractItemKey = (item) => item.id; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + {item.icon} + + {item.title} + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + item: { + height: 80, + justifyContent: 'center', + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + paddingHorizontal: 16, + }, + list: { + backgroundColor: theme.colors.screen.base, + }, + container: { + flexDirection: 'row', + alignItems: 'center', + }, + icon: { + width: 34, + textAlign: 'center', + marginRight: 16, + }, +})); diff --git a/frontend/app/screens/navigation/sideMenu.js b/frontend/app/screens/navigation/sideMenu.js new file mode 100644 index 0000000..7f5c5a1 --- /dev/null +++ b/frontend/app/screens/navigation/sideMenu.js @@ -0,0 +1,113 @@ +import React from 'react'; +import { + TouchableHighlight, + View, + ScrollView, + Image, + Platform, + StyleSheet, +} from 'react-native'; +import { + RkStyleSheet, + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import { MainRoutes } from '../../config/navigation/routes'; +import { FontAwesome, FontIcons } from '../../assets/icons'; +import NavigationType from '../../config/navigation/propTypes'; +import * as Screens from '../index'; + +export const NavbarRoutes = [ + { + id: 'Articles2', + title: 'Problems', + icon: FontIcons.article, + screen: Screens.Articles2, + + }, { + id: 'Login1', + title: 'Login', + icon: FontIcons.login, + screen: Screens.LoginV1, + + }, { + id: 'AddProblem', + title: 'Add Problem', + icon: FontIcons.article, + screen: Screens.AddToCardForm, + + }]; + +export class SideMenu extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + + onMenuItemPressed = (item) => { + this.props.navigation.navigate(item.id); + }; + + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/smallLogo.png') : require('../../assets/images/smallLogoDark.png') + ); + + renderIcon = () => ( + + ); + + renderMenu = () => NavbarRoutes.map(this.renderMenuItem); + + renderMenuItem = (item) => ( + this.onMenuItemPressed(item)}> + + + {item.icon} + + {item.title} + + {FontAwesome.chevronRight} + + + ); + + render = () => ( + + + + EcoAlerts + + {this.renderMenu()} + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + height: 80, + paddingHorizontal: 16, + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + }, + root: { + paddingTop: Platform.OS === 'ios' ? 20 : 0, + backgroundColor: theme.colors.screen.base, + }, + content: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + }, + icon: { + marginRight: 13, + }, +})); diff --git a/frontend/app/screens/other/index.js b/frontend/app/screens/other/index.js new file mode 100644 index 0000000..9784f88 --- /dev/null +++ b/frontend/app/screens/other/index.js @@ -0,0 +1,2 @@ +export * from './splash'; +export * from './settings'; diff --git a/frontend/app/screens/other/settings.js b/frontend/app/screens/other/settings.js new file mode 100644 index 0000000..910deb0 --- /dev/null +++ b/frontend/app/screens/other/settings.js @@ -0,0 +1,176 @@ +import React from 'react'; +import { + ScrollView, + View, + TouchableOpacity, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; +import { + RkSwitch, + FindFriends, +} from '../../components'; +import { FontAwesome } from '../../assets/icons'; + +export class Settings extends React.Component { + static navigationOptions = { + title: 'Settings'.toUpperCase(), + }; + + state = { + sendPush: true, + shouldRefresh: false, + twitterEnabled: true, + googleEnabled: false, + facebookEnabled: true, + }; + + onPushNotificationsSettingChanged = (value) => { + this.setState({ sendPush: value }); + }; + + onRefreshAutomaticallySettingChanged = (value) => { + this.setState({ shouldRefresh: value }); + }; + + onFindFriendsTwitterButtonPressed = () => { + this.setState({ twitterEnabled: !this.state.twitterEnabled }); + }; + + onFindFriendsGoogleButtonPressed = () => { + this.setState({ googleEnabled: !this.state.googleEnabled }); + }; + + onFindFriendsFacebookButtonPressed = () => { + this.setState({ facebookEnabled: !this.state.facebookEnabled }); + }; + + render = () => ( + + + + PROFILE SETTINGS + + + + Edit Profile + + + + + Change Password + + + + Send Push Notifications + + + + Refresh Automatically + + + + + + FIND FRIENDS + + + + + + + + + + + + + + SUPPORT + + + + Help + + + + + Privacy Policy + + + + + Terms & Conditions + + + + + Logout + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.base, + }, + header: { + paddingVertical: 25, + }, + section: { + marginVertical: 25, + }, + heading: { + paddingBottom: 12.5, + }, + row: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingHorizontal: 17.5, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + alignItems: 'center', + }, + rowButton: { + flex: 1, + paddingVertical: 24, + }, + switch: { + marginVertical: 14, + }, +})); diff --git a/frontend/app/screens/other/splash.js b/frontend/app/screens/other/splash.js new file mode 100644 index 0000000..33e7abe --- /dev/null +++ b/frontend/app/screens/other/splash.js @@ -0,0 +1,108 @@ +import React from 'react'; +import { + StyleSheet, + Image, + View, + Dimensions, + StatusBar, +} from 'react-native'; +import { + RkText, + RkTheme, +} from 'react-native-ui-kitten'; +import { + StackActions, + NavigationActions, +} from 'react-navigation'; +import { ProgressBar } from '../../components'; +import { KittenTheme } from '../../config/theme'; +import { scale, scaleVertical } from '../../utils/scale'; +import NavigationType from '../../config/navigation/propTypes'; + +const delay = 800; + +export class SplashScreen extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + state = { + progress: 0, + }; + + componentDidMount() { + StatusBar.setHidden(true, 'none'); + RkTheme.setTheme(KittenTheme); + this.timer = setInterval(this.updateProgress, delay); + } + + componentWillUnmount() { + clearInterval(this.timer); + } + + updateProgress = () => { + if (this.state.progress === 1) { + clearInterval(this.timer); + setTimeout(this.onLoaded, delay); + } else { + const randProgress = this.state.progress + (Math.random() * 0.5); + this.setState({ progress: randProgress > 1 ? 1 : randProgress }); + } + }; + + onLoaded = () => { + StatusBar.setHidden(false, 'slide'); + const toHome = StackActions.reset({ + index: 0, + actions: [NavigationActions.navigate({ routeName: 'Home' })], + }); + this.props.navigation.dispatch(toHome); + }; + + render = () => ( + + + + + EcoAlerts + The best ecological problems coordinator + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + backgroundColor: KittenTheme.colors.screen.base, + justifyContent: 'space-between', + flex: 1, + }, + image: { + resizeMode: 'cover', + height: scaleVertical(430), + }, + text: { + alignItems: 'center', + }, + hero: { + fontSize: 37, + }, + appName: { + textAlign: 'center', + fontSize: 33, + }, + progress: { + alignSelf: 'center', + marginBottom: 35, + backgroundColor: '#e5e5e5', + }, +}); diff --git a/frontend/app/screens/social/contacts.js b/frontend/app/screens/social/contacts.js new file mode 100644 index 0000000..8eaacae --- /dev/null +++ b/frontend/app/screens/social/contacts.js @@ -0,0 +1,124 @@ +import React from 'react'; +import { + FlatList, + View, + StyleSheet, + TouchableOpacity, +} from 'react-native'; +import _ from 'lodash'; +import { + RkStyleSheet, + RkText, + RkTextInput, +} from 'react-native-ui-kitten'; +import { data } from '../../data'; +import { Avatar } from '../../components/avatar'; +import { FontAwesome } from '../../assets/icons'; +import NavigationType from '../../config/navigation/propTypes'; + +export class Contacts extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'Contacts'.toUpperCase(), + }; + + state = { + data: { + original: data.getUsers(), + filtered: data.getUsers(), + }, + }; + + extractItemKey = (item) => `${item.id}`; + + onSearchInputChanged = (event) => { + const pattern = new RegExp(event.nativeEvent.text, 'i'); + const contacts = _.filter(this.state.data.original, contact => { + const filterResult = { + firstName: contact.firstName.search(pattern), + lastName: contact.lastName.search(pattern), + }; + return filterResult.firstName !== -1 || filterResult.lastName !== -1 ? contact : undefined; + }); + this.setState({ + data: { + original: this.state.data.original, + filtered: contacts, + }, + }); + }; + + onItemPressed = (item) => { + this.props.navigation.navigate('ProfileV1', { id: item.id }); + }; + + renderItem = ({ item }) => ( + this.onItemPressed(item)}> + + + {`${item.firstName} ${item.lastName}`} + + + ); + + renderSeparator = () => ( + + ); + + renderHeaderLabel = () => ( + {FontAwesome.search} + ); + + renderHeader = () => ( + + + + ); + + render = () => ( + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + searchContainer: { + backgroundColor: theme.colors.screen.bold, + paddingHorizontal: 16, + paddingVertical: 10, + height: 60, + alignItems: 'center', + }, + container: { + flexDirection: 'row', + padding: 16, + alignItems: 'center', + }, + avatar: { + marginRight: 16, + }, + separator: { + flex: 1, + height: StyleSheet.hairlineWidth, + backgroundColor: theme.colors.border.base, + }, +})); diff --git a/frontend/app/screens/social/feed.js b/frontend/app/screens/social/feed.js new file mode 100644 index 0000000..3de46f2 --- /dev/null +++ b/frontend/app/screens/social/feed.js @@ -0,0 +1,73 @@ +import React from 'react'; +import { + FlatList, + View, + Image, +} from 'react-native'; +import { + RkCard, + RkText, RkStyleSheet, +} from 'react-native-ui-kitten'; +import { Avatar } from '../../components/avatar'; +import { SocialBar } from '../../components/socialBar'; +import { data } from '../../data'; + +const moment = require('moment'); + +export class Feed extends React.Component { + static navigationOptions = { + title: 'Feed'.toUpperCase(), + }; + + state = { + data: data.getArticles('post'), + }; + + extractItemKey = (item) => `${item.id}`; + + renderItem = ({ item }) => ( + + + + + {`${item.user.firstName} ${item.user.lastName}`} + {moment().add(item.time, 'seconds').fromNow()} + + + + + {item.text} + + + + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + container: { + backgroundColor: theme.colors.screen.scroll, + paddingVertical: 8, + paddingHorizontal: 10, + }, + card: { + marginVertical: 8, + }, + avatar: { + marginRight: 16, + }, +})); diff --git a/frontend/app/screens/social/index.js b/frontend/app/screens/social/index.js new file mode 100644 index 0000000..bd66176 --- /dev/null +++ b/frontend/app/screens/social/index.js @@ -0,0 +1,7 @@ +export * from './profile1'; +export * from './profile2'; +export * from './profile3'; +export * from './profileSettings'; +export * from './notifications'; +export * from './contacts'; +export * from './feed'; diff --git a/frontend/app/screens/social/notifications.js b/frontend/app/screens/social/notifications.js new file mode 100644 index 0000000..c397d17 --- /dev/null +++ b/frontend/app/screens/social/notifications.js @@ -0,0 +1,98 @@ +import React from 'react'; +import { + FlatList, + View, + Image, +} from 'react-native'; +import { RkStyleSheet, RkText } from 'react-native-ui-kitten'; +import { Avatar } from '../../components'; +import { data } from '../../data'; + +const moment = require('moment'); + +export class Notifications extends React.Component { + static navigationOptions = { + title: 'Notifications', + }; + + state = { + data: data.getNotifications(), + }; + + extractItemKey = (item) => `${item.id}`; + + renderAttachment = (item) => { + const hasAttachment = item.attach !== undefined; + return hasAttachment ? : ; + }; + + renderItem = ({ item }) => ( + + + + + + + {`${item.user.firstName} ${item.user.lastName}`} + {item.description} + + + {moment().add(item.time, 'seconds').fromNow()} + + + {this.renderAttachment(item)} + + + ); + + render = () => ( + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + container: { + padding: 16, + flexDirection: 'row', + borderBottomWidth: 1, + borderColor: theme.colors.border.base, + alignItems: 'flex-start', + }, + avatar: {}, + text: { + marginBottom: 5, + }, + content: { + flex: 1, + marginLeft: 16, + marginRight: 0, + }, + mainContent: { + marginRight: 60, + }, + img: { + height: 50, + width: 50, + margin: 0, + }, + attachment: { + position: 'absolute', + right: 0, + height: 50, + width: 50, + }, +})); diff --git a/frontend/app/screens/social/profile1.js b/frontend/app/screens/social/profile1.js new file mode 100644 index 0000000..1f3ec09 --- /dev/null +++ b/frontend/app/screens/social/profile1.js @@ -0,0 +1,104 @@ +import React from 'react'; +import { + View, + ScrollView, +} from 'react-native'; +import { + RkText, + RkButton, RkStyleSheet, +} from 'react-native-ui-kitten'; +import { Avatar } from '../../components/avatar'; +import { Gallery } from '../../components/gallery'; +import { data } from '../../data/'; +import formatNumber from '../../utils/textUtils'; +import NavigationType from '../../config/navigation/propTypes'; + +export class ProfileV1 extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + title: 'User Profile'.toUpperCase(), + }; + + state = { + data: undefined, + }; + + constructor(props) { + super(props); + const id = this.props.navigation.getParam('id', 1); + this.state.data = data.getUser(id); + } + + render = () => ( + + + + {`${this.state.data.firstName} ${this.state.data.lastName}`} + + + + {this.state.data.postCount} + Posts + + + {formatNumber(this.state.data.followersCount)} + Followers + + + {this.state.data.followingCount} + Following + + + + FOLLOW + + MESSAGE + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + header: { + alignItems: 'center', + paddingTop: 25, + paddingBottom: 17, + }, + userInfo: { + flexDirection: 'row', + paddingVertical: 18, + }, + bordered: { + borderBottomWidth: 1, + borderColor: theme.colors.border.base, + }, + section: { + flex: 1, + alignItems: 'center', + }, + space: { + marginBottom: 3, + }, + separator: { + backgroundColor: theme.colors.border.base, + alignSelf: 'center', + flexDirection: 'row', + flex: 0, + width: 1, + height: 42, + }, + buttons: { + flexDirection: 'row', + paddingVertical: 8, + }, + button: { + flex: 1, + alignSelf: 'center', + }, +})); diff --git a/frontend/app/screens/social/profile2.js b/frontend/app/screens/social/profile2.js new file mode 100644 index 0000000..1636910 --- /dev/null +++ b/frontend/app/screens/social/profile2.js @@ -0,0 +1,108 @@ +import React from 'react'; +import { + View, + ScrollView, +} from 'react-native'; +import { + RkText, + RkButton, RkStyleSheet, +} from 'react-native-ui-kitten'; +import { + Avatar, + Gallery, +} from '../../components'; +import { data } from '../../data'; +import { FontIcons } from '../../assets/icons'; +import formatNumber from '../../utils/textUtils'; + +export class ProfileV2 extends React.Component { + static navigationOptions = { + title: 'User Profile'.toUpperCase(), + }; + + state = { + data: data.getUser(), + }; + + render = () => ( + + + + + + {FontIcons.profile} + + + + + + {FontIcons.mail} + + + + + {`${this.state.data.firstName} ${this.state.data.lastName}`} + + + + + {this.state.data.postCount} + Posts + + + {formatNumber(this.state.data.followersCount)} + Followers + + + {this.state.data.followingCount} + Following + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + header: { + paddingTop: 25, + paddingBottom: 17, + }, + row: { + flexDirection: 'row', + + }, + userInfo: { + flexDirection: 'row', + paddingVertical: 18, + }, + bordered: { + borderBottomWidth: 1, + borderColor: theme.colors.border.base, + }, + section: { + flex: 1, + alignItems: 'center', + }, + space: { + marginBottom: 3, + }, + separator: { + backgroundColor: theme.colors.border.base, + alignSelf: 'center', + flexDirection: 'row', + flex: 0, + width: 1, + height: 42, + }, + buttons: { + flex: 1, + }, + button: { + marginTop: 27.5, + alignSelf: 'center', + }, +})); diff --git a/frontend/app/screens/social/profile3.js b/frontend/app/screens/social/profile3.js new file mode 100644 index 0000000..985dc1e --- /dev/null +++ b/frontend/app/screens/social/profile3.js @@ -0,0 +1,96 @@ +import React from 'react'; +import { + View, + ScrollView, +} from 'react-native'; +import { + RkStyleSheet, + RkText, +} from 'react-native-ui-kitten'; +import { + Avatar, + Gallery, + GradientButton, +} from '../../components'; +import { data } from '../../data'; +import formatNumber from '../../utils/textUtils'; + +export class ProfileV3 extends React.Component { + static navigationOptions = { + title: 'User Profile'.toUpperCase(), + }; + + state = { + data: data.getUser(), + }; + + render = () => ( + + + + {`${this.state.data.firstName} ${this.state.data.lastName}`} + + + + + + {this.state.data.postCount} + Posts + + + {formatNumber(this.state.data.followersCount)} + Followers + + + {this.state.data.followingCount} + Following + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + header: { + alignItems: 'center', + paddingTop: 25, + paddingBottom: 17, + }, + userInfo: { + flexDirection: 'row', + paddingVertical: 18, + }, + bordered: { + borderBottomWidth: 1, + borderColor: theme.colors.border.base, + }, + section: { + flex: 1, + alignItems: 'center', + }, + space: { + marginBottom: 3, + }, + separator: { + backgroundColor: theme.colors.border.base, + alignSelf: 'center', + flexDirection: 'row', + flex: 0, + width: 1, + height: 42, + }, + buttons: { + flexDirection: 'row', + paddingVertical: 8, + }, + button: { + marginTop: 18, + alignSelf: 'center', + width: 140, + }, + +})); diff --git a/frontend/app/screens/social/profileSettings.js b/frontend/app/screens/social/profileSettings.js new file mode 100644 index 0000000..0be1b94 --- /dev/null +++ b/frontend/app/screens/social/profileSettings.js @@ -0,0 +1,200 @@ +import React from 'react'; +import { + ScrollView, + View, + StyleSheet, +} from 'react-native'; +import { + RkText, + RkTextInput, + RkAvoidKeyboard, + RkTheme, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { data } from '../../data'; +import { + Avatar, + SocialSetting, + GradientButton, +} from '../../components'; +import { FontAwesome } from '../../assets/icons'; + +export class ProfileSettings extends React.Component { + static navigationOptions = { + title: 'Profile Settings'.toUpperCase(), + }; + + user = data.getUser(); + + state = { + firstName: this.user.firstName, + lastName: this.user.lastName, + email: this.user.email, + country: this.user.country, + phone: this.user.phone, + password: this.user.password, + newPassword: this.user.newPassword, + confirmPassword: this.user.confirmPassword, + }; + + onFirstNameInputChanged = (text) => { + this.setState({ firstName: text }); + }; + + onLastNameInputChanged = (text) => { + this.setState({ lastName: text }); + }; + + onEmailInputChanged = (text) => { + this.setState({ email: text }); + }; + + onCountryInputChanged = (text) => { + this.setState({ country: text }); + }; + + onPhoneInputChanged = (text) => { + this.setState({ phone: text }); + }; + + onPasswordInputChanged = (text) => { + this.setState({ password: text }); + }; + + onNewPasswordInputChanged = (text) => { + this.setState({ newPassword: text }); + }; + + onConfirmPasswordInputChanged = (text) => { + this.setState({ confirmPassword: text }); + }; + + render = () => ( + + + + + + + + INFO + + + + + + + + + + + + + + + + + + + + CHANGE PASSWORD + + + + + + + + + + + + + + CONNECT YOUR ACCOUNT + + + + + + + + + + + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + }, + header: { + backgroundColor: theme.colors.screen.neutral, + paddingVertical: 25, + }, + section: { + marginVertical: 25, + }, + heading: { + paddingBottom: 12.5, + }, + row: { + flexDirection: 'row', + paddingHorizontal: 17.5, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: theme.colors.border.base, + alignItems: 'center', + }, + button: { + marginHorizontal: 16, + marginBottom: 32, + }, +})); diff --git a/frontend/app/screens/theme/index.js b/frontend/app/screens/theme/index.js new file mode 100644 index 0000000..22cacb2 --- /dev/null +++ b/frontend/app/screens/theme/index.js @@ -0,0 +1 @@ +export * from './themes'; diff --git a/frontend/app/screens/theme/themes.js b/frontend/app/screens/theme/themes.js new file mode 100644 index 0000000..82f4165 --- /dev/null +++ b/frontend/app/screens/theme/themes.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { + View, + Image, + StatusBar, + Platform, +} from 'react-native'; +import { + RkText, + RkTheme, + RkStyleSheet, +} from 'react-native-ui-kitten'; +import { DarkKittenTheme } from '../../config/darkTheme'; +import { KittenTheme } from '../../config/theme'; +import { GradientButton } from '../../components/gradientButton'; +import { scale, scaleVertical } from '../../utils/scale'; + +export class Themes extends React.Component { + static navigationOptions = { + title: 'Theme'.toUpperCase(), + }; + + onLightThemeApplyButtonPressed = () => { + StatusBar.setBarStyle('dark-content', true); + if (Platform.OS === 'android') { + StatusBar.setBackgroundColor(KittenTheme.colors.screen.base); + } + RkTheme.setTheme(KittenTheme); + }; + + onDarkThemeApplyButtonPressed = () => { + StatusBar.setBarStyle('light-content', true); + if (Platform.OS === 'android') { + StatusBar.setBackgroundColor(DarkKittenTheme.colors.screen.base); + } + RkTheme.setTheme(DarkKittenTheme); + }; + + render = () => ( + + + Light Theme + + + + + Dark Theme + + + + + ); +} + +const styles = RkStyleSheet.create(theme => ({ + root: { + backgroundColor: theme.colors.screen.base, + flex: 1, + paddingHorizontal: scale(72), + + }, + image: { + height: scaleVertical(160), + }, + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'space-between', + paddingVertical: scaleVertical(20), + }, +})); diff --git a/frontend/app/screens/walkthroughs/index.js b/frontend/app/screens/walkthroughs/index.js new file mode 100644 index 0000000..e7f1eb0 --- /dev/null +++ b/frontend/app/screens/walkthroughs/index.js @@ -0,0 +1 @@ +export * from './walkthroughScreen'; diff --git a/frontend/app/screens/walkthroughs/walkthrough1.js b/frontend/app/screens/walkthroughs/walkthrough1.js new file mode 100644 index 0000000..2f08f97 --- /dev/null +++ b/frontend/app/screens/walkthroughs/walkthrough1.js @@ -0,0 +1,40 @@ +import React from 'react'; +import { + View, + Image, +} from 'react-native'; +import { + RkText, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; + +export class Walkthrough1 extends React.Component { + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/kittenImage.png') : require('../../assets/images/kittenImageDark.png') + ); + + renderImage = () => ( + + ); + + render = () => ( + + {this.renderImage()} + Welcome to EcoAlerts + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + backgroundColor: theme.colors.screen.base, + alignItems: 'center', + justifyContent: 'center', + flex: 1, + }, + text: { + marginTop: 20, + }, +})); diff --git a/frontend/app/screens/walkthroughs/walkthrough2.js b/frontend/app/screens/walkthroughs/walkthrough2.js new file mode 100644 index 0000000..6e387b8 --- /dev/null +++ b/frontend/app/screens/walkthroughs/walkthrough2.js @@ -0,0 +1,46 @@ +import React from 'react'; +import { + View, + Image, + Dimensions, +} from 'react-native'; +import { + RkText, + RkStyleSheet, + RkTheme, +} from 'react-native-ui-kitten'; + +export class Walkthrough2 extends React.Component { + getThemeImageSource = (theme) => ( + theme.name === 'light' ? + require('../../assets/images/screensImage.png') : require('../../assets/images/screensImageDark.png') + ); + + renderImage = () => ( + + ); + + render = () => ( + + {this.renderImage()} + Share info about ecological problems around! + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + backgroundColor: theme.colors.screen.base, + alignItems: 'center', + justifyContent: 'center', + flex: 1, + }, + text: { + textAlign: 'center', + marginTop: 20, + marginHorizontal: 30, + }, +})); diff --git a/frontend/app/screens/walkthroughs/walkthroughScreen.js b/frontend/app/screens/walkthroughs/walkthroughScreen.js new file mode 100644 index 0000000..f0c21b5 --- /dev/null +++ b/frontend/app/screens/walkthroughs/walkthroughScreen.js @@ -0,0 +1,61 @@ +import React from 'react'; +import { View } from 'react-native'; +import { RkStyleSheet } from 'react-native-ui-kitten'; +import { + GradientButton, + PaginationIndicator, +} from '../../components/'; +import { Walkthrough } from '../../components/walkthrough'; +import { Walkthrough1 } from './walkthrough1'; +import { Walkthrough2 } from './walkthrough2'; +import NavigationType from '../../config/navigation/propTypes'; + +export class WalkthroughScreen extends React.Component { + static propTypes = { + navigation: NavigationType.isRequired, + }; + static navigationOptions = { + header: null, + }; + + state = { + index: 0, + }; + + onWalkThroughIndexChanged = (index) => { + this.setState({ index }); + }; + + onStartButtonPressed = () => { + this.props.navigation.navigate('Articles2'); + }; + + render = () => ( + + + + + + + + + ) +} + +const styles = RkStyleSheet.create(theme => ({ + screen: { + backgroundColor: theme.colors.screen.base, + paddingVertical: 28, + alignItems: 'center', + flex: 1, + }, + button: { + marginTop: 25, + marginHorizontal: 16, + }, +})); diff --git a/frontend/app/utils/scale.js b/frontend/app/utils/scale.js new file mode 100644 index 0000000..f754d48 --- /dev/null +++ b/frontend/app/utils/scale.js @@ -0,0 +1,13 @@ +import { Dimensions } from 'react-native'; + +const { width, height } = Dimensions.get('window'); + +// Guideline sizes are based on standard ~5" screen mobile device +const guidelineBaseWidth = 350; +const guidelineBaseHeight = 680; + +const scale = size => (width / guidelineBaseWidth) * size; +const scaleVertical = size => (height / guidelineBaseHeight) * size; +const scaleModerate = (size, factor = 0.5) => size + ((scale(size) - size) * factor); + +export { scale, scaleVertical, scaleModerate }; diff --git a/frontend/app/utils/textUtils.js b/frontend/app/utils/textUtils.js new file mode 100644 index 0000000..589f48f --- /dev/null +++ b/frontend/app/utils/textUtils.js @@ -0,0 +1,5 @@ +function formatNumber(num) { + return num > 999 ? `${(num / 1000).toFixed(1)}k` : num; +} + +export default formatNumber; -- cgit v1.2.3