├── .babelrc ├── .buckconfig ├── .editorconfig ├── .env.example ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App ├── Components │ ├── Styles │ │ └── TopDoctorStyle.js │ └── TopDoctor.js ├── Config │ ├── AppConfig.js │ ├── DebugConfig.js │ ├── README.md │ ├── ReactotronConfig.js │ ├── ReduxPersist.js │ └── index.js ├── Containers │ ├── AccountScreen.js │ ├── App.js │ ├── DoctorDetailScreen.js │ ├── HomeScreen.js │ ├── InboxScreen.js │ ├── README.md │ ├── RootContainer.js │ ├── SplashScreen.js │ └── Styles │ │ ├── AccountScreenStyle.js │ │ ├── DoctorDetailScreenStyle.js │ │ ├── HomeScreenStyle.js │ │ ├── InboxScreenStyle.js │ │ ├── LaunchScreenStyles.js │ │ ├── README.md │ │ ├── RootContainerStyles.js │ │ └── SplashScreenStyle.js ├── Fixtures │ ├── README.md │ ├── gantman.json │ ├── rateLimit.json │ ├── root.json │ └── skellock.json ├── I18n │ ├── I18n.js │ ├── README.md │ ├── index.js │ ├── languages │ │ ├── af.json │ │ ├── am.json │ │ ├── ar.json │ │ ├── bg.json │ │ ├── ca.json │ │ ├── cs.json │ │ ├── da.json │ │ ├── de.json │ │ ├── el.json │ │ ├── english.json │ │ ├── es.json │ │ ├── et.json │ │ ├── fi.json │ │ ├── fil.json │ │ ├── fr.json │ │ ├── he.json │ │ ├── hi.json │ │ ├── hr.json │ │ ├── hu.json │ │ ├── id.json │ │ ├── it.json │ │ ├── ja.json │ │ ├── ko.json │ │ ├── lt.json │ │ ├── lv.json │ │ ├── ms.json │ │ ├── nb.json │ │ ├── nl.json │ │ ├── no.json │ │ ├── pl.json │ │ ├── pt.json │ │ ├── ro.json │ │ ├── ru.json │ │ ├── sk.json │ │ ├── sl.json │ │ ├── sr.json │ │ ├── sv.json │ │ ├── sw.json │ │ ├── th.json │ │ ├── tr.json │ │ ├── uk.json │ │ ├── vi.json │ │ ├── zh.json │ │ └── zu.json │ └── platform_languages.txt ├── Images │ ├── detail-doctor.jpg │ ├── icon-back.svg │ ├── icon-bandage.svg │ ├── icon-bookmark.svg │ ├── icon-care.svg │ ├── icon-chat.svg │ ├── icon-clinic.svg │ ├── icon-heart.svg │ ├── icon-medicine.svg │ ├── icon-search.svg │ ├── icon-star5.svg │ ├── icon-stethoscope.svg │ ├── icon-syringe.svg │ ├── icon-teeth.svg │ ├── thumb-doctor1.jpg │ ├── thumb-doctor2.jpg │ └── thumb-doctor3.jpg ├── Lib │ └── README.md ├── Navigation │ ├── AppNavigation.js │ ├── BottomNavigation.js │ ├── ReduxNavigation.js │ └── Styles │ │ └── NavigationStyles.js ├── Redux │ ├── CreateStore.js │ ├── GithubRedux.js │ ├── NavigationRedux.js │ ├── ScreenTrackingMiddleware.js │ ├── SearchRedux.js │ ├── StartupRedux.js │ └── index.js ├── Sagas │ ├── GithubSagas.js │ ├── StartupSagas.js │ └── index.js ├── Services │ ├── Api.js │ ├── ExamplesRegistry.js │ ├── FixtureApi.js │ ├── ImmutablePersistenceTransform.js │ ├── NavigationService.js │ └── Rehydration.js ├── Themes │ ├── ApplicationStyles.js │ ├── Colors.js │ ├── Fonts.js │ ├── Images.js │ ├── Metrics.js │ ├── Namespace.js │ ├── Osmicsx.js │ ├── README.md │ ├── Svg.js │ └── index.js └── Transforms │ ├── ConvertFromKelvin.js │ └── README.md ├── LICENSE ├── README.md ├── android ├── app │ ├── BUCK │ ├── build.gradle │ ├── build_defs.bzl │ ├── debug.keystore │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── fonts │ │ │ ├── AntDesign.ttf │ │ │ ├── Entypo.ttf │ │ │ ├── EvilIcons.ttf │ │ │ ├── Feather.ttf │ │ │ ├── FontAwesome.ttf │ │ │ ├── FontAwesome5_Brands.ttf │ │ │ ├── FontAwesome5_Regular.ttf │ │ │ ├── FontAwesome5_Solid.ttf │ │ │ ├── Foundation.ttf │ │ │ ├── Ionicons.ttf │ │ │ ├── Lato-Black.ttf │ │ │ ├── Lato-Bold.ttf │ │ │ ├── Lato-Regular.ttf │ │ │ ├── MaterialCommunityIcons.ttf │ │ │ ├── MaterialIcons.ttf │ │ │ ├── Octicons.ttf │ │ │ ├── SimpleLineIcons.ttf │ │ │ └── Zocial.ttf │ │ ├── java │ │ └── com │ │ │ └── gdoctor │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.java │ │ └── res │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── app.json ├── assets └── fonts │ ├── Lato-Black.ttf │ ├── Lato-Bold.ttf │ └── Lato-Regular.ttf ├── babel.config.js ├── ignite ├── ignite.json └── plugins │ └── .gitkeep ├── index.js ├── ios ├── Podfile ├── Podfile.lock ├── gDoctor-tvOS │ └── Info.plist ├── gDoctor-tvOSTests │ └── Info.plist ├── gDoctor.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── gDoctor-tvOS.xcscheme │ │ └── gDoctor.xcscheme ├── gDoctor.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── gDoctor │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Info.plist │ └── main.m └── gDoctorTests │ ├── Info.plist │ └── gDoctorTests.m ├── metro.config.js ├── package.json ├── react-native.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["module:metro-react-native-babel-preset"], 3 | "env": { 4 | "production": { 5 | "plugins": ["ignite-ignore-reactotron"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | 15 | 16 | [*.gradle] 17 | indent_size = 4 -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # This is an example where you can store your environment variables. Copy this file to .env 2 | # Now your app will have access to the variables added below. 3 | # For more instructions see section "Secrets" in README.md 4 | 5 | API_URL=https://myapi.com 6 | GOOGLE_MAPS_API_KEY=abcdefgh 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | # Xcode 5 | # 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | *.xcuserstate 21 | 22 | # Android/IntelliJ 23 | # 24 | build/ 25 | .idea 26 | .gradle 27 | local.properties 28 | *.iml 29 | 30 | # node.js 31 | # 32 | node_modules/ 33 | npm-debug.log 34 | yarn-error.log 35 | 36 | # BUCK 37 | buck-out/ 38 | \.buckd/ 39 | *.keystore 40 | !debug.keystore 41 | 42 | # fastlane 43 | # 44 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 45 | # screenshots whenever they are needed. 46 | # For more information about the recommended setup visit: 47 | # https://docs.fastlane.tools/best-practices/source-control/ 48 | 49 | */fastlane/report.xml 50 | */fastlane/Preview.html 51 | */fastlane/screenshots 52 | 53 | # Bundle artifact 54 | *.jsbundle 55 | 56 | # CocoaPods 57 | /ios/Pods/ 58 | 59 | # Misc 60 | # 61 | .env 62 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /App/Components/Styles/TopDoctorStyle.js: -------------------------------------------------------------------------------- 1 | import { connect } from '../../Themes/Osmicsx' 2 | 3 | export default connect({ 4 | headerContainer: [ 5 | "full", 6 | "row", 7 | "items-end", 8 | "justify-between", 9 | "mb-5", 10 | "mt-5" 11 | ], 12 | headerTitle: [ 13 | "text-lg", 14 | "text-dark", 15 | "font-bold" 16 | ], 17 | headerMore: [ 18 | "text-xs", 19 | "text-blue-native", 20 | "font-regular" 21 | ], 22 | card: [ 23 | "flex", 24 | "row", 25 | "mb-3" 26 | ], 27 | cardFooter: [ 28 | "row", 29 | "items-center", 30 | "justify-between" 31 | ], 32 | thumb: [ 33 | "w-88", 34 | "h-80", 35 | "rounded-lg", 36 | "mr-3" 37 | ], 38 | name: [ 39 | "text-base", 40 | "text-dark", 41 | "font-bold", 42 | "mt-1", 43 | "mb-1" 44 | ], 45 | infoWrapper: [ 46 | "full", 47 | "row", 48 | "items-center", 49 | "mb-3" 50 | ], 51 | info: [ 52 | "text-muted", 53 | "font-regular", 54 | "font-sm" 55 | ], 56 | infoDot: [ 57 | "small-dot", 58 | "bg-muted", 59 | "mx-2", 60 | "rounded-full" 61 | ], 62 | totalReview: [ 63 | "text-xxs", 64 | "text-muted", 65 | "font-regular", 66 | "ml-2" 67 | ], 68 | status: [ 69 | "w-56", 70 | "h-24", 71 | "rounded", 72 | "items-center", 73 | "justify-center" 74 | ], 75 | statusLabel: [ 76 | "font-regular", 77 | "text-sm" 78 | ], 79 | reviewWrapper: [ 80 | "row", 81 | "items-center" 82 | ] 83 | }) 84 | -------------------------------------------------------------------------------- /App/Components/TopDoctor.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { FlatList, TouchableOpacity, View, Image, Text } from 'react-native' 3 | import NavigationService from '../Services/NavigationService' 4 | 5 | import styles from './Styles/TopDoctorStyle' 6 | import { apply } from '../Themes/Osmicsx' 7 | import { 8 | IconStar5 9 | } from '../Themes/Svg' 10 | 11 | const topDoctor = props => { 12 | const { ...restProps } = props 13 | 14 | return ( 15 | ( 18 | 19 | Top Doctors 20 | 21 | View all 22 | 23 | )} 24 | renderItem={({ item, index }) => ( 25 | NavigationService.navigate("DoctorDetail", {data:item})}> 29 | 30 | 31 | 32 | {item.name} 33 | 34 | {item.role} 35 | 36 | {item.hospital} 37 | 38 | 39 | 40 | 41 | 42 | ({item.totalReview}) 43 | 44 | 45 | 49 | {item.open ? "Open" : "Close"} 53 | 54 | 55 | 56 | 57 | )} 58 | /> 59 | ) 60 | } 61 | 62 | export default topDoctor 63 | -------------------------------------------------------------------------------- /App/Config/AppConfig.js: -------------------------------------------------------------------------------- 1 | // Simple React Native specific changes 2 | 3 | import '../I18n/I18n' 4 | 5 | export default { 6 | // font scaling override - RN default is on 7 | allowTextFontScaling: true 8 | } 9 | -------------------------------------------------------------------------------- /App/Config/DebugConfig.js: -------------------------------------------------------------------------------- 1 | export default { 2 | useFixtures: false, 3 | ezLogin: false, 4 | yellowBox: __DEV__, 5 | reduxLogging: __DEV__, 6 | includeExamples: __DEV__, 7 | useReactotron: __DEV__ 8 | } 9 | -------------------------------------------------------------------------------- /App/Config/README.md: -------------------------------------------------------------------------------- 1 | ### Config Folder 2 | All application specific configuration falls in this folder. 3 | 4 | `AppConfig.js` - production values. 5 | `DebugConfig.js` - development-wide globals. 6 | `ReactotronConfig.js` - Reactotron client settings. 7 | `ReduxPersist.js` - rehydrate Redux state. 8 | -------------------------------------------------------------------------------- /App/Config/ReactotronConfig.js: -------------------------------------------------------------------------------- 1 | import Config from '../Config/DebugConfig' 2 | import Immutable from 'seamless-immutable' 3 | import Reactotron from 'reactotron-react-native' 4 | import { reactotronRedux as reduxPlugin } from 'reactotron-redux' 5 | import sagaPlugin from 'reactotron-redux-saga' 6 | 7 | const reactotron = Reactotron 8 | .configure({ name: 'Ignite App' }) 9 | .useReactNative() 10 | .use(reduxPlugin({ onRestore: Immutable })) 11 | .use(sagaPlugin()) 12 | 13 | if (Config.useReactotron) { 14 | // https://github.com/infinitered/reactotron for more options! 15 | 16 | reactotron.connect() 17 | 18 | // Let's clear Reactotron on every time we load the app 19 | reactotron.clear() 20 | 21 | // Totally hacky, but this allows you to not both importing reactotron-react-native 22 | // on every file. This is just DEV mode, so no big deal. 23 | } 24 | export default reactotron 25 | console.tron = reactotron 26 | -------------------------------------------------------------------------------- /App/Config/ReduxPersist.js: -------------------------------------------------------------------------------- 1 | import immutablePersistenceTransform from '../Services/ImmutablePersistenceTransform' 2 | import { AsyncStorage } from 'react-native' 3 | 4 | // More info here: https://shift.infinite.red/shipping-persistant-reducers-7341691232b1 5 | const REDUX_PERSIST = { 6 | active: true, 7 | reducerVersion: '1.0', 8 | storeConfig: { 9 | key: 'primary', 10 | storage: AsyncStorage, 11 | // Reducer keys that you do NOT want stored to persistence here. 12 | blacklist: ['login', 'search', 'nav'], 13 | // Optionally, just specify the keys you DO want stored to persistence. 14 | // An empty array means 'don't store any reducers' -> infinitered/ignite#409 15 | // whitelist: [], 16 | transforms: [immutablePersistenceTransform] 17 | } 18 | } 19 | 20 | export default REDUX_PERSIST 21 | -------------------------------------------------------------------------------- /App/Config/index.js: -------------------------------------------------------------------------------- 1 | import DebugConfig from './DebugConfig' 2 | import AppConfig from './AppConfig' // eslint-disable-line no-unused-vars 3 | 4 | if (__DEV__) { 5 | // If ReactNative's yellow box warnings are too much, it is possible to turn 6 | // it off, but the healthier approach is to fix the warnings. =) 7 | console.disableYellowBox = !DebugConfig.yellowBox 8 | } 9 | -------------------------------------------------------------------------------- /App/Containers/AccountScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { ScrollView, View, Text } from 'react-native' 3 | import { connect } from 'react-redux' 4 | 5 | // Styles 6 | import styles from './Styles/AccountScreenStyle' 7 | 8 | class AccountScreen extends Component { 9 | static navigationOptions = ({ navigation }) => ({ 10 | headerShown: false 11 | }) 12 | 13 | constructor (props) { 14 | super(props) 15 | this.state = {} 16 | } 17 | 18 | render () { 19 | return ( 20 | 21 | 22 | 23 | ) 24 | } 25 | } 26 | 27 | const mapStateToProps = (state) => { 28 | return { 29 | } 30 | } 31 | 32 | const mapDispatchToProps = (dispatch) => { 33 | return { 34 | } 35 | } 36 | 37 | export default connect(mapStateToProps, mapDispatchToProps)(AccountScreen) 38 | -------------------------------------------------------------------------------- /App/Containers/App.js: -------------------------------------------------------------------------------- 1 | import '../Config' 2 | import DebugConfig from '../Config/DebugConfig' 3 | import React, { Component } from 'react' 4 | import { Provider } from 'react-redux' 5 | import RootContainer from './RootContainer' 6 | import createStore from '../Redux' 7 | import 'react-native-gesture-handler' 8 | import { enableScreens } from 'react-native-screens' 9 | 10 | enableScreens() 11 | 12 | // create our store 13 | const store = createStore() 14 | 15 | /** 16 | * Provides an entry point into our application. Both index.ios.js and index.android.js 17 | * call this component first. 18 | * 19 | * We create our Redux store here, put it into a provider and then bring in our 20 | * RootContainer. 21 | * 22 | * We separate like this to play nice with React Native's hot reloading. 23 | */ 24 | class App extends Component { 25 | render () { 26 | return ( 27 | 28 | 29 | 30 | ) 31 | } 32 | } 33 | 34 | // allow reactotron overlay for fast design in dev mode 35 | export default DebugConfig.useReactotron 36 | ? console.tron.overlay(App) 37 | : App 38 | -------------------------------------------------------------------------------- /App/Containers/DoctorDetailScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | StatusBar, 4 | SafeAreaView, 5 | ScrollView, 6 | Text, 7 | View, 8 | ImageBackground, 9 | TouchableOpacity, 10 | TouchableNativeFeedback 11 | } from 'react-native' 12 | import { connect } from 'react-redux' 13 | 14 | import { 15 | IconBack, 16 | IconBookmark, 17 | IconChat 18 | } from '../Themes/Svg' 19 | 20 | // Styles 21 | import styles from './Styles/DoctorDetailScreenStyle' 22 | import { Images } from '../Themes' 23 | import { apply } from '../Themes/Osmicsx' 24 | import { colors } from 'osmicsx' 25 | 26 | class DoctorDetailScreen extends Component { 27 | constructor (props) { 28 | super(props) 29 | 30 | this.state = { 31 | 32 | } 33 | } 34 | 35 | render () { 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | 43 | this.props.navigation.goBack()}> 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | dr. Gilang Segara Bening 55 | 56 | Heart 57 | 58 | Persahabatan Hospital 59 | 60 | 61 | dr. Gilang is one of the best doctors in the Persahabatan Hospital. He has saved more than 1000 patients in the past 3 years. He has also received many awards from domestic and abroad as the best doctors. He is available on a private or schedule. 62 | 63 | 64 | 65 | Experience 66 | 3 yr 67 | 68 | 69 | 70 | Patient 71 | 1221 ps 72 | 73 | 74 | 75 | Rating 76 | 5.0 77 | 78 | 79 | 80 | 81 | 82 | 83 | alert("hello!")} 85 | background={TouchableNativeFeedback.Ripple("rgba(255,255,255, 0.25)")}> 86 | 87 | 88 | 89 | 90 | 91 | alert("hello!")} 93 | background={TouchableNativeFeedback.Ripple("rgba(255,255,255, 0.25)")}> 94 | 95 | Make an Appointment 96 | 97 | 98 | 99 | 100 | ) 101 | } 102 | } 103 | 104 | const mapStateToProps = (state) => { 105 | return { 106 | } 107 | } 108 | 109 | const mapDispatchToProps = (dispatch) => { 110 | return { 111 | } 112 | } 113 | 114 | export default connect(mapStateToProps, mapDispatchToProps)(DoctorDetailScreen) 115 | -------------------------------------------------------------------------------- /App/Containers/HomeScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { StatusBar, SafeAreaView, ScrollView, View, Text, FlatList, TouchableOpacity } from 'react-native' 3 | import { connect } from 'react-redux' 4 | 5 | import { 6 | IconSearch, 7 | IconBandage, 8 | IconCare, 9 | IconClinic, 10 | IconHeart, 11 | IconMedicine, 12 | IconStethoscope, 13 | IconSyringe, 14 | IconTeeth, 15 | } from '../Themes/Svg' 16 | 17 | // Styles 18 | import styles from './Styles/HomeScreenStyle' 19 | import { Images } from '../Themes' 20 | import { colors } from 'osmicsx' 21 | import { apply } from '../Themes/Osmicsx' 22 | 23 | // Import Components 24 | import TopDoctor from '../Components/TopDoctor' 25 | 26 | const formatData = (data, numColumns) => { 27 | const numberOfFullRows = Math.floor(data.length / numColumns); 28 | let newArr = data 29 | 30 | let numberOfElementsLastRow = data.length - (numberOfFullRows * numColumns); 31 | while (numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0) { 32 | newArr.push({ key: `blank-${numberOfElementsLastRow}`, empty: true }); 33 | numberOfElementsLastRow = numberOfElementsLastRow + 1; 34 | } 35 | 36 | return newArr; 37 | }; 38 | 39 | class HomeScreen extends Component { 40 | static navigationOptions = ({ navigation }) => ({ 41 | headerShown: false 42 | }) 43 | 44 | constructor (props) { 45 | super(props) 46 | 47 | this.state = { 48 | categories: [{ 49 | name: "Consultation", 50 | color: "bg-blue-native", 51 | icon: 52 | }, { 53 | name: "Dental", 54 | color: "bg-purple-native", 55 | icon: 56 | }, { 57 | name: "Heart", 58 | color: "bg-orange-native", 59 | icon: 60 | }, { 61 | name: "Hospitals", 62 | color: "bg-yellow-native", 63 | icon: 64 | }, { 65 | name: "Medicines", 66 | color: "bg-green-native", 67 | icon: 68 | }, { 69 | name: "Physician", 70 | color: "bg-cyan-native", 71 | icon: 72 | }, { 73 | name: "Skin", 74 | color: "bg-pink-native", 75 | icon: 76 | }, { 77 | name: "Surgeon", 78 | color: "bg-red-native", 79 | icon: 80 | }], 81 | 82 | topDoctors: [{ 83 | name: "dr. Gilang Segara Bening", 84 | thumb: Images.thumbDoctor1, 85 | role: "Heart", 86 | hospital: "Persahabatan Hospital", 87 | open: true, 88 | star: 5, 89 | totalReview: 1221 90 | }, { 91 | name: "dr. Shabil Chan", 92 | thumb: Images.thumbDoctor2, 93 | role: "Dental", 94 | hospital: "Columbia Asia Hospital", 95 | open: true, 96 | star: 5, 97 | totalReview: 964 98 | }, { 99 | name: "dr. Mustakim", 100 | thumb: Images.thumbDoctor3, 101 | role: "Eye", 102 | hospital: "Columbia Asia Hospital", 103 | open: false, 104 | star: 5, 105 | totalReview: 762 106 | }] 107 | } 108 | } 109 | 110 | render () { 111 | const { categories, topDoctors } = this.state 112 | 113 | return ( 114 | 115 | 116 | 117 | 118 | 119 | Find your doctor 120 | 121 | 122 | Search doctor, medicines etc 123 | 124 | 125 | 126 | 127 | 128 | index.toString()} 132 | numColumns={4} 133 | contentContainerStyle={apply(["pt-5", "items-center"])} 134 | renderItem={({ item, index }) => { 135 | if (item.empty) { 136 | return 137 | } else { 138 | return ( 139 | 142 | 143 | 144 | 145 | 146 | {item.icon} 147 | 148 | 149 | {item.name} 150 | 151 | 152 | ) 153 | } 154 | }} 155 | /> 156 | 157 | 158 | index.toString()} 162 | /> 163 | 164 | 165 | 166 | ) 167 | } 168 | } 169 | 170 | const mapStateToProps = (state) => { 171 | return { 172 | } 173 | } 174 | 175 | const mapDispatchToProps = (dispatch) => { 176 | return { 177 | } 178 | } 179 | 180 | export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen) 181 | -------------------------------------------------------------------------------- /App/Containers/InboxScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { ScrollView, View, Text } from 'react-native' 3 | import { connect } from 'react-redux' 4 | 5 | // Styles 6 | import styles from './Styles/InboxScreenStyle' 7 | 8 | class InboxScreen extends Component { 9 | static navigationOptions = ({ navigation }) => ({ 10 | headerShown: false 11 | }) 12 | 13 | constructor (props) { 14 | super(props) 15 | this.state = {} 16 | } 17 | 18 | render () { 19 | return ( 20 | 21 | ) 22 | } 23 | } 24 | 25 | const mapStateToProps = (state) => { 26 | return { 27 | } 28 | } 29 | 30 | const mapDispatchToProps = (dispatch) => { 31 | return { 32 | } 33 | } 34 | 35 | export default connect(mapStateToProps, mapDispatchToProps)(InboxScreen) 36 | -------------------------------------------------------------------------------- /App/Containers/README.md: -------------------------------------------------------------------------------- 1 | ### Containers Folder 2 | A container is what they call a "Smart Component" in Redux. It is a component 3 | which knows about Redux. They are usually used as "Screens". 4 | 5 | Also located in here are 2 special containers: `App.js` and `RootContainer.js`. 6 | 7 | `App.js` is first component loaded after `index.ios.js` or `index.android.js`. The purpose of this file is to setup Redux or any other non-visual "global" modules. Having Redux setup here helps with the hot-reloading process in React Native during development as it won't try to reload your sagas and reducers should your colors change (for example). 8 | 9 | `RootContainer.js` is the first visual component in the app. It is the ancestor of all other screens and components. 10 | 11 | You'll probably find you'll have great mileage in Ignite apps without even touching these 2 files. They, of course, belong to you, so when you're ready to add something non-visual like Firebase or something visual like an overlay, you have spots to place these additions. 12 | -------------------------------------------------------------------------------- /App/Containers/RootContainer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { View, StatusBar } from 'react-native' 3 | import ReduxNavigation from '../Navigation/ReduxNavigation' 4 | import { connect } from 'react-redux' 5 | import StartupActions from '../Redux/StartupRedux' 6 | import ReduxPersist from '../Config/ReduxPersist' 7 | 8 | // Styles 9 | import styles from './Styles/RootContainerStyles' 10 | 11 | class RootContainer extends Component { 12 | componentDidMount () { 13 | // if redux persist is not active fire startup action 14 | if (!ReduxPersist.active) { 15 | this.props.startup() 16 | } 17 | } 18 | 19 | render () { 20 | return ( 21 | 22 | 23 | 24 | 25 | ) 26 | } 27 | } 28 | 29 | // wraps dispatch to create nicer functions to call within our component 30 | const mapDispatchToProps = (dispatch) => ({ 31 | startup: () => dispatch(StartupActions.startup()) 32 | }) 33 | 34 | export default connect(null, mapDispatchToProps)(RootContainer) 35 | -------------------------------------------------------------------------------- /App/Containers/SplashScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { View, Text } from 'react-native' 3 | import { connect } from 'react-redux' 4 | 5 | // Styles 6 | import styles from './Styles/SplashScreenStyle' 7 | import { apply } from '../Themes/Osmicsx' 8 | 9 | class SplashScreen extends Component { 10 | constructor (props) { 11 | super(props) 12 | this.state = {} 13 | } 14 | 15 | componentDidMount() { 16 | setTimeout(() => { 17 | this.props.navigation.navigate("App") 18 | }, 1500) 19 | } 20 | 21 | render () { 22 | return ( 23 | 24 | This is Splash Sreen! 25 | 26 | ) 27 | } 28 | } 29 | 30 | const mapStateToProps = (state) => { 31 | return { 32 | } 33 | } 34 | 35 | const mapDispatchToProps = (dispatch) => { 36 | return { 37 | } 38 | } 39 | 40 | export default connect(mapStateToProps, mapDispatchToProps)(SplashScreen) 41 | -------------------------------------------------------------------------------- /App/Containers/Styles/AccountScreenStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Colors, Metrics } from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | container: { 6 | flex: 1, 7 | marginTop: Metrics.navBarHeight, 8 | backgroundColor: Colors.background 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /App/Containers/Styles/DoctorDetailScreenStyle.js: -------------------------------------------------------------------------------- 1 | import { connect } from '../../Themes/Osmicsx' 2 | 3 | export default connect({ 4 | imgHeader: [ 5 | "full", 6 | "h-s80", 7 | "pt-10" 8 | ], 9 | imgHeaderRow: [ 10 | "full", 11 | "row", 12 | "px-10", 13 | "items-center", 14 | "justify-between" 15 | ], 16 | content: [ 17 | "p-5", 18 | "pt-7" 19 | ], 20 | name: [ 21 | "text-dark", 22 | "font-bold", 23 | "text-3xl", 24 | "mb-3" 25 | ], 26 | infoWrapper: [ 27 | "full", 28 | "row", 29 | "items-center", 30 | "mb-5" 31 | ], 32 | info: [ 33 | "text-gray-dark", 34 | "font-regular", 35 | "font-sm" 36 | ], 37 | infoDot: [ 38 | "medium-dot", 39 | "bg-muted", 40 | "mx-2", 41 | "rounded-full" 42 | ], 43 | contentText: [ 44 | "text-regular", 45 | "text-sm", 46 | "text-dark", 47 | "flex-wrap", 48 | "leading-6" 49 | ], 50 | spec: [ 51 | "flex", 52 | "row", 53 | "items-center", 54 | "justify-center", 55 | "py-6" 56 | ], 57 | specCol: [ 58 | "items-center", 59 | "border-r", 60 | "border-muted", 61 | "px-7" 62 | ], 63 | specTitle: [ 64 | "font-bold", 65 | "text-dark", 66 | "text-base", 67 | "text-center", 68 | "mb-5" 69 | ], 70 | specContent: [ 71 | "font-regular", 72 | "text-blue-native", 73 | "text-2xl" 74 | ], 75 | specHelper: [ 76 | "font-regular", 77 | "text-muted", 78 | "text-sm" 79 | ], 80 | footer: [ 81 | "shadow-lg", 82 | "full", 83 | "absolute", 84 | "row", 85 | "items-center", 86 | "justify-between", 87 | "bottom-0", 88 | "z-20", 89 | "p-5" 90 | ], 91 | btnChat: [ 92 | "bg-blue-native", 93 | "w-56", 94 | "h-56", 95 | "items-center", 96 | "justify-center", 97 | "rounded-lg", 98 | "mr-4" 99 | ], 100 | btnAppointment: [ 101 | "bg-green-native", 102 | "flex", 103 | "h-56", 104 | "items-center", 105 | "justify-center", 106 | "rounded-lg" 107 | ], 108 | btnFooterLabel: [ 109 | "text-sm", 110 | "text-white", 111 | "font-regular", 112 | "text-center" 113 | ] 114 | }) 115 | -------------------------------------------------------------------------------- /App/Containers/Styles/HomeScreenStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Colors, Metrics } from '../../Themes/' 3 | import { scaleWidth } from 'osmicsx' 4 | import { connect } from '../../Themes/Osmicsx' 5 | 6 | export default connect({ 7 | container: [ 8 | "flex", 9 | "bg-white" 10 | ], 11 | greetings: [ 12 | "font-regular", 13 | "text-dark", 14 | "text-7xl", 15 | "mt-7" 16 | ], 17 | searchWrapper: [ 18 | "full", 19 | "row", 20 | "items-center", 21 | "justify-between", 22 | "bg-background", 23 | "rounded-lg", 24 | "p-3", 25 | "px-3", 26 | "mt-5", 27 | "mb-1" 28 | ], 29 | searchLabel: [ 30 | "font-regular", 31 | "text-gray-dark", 32 | "text-sm" 33 | ], 34 | categoryCard: [ 35 | "mb-5", 36 | "min-w-38", 37 | { marginLeft: scaleWidth(5) } 38 | ], 39 | categoryRectangle: [ 40 | "w-56", 41 | "h-56", 42 | "items-center", 43 | "justify-center", 44 | "rounded-lg" 45 | ], 46 | categoryWrapper: [ 47 | "items-center", 48 | "justify-center" 49 | ], 50 | categoryCircle: [ 51 | "bg-soft-white", 52 | "absolute", 53 | "rounded-full", 54 | "w-28", 55 | "h-28", 56 | "-top-3", 57 | "-left-3", 58 | "z-20" 59 | ], 60 | categoryLabel: [ 61 | "font-bold", 62 | "text-xs", 63 | "text-dark", 64 | "mt-3" 65 | ] 66 | }) 67 | -------------------------------------------------------------------------------- /App/Containers/Styles/InboxScreenStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Colors, Metrics } from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | container: { 6 | flex: 1, 7 | marginTop: Metrics.navBarHeight, 8 | backgroundColor: Colors.background 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /App/Containers/Styles/LaunchScreenStyles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Metrics, ApplicationStyles } from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | ...ApplicationStyles.screen, 6 | container: { 7 | paddingBottom: Metrics.baseMargin 8 | }, 9 | logo: { 10 | marginTop: Metrics.doubleSection, 11 | height: Metrics.images.logo, 12 | width: Metrics.images.logo, 13 | resizeMode: 'contain' 14 | }, 15 | centered: { 16 | alignItems: 'center' 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /App/Containers/Styles/README.md: -------------------------------------------------------------------------------- 1 | ### Styles Folder 2 | Container styles are separated from functionality. 3 | -------------------------------------------------------------------------------- /App/Containers/Styles/RootContainerStyles.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native' 2 | import {Fonts, Metrics, Colors} from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | applicationView: { 6 | flex: 1 7 | }, 8 | container: { 9 | flex: 1, 10 | justifyContent: 'center', 11 | backgroundColor: Colors.background 12 | }, 13 | welcome: { 14 | fontSize: 20, 15 | textAlign: 'center', 16 | fontFamily: Fonts.type.base, 17 | margin: Metrics.baseMargin 18 | }, 19 | myImage: { 20 | width: 200, 21 | height: 200, 22 | alignSelf: 'center' 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /App/Containers/Styles/SplashScreenStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Colors, Metrics } from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | container: { 6 | flex: 1, 7 | marginTop: Metrics.navBarHeight, 8 | backgroundColor: Colors.background 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /App/Fixtures/README.md: -------------------------------------------------------------------------------- 1 | ### Fixtures folder 2 | All key API responses are housed here. 3 | 4 | These API responses can be used for several reasons. _E.G._: 5 | * To bypass logins when building any screen of the application 6 | * To quickly test API parsing in unit tests 7 | * To separate Network from Data concerns while coding 8 | -------------------------------------------------------------------------------- /App/Fixtures/gantman.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_count": 7, 3 | "incomplete_results": false, 4 | "items": [ 5 | { 6 | "login": "GantMan", 7 | "id": 997157, 8 | "avatar_url": "https://avatars.githubusercontent.com/u/997157?v=3", 9 | "gravatar_id": "", 10 | "url": "https://api.github.com/users/GantMan", 11 | "html_url": "https://github.com/GantMan", 12 | "followers_url": "https://api.github.com/users/GantMan/followers", 13 | "following_url": "https://api.github.com/users/GantMan/following{/other_user}", 14 | "gists_url": "https://api.github.com/users/GantMan/gists{/gist_id}", 15 | "starred_url": "https://api.github.com/users/GantMan/starred{/owner}{/repo}", 16 | "subscriptions_url": "https://api.github.com/users/GantMan/subscriptions", 17 | "organizations_url": "https://api.github.com/users/GantMan/orgs", 18 | "repos_url": "https://api.github.com/users/GantMan/repos", 19 | "events_url": "https://api.github.com/users/GantMan/events{/privacy}", 20 | "received_events_url": "https://api.github.com/users/GantMan/received_events", 21 | "type": "User", 22 | "site_admin": false, 23 | "score": 122.12115 24 | }, 25 | { 26 | "login": "vlad-G", 27 | "id": 13520880, 28 | "avatar_url": "https://avatars.githubusercontent.com/u/13520880?v=3", 29 | "gravatar_id": "", 30 | "url": "https://api.github.com/users/vlad-G", 31 | "html_url": "https://github.com/vlad-G", 32 | "followers_url": "https://api.github.com/users/vlad-G/followers", 33 | "following_url": "https://api.github.com/users/vlad-G/following{/other_user}", 34 | "gists_url": "https://api.github.com/users/vlad-G/gists{/gist_id}", 35 | "starred_url": "https://api.github.com/users/vlad-G/starred{/owner}{/repo}", 36 | "subscriptions_url": "https://api.github.com/users/vlad-G/subscriptions", 37 | "organizations_url": "https://api.github.com/users/vlad-G/orgs", 38 | "repos_url": "https://api.github.com/users/vlad-G/repos", 39 | "events_url": "https://api.github.com/users/vlad-G/events{/privacy}", 40 | "received_events_url": "https://api.github.com/users/vlad-G/received_events", 41 | "type": "User", 42 | "site_admin": false, 43 | "score": 12.69848 44 | }, 45 | { 46 | "login": "gantmani", 47 | "id": 3034094, 48 | "avatar_url": "https://avatars.githubusercontent.com/u/3034094?v=3", 49 | "gravatar_id": "", 50 | "url": "https://api.github.com/users/gantmani", 51 | "html_url": "https://github.com/gantmani", 52 | "followers_url": "https://api.github.com/users/gantmani/followers", 53 | "following_url": "https://api.github.com/users/gantmani/following{/other_user}", 54 | "gists_url": "https://api.github.com/users/gantmani/gists{/gist_id}", 55 | "starred_url": "https://api.github.com/users/gantmani/starred{/owner}{/repo}", 56 | "subscriptions_url": "https://api.github.com/users/gantmani/subscriptions", 57 | "organizations_url": "https://api.github.com/users/gantmani/orgs", 58 | "repos_url": "https://api.github.com/users/gantmani/repos", 59 | "events_url": "https://api.github.com/users/gantmani/events{/privacy}", 60 | "received_events_url": "https://api.github.com/users/gantmani/received_events", 61 | "type": "User", 62 | "site_admin": false, 63 | "score": 11.641713 64 | }, 65 | { 66 | "login": "sgantman", 67 | "id": 5911526, 68 | "avatar_url": "https://avatars.githubusercontent.com/u/5911526?v=3", 69 | "gravatar_id": "", 70 | "url": "https://api.github.com/users/sgantman", 71 | "html_url": "https://github.com/sgantman", 72 | "followers_url": "https://api.github.com/users/sgantman/followers", 73 | "following_url": "https://api.github.com/users/sgantman/following{/other_user}", 74 | "gists_url": "https://api.github.com/users/sgantman/gists{/gist_id}", 75 | "starred_url": "https://api.github.com/users/sgantman/starred{/owner}{/repo}", 76 | "subscriptions_url": "https://api.github.com/users/sgantman/subscriptions", 77 | "organizations_url": "https://api.github.com/users/sgantman/orgs", 78 | "repos_url": "https://api.github.com/users/sgantman/repos", 79 | "events_url": "https://api.github.com/users/sgantman/events{/privacy}", 80 | "received_events_url": "https://api.github.com/users/sgantman/received_events", 81 | "type": "User", 82 | "site_admin": false, 83 | "score": 7.926345 84 | }, 85 | { 86 | "login": "michaelgantman", 87 | "id": 16693070, 88 | "avatar_url": "https://avatars.githubusercontent.com/u/16693070?v=3", 89 | "gravatar_id": "", 90 | "url": "https://api.github.com/users/michaelgantman", 91 | "html_url": "https://github.com/michaelgantman", 92 | "followers_url": "https://api.github.com/users/michaelgantman/followers", 93 | "following_url": "https://api.github.com/users/michaelgantman/following{/other_user}", 94 | "gists_url": "https://api.github.com/users/michaelgantman/gists{/gist_id}", 95 | "starred_url": "https://api.github.com/users/michaelgantman/starred{/owner}{/repo}", 96 | "subscriptions_url": "https://api.github.com/users/michaelgantman/subscriptions", 97 | "organizations_url": "https://api.github.com/users/michaelgantman/orgs", 98 | "repos_url": "https://api.github.com/users/michaelgantman/repos", 99 | "events_url": "https://api.github.com/users/michaelgantman/events{/privacy}", 100 | "received_events_url": "https://api.github.com/users/michaelgantman/received_events", 101 | "type": "User", 102 | "site_admin": false, 103 | "score": 7.926345 104 | }, 105 | { 106 | "login": "gantmanis", 107 | "id": 19141249, 108 | "avatar_url": "https://avatars.githubusercontent.com/u/19141249?v=3", 109 | "gravatar_id": "", 110 | "url": "https://api.github.com/users/gantmanis", 111 | "html_url": "https://github.com/gantmanis", 112 | "followers_url": "https://api.github.com/users/gantmanis/followers", 113 | "following_url": "https://api.github.com/users/gantmanis/following{/other_user}", 114 | "gists_url": "https://api.github.com/users/gantmanis/gists{/gist_id}", 115 | "starred_url": "https://api.github.com/users/gantmanis/starred{/owner}{/repo}", 116 | "subscriptions_url": "https://api.github.com/users/gantmanis/subscriptions", 117 | "organizations_url": "https://api.github.com/users/gantmanis/orgs", 118 | "repos_url": "https://api.github.com/users/gantmanis/repos", 119 | "events_url": "https://api.github.com/users/gantmanis/events{/privacy}", 120 | "received_events_url": "https://api.github.com/users/gantmanis/received_events", 121 | "type": "User", 122 | "site_admin": false, 123 | "score": 7.8813524 124 | }, 125 | { 126 | "login": "Gantman2014", 127 | "id": 7669410, 128 | "avatar_url": "https://avatars.githubusercontent.com/u/7669410?v=3", 129 | "gravatar_id": "", 130 | "url": "https://api.github.com/users/Gantman2014", 131 | "html_url": "https://github.com/Gantman2014", 132 | "followers_url": "https://api.github.com/users/Gantman2014/followers", 133 | "following_url": "https://api.github.com/users/Gantman2014/following{/other_user}", 134 | "gists_url": "https://api.github.com/users/Gantman2014/gists{/gist_id}", 135 | "starred_url": "https://api.github.com/users/Gantman2014/starred{/owner}{/repo}", 136 | "subscriptions_url": "https://api.github.com/users/Gantman2014/subscriptions", 137 | "organizations_url": "https://api.github.com/users/Gantman2014/orgs", 138 | "repos_url": "https://api.github.com/users/Gantman2014/repos", 139 | "events_url": "https://api.github.com/users/Gantman2014/events{/privacy}", 140 | "received_events_url": "https://api.github.com/users/Gantman2014/received_events", 141 | "type": "User", 142 | "site_admin": false, 143 | "score": 7.8813524 144 | } 145 | ] 146 | } -------------------------------------------------------------------------------- /App/Fixtures/rateLimit.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": { 3 | "core": { 4 | "limit": 60, 5 | "remaining": 42, 6 | "reset": 1488126913 7 | }, 8 | "search": { 9 | "limit": 10, 10 | "remaining": 9, 11 | "reset": 1488126003 12 | } 13 | }, 14 | "rate": { 15 | "limit": 60, 16 | "remaining": 42, 17 | "reset": 1488126913 18 | } 19 | } -------------------------------------------------------------------------------- /App/Fixtures/root.json: -------------------------------------------------------------------------------- 1 | { 2 | "current_user_url": "https://api.github.com/user", 3 | "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}", 4 | "authorizations_url": "https://api.github.com/authorizations", 5 | "code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}", 6 | "commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}", 7 | "emails_url": "https://api.github.com/user/emails", 8 | "emojis_url": "https://api.github.com/emojis", 9 | "events_url": "https://api.github.com/events", 10 | "feeds_url": "https://api.github.com/feeds", 11 | "followers_url": "https://api.github.com/user/followers", 12 | "following_url": "https://api.github.com/user/following{/target}", 13 | "gists_url": "https://api.github.com/gists{/gist_id}", 14 | "hub_url": "https://api.github.com/hub", 15 | "issue_search_url": "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}", 16 | "issues_url": "https://api.github.com/issues", 17 | "keys_url": "https://api.github.com/user/keys", 18 | "notifications_url": "https://api.github.com/notifications", 19 | "organization_repositories_url": "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}", 20 | "organization_url": "https://api.github.com/orgs/{org}", 21 | "public_gists_url": "https://api.github.com/gists/public", 22 | "rate_limit_url": "https://api.github.com/rate_limit", 23 | "repository_url": "https://api.github.com/repos/{owner}/{repo}", 24 | "repository_search_url": "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}", 25 | "current_user_repositories_url": "https://api.github.com/user/repos{?type,page,per_page,sort}", 26 | "starred_url": "https://api.github.com/user/starred{/owner}{/repo}", 27 | "starred_gists_url": "https://api.github.com/gists/starred", 28 | "team_url": "https://api.github.com/teams", 29 | "user_url": "https://api.github.com/users/{user}", 30 | "user_organizations_url": "https://api.github.com/user/orgs", 31 | "user_repositories_url": "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}", 32 | "user_search_url": "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}" 33 | } -------------------------------------------------------------------------------- /App/Fixtures/skellock.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_count": 1, 3 | "incomplete_results": false, 4 | "items": [ 5 | { 6 | "login": "skellock", 7 | "id": 68273, 8 | "avatar_url": "https://avatars.githubusercontent.com/u/68273?v=3", 9 | "gravatar_id": "", 10 | "url": "https://api.github.com/users/skellock", 11 | "html_url": "https://github.com/skellock", 12 | "followers_url": "https://api.github.com/users/skellock/followers", 13 | "following_url": "https://api.github.com/users/skellock/following{/other_user}", 14 | "gists_url": "https://api.github.com/users/skellock/gists{/gist_id}", 15 | "starred_url": "https://api.github.com/users/skellock/starred{/owner}{/repo}", 16 | "subscriptions_url": "https://api.github.com/users/skellock/subscriptions", 17 | "organizations_url": "https://api.github.com/users/skellock/orgs", 18 | "repos_url": "https://api.github.com/users/skellock/repos", 19 | "events_url": "https://api.github.com/users/skellock/events{/privacy}", 20 | "received_events_url": "https://api.github.com/users/skellock/received_events", 21 | "type": "User", 22 | "site_admin": false, 23 | "score": 107.22611 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /App/I18n/I18n.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import I18n from 'react-native-i18n' 4 | 5 | // Enable fallbacks if you want `en-US` and `en-GB` to fallback to `en` 6 | I18n.fallbacks = true 7 | 8 | // English language is the main language for fall back: 9 | I18n.translations = { 10 | en: require('./languages/english.json') 11 | } 12 | 13 | let languageCode = I18n.locale.substr(0, 2) 14 | 15 | // All other translations for the app goes to the respective language file: 16 | switch (languageCode) { 17 | case 'af': 18 | I18n.translations.af = require('./languages/af.json') 19 | break 20 | case 'am': 21 | I18n.translations.am = require('./languages/am.json') 22 | break 23 | case 'ar': 24 | I18n.translations.ar = require('./languages/ar.json') 25 | break 26 | case 'bg': 27 | I18n.translations.bg = require('./languages/bg.json') 28 | break 29 | case 'ca': 30 | I18n.translations.ca = require('./languages/ca.json') 31 | break 32 | case 'cs': 33 | I18n.translations.cs = require('./languages/cs.json') 34 | break 35 | case 'da': 36 | I18n.translations.da = require('./languages/da.json') 37 | break 38 | case 'de': 39 | I18n.translations.de = require('./languages/de.json') 40 | break 41 | case 'el': 42 | I18n.translations.el = require('./languages/el.json') 43 | break 44 | case 'es': 45 | I18n.translations.es = require('./languages/es.json') 46 | break 47 | case 'et': 48 | I18n.translations.et = require('./languages/et.json') 49 | break 50 | case 'fi': 51 | let addCode = I18n.locale.substr(0, 3) 52 | if (addCode === 'fil') { 53 | I18n.translations.fil = require('./languages/fil.json') 54 | } else { 55 | I18n.translations.fi = require('./languages/fi.json') 56 | } 57 | break 58 | case 'fr': 59 | I18n.translations.fr = require('./languages/fr.json') 60 | break 61 | case 'he': 62 | I18n.translations.he = require('./languages/he.json') 63 | break 64 | case 'hi': 65 | I18n.translations.hi = require('./languages/hi.json') 66 | break 67 | case 'hr': 68 | I18n.translations.hr = require('./languages/hr.json') 69 | break 70 | case 'hu': 71 | I18n.translations.hu = require('./languages/hu.json') 72 | break 73 | case 'id': 74 | I18n.translations.id = require('./languages/id.json') 75 | break 76 | case 'it': 77 | I18n.translations.it = require('./languages/it.json') 78 | break 79 | case 'ja': 80 | I18n.translations.ja = require('./languages/ja.json') 81 | break 82 | case 'ko': 83 | I18n.translations.ko = require('./languages/ko.json') 84 | break 85 | case 'lt': 86 | I18n.translations.lt = require('./languages/lt.json') 87 | break 88 | case 'lv': 89 | I18n.translations.lv = require('./languages/lv.json') 90 | break 91 | case 'ms': 92 | I18n.translations.ms = require('./languages/ms.json') 93 | break 94 | case 'nb': 95 | I18n.translations.nb = require('./languages/nb.json') 96 | break 97 | case 'nl': 98 | I18n.translations.nl = require('./languages/nl.json') 99 | break 100 | case 'no': 101 | I18n.translations.no = require('./languages/no.json') 102 | break 103 | case 'pl': 104 | I18n.translations.pl = require('./languages/pl.json') 105 | break 106 | case 'pt': 107 | I18n.translations.pt = require('./languages/pt.json') 108 | break 109 | case 'ro': 110 | I18n.translations.ro = require('./languages/ro.json') 111 | break 112 | case 'ru': 113 | I18n.translations.ru = require('./languages/ru.json') 114 | break 115 | case 'sl': 116 | I18n.translations.sl = require('./languages/sl.json') 117 | break 118 | case 'sk': 119 | I18n.translations.sk = require('./languages/sk.json') 120 | break 121 | case 'sr': 122 | I18n.translations.sr = require('./languages/sr.json') 123 | break 124 | case 'sv': 125 | I18n.translations.sv = require('./languages/sv.json') 126 | break 127 | case 'sw': 128 | I18n.translations.sw = require('./languages/sw.json') 129 | break 130 | case 'th': 131 | I18n.translations.th = require('./languages/th.json') 132 | break 133 | case 'tr': 134 | I18n.translations.tr = require('./languages/tr.json') 135 | break 136 | case 'uk': 137 | I18n.translations.uk = require('./languages/uk.json') 138 | break 139 | case 'vi': 140 | I18n.translations.vi = require('./languages/vi.json') 141 | break 142 | case 'zh': 143 | I18n.translations.zh = require('./languages/zh.json') 144 | break 145 | case 'zu': 146 | I18n.translations.zu = require('./languages/zu.json') 147 | break 148 | } 149 | -------------------------------------------------------------------------------- /App/I18n/README.md: -------------------------------------------------------------------------------- 1 | # Idea 2 | 3 | Shipping app with localization for all available languages. The main idea here is to minimize the memory required of other languages that is not used by the platform. 4 | 5 | For example if the phone is localized in French, then this will only load the French and English translations into memory and ignore the 30+ other languages available. 6 | 7 | English translation is set as default fallback in case some translations are not available in the chosen language. 8 | 9 | # Installation 10 | 11 | Run `ignite add i18n`. 12 | 13 | # Usage 14 | 15 | TODO: Real usage example. 16 | 17 | import I18n from 'App/I18n'; 18 | 19 | render() { 20 | ... 21 | { I18n.t('welcome') } 22 | ... 23 | } 24 | -------------------------------------------------------------------------------- /App/I18n/index.js: -------------------------------------------------------------------------------- 1 | import I18n from 'react-native-i18n' 2 | 3 | const missingTranslationRegex = /^\[missing ".*" translation\]$/ 4 | 5 | // This function is a wrapper to avoid exception wich leads in a crash 6 | const translateOrFallback = (initialMsg, options) => { 7 | // We tried to translate something else than a string 8 | // The native I18n function will simply crash instead of rejecting the attempt with an error message 9 | if (typeof initialMsg !== 'string') { 10 | __DEV__ && 11 | console.log( 12 | `I18n: you must give a string to translate instead of "${typeof initialMsg}"` 13 | ) 14 | 15 | return '' // We don't return any message as we don't know what to send 16 | } 17 | 18 | let localMsg = I18n.t(initialMsg, options) 19 | 20 | // The translation does not exist, the default message is not very sexy 21 | // Instead we return the message we tried to translate 22 | if (missingTranslationRegex.test(localMsg)) { 23 | __DEV__ && 24 | console.log( 25 | `translation "${initialMsg}" does not exists in translations files` 26 | ) 27 | 28 | return initialMsg 29 | } 30 | 31 | return localMsg 32 | } 33 | 34 | export default { 35 | ...I18n, 36 | t: translateOrFallback 37 | } 38 | -------------------------------------------------------------------------------- /App/I18n/languages/af.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/am.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ar.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/bg.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ca.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/cs.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/da.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/de.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/el.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/english.json: -------------------------------------------------------------------------------- 1 | { 2 | "signIn": "Sign In", 3 | "logOut": "Log Out", 4 | "loginLogoutExampleTitle": "Login/Logout Redux + Sagas Example", 5 | "progressiveImageComponent": "Progressive Image Component", 6 | "api": "API", 7 | "locale": "I18n Locale", 8 | "rnVectorIcons": "RN Vector Icons", 9 | "loginWithFacebook": "Login with Facebook", 10 | "rni18n": "RN i18n", 11 | "igniteGenerated": "Ignite Generate Screens", 12 | "forgotPassword": "Forgot Password", 13 | "username": "Username", 14 | "password": "Password", 15 | "cancel": "Cancel", 16 | "welcome": "Welcome", 17 | "login": "Login", 18 | "tempIndicator": "F", 19 | "componentExamples": "Component Examples", 20 | "usageExamples": "Usage Examples", 21 | "apiTesting": "API Testing", 22 | "themeSettings": "Theme Settings", 23 | "deviceDetails": "Device Details", 24 | "noItems": "No Items", 25 | "search": "Search" 26 | } 27 | -------------------------------------------------------------------------------- /App/I18n/languages/es.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/et.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/fi.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/fil.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "signIn": "Se connecter", 3 | "logOut": "Se déconnecter", 4 | "loginLogoutExampleTitle": "Connexion / Déconnexion Redux + Sagas Exemple", 5 | "progressiveImageComponent": "Composant Image Progressive", 6 | "api": "Mon Dieu! Une API pour vous!", 7 | "locale": "I18n Paramètres régionaux", 8 | "rnVectorIcons": "RN icônes vectorielles", 9 | "loginWithFacebook": "Se connecter avec Facebook", 10 | "rni18n": "RN i18n", 11 | "igniteGenerated": "Ignite Générer des Écrans", 12 | "forgotPassword": "Mot de passe oublié", 13 | "username": "Nom d'utilisateur", 14 | "password": "Mot de passe", 15 | "cancel": "Annuler", 16 | "welcome": "Bienvenue", 17 | "login": "S'identifier", 18 | "tempIndicator": "C", 19 | "componentExamples": "Exemples de Composants", 20 | "usageExamples": "Exemples d'utilisation", 21 | "apiTesting": "API Testing", 22 | "themeSettings": "Réglage des thèmes", 23 | "deviceDetails": "Détails du périphérique", 24 | "noItems": "Aucun" 25 | } 26 | -------------------------------------------------------------------------------- /App/I18n/languages/he.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/hi.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/hr.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/hu.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/id.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/it.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ja.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ko.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/lt.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/lv.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ms.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/nb.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/nl.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/no.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/pl.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/pt.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ro.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/ru.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/sk.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/sl.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/sr.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/sv.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/sw.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/th.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/tr.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/uk.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/vi.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/zh.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/languages/zu.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App/I18n/platform_languages.txt: -------------------------------------------------------------------------------- 1 | Android: iOS: 2 | -------------- ------------- 3 | Afrikaans af 4 | Amharic am 5 | Arabic ar 6 | Bulgarian bg 7 | Catalan ca Catalan ca 8 | Chinese (Hong Kong) zh-HK Chinese (Hong Kong) zh-HK 9 | Chinese (PRC) zh-CN Chinese (Simplified) zh-Hans 10 | Chinese (Taiwan) zh-TW Chinese (Traditional) zh-Hant 11 | Croatian hr Croatian hr 12 | Czech cs Czech cs 13 | Danish da Danish da 14 | Dutch nl Dutch nl 15 | English (US) en-US English en 16 | English (AU) en-AU English (Australian) en-AU 17 | English (UK) en-GB English (British) en-GB 18 | English (Canadian) en-CA 19 | English (Indian) en-IN 20 | Estonian et 21 | Filipino fil 22 | Finnish fi Finnish fi 23 | French (Canada) fr-CA French (Canadian) fr-CA 24 | French (France) fr-FR French fr 25 | German de German de 26 | Greek el Greek el 27 | Hebrew he 28 | Hindi hi Hindi hi 29 | Hungarian hu Hungarian hu 30 | Indonesian id / in Indonesian id 31 | Italian it Italian it 32 | Japanese ja Japanese ja 33 | Korean ko Korean ko 34 | Latvian lv Malay ms 35 | Lithuanian lt 36 | Malay ms 37 | Norwegian no 38 | Norwegian (Bokmal) nb 39 | Polish pl Polish pl 40 | Portuguese (Brazil) pt-BR Portuguese (Brazil) pt-BR 41 | Portuguese (Portugal) pt-PT Portuguese pt 42 | Romanian ro Romanian ro 43 | Russian ru Russian ru 44 | Serbian sr 45 | Slovak sk Slovak sk 46 | Slovenian sl 47 | Spanish (Latin America) es-419 Spanish (Mexico) es-M 48 | Spanish (Spain) es-ES Spanish es 49 | Swahili sw 50 | Swedish sv Swedish sv 51 | Thai th Thai th 52 | Turkish tr Turkish tr 53 | Ukrainian uk Ukrainian uk 54 | Zulu zu Vietnamese vi 55 | -------------------------------------------------------------------------------- /App/Images/detail-doctor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/App/Images/detail-doctor.jpg -------------------------------------------------------------------------------- /App/Images/icon-back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /App/Images/icon-bandage.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /App/Images/icon-bookmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /App/Images/icon-care.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /App/Images/icon-chat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /App/Images/icon-clinic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /App/Images/icon-heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /App/Images/icon-medicine.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /App/Images/icon-search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /App/Images/icon-star5.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /App/Images/icon-stethoscope.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /App/Images/icon-syringe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /App/Images/icon-teeth.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /App/Images/thumb-doctor1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/App/Images/thumb-doctor1.jpg -------------------------------------------------------------------------------- /App/Images/thumb-doctor2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/App/Images/thumb-doctor2.jpg -------------------------------------------------------------------------------- /App/Images/thumb-doctor3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/App/Images/thumb-doctor3.jpg -------------------------------------------------------------------------------- /App/Lib/README.md: -------------------------------------------------------------------------------- 1 | # Lib 2 | 3 | At first glance, this could appear to be a "miscellaneous" folder, but we recommend that you treat this as proving ground for components that could be reusable outside your project. 4 | 5 | Maybe you're writing a set of utilities that you could use outside your project, but they're not quite ready or battle tested. This folder would be a great place to put them. They ideally be pure functions have no dependencies on other things in your App folder. 6 | -------------------------------------------------------------------------------- /App/Navigation/AppNavigation.js: -------------------------------------------------------------------------------- 1 | import { createAppContainer, createSwitchNavigator } from 'react-navigation' 2 | import { createStackNavigator } from 'react-navigation-stack'; 3 | import BottomNavigation from './BottomNavigation' 4 | 5 | import styles from './Styles/NavigationStyles' 6 | 7 | import SplashScreen from '../Containers/SplashScreen' 8 | 9 | // home stack 10 | import HomeScreen from '../Containers/HomeScreen' 11 | import DoctorDetailScreen from '../Containers/DoctorDetailScreen' 12 | 13 | // inbox stack 14 | import InboxScreen from '../Containers/InboxScreen' 15 | 16 | // account stack 17 | import AccountScreen from '../Containers/AccountScreen' 18 | 19 | // Manifest of possible screens 20 | const AppStack = createStackNavigator({ 21 | MainScreen: { 22 | screen: BottomNavigation, 23 | navigationOptions: ({ navigation }) => ({ 24 | headerShown: false 25 | }) 26 | }, 27 | 28 | // Home Stack 29 | HomeScreen: { screen: HomeScreen }, 30 | DoctorDetail: { screen: DoctorDetailScreen }, 31 | 32 | // Inbox Stack 33 | InboxScreen: { screen: InboxScreen }, 34 | 35 | // Account Stack 36 | AccountScreen: { screen: AccountScreen }, 37 | }, { 38 | // Default config for all screens 39 | headerMode: 'none', 40 | initialRouteName: 'MainScreen', 41 | navigationOptions: { 42 | headerStyle: styles.header 43 | } 44 | }) 45 | 46 | const MainNav = createSwitchNavigator({ 47 | SplashScreen, 48 | App: AppStack 49 | }, { 50 | initialRouteName: 'SplashScreen' 51 | }) 52 | 53 | export default createAppContainer(MainNav) 54 | -------------------------------------------------------------------------------- /App/Navigation/BottomNavigation.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { createStackNavigator } from 'react-navigation-stack' 3 | import { createBottomTabNavigator } from 'react-navigation-tabs' 4 | import { Fonts } from '../Themes' 5 | import { Image, Text, View, Platform } from 'react-native' 6 | import { apply, colors } from 'osmicsx' 7 | import Icon from 'react-native-vector-icons/Ionicons' 8 | 9 | // Import Styles 10 | import styles from './Styles/NavigationStyles' 11 | import customColor from '../Themes/Namespace' 12 | 13 | // Import Screens 14 | import HomeScreen from '../Containers/HomeScreen' 15 | import InboxScreen from '../Containers/InboxScreen' 16 | import AccountScreen from '../Containers/AccountScreen' 17 | 18 | const OS = Platform.OS 19 | 20 | export default createBottomTabNavigator({ 21 | Home: { 22 | screen: createStackNavigator({ 23 | HomeScreen 24 | }, { 25 | headerMode: 'screen', 26 | navigationOptions: navigation => ({ 27 | tabBarIcon: ({ focused, tintColor }) => 28 | 29 | }) 30 | }) 31 | }, 32 | Inbox: { 33 | screen: createStackNavigator({ 34 | InboxScreen 35 | }, { 36 | headerMode: 'screen', 37 | navigationOptions: navigation => ({ 38 | tabBarIcon: ({ focused, tintColor }) => 39 | 40 | }) 41 | }) 42 | }, 43 | Account: { 44 | screen: createStackNavigator({ 45 | AccountScreen 46 | }, { 47 | headerMode: 'screen', 48 | navigationOptions: navigation => ({ 49 | tabBarIcon: ({ focused, tintColor }) => 50 | 51 | }) 52 | }) 53 | }, 54 | }, { 55 | initialRouteName: 'Home', 56 | tabBarOptions: { 57 | activeTintColor: customColor["blue-native"], 58 | inactiveTintColor: colors["gray-500"], 59 | style: apply([ 60 | "bg-white", 61 | "p-4", 62 | "border-t-0", 63 | "border=0", 64 | "shadow-lg" 65 | ]), 66 | labelStyle:{ 67 | fontFamily: Fonts.type.regular, 68 | fontSize: 12 69 | }, 70 | showLabel: false 71 | }, 72 | allowFontScaling: false 73 | }) 74 | -------------------------------------------------------------------------------- /App/Navigation/ReduxNavigation.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { BackHandler, Platform } from 'react-native' 3 | import { 4 | createReactNavigationReduxMiddleware, 5 | createReduxContainer 6 | } from 'react-navigation-redux-helpers' 7 | import { connect } from 'react-redux' 8 | import AppNavigation from './AppNavigation' 9 | import NavigationServices from '../Services/NavigationService' 10 | 11 | export const appNavigatorMiddleware = createReactNavigationReduxMiddleware( 12 | (state) => state.nav, 13 | 'root' 14 | ) 15 | 16 | const ReduxAppNavigator = createReduxContainer(AppNavigation, 'root') 17 | 18 | class ReduxNavigation extends React.Component { 19 | componentDidMount () { 20 | if (Platform.OS === 'ios') return 21 | BackHandler.addEventListener('hardwareBackPress', () => { 22 | const { dispatch, nav } = this.props 23 | // change to whatever is your first screen, otherwise unpredictable results may occur 24 | if (nav.routes.length === 1 && (nav.routes[0].routeName === 'LaunchScreen')) { 25 | return false 26 | } 27 | // if (shouldCloseApp(nav)) return false 28 | dispatch({ type: 'Navigation/BACK' }) 29 | return true 30 | }) 31 | } 32 | 33 | componentWillUnmount () { 34 | if (Platform.OS === 'ios') return 35 | BackHandler.removeEventListener('hardwareBackPress', undefined) 36 | } 37 | 38 | render () { 39 | return NavigationServices.setTopLevelNavigator(navRef)} 41 | dispatch={this.props.dispatch} 42 | state={this.props.nav} 43 | /> 44 | } 45 | } 46 | 47 | const mapStateToProps = state => ({ 48 | nav: state.nav 49 | }) 50 | export default connect(mapStateToProps)(ReduxNavigation) 51 | -------------------------------------------------------------------------------- /App/Navigation/Styles/NavigationStyles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { Colors } from '../../Themes/' 3 | 4 | export default StyleSheet.create({ 5 | header: { 6 | backgroundColor: Colors.backgroundColor 7 | } 8 | }) 9 | -------------------------------------------------------------------------------- /App/Redux/CreateStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose } from 'redux' 2 | import Rehydration from '../Services/Rehydration' 3 | import ReduxPersist from '../Config/ReduxPersist' 4 | import Config from '../Config/DebugConfig' 5 | import createSagaMiddleware from 'redux-saga' 6 | import ScreenTracking from './ScreenTrackingMiddleware' 7 | import { appNavigatorMiddleware } from '../Navigation/ReduxNavigation' 8 | import Reactotron from '../Config/ReactotronConfig' 9 | 10 | // creates the store 11 | export default (rootReducer, rootSaga) => { 12 | /* ------------- Redux Configuration ------------- */ 13 | 14 | const middleware = [] 15 | const enhancers = [] 16 | 17 | /* ------------- Navigation Middleware ------------ */ 18 | middleware.push(appNavigatorMiddleware) 19 | 20 | /* ------------- Analytics Middleware ------------- */ 21 | middleware.push(ScreenTracking) 22 | 23 | /* ------------- Saga Middleware ------------- */ 24 | 25 | const sagaMonitor = Config.useReactotron ? console.tron.createSagaMonitor() : null 26 | const sagaMiddleware = createSagaMiddleware({ sagaMonitor }) 27 | middleware.push(sagaMiddleware) 28 | 29 | /* ------------- Assemble Middleware ------------- */ 30 | 31 | enhancers.push(applyMiddleware(...middleware)) 32 | 33 | // if Reactotron is enabled (default for __DEV__), we'll create the store through Reactotron 34 | const createAppropriateStore = createStore 35 | if (Config.useReactotron) { 36 | enhancers.push(Reactotron.createEnhancer()) 37 | } 38 | const store = createAppropriateStore(rootReducer, compose(...enhancers)) 39 | 40 | // configure persistStore and check reducer version number 41 | if (ReduxPersist.active) { 42 | Rehydration.updateReducers(store) 43 | } 44 | 45 | // kick off root saga 46 | let sagasManager = sagaMiddleware.run(rootSaga) 47 | 48 | return { 49 | store, 50 | sagasManager, 51 | sagaMiddleware 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /App/Redux/GithubRedux.js: -------------------------------------------------------------------------------- 1 | import { createReducer, createActions } from 'reduxsauce' 2 | import Immutable from 'seamless-immutable' 3 | 4 | /* ------------- Types and Action Creators ------------- */ 5 | 6 | const { Types, Creators } = createActions({ 7 | userRequest: ['username'], 8 | userSuccess: ['avatar'], 9 | userFailure: null 10 | }) 11 | 12 | export const GithubTypes = Types 13 | export default Creators 14 | 15 | /* ------------- Initial State ------------- */ 16 | 17 | export const INITIAL_STATE = Immutable({ 18 | avatar: null, 19 | fetching: null, 20 | error: null, 21 | username: null 22 | }) 23 | 24 | /* ------------- Selectors ------------- */ 25 | 26 | export const GithubSelectors = { 27 | selectAvatar: state => state.github.avatar 28 | } 29 | 30 | /* ------------- Reducers ------------- */ 31 | 32 | // request the avatar for a user 33 | export const request = (state, { username }) => 34 | state.merge({ fetching: true, username, avatar: null }) 35 | 36 | // successful avatar lookup 37 | export const success = (state, action) => { 38 | const { avatar } = action 39 | return state.merge({ fetching: false, error: null, avatar }) 40 | } 41 | 42 | // failed to get the avatar 43 | export const failure = (state) => 44 | state.merge({ fetching: false, error: true, avatar: null }) 45 | 46 | /* ------------- Hookup Reducers To Types ------------- */ 47 | 48 | export const reducer = createReducer(INITIAL_STATE, { 49 | [Types.USER_REQUEST]: request, 50 | [Types.USER_SUCCESS]: success, 51 | [Types.USER_FAILURE]: failure 52 | }) 53 | -------------------------------------------------------------------------------- /App/Redux/NavigationRedux.js: -------------------------------------------------------------------------------- 1 | import AppNavigation from '../Navigation/AppNavigation' 2 | 3 | export const reducer = (state, action) => { 4 | const newState = AppNavigation.router.getStateForAction(action, state) 5 | return newState || state 6 | } 7 | -------------------------------------------------------------------------------- /App/Redux/ScreenTrackingMiddleware.js: -------------------------------------------------------------------------------- 1 | import { NavigationActions } from 'react-navigation' 2 | 3 | // gets the current screen from navigation state 4 | const getCurrentRouteName = (navigationState) => { 5 | if (!navigationState) { 6 | return null 7 | } 8 | const route = navigationState.routes[navigationState.index] 9 | // dive into nested navigators 10 | if (route.routes) { 11 | return getCurrentRouteName(route) 12 | } 13 | return route.routeName 14 | } 15 | 16 | const screenTracking = ({ getState }) => next => (action) => { 17 | if ( 18 | action.type !== NavigationActions.NAVIGATE && 19 | action.type !== NavigationActions.BACK 20 | ) { 21 | return next(action) 22 | } 23 | 24 | const currentScreen = getCurrentRouteName(getState().nav) 25 | const result = next(action) 26 | const nextScreen = getCurrentRouteName(getState().nav) 27 | if (nextScreen !== currentScreen) { 28 | try { 29 | console.tron.log(`NAVIGATING ${currentScreen} to ${nextScreen}`) 30 | // Example: Analytics.trackEvent('user_navigation', {currentScreen, nextScreen}) 31 | } catch (e) { 32 | console.tron.log(e) 33 | } 34 | } 35 | return result 36 | } 37 | 38 | export default screenTracking 39 | -------------------------------------------------------------------------------- /App/Redux/SearchRedux.js: -------------------------------------------------------------------------------- 1 | import { createReducer, createActions } from 'reduxsauce' 2 | import Immutable from 'seamless-immutable' 3 | import { filter } from 'ramda' 4 | import { startsWith } from 'ramdasauce' 5 | 6 | const LIST_DATA = ['sausage', 'blubber', 'pencil', 'cloud', 'moon', 'water', 'computer', 'school', 7 | 'network', 'hammer', 'walking', 'violently', 'mediocre', 'literature', 'chair', 'two', 'window', 8 | 'cords', 'musical', 'zebra', 'xylophone', 'penguin', 'home', 'dog', 'final', 'ink', 'teacher', 'fun', 9 | 'website', 'banana', 'uncle', 'softly', 'mega', 'ten', 'awesome', 'attatch', 'blue', 'internet', 'bottle', 10 | 'tight', 'zone', 'tomato', 'prison', 'hydro', 'cleaning', 'telivision', 'send', 'frog', 'cup', 'book', 11 | 'zooming', 'falling', 'evily', 'gamer', 'lid', 'juice', 'moniter', 'captain', 'bonding', 'loudly', 'thudding', 12 | 'guitar', 'shaving', 'hair', 'soccer', 'water', 'racket', 'table', 'late', 'media', 'desktop', 'flipper', 13 | 'club', 'flying', 'smooth', 'monster', 'purple', 'guardian', 'bold', 'hyperlink', 'presentation', 'world', 'national', 14 | 'comment', 'element', 'magic', 'lion', 'sand', 'crust', 'toast', 'jam', 'hunter', 'forest', 'foraging', 15 | 'silently', 'tawesomated', 'joshing', 'pong', 'RANDOM', 'WORD' 16 | ] 17 | 18 | /* ------------- Types and Action Creators ------------- */ 19 | 20 | const { Types, Creators } = createActions({ 21 | search: ['searchTerm'], 22 | cancelSearch: null 23 | }) 24 | 25 | export const TemperatureTypes = Types 26 | export default Creators 27 | 28 | /* ------------- Initial State ------------- */ 29 | 30 | export const INITIAL_STATE = Immutable({ 31 | searchTerm: '', 32 | searching: false, 33 | results: LIST_DATA 34 | }) 35 | 36 | /* ------------- Reducers ------------- */ 37 | 38 | export const performSearch = (state, { searchTerm }) => { 39 | const results = filter(startsWith(searchTerm), LIST_DATA) 40 | return state.merge({ searching: true, searchTerm, results }) 41 | } 42 | 43 | export const cancelSearch = (state) => INITIAL_STATE 44 | 45 | /* ------------- Hookup Reducers To Types ------------- */ 46 | 47 | export const reducer = createReducer(INITIAL_STATE, { 48 | [Types.SEARCH]: performSearch, 49 | [Types.CANCEL_SEARCH]: cancelSearch 50 | }) 51 | -------------------------------------------------------------------------------- /App/Redux/StartupRedux.js: -------------------------------------------------------------------------------- 1 | import { createActions } from 'reduxsauce' 2 | 3 | /* ------------- Types and Action Creators ------------- */ 4 | 5 | const { Types, Creators } = createActions({ 6 | startup: null 7 | }) 8 | 9 | export const StartupTypes = Types 10 | export default Creators 11 | -------------------------------------------------------------------------------- /App/Redux/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import { persistReducer } from 'redux-persist' 3 | import configureStore from './CreateStore' 4 | import rootSaga from '../Sagas/' 5 | import ReduxPersist from '../Config/ReduxPersist' 6 | 7 | /* ------------- Assemble The Reducers ------------- */ 8 | export const reducers = combineReducers({ 9 | nav: require('./NavigationRedux').reducer, 10 | github: require('./GithubRedux').reducer, 11 | search: require('./SearchRedux').reducer 12 | }) 13 | 14 | export default () => { 15 | let finalReducers = reducers 16 | // If rehydration is on use persistReducer otherwise default combineReducers 17 | if (ReduxPersist.active) { 18 | const persistConfig = ReduxPersist.storeConfig 19 | finalReducers = persistReducer(persistConfig, reducers) 20 | } 21 | 22 | let { store, sagasManager, sagaMiddleware } = configureStore(finalReducers, rootSaga) 23 | 24 | if (module.hot) { 25 | module.hot.accept(() => { 26 | const nextRootReducer = require('./').reducers 27 | store.replaceReducer(nextRootReducer) 28 | 29 | const newYieldedSagas = require('../Sagas').default 30 | sagasManager.cancel() 31 | sagasManager.done.then(() => { 32 | sagasManager = sagaMiddleware(newYieldedSagas) 33 | }) 34 | }) 35 | } 36 | 37 | return store 38 | } 39 | -------------------------------------------------------------------------------- /App/Sagas/GithubSagas.js: -------------------------------------------------------------------------------- 1 | import { call, put } from 'redux-saga/effects' 2 | import { path } from 'ramda' 3 | import GithubActions from '../Redux/GithubRedux' 4 | 5 | export function * getUserAvatar (api, action) { 6 | const { username } = action 7 | // make the call to the api 8 | const response = yield call(api.getUser, username) 9 | 10 | if (response.ok) { 11 | const firstUser = path(['data', 'items'], response)[0] 12 | const avatar = firstUser.avatar_url 13 | // do data conversion here if needed 14 | yield put(GithubActions.userSuccess(avatar)) 15 | } else { 16 | yield put(GithubActions.userFailure()) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /App/Sagas/StartupSagas.js: -------------------------------------------------------------------------------- 1 | import { put, select } from 'redux-saga/effects' 2 | import GithubActions, { GithubSelectors } from '../Redux/GithubRedux' 3 | import { is } from 'ramda' 4 | 5 | // exported to make available for tests 6 | export const selectAvatar = GithubSelectors.selectAvatar 7 | 8 | // process STARTUP actions 9 | export function * startup (action) { 10 | if (__DEV__ && console.tron) { 11 | // straight-up string logging 12 | console.tron.log('Hello, I\'m an example of how to log via Reactotron.') 13 | 14 | // logging an object for better clarity 15 | console.tron.log({ 16 | message: 'pass objects for better logging', 17 | someGeneratorFunction: selectAvatar 18 | }) 19 | 20 | // fully customized! 21 | const subObject = { a: 1, b: [1, 2, 3], c: true } 22 | subObject.circularDependency = subObject // osnap! 23 | console.tron.display({ 24 | name: '🔥 IGNITE 🔥', 25 | preview: 'You should totally expand this', 26 | value: { 27 | '💃': 'Welcome to the future!', 28 | subObject, 29 | someInlineFunction: () => true, 30 | someGeneratorFunction: startup, 31 | someNormalFunction: selectAvatar 32 | } 33 | }) 34 | } 35 | const avatar = yield select(selectAvatar) 36 | // only get if we don't have it yet 37 | if (!is(String, avatar)) { 38 | yield put(GithubActions.userRequest('GantMan')) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /App/Sagas/index.js: -------------------------------------------------------------------------------- 1 | import { takeLatest, all } from 'redux-saga/effects' 2 | import API from '../Services/Api' 3 | import FixtureAPI from '../Services/FixtureApi' 4 | import DebugConfig from '../Config/DebugConfig' 5 | 6 | /* ------------- Types ------------- */ 7 | 8 | import { StartupTypes } from '../Redux/StartupRedux' 9 | import { GithubTypes } from '../Redux/GithubRedux' 10 | 11 | /* ------------- Sagas ------------- */ 12 | 13 | import { startup } from './StartupSagas' 14 | import { getUserAvatar } from './GithubSagas' 15 | 16 | /* ------------- API ------------- */ 17 | 18 | // The API we use is only used from Sagas, so we create it here and pass along 19 | // to the sagas which need it. 20 | const api = DebugConfig.useFixtures ? FixtureAPI : API.create() 21 | 22 | /* ------------- Connect Types To Sagas ------------- */ 23 | 24 | export default function * root () { 25 | yield all([ 26 | // some sagas only receive an action 27 | takeLatest(StartupTypes.STARTUP, startup), 28 | 29 | // some sagas receive extra parameters in addition to an action 30 | takeLatest(GithubTypes.USER_REQUEST, getUserAvatar, api) 31 | ]) 32 | } 33 | -------------------------------------------------------------------------------- /App/Services/Api.js: -------------------------------------------------------------------------------- 1 | // a library to wrap and simplify api calls 2 | import apisauce from 'apisauce' 3 | 4 | // our "constructor" 5 | const create = (baseURL = 'https://api.github.com/') => { 6 | // ------ 7 | // STEP 1 8 | // ------ 9 | // 10 | // Create and configure an apisauce-based api object. 11 | // 12 | const api = apisauce.create({ 13 | // base URL is read from the "constructor" 14 | baseURL, 15 | // here are some default headers 16 | headers: { 17 | 'Cache-Control': 'no-cache' 18 | }, 19 | // 10 second timeout... 20 | timeout: 10000 21 | }) 22 | 23 | // ------ 24 | // STEP 2 25 | // ------ 26 | // 27 | // Define some functions that call the api. The goal is to provide 28 | // a thin wrapper of the api layer providing nicer feeling functions 29 | // rather than "get", "post" and friends. 30 | // 31 | // I generally don't like wrapping the output at this level because 32 | // sometimes specific actions need to be take on `403` or `401`, etc. 33 | // 34 | // Since we can't hide from that, we embrace it by getting out of the 35 | // way at this level. 36 | // 37 | const getRoot = () => api.get('') 38 | const getRate = () => api.get('rate_limit') 39 | const getUser = (username) => api.get('search/users', {q: username}) 40 | 41 | // ------ 42 | // STEP 3 43 | // ------ 44 | // 45 | // Return back a collection of functions that we would consider our 46 | // interface. Most of the time it'll be just the list of all the 47 | // methods in step 2. 48 | // 49 | // Notice we're not returning back the `api` created in step 1? That's 50 | // because it is scoped privately. This is one way to create truly 51 | // private scoped goodies in JavaScript. 52 | // 53 | return { 54 | // a list of the API functions from step 2 55 | getRoot, 56 | getRate, 57 | getUser 58 | } 59 | } 60 | 61 | // let's return back our create method as the default. 62 | export default { 63 | create 64 | } 65 | -------------------------------------------------------------------------------- /App/Services/ExamplesRegistry.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Text, View } from 'react-native' 3 | import R from 'ramda' 4 | import { ApplicationStyles } from '../Themes' 5 | import DebugConfig from '../Config/DebugConfig' 6 | let globalComponentExamplesRegistry = [] 7 | let globalPluginExamplesRegistry = [] 8 | 9 | export const addComponentExample = (title, usage = () => {}) => { if (DebugConfig.includeExamples) globalComponentExamplesRegistry.push({title, usage}) } // eslint-disable-line 10 | 11 | export const addPluginExample = (title, usage = () => {}) => { if (DebugConfig.includeExamples) globalPluginExamplesRegistry.push({title, usage}) } // eslint-disable-line 12 | 13 | const renderComponentExample = (example) => { 14 | return ( 15 | 16 | 17 | {example.title} 18 | 19 | {example.usage.call()} 20 | 21 | ) 22 | } 23 | 24 | const renderPluginExample = (example) => { 25 | return ( 26 | 27 | 28 | {example.title} 29 | 30 | {example.usage.call()} 31 | 32 | ) 33 | } 34 | 35 | export const renderComponentExamples = () => R.map(renderComponentExample, globalComponentExamplesRegistry) 36 | 37 | export const renderPluginExamples = () => R.map(renderPluginExample, globalPluginExamplesRegistry) 38 | 39 | // Default for readability 40 | export default { 41 | renderComponentExamples, 42 | addComponentExample, 43 | renderPluginExamples, 44 | addPluginExample 45 | } 46 | -------------------------------------------------------------------------------- /App/Services/FixtureApi.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // Functions return fixtures 3 | getRoot: () => { 4 | return { 5 | ok: true, 6 | data: require('../Fixtures/root.json') 7 | } 8 | }, 9 | getRate: () => { 10 | return { 11 | ok: true, 12 | data: require('../Fixtures/rateLimit.json') 13 | } 14 | }, 15 | getUser: (username) => { 16 | // This fixture only supports gantman or else returns skellock 17 | const gantmanData = require('../Fixtures/gantman.json') 18 | const skellockData = require('../Fixtures/skellock.json') 19 | return { 20 | ok: true, 21 | data: username.toLowerCase() === 'gantman' ? gantmanData : skellockData 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /App/Services/ImmutablePersistenceTransform.js: -------------------------------------------------------------------------------- 1 | import R from 'ramda' 2 | import Immutable from 'seamless-immutable' 3 | 4 | // is this object already Immutable? 5 | const isImmutable = R.has('asMutable') 6 | 7 | // change this Immutable object into a JS object 8 | const convertToJs = (state) => state.asMutable({deep: true}) 9 | 10 | // optionally convert this object into a JS object if it is Immutable 11 | const fromImmutable = R.when(isImmutable, convertToJs) 12 | 13 | // convert this JS object into an Immutable object 14 | const toImmutable = (raw) => Immutable(raw) 15 | 16 | // the transform interface that redux-persist is expecting 17 | export default { 18 | out: (state) => { 19 | // console.log({ retrieving: state }) 20 | return toImmutable(state) 21 | }, 22 | in: (raw) => { 23 | // console.log({ storing: raw }) 24 | return fromImmutable(raw) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /App/Services/NavigationService.js: -------------------------------------------------------------------------------- 1 | import { StackActions, NavigationActions } from 'react-navigation'; 2 | 3 | let _navigator; 4 | 5 | function setTopLevelNavigator(navigatorRef) { 6 | _navigator = navigatorRef; 7 | } 8 | 9 | function navigate(routeName, params) { 10 | /** OPTIONAL you can use this navigation object */ 11 | const navigation = _navigator.currentNavProp 12 | navigation.navigate({ routeName, params }) 13 | // _navigator.props.dispatch( 14 | // NavigationActions.navigate({ 15 | // routeName, 16 | // params, 17 | // }) 18 | // ); 19 | } 20 | 21 | function goBack() { 22 | const navigation = _navigator.currentNavProp 23 | navigation.goBack() 24 | } 25 | 26 | function replace(routeName, params) { 27 | const navigation = _navigator.currentNavProp 28 | _navigator.props.dispatch( 29 | StackActions.replace({ 30 | routeName, 31 | params 32 | }) 33 | ) 34 | } 35 | 36 | function dispatch(action) { 37 | const navigation = _navigator.currentNavProp 38 | navigation.dispatch(action) 39 | } 40 | 41 | function findActiveScreen(state) { 42 | const {routes, index} = state 43 | if (routes && routes[index]) { 44 | return findActiveScreen(routes[index]) 45 | } else { 46 | return state 47 | } 48 | } 49 | 50 | function getActiveScreenAndParams() { 51 | const navigation = _navigator.currentNavProp 52 | const {state} = navigation 53 | return findActiveScreen(state, null) 54 | } 55 | 56 | // add other navigation functions that you need and export them 57 | 58 | export default { 59 | navigate, 60 | replace, 61 | goBack, 62 | dispatch, 63 | setTopLevelNavigator, 64 | getActiveScreenAndParams, 65 | }; 66 | -------------------------------------------------------------------------------- /App/Services/Rehydration.js: -------------------------------------------------------------------------------- 1 | import ReduxPersist from '../Config/ReduxPersist' 2 | import { AsyncStorage } from 'react-native' 3 | import { persistStore } from 'redux-persist' 4 | import StartupActions from '../Redux/StartupRedux' 5 | import DebugConfig from '../Config/DebugConfig' 6 | 7 | const updateReducers = (store: Object) => { 8 | const reducerVersion = ReduxPersist.reducerVersion 9 | const startup = () => store.dispatch(StartupActions.startup()) 10 | 11 | // Check to ensure latest reducer version 12 | AsyncStorage.getItem('reducerVersion').then((localVersion) => { 13 | if (localVersion !== reducerVersion) { 14 | if (DebugConfig.useReactotron) { 15 | console.tron.display({ 16 | name: 'PURGE', 17 | value: { 18 | 'Old Version:': localVersion, 19 | 'New Version:': reducerVersion 20 | }, 21 | preview: 'Reducer Version Change Detected', 22 | important: true 23 | }) 24 | } 25 | // Purge store 26 | persistStore(store, null, startup).purge() 27 | AsyncStorage.setItem('reducerVersion', reducerVersion) 28 | } else { 29 | persistStore(store, null, startup) 30 | } 31 | }).catch(() => { 32 | persistStore(store, null, startup) 33 | AsyncStorage.setItem('reducerVersion', reducerVersion) 34 | }) 35 | } 36 | 37 | export default { updateReducers } 38 | -------------------------------------------------------------------------------- /App/Themes/ApplicationStyles.js: -------------------------------------------------------------------------------- 1 | import Fonts from './Fonts' 2 | import Metrics from './Metrics' 3 | import Colors from './Colors' 4 | 5 | // This file is for a reusable grouping of Theme items. 6 | // Similar to an XML fragment layout in Android 7 | 8 | const ApplicationStyles = { 9 | screen: { 10 | mainContainer: { 11 | flex: 1, 12 | backgroundColor: Colors.transparent 13 | }, 14 | backgroundImage: { 15 | position: 'absolute', 16 | top: 0, 17 | left: 0, 18 | bottom: 0, 19 | right: 0 20 | }, 21 | container: { 22 | flex: 1, 23 | paddingTop: Metrics.baseMargin, 24 | backgroundColor: Colors.transparent 25 | }, 26 | section: { 27 | margin: Metrics.section, 28 | padding: Metrics.baseMargin 29 | }, 30 | sectionText: { 31 | ...Fonts.style.normal, 32 | paddingVertical: Metrics.doubleBaseMargin, 33 | color: Colors.snow, 34 | marginVertical: Metrics.smallMargin, 35 | textAlign: 'center' 36 | }, 37 | subtitle: { 38 | color: Colors.snow, 39 | padding: Metrics.smallMargin, 40 | marginBottom: Metrics.smallMargin, 41 | marginHorizontal: Metrics.smallMargin 42 | }, 43 | titleText: { 44 | ...Fonts.style.h2, 45 | fontSize: 14, 46 | color: Colors.text 47 | } 48 | }, 49 | darkLabelContainer: { 50 | padding: Metrics.smallMargin, 51 | paddingBottom: Metrics.doubleBaseMargin, 52 | borderBottomColor: Colors.border, 53 | borderBottomWidth: 1, 54 | marginBottom: Metrics.baseMargin 55 | }, 56 | darkLabel: { 57 | fontFamily: Fonts.type.bold, 58 | color: Colors.snow 59 | }, 60 | groupContainer: { 61 | margin: Metrics.smallMargin, 62 | flexDirection: 'row', 63 | justifyContent: 'space-around', 64 | alignItems: 'center' 65 | }, 66 | sectionTitle: { 67 | ...Fonts.style.h4, 68 | color: Colors.coal, 69 | backgroundColor: Colors.ricePaper, 70 | padding: Metrics.smallMargin, 71 | marginTop: Metrics.smallMargin, 72 | marginHorizontal: Metrics.baseMargin, 73 | borderWidth: 1, 74 | borderColor: Colors.ember, 75 | alignItems: 'center', 76 | textAlign: 'center' 77 | } 78 | } 79 | 80 | export default ApplicationStyles 81 | -------------------------------------------------------------------------------- /App/Themes/Colors.js: -------------------------------------------------------------------------------- 1 | const colors = { 2 | background: '#1F0808', 3 | clear: 'rgba(0,0,0,0)', 4 | facebook: '#3b5998', 5 | transparent: 'rgba(0,0,0,0)', 6 | silver: '#F7F7F7', 7 | steel: '#CCCCCC', 8 | error: 'rgba(200, 0, 0, 0.8)', 9 | ricePaper: 'rgba(255,255,255, 0.75)', 10 | frost: '#D8D8D8', 11 | cloud: 'rgba(200,200,200, 0.35)', 12 | windowTint: 'rgba(0, 0, 0, 0.4)', 13 | panther: '#161616', 14 | charcoal: '#595959', 15 | coal: '#2d2d2d', 16 | bloodOrange: '#fb5f26', 17 | snow: 'white', 18 | ember: 'rgba(164, 0, 48, 0.5)', 19 | fire: '#e73536', 20 | drawer: 'rgba(30, 30, 29, 0.95)', 21 | eggplant: '#251a34', 22 | border: '#483F53', 23 | banner: '#5F3E63', 24 | text: '#E0D7E5' 25 | } 26 | 27 | export default colors 28 | -------------------------------------------------------------------------------- /App/Themes/Fonts.js: -------------------------------------------------------------------------------- 1 | const type = { 2 | base: 'Avenir-Book', 3 | bold: 'Avenir-Black', 4 | emphasis: 'HelveticaNeue-Italic' 5 | } 6 | 7 | const size = { 8 | h1: 38, 9 | h2: 34, 10 | h3: 30, 11 | h4: 26, 12 | h5: 20, 13 | h6: 19, 14 | input: 18, 15 | regular: 17, 16 | medium: 14, 17 | small: 12, 18 | tiny: 8.5 19 | } 20 | 21 | const style = { 22 | h1: { 23 | fontFamily: type.base, 24 | fontSize: size.h1 25 | }, 26 | h2: { 27 | fontWeight: 'bold', 28 | fontSize: size.h2 29 | }, 30 | h3: { 31 | fontFamily: type.emphasis, 32 | fontSize: size.h3 33 | }, 34 | h4: { 35 | fontFamily: type.base, 36 | fontSize: size.h4 37 | }, 38 | h5: { 39 | fontFamily: type.base, 40 | fontSize: size.h5 41 | }, 42 | h6: { 43 | fontFamily: type.emphasis, 44 | fontSize: size.h6 45 | }, 46 | normal: { 47 | fontFamily: type.base, 48 | fontSize: size.regular 49 | }, 50 | description: { 51 | fontFamily: type.base, 52 | fontSize: size.medium 53 | } 54 | } 55 | 56 | export default { 57 | type, 58 | size, 59 | style 60 | } 61 | -------------------------------------------------------------------------------- /App/Themes/Images.js: -------------------------------------------------------------------------------- 1 | // leave off @2x/@3x 2 | const images = { 3 | thumbDoctor1: require('../Images/thumb-doctor1.jpg'), 4 | thumbDoctor2: require('../Images/thumb-doctor2.jpg'), 5 | thumbDoctor3: require('../Images/thumb-doctor3.jpg'), 6 | detailDoctor: require('../Images/detail-doctor.jpg') 7 | } 8 | 9 | export default images 10 | -------------------------------------------------------------------------------- /App/Themes/Metrics.js: -------------------------------------------------------------------------------- 1 | import {Dimensions, Platform} from 'react-native' 2 | 3 | const { width, height } = Dimensions.get('window') 4 | 5 | // Used via Metrics.baseMargin 6 | const metrics = { 7 | marginHorizontal: 10, 8 | marginVertical: 10, 9 | section: 25, 10 | baseMargin: 10, 11 | doubleBaseMargin: 20, 12 | smallMargin: 5, 13 | doubleSection: 50, 14 | horizontalLineHeight: 1, 15 | screenWidth: width < height ? width : height, 16 | screenHeight: width < height ? height : width, 17 | navBarHeight: (Platform.OS === 'ios') ? 64 : 54, 18 | buttonRadius: 4, 19 | icons: { 20 | tiny: 15, 21 | small: 20, 22 | medium: 30, 23 | large: 45, 24 | xl: 50 25 | }, 26 | images: { 27 | small: 20, 28 | medium: 40, 29 | large: 60, 30 | logo: 200 31 | } 32 | } 33 | 34 | export default metrics 35 | -------------------------------------------------------------------------------- /App/Themes/Namespace.js: -------------------------------------------------------------------------------- 1 | import { scaleHeight, scaleWidth } from 'osmicsx' 2 | import { Platform } from 'react-native' 3 | 4 | export default { 5 | "blue-native": "#639AFF", 6 | "purple-native": "#B79CFF", 7 | "orange-native": "#FFA188", 8 | "yellow-native": "#FFB547", 9 | "green-native": "#1AD37A", 10 | "cyan-native": "#05D1ED", 11 | "pink-native": "#FF71C6", 12 | "red-native": "#FF7070", 13 | 14 | // size 15 | "text-xxs": { fontSize: 10 }, 16 | "text-7xl": { fontSize: 34 }, 17 | 18 | "font-regular": { fontFamily: "Lato-Regular" }, 19 | "font-bold": { fontFamily: "Lato-Bold" }, 20 | "font-black": { fontFamily: "Lato-Black" }, 21 | 22 | "text-blue-native": { color: "#639AFF" }, 23 | "bg-blue-native": { backgroundColor: "#639AFF" }, 24 | 25 | "text-purple-native": { color: "#B79CFF" }, 26 | "bg-purple-native": { backgroundColor: "#B79CFF" }, 27 | 28 | "text-orange-native": { color: "#FFA188" }, 29 | "bg-orange-native": { backgroundColor: "#FFA188" }, 30 | 31 | "text-yellow-native": { color: "#FFB547" }, 32 | "bg-yellow-native": { backgroundColor: "#FFB547" }, 33 | "bg-yellow-light": { backgroundColor: "#FFE848" }, 34 | 35 | "text-green-native": { color: "#1AD37A" }, 36 | "bg-green-native": { backgroundColor: "#1AD37A" }, 37 | "bg-soft-green": { backgroundColor: "#CCF5E1" }, 38 | "text-dark-green": { color: "#00CC6A" }, 39 | 40 | "text-cyan-native": { color: "#05D1ED" }, 41 | "bg-cyan-native": { backgroundColor: "#05D1ED" }, 42 | 43 | "text-pink-native": { color: "#FF71C6" }, 44 | "bg-pink-native": { backgroundColor: "#FF71C6" }, 45 | 46 | "text-red-native": { color: "#FF7070" }, 47 | "bg-red-native": { backgroundColor: "#FF7070" }, 48 | "text-dark-red": { color: "#CC4900" }, 49 | "bg-soft-red": { backgroundColor: "#F7E4D9" }, 50 | 51 | "bg-muted": { backgroundColor: "#CACCCF" }, 52 | "text-muted": { color: "#CACCCF" }, 53 | "border-muted": { borderColor: "#CACCCF" }, 54 | 55 | "bg-background": { backgroundColor: "#F6F6F6" }, 56 | "text-gray-dark": { color: "#A0A4A8" }, 57 | "text-dark": { color: "#25282B" }, 58 | 59 | "bg-soft-white": { backgroundColor: "rgba(255,255,255, 0.25)" }, 60 | 61 | // Width and Height 62 | "w-56": { width: 56 }, 63 | "h-56": { height: 56 }, 64 | "w-28": { width: 28 }, 65 | "h-28": { height: 28 }, 66 | "w-88": { width: 88 }, 67 | "h-80": { height: 80 }, 68 | "h-24": { height: 24 }, 69 | "h-s80": { height: scaleHeight(80) }, 70 | "min-w-38": { width: scaleWidth(38) }, 71 | 72 | // top right bottom left 73 | "-top-3": { top: scaleWidth(-3) }, 74 | "-left-3": { left: scaleWidth(Platform.OS == "android" ? 5 : 2) }, 75 | 76 | // etc 77 | "small-dot": { width: 3, height: 3 }, 78 | "medium-dot": { width: 5, height: 5 }, 79 | 80 | "border-r": { borderRightWidth: 1 }, 81 | "border-r-0": { borderRightWidth: 0 } 82 | } 83 | -------------------------------------------------------------------------------- /App/Themes/Osmicsx.js: -------------------------------------------------------------------------------- 1 | import Namespace from './Namespace' // your custom style file 2 | import { OsmiProvider } from 'osmicsx' 3 | 4 | const provider = new OsmiProvider(Namespace); 5 | 6 | const { apply, connect } = provider; 7 | 8 | export { 9 | apply, 10 | connect 11 | } 12 | -------------------------------------------------------------------------------- /App/Themes/README.md: -------------------------------------------------------------------------------- 1 | ### Themes Folder 2 | Application specific themes 3 | * Base Styles 4 | * Fonts 5 | * Metrics 6 | * Colors 7 | 8 | etc. 9 | -------------------------------------------------------------------------------- /App/Themes/Svg.js: -------------------------------------------------------------------------------- 1 | import IconSearchSvg from '../Images/icon-search.svg' 2 | import IconBackSvg from '../Images/icon-back.svg' 3 | import IconBookmarkSvg from '../Images/icon-bookmark.svg' 4 | import IconChatSvg from '../Images/icon-chat.svg' 5 | 6 | // Category Home 7 | import IconBandageSvg from '../Images/icon-bandage.svg' 8 | import IconCareSvg from '../Images/icon-care.svg' 9 | import IconClinicSvg from '../Images/icon-clinic.svg' 10 | import IconHeartSvg from '../Images/icon-heart.svg' 11 | import IconMedicineSvg from '../Images/icon-medicine.svg' 12 | import IconStethoscopeSvg from '../Images/icon-stethoscope.svg' 13 | import IconSyringeSvg from '../Images/icon-syringe.svg' 14 | import IconTeethSvg from '../Images/icon-teeth.svg' 15 | 16 | // star 17 | import IconStar5Svg from '../Images/icon-star5.svg' 18 | 19 | export const IconSearch = IconSearchSvg 20 | export const IconBack = IconBackSvg 21 | export const IconBookmark = IconBookmarkSvg 22 | export const IconChat = IconChatSvg 23 | 24 | // Category Home 25 | export const IconBandage = IconBandageSvg 26 | export const IconCare = IconCareSvg 27 | export const IconClinic = IconClinicSvg 28 | export const IconHeart = IconHeartSvg 29 | export const IconMedicine = IconMedicineSvg 30 | export const IconStethoscope = IconStethoscopeSvg 31 | export const IconSyringe = IconSyringeSvg 32 | export const IconTeeth = IconTeethSvg 33 | 34 | // star 35 | export const IconStar5 = IconStar5Svg 36 | -------------------------------------------------------------------------------- /App/Themes/index.js: -------------------------------------------------------------------------------- 1 | import Colors from './Colors' 2 | import Fonts from './Fonts' 3 | import Metrics from './Metrics' 4 | import Images from './Images' 5 | import ApplicationStyles from './ApplicationStyles' 6 | 7 | export { Colors, Fonts, Images, Metrics, ApplicationStyles } 8 | -------------------------------------------------------------------------------- /App/Transforms/ConvertFromKelvin.js: -------------------------------------------------------------------------------- 1 | export default (kelvin: number) => { 2 | const celsius = kelvin - 273.15 3 | const fahrenheit = (celsius * 1.8000) + 32 4 | 5 | return Math.round(fahrenheit) 6 | } 7 | -------------------------------------------------------------------------------- /App/Transforms/README.md: -------------------------------------------------------------------------------- 1 | # Transforms 2 | 3 | A common pattern when working with APIs is to change data to play nice between your app & the API. 4 | 5 | We've found this to be the case in every project we've worked on. So much so that we're recommending that you create a folder dedicated to these transformations. 6 | 7 | Transforms are not necessarily a bad thing (although an API might have you transforming more than you'd like). 8 | 9 | For example, you may: 10 | 11 | * turn appropriate strings to date objects 12 | * convert snake case to camel case 13 | * normalize or denormalize things 14 | * create lookup tables 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LibsCode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

gDoctor


3 | gDoctor is an open source mobile app built with React Native and OsmiCSX for learning purpose. 4 |

5 | 6 |

7 | LICENSE 8 | Stars 9 | JS Standard 10 | React Native 11 | OsmiCSX 12 |

13 | 14 | --- 15 | 16 |

17 | 18 | 19 |

20 | 21 | ## Prerequisites 22 | - Xcode or Android Studio installed and exported on your ~/.bash_profile or similar 23 | - JDK 1.8 24 | - Node >= 12.* 25 | - react-native-cli 26 | 27 | ## Installation 28 | open terminal and change directory to your desired folder, then: 29 | ``` 30 | $ git clone git@github.com:libscode/gDoctor.git YourAppName 31 | $ cd YourAppName 32 | $ yarn install 33 | $ cd ios && pod install 34 | ``` 35 | ## Run Your App 36 | ``` 37 | $ npx react-native run-android 38 | $ npx react-native run-ios 39 | ``` 40 | ## License 41 | The code is available at [GitHub][home] under the [MIT license][license-url]. 42 | 43 | ## Additional 44 | **To Lint on Commit** 45 | 46 | This is implemented using [husky](https://github.com/typicode/husky). There is no additional setup needed. 47 | 48 | **Bypass Lint** 49 | 50 | If you have to bypass lint for a special commit that you will come back and clean (pushing something to a branch etc.) then you can bypass git hooks with adding `--no-verify` to your commit command. 51 | 52 | **Understanding Linting Errors** 53 | 54 | The linting rules are from JS Standard and React-Standard. [Regular JS errors can be found with descriptions here](http://eslint.org/docs/rules/), while [React errors and descriptions can be found here](https://github.com/yannickcr/eslint-plugin-react). 55 | 56 | ## :closed_lock_with_key: Secrets 57 | 58 | This project uses [react-native-config](https://github.com/luggit/react-native-config) to expose config variables to your javascript code in React Native. You can store API keys 59 | and other sensitive information in a `.env` file: 60 | 61 | ``` 62 | API_URL=https://myapi.com 63 | GOOGLE_MAPS_API_KEY=abcdefgh 64 | ``` 65 | 66 | and access them from React Native like so: 67 | 68 | ``` 69 | import Secrets from 'react-native-config' 70 | 71 | Secrets.API_URL // 'https://myapi.com' 72 | Secrets.GOOGLE_MAPS_API_KEY // 'abcdefgh' 73 | ``` 74 | 75 | The `.env` file is ignored by git keeping those secrets out of your repo. 76 | 77 | ### Get started: 78 | 1. Copy .env.example to .env 79 | 2. Add your config variables 80 | 3. Follow instructions at [https://github.com/luggit/react-native-config#setup](https://github.com/luggit/react-native-config#setup) 81 | 4. Done! 82 | 83 | ## Credit 84 | [Medical Icon Pack (FlatIcon)](https://www.flaticon.com/packs/medical-71) 85 | 86 | ## Contributors 87 | Suggestions and contributions are welcome via Pull Requests. 88 | 89 | | [
Rully Ardiansyah](https://github.com/DeVoresyah)
[💻](https://github.com/libscode/gDoctor/commits?author=DeVoresyah "Code") [📖](https://github.com/libscode/gDoctor/commits?author=DeVoresyah "Documentation") [💬](#question-devoresyah "Answering Questions") [👀](#review-devoresyah "Reviewed Pull Requests") [💡](#example-devoresyah "Examples") | [
Gilang Segara Bening](https://dribbble.com/bungspaces)
[🎨](#logo-design "UI/UX Design") [💡](#concept-arkanpo "Concept") | 90 | | :---: | :---: | 91 | 92 | 93 | [home]: https://github.com/libscode/gDoctor 94 | -------------------------------------------------------------------------------- /android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.gdoctor", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.gdoctor", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 22 | * bundleCommand: "ram-bundle", 23 | * 24 | * // whether to bundle JS and assets in debug mode 25 | * bundleInDebug: false, 26 | * 27 | * // whether to bundle JS and assets in release mode 28 | * bundleInRelease: true, 29 | * 30 | * // whether to bundle JS and assets in another build variant (if configured). 31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 32 | * // The configuration property can be in the following formats 33 | * // 'bundleIn${productFlavor}${buildType}' 34 | * // 'bundleIn${buildType}' 35 | * // bundleInFreeDebug: true, 36 | * // bundleInPaidRelease: true, 37 | * // bundleInBeta: true, 38 | * 39 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 40 | * // for example: to disable dev mode in the staging build type (if configured) 41 | * devDisabledInStaging: true, 42 | * // The configuration property can be in the following formats 43 | * // 'devDisabledIn${productFlavor}${buildType}' 44 | * // 'devDisabledIn${buildType}' 45 | * 46 | * // the root of your project, i.e. where "package.json" lives 47 | * root: "../../", 48 | * 49 | * // where to put the JS bundle asset in debug mode 50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 51 | * 52 | * // where to put the JS bundle asset in release mode 53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 54 | * 55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 56 | * // require('./image.png')), in debug mode 57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 58 | * 59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 60 | * // require('./image.png')), in release mode 61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 62 | * 63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 67 | * // for example, you might want to remove it from here. 68 | * inputExcludes: ["android/**", "ios/**"], 69 | * 70 | * // override which node gets called and with what additional arguments 71 | * nodeExecutableAndArgs: ["node"], 72 | * 73 | * // supply additional arguments to the packager 74 | * extraPackagerArgs: [] 75 | * ] 76 | */ 77 | 78 | project.ext.react = [ 79 | entryFile: "index.js", 80 | enableHermes: true, // clean and rebuild if changing 81 | ] 82 | 83 | apply from: "../../node_modules/react-native/react.gradle" 84 | 85 | /** 86 | * Set this to true to create two separate APKs instead of one: 87 | * - An APK that only works on ARM devices 88 | * - An APK that only works on x86 devices 89 | * The advantage is the size of the APK is reduced by about 4MB. 90 | * Upload all the APKs to the Play Store and people will download 91 | * the correct one based on the CPU architecture of their device. 92 | */ 93 | def enableSeparateBuildPerCPUArchitecture = true 94 | 95 | /** 96 | * Run Proguard to shrink the Java bytecode in release builds. 97 | */ 98 | def enableProguardInReleaseBuilds = true 99 | 100 | /** 101 | * The preferred build flavor of JavaScriptCore. 102 | * 103 | * For example, to use the international variant, you can use: 104 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 105 | * 106 | * The international variant includes ICU i18n library and necessary data 107 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 108 | * give correct results when using with locales other than en-US. Note that 109 | * this variant is about 6MiB larger per architecture than default. 110 | */ 111 | def jscFlavor = 'org.webkit:android-jsc:+' 112 | 113 | /** 114 | * Whether to enable the Hermes VM. 115 | * 116 | * This should be set on project.ext.react and mirrored here. If it is not set 117 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 118 | * and the benefits of using Hermes will therefore be sharply reduced. 119 | */ 120 | def enableHermes = project.ext.react.get("enableHermes", false); 121 | 122 | android { 123 | compileSdkVersion rootProject.ext.compileSdkVersion 124 | 125 | compileOptions { 126 | sourceCompatibility JavaVersion.VERSION_1_8 127 | targetCompatibility JavaVersion.VERSION_1_8 128 | } 129 | 130 | defaultConfig { 131 | applicationId "com.gdoctor" 132 | minSdkVersion rootProject.ext.minSdkVersion 133 | targetSdkVersion rootProject.ext.targetSdkVersion 134 | versionCode 1 135 | versionName "1.0" 136 | } 137 | splits { 138 | abi { 139 | reset() 140 | enable enableSeparateBuildPerCPUArchitecture 141 | universalApk true // If true, also generate a universal APK 142 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 143 | } 144 | } 145 | signingConfigs { 146 | debug { 147 | storeFile file('debug.keystore') 148 | storePassword 'android' 149 | keyAlias 'androiddebugkey' 150 | keyPassword 'android' 151 | } 152 | release { 153 | if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) { 154 | storeFile file(MYAPP_UPLOAD_STORE_FILE) 155 | storePassword MYAPP_UPLOAD_STORE_PASSWORD 156 | keyAlias MYAPP_UPLOAD_KEY_ALIAS 157 | keyPassword MYAPP_UPLOAD_KEY_PASSWORD 158 | } 159 | } 160 | } 161 | buildTypes { 162 | debug { 163 | signingConfig signingConfigs.debug 164 | } 165 | release { 166 | // Caution! In production, you need to generate your own keystore file. 167 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 168 | signingConfig signingConfigs.release 169 | minifyEnabled enableProguardInReleaseBuilds 170 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 171 | } 172 | } 173 | // applicationVariants are e.g. debug, release 174 | applicationVariants.all { variant -> 175 | variant.outputs.each { output -> 176 | // For each separate APK per architecture, set a unique version code as described here: 177 | // https://developer.android.com/studio/build/configure-apk-splits.html 178 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 179 | def abi = output.getFilter(OutputFile.ABI) 180 | if (abi != null) { // null for the universal-debug, universal-release variants 181 | output.versionCodeOverride = 182 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 183 | } 184 | 185 | } 186 | } 187 | } 188 | 189 | dependencies { 190 | implementation project(':react-native-vector-icons') 191 | implementation fileTree(dir: "libs", include: ["*.jar"]) 192 | implementation "com.facebook.react:react-native:+" // From node_modules 193 | implementation 'androidx.appcompat:appcompat:1.1.0-rc01' 194 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02' 195 | 196 | if (enableHermes) { 197 | def hermesPath = "../../node_modules/hermes-engine/android/"; 198 | debugImplementation files(hermesPath + "hermes-debug.aar") 199 | releaseImplementation files(hermesPath + "hermes-release.aar") 200 | } else { 201 | implementation jscFlavor 202 | } 203 | } 204 | 205 | // Run this once to be able to run the application with BUCK 206 | // puts all compile dependencies into folder libs for BUCK to use 207 | task copyDownloadableDepsToLibs(type: Copy) { 208 | from configurations.compile 209 | into 'libs' 210 | } 211 | 212 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 213 | -------------------------------------------------------------------------------- /android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/debug.keystore -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -keep public class com.horcrux.svg.** {*;} 12 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/AntDesign.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/AntDesign.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Feather.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Feather.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Lato-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Lato-Black.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /android/app/src/main/java/com/gdoctor/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gdoctor; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | import com.facebook.react.ReactActivityDelegate; 6 | import com.facebook.react.ReactRootView; 7 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 8 | 9 | public class MainActivity extends ReactActivity { 10 | 11 | @Override 12 | protected ReactActivityDelegate createReactActivityDelegate() { 13 | return new ReactActivityDelegate(this, getMainComponentName()) { 14 | @Override 15 | protected ReactRootView createRootView() { 16 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 17 | } 18 | }; 19 | } 20 | 21 | /** 22 | * Returns the name of the main component registered from JavaScript. This is used to schedule 23 | * rendering of the component. 24 | */ 25 | @Override 26 | protected String getMainComponentName() { 27 | return "gDoctor"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/gdoctor/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.gdoctor; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.oblador.vectoricons.VectorIconsPackage; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = 17 | new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | @SuppressWarnings("UnnecessaryLocalVariable") 26 | List packages = new PackageList(this).getPackages(); 27 | // Packages that cannot be autolinked yet can be added manually here, for example: 28 | // packages.add(new MyReactNativePackage()); 29 | return packages; 30 | } 31 | 32 | @Override 33 | protected String getJSMainModuleName() { 34 | return "index"; 35 | } 36 | }; 37 | 38 | @Override 39 | public ReactNativeHost getReactNativeHost() { 40 | return mReactNativeHost; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | SoLoader.init(this, /* native exopackage */ false); 47 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled 48 | } 49 | 50 | /** 51 | * Loads Flipper in React Native templates. 52 | * 53 | * @param context 54 | */ 55 | private static void initializeFlipper(Context context) { 56 | if (BuildConfig.DEBUG) { 57 | try { 58 | /* 59 | We use reflection here to pick up the class that initializes Flipper, 60 | since Flipper library is not available in release mode 61 | */ 62 | Class aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper"); 63 | aClass.getMethod("initializeFlipper", Context.class).invoke(null, context); 64 | } catch (ClassNotFoundException e) { 65 | e.printStackTrace(); 66 | } catch (NoSuchMethodException e) { 67 | e.printStackTrace(); 68 | } catch (IllegalAccessException e) { 69 | e.printStackTrace(); 70 | } catch (InvocationTargetException e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | gDoctor 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.4.2") 16 | 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenLocal() 25 | maven { 26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 27 | url("$rootDir/../node_modules/react-native/android") 28 | } 29 | maven { 30 | // Android JSC is installed from npm 31 | url("$rootDir/../node_modules/jsc-android/dist") 32 | } 33 | 34 | google() 35 | jcenter() 36 | maven { url 'https://jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | 23 | MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore 24 | MYAPP_UPLOAD_KEY_ALIAS=my-key-alias 25 | MYAPP_UPLOAD_STORE_PASSWORD=secure123 26 | MYAPP_UPLOAD_KEY_PASSWORD=secure123 27 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'gDoctor' 2 | include ':react-native-vector-icons' 3 | project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') 4 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 5 | include ':app' 6 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gDoctor", 3 | "displayName": "gDoctor" 4 | } -------------------------------------------------------------------------------- /assets/fonts/Lato-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/assets/fonts/Lato-Black.ttf -------------------------------------------------------------------------------- /assets/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/assets/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/assets/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /ignite/ignite.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdWith": "3.5.1", 3 | "boilerplate": "ignite-andross", 4 | "examples": "classic", 5 | "navigation": "react-navigation", 6 | "askToOverwrite": true, 7 | "generators": { 8 | "component": "ignite-andross", 9 | "container": "ignite-andross", 10 | "listview": "ignite-andross", 11 | "list": "ignite-andross", 12 | "redux": "ignite-andross", 13 | "saga": "ignite-andross", 14 | "screen": "ignite-andross" 15 | }, 16 | "boilerplateVersion": "4.2.0" 17 | } -------------------------------------------------------------------------------- /ignite/plugins/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libscode/gDoctor/14242a614de669025373af97c0d58ac3f14c71e2/ignite/plugins/.gitkeep -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import './App/Config/ReactotronConfig' 2 | import { AppRegistry } from 'react-native' 3 | import App from './App/Containers/App' 4 | 5 | AppRegistry.registerComponent('gDoctor', () => App) 6 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | target 'gDoctor' do 5 | # Pods for gDoctor 6 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 7 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 8 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 9 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 10 | pod 'React', :path => '../node_modules/react-native/' 11 | pod 'React-Core', :path => '../node_modules/react-native/' 12 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 13 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 14 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 15 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 16 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 17 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 18 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 19 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 20 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 21 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 22 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 23 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 24 | 25 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 26 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 27 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 28 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 29 | pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" 30 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 31 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 32 | 33 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 34 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 35 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 36 | 37 | 38 | 39 | 40 | pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons' 41 | 42 | target 'gDoctorTests' do 43 | inherit! :search_paths 44 | # Pods for testing 45 | end 46 | 47 | use_native_modules! 48 | end 49 | 50 | target 'gDoctor-tvOS' do 51 | # Pods for gDoctor-tvOS 52 | 53 | target 'gDoctor-tvOSTests' do 54 | inherit! :search_paths 55 | # Pods for testing 56 | end 57 | 58 | end 59 | -------------------------------------------------------------------------------- /ios/gDoctor-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ios/gDoctor-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/gDoctor.xcodeproj/xcshareddata/xcschemes/gDoctor-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ios/gDoctor.xcodeproj/xcshareddata/xcschemes/gDoctor.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ios/gDoctor.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/gDoctor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/gDoctor/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/gDoctor/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 19 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 20 | moduleName:@"gDoctor" 21 | initialProperties:nil]; 22 | 23 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 24 | 25 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 26 | UIViewController *rootViewController = [UIViewController new]; 27 | rootViewController.view = rootView; 28 | self.window.rootViewController = rootViewController; 29 | [self.window makeKeyAndVisible]; 30 | return YES; 31 | } 32 | 33 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 34 | { 35 | #if DEBUG 36 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 37 | #else 38 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 39 | #endif 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ios/gDoctor/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ios/gDoctor/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ios/gDoctor/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ios/gDoctor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | gDoctor 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | UIAppFonts 57 | 58 | Lato-Black.ttf 59 | Lato-Bold.ttf 60 | Lato-Regular.ttf 61 | AntDesign.ttf 62 | Entypo.ttf 63 | EvilIcons.ttf 64 | Feather.ttf 65 | FontAwesome.ttf 66 | FontAwesome5_Brands.ttf 67 | FontAwesome5_Regular.ttf 68 | FontAwesome5_Solid.ttf 69 | Foundation.ttf 70 | Ionicons.ttf 71 | MaterialCommunityIcons.ttf 72 | MaterialIcons.ttf 73 | Octicons.ttf 74 | SimpleLineIcons.ttf 75 | Zocial.ttf 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /ios/gDoctor/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ios/gDoctorTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/gDoctorTests/gDoctorTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 16 | 17 | @interface gDoctorTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation gDoctorTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | #ifdef DEBUG 44 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 45 | if (level >= RCTLogLevelError) { 46 | redboxError = message; 47 | } 48 | }); 49 | #endif 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | #ifdef DEBUG 64 | RCTSetLogFunction(RCTDefaultLogFunction); 65 | #endif 66 | 67 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 68 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require("metro-config"); 2 | 3 | module.exports = (async () => { 4 | const { 5 | resolver: { sourceExts, assetExts } 6 | } = await getDefaultConfig(); 7 | return { 8 | transformer: { 9 | babelTransformerPath: require.resolve("react-native-svg-transformer"), 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | resolver: { 18 | assetExts: assetExts.filter(ext => ext !== "svg"), 19 | sourceExts: [...sourceExts, "svg"] 20 | } 21 | }; 22 | })(); 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gDoctor", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "standard --verbose | snazzy", 11 | "clean": "rm -rf $TMPDIR/react-* && watchman watch-del-all && npm cache clean --force", 12 | "clean:android": "cd android/ && ./gradlew clean && cd .. && npx react-native run-android", 13 | "newclear": "rm -rf $TMPDIR/react-* && watchman watch-del-all && rm -rf ios/build && rm -rf node_modules/ && npm cache clean --force && npm i", 14 | "test:watch": "jest --watch", 15 | "updateSnapshot": "jest --updateSnapshot", 16 | "coverage": "jest --coverage && open coverage/lcov-report/index.html || xdg-open coverage/lcov-report/index.html", 17 | "android:build": "cd android && ./gradlew assembleRelease", 18 | "android:install": "cd android && ./gradlew assembleRelease && ./gradlew installRelease", 19 | "android:hockeyapp": "cd android && ./gradlew assembleRelease && puck -submit=auto app/build/outputs/apk/app-release.apk", 20 | "android:devices": "$ANDROID_HOME/platform-tools/adb devices", 21 | "android:logcat": "$ANDROID_HOME/platform-tools/adb logcat *:S ReactNative:V ReactNativeJS:V", 22 | "android:shake": "$ANDROID_HOME/platform-tools/adb devices | grep '\\t' | awk '{print $1}' | sed 's/\\s//g' | xargs -I {} $ANDROID_HOME/platform-tools/adb -s {} shell input keyevent 82", 23 | "storybook": "storybook start -p 7007", 24 | "lintdiff": "git diff --name-only --cached --relative | grep '\\.js$' | xargs standard | snazzy", 25 | "fixcode": "standard --fix", 26 | "git-hook": "npm run lint -s && npm run test -s" 27 | }, 28 | "dependencies": { 29 | "@react-native-community/masked-view": "^0.1.6", 30 | "apisauce": "^1.1.1", 31 | "babel-plugin-ignite-ignore-reactotron": "^0.3.0", 32 | "format-json": "^1.0.3", 33 | "identity-obj-proxy": "^3.0.0", 34 | "lodash": "^4.17.15", 35 | "osmicsx": "^0.3.2", 36 | "prop-types": "^15.7.2", 37 | "querystringify": "^2.1.1", 38 | "ramda": "^0.27.0", 39 | "ramdasauce": "^2.1.3", 40 | "react": "16.9.0", 41 | "react-native": "0.61.4", 42 | "react-native-animatable": "^1.3.3", 43 | "react-native-config": "^0.12.0", 44 | "react-native-device-info": "^5.3.0", 45 | "react-native-gesture-handler": "^1.6.0", 46 | "react-native-i18n": "2.0.14", 47 | "react-native-reanimated": "^1.7.1", 48 | "react-native-safe-area-context": "^0.7.3", 49 | "react-native-screens": "^2.0.0-beta.10", 50 | "react-native-svg": "^12.0.3", 51 | "react-native-vector-icons": "6.1.0", 52 | "react-navigation": "4.1.1", 53 | "react-navigation-redux-helpers": "^4.0.1", 54 | "react-navigation-stack": "^2.1.1", 55 | "react-navigation-tabs": "^2.7.0", 56 | "react-redux": "^7.1.3", 57 | "redux": "^4.0.4", 58 | "redux-persist": "^5.10.0", 59 | "redux-saga": "^1.1.3", 60 | "reduxsauce": "^1.1.1", 61 | "seamless-immutable": "^7.1.4" 62 | }, 63 | "devDependencies": { 64 | "@babel/core": "^7.7.2", 65 | "@babel/runtime": "^7.7.2", 66 | "@react-native-community/eslint-config": "^0.0.5", 67 | "@storybook/addon-actions": "5.0.11", 68 | "@storybook/addon-links": "5.0.11", 69 | "@storybook/addon-storyshots": "^4.1.11", 70 | "@storybook/addons": "^4.1.11", 71 | "@storybook/channels": "^4.1.11", 72 | "@storybook/react-native": "^4.1.11", 73 | "babel-eslint": "7.1.1", 74 | "babel-jest": "^24.9.0", 75 | "eslint": "^6.6.0", 76 | "ignite-andross": "^4.2.0", 77 | "ignite-animatable": "1.0.2", 78 | "ignite-i18n": "1.2.0", 79 | "ignite-redux-persist": "1.1.2", 80 | "ignite-standard": "1.0.0", 81 | "ignite-vector-icons": "1.1.1", 82 | "jest": "^24.9.0", 83 | "metro-react-native-babel-preset": "^0.57.0", 84 | "react-native-svg-transformer": "^0.14.3", 85 | "react-test-renderer": "16.9.0", 86 | "reactotron-react-native": "^4.0.2", 87 | "reactotron-redux": "^3.1.2", 88 | "reactotron-redux-saga": "^4.2.2", 89 | "snazzy": "^8.0.0", 90 | "standard": "10.0.2" 91 | }, 92 | "jest": { 93 | "preset": "react-native", 94 | "testMatch": [ 95 | "/Tests/**/*.js", 96 | "**/?(*.)(spec|test).js?(x)" 97 | ], 98 | "testPathIgnorePatterns": [ 99 | "/node_modules/", 100 | "/Tests/Setup.js" 101 | ], 102 | "moduleNameMapper": { 103 | "^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "identity-obj-proxy" 104 | }, 105 | "transform": { 106 | "^.+\\.(js)$": "/node_modules/react-native/jest/preprocessor.js" 107 | }, 108 | "setupFiles": [ 109 | "/Tests/Setup" 110 | ] 111 | }, 112 | "config": {}, 113 | "standard": { 114 | "parser": "babel-eslint", 115 | "globals": [ 116 | "describe", 117 | "test", 118 | "jest", 119 | "expect", 120 | "fetch", 121 | "navigator", 122 | "__DEV__", 123 | "XMLHttpRequest", 124 | "FormData", 125 | "React$Element" 126 | ] 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | project: { 3 | ios: {}, 4 | android: {} 5 | }, 6 | assets: ['./assets/fonts/'] 7 | } 8 | --------------------------------------------------------------------------------