├── frontend ├── .watchmanconfig ├── .gitattributes ├── app.json ├── babel.config.js ├── android │ ├── app │ │ ├── debug.keystore │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── 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 │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── devdoido │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ └── MainApplication.java │ │ │ │ └── AndroidManifest.xml │ │ │ └── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── devdoido │ │ │ │ └── ReactNativeFlipper.java │ │ ├── proguard-rules.pro │ │ ├── build_defs.bzl │ │ ├── BUCK │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── build.gradle │ ├── gradle.properties │ ├── gradlew.bat │ └── gradlew ├── ios │ ├── devdoido │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Info.plist │ │ ├── AppDelegate.m │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── devdoidoTests │ │ ├── Info.plist │ │ └── devdoidoTests.m │ ├── devdoido-tvOSTests │ │ └── Info.plist │ ├── devdoido-tvOS │ │ └── Info.plist │ ├── devdoido.xcodeproj │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ ├── devdoido.xcscheme │ │ │ │ └── devdoido-tvOS.xcscheme │ │ └── project.pbxproj │ └── Podfile ├── .buckconfig ├── src │ ├── services │ │ └── api.js │ ├── appStore │ │ ├── appSagas.js │ │ ├── appModules │ │ │ ├── user │ │ │ │ ├── actions.js │ │ │ │ ├── reducer.js │ │ │ │ └── sagas.js │ │ │ └── auth │ │ │ │ ├── actions.js │ │ │ │ ├── reducer.js │ │ │ │ └── sagas.js │ │ └── appStore.js │ ├── screens │ │ ├── Home │ │ │ ├── styles.js │ │ │ └── Home.js │ │ ├── Payment │ │ │ ├── PaymentCart │ │ │ │ ├── styles.js │ │ │ │ └── PaymentCart.js │ │ │ ├── PaymentAddress │ │ │ │ ├── styles.js │ │ │ │ └── PaymentAddress.js │ │ │ └── CompleteRegister │ │ │ │ ├── styles.js │ │ │ │ └── CompleteRegister.js │ │ ├── Profile │ │ │ ├── styles.js │ │ │ └── Profile.js │ │ ├── SignUp │ │ │ ├── styles.js │ │ │ └── SignUp.js │ │ └── SignIn │ │ │ ├── styles.js │ │ │ └── SignIn.js │ ├── components │ │ ├── Background │ │ │ └── Background.js │ │ ├── Input │ │ │ ├── styles.js │ │ │ └── Input.js │ │ └── Button │ │ │ ├── styles.js │ │ │ └── Button.js │ ├── utils │ │ ├── appMetrics.js │ │ └── appColors.js │ ├── appNavigation │ │ ├── NavigatorSelector.js │ │ └── navigators │ │ │ ├── AdminNavigator.js │ │ │ └── ClientNavigator.js │ └── config │ │ └── reactotronConfig.js ├── .editorconfig ├── .prettierrc.js ├── index.js ├── __tests__ │ └── App-test.js ├── metro.config.js ├── routes.js ├── .gitignore ├── App.js ├── .eslintrc.js ├── .flowconfig └── package.json ├── backend ├── .gitignore ├── server.js ├── README.md ├── .eslintrc.js ├── routes │ ├── card-router.js │ ├── transaction-router.js │ └── user-router.js ├── controllers │ ├── card-controller.js │ ├── user-controller.js │ └── transaction-controller.js ├── repositories │ ├── transaction-repository.js │ ├── card-repository.js │ └── user-repository.js ├── bin │ ├── express.js │ ├── helpers │ │ └── validation.js │ └── base │ │ ├── repository-base.js │ │ └── controller-base.js ├── package.json ├── models │ ├── transaction-model.js │ ├── user-model.js │ └── card-model.js └── middlewares │ └── authentication.js └── README.md /frontend/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /frontend/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /frontend/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devdoido", 3 | "displayName": "devdoido" 4 | } -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/debug.keystore -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | devdoido 3 | 4 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /frontend/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /frontend/src/services/api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const api = axios.create({baseURL: 'https://devdoido.herokuapp.com/api/'}); 4 | 5 | export default api; 6 | -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style = space 4 | indent_size = 2 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gumiranda/pagarme-reactnative/HEAD/frontend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /frontend/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | eslintIntegration: true, 7 | arrowParens: 'avoid', 8 | }; 9 | -------------------------------------------------------------------------------- /frontend/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /frontend/src/appStore/appSagas.js: -------------------------------------------------------------------------------- 1 | import {all} from 'redux-saga/effects'; 2 | import auth from './appModules/auth/sagas'; 3 | import user from './appModules/user/sagas'; 4 | 5 | export default function* appSagas() { 6 | return yield all([auth, user]); 7 | } 8 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /backend/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const app = require('./bin/express'); 4 | const server = require('http').Server(app); 5 | 6 | let port = process.env.PORT || 3333; 7 | 8 | server.listen(port,()=>{ 9 | console.log('Servidor do faustão está no ar, no seu computador'); 10 | }); -------------------------------------------------------------------------------- /frontend/src/screens/Home/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {appColors} from '../../utils/appColors'; 3 | 4 | export const Title = styled.Text` 5 | font-size: 20px; 6 | color: ${appColors.white}; 7 | font-weight: bold; 8 | align-self: center; 9 | margin-vertical: 15px; 10 | `; 11 | -------------------------------------------------------------------------------- /frontend/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /frontend/src/components/Background/Background.js: -------------------------------------------------------------------------------- 1 | import LinearGradient from 'react-native-linear-gradient'; 2 | import styled from 'styled-components/native'; 3 | import {appColors} from '../../utils/appColors'; 4 | 5 | export default styled(LinearGradient).attrs({ 6 | colors: [appColors.primary, appColors.black], 7 | })` 8 | flex: 1; 9 | `; 10 | -------------------------------------------------------------------------------- /frontend/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /frontend/src/components/Input/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {appColors} from '../../utils/appColors'; 3 | 4 | export const Container = styled.View` 5 | padding: 0 15px; 6 | height: 54px; 7 | background: ${appColors.white90}; 8 | border-radius: 4px; 9 | flex-direction: row; 10 | align-items: center; 11 | `; 12 | -------------------------------------------------------------------------------- /frontend/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /backend/README.md: -------------------------------------------------------------------------------- 1 | # Estruturação Inicial Backend Node Express MongoDB 2 | Estruturação inicial do backend do canal do dev Doido Aula 1 - com Fausto Silva https://www.youtube.com/watch?v=UFl0ZYZ-1Ho 3 | 4 | 5 | Não esqueça de setar as variáveis no .env e o definindo seu ambiente (DEV por exemplo, pelo comando SET NODE_ENV=development no cmd) e no .env definir NODE_ENV=development e as variáveis secretKey,connection,pagarme. 6 | -------------------------------------------------------------------------------- /backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | commonjs: true, 4 | es6: true, 5 | node: true, 6 | }, 7 | extends: ['airbnb-base', 'prettier'], 8 | globals: { 9 | Atomics: 'readonly', 10 | SharedArrayBuffer: 'readonly', 11 | }, 12 | parser: 'babel-eslint', 13 | parserOptions: { 14 | ecmaVersion: 11, 15 | }, 16 | rules: { 17 | 'import/prefer-default-export': 'off', 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /frontend/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /backend/routes/card-router.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | const controller = require('../controllers/card-controller'); 5 | const auth = require('../middlewares/authentication'); 6 | 7 | const _ctrl = new controller(); 8 | 9 | router.get('/', auth, _ctrl.get); 10 | // router.post("/",auth,_ctrl.post); 11 | router.delete('/:id', auth, _ctrl.delete); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /frontend/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'devdoido' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | include ':@react-native-community_async-storage' 5 | project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android') 6 | -------------------------------------------------------------------------------- /backend/routes/transaction-router.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | const controller = require('../controllers/transaction-controller'); 5 | const auth = require('../middlewares/authentication'); 6 | 7 | const _ctrl = new controller(); 8 | 9 | router.get('/', auth, _ctrl.get); 10 | router.post('/', auth, _ctrl.post); 11 | router.delete('/:id', auth, _ctrl.delete); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /frontend/src/utils/appMetrics.js: -------------------------------------------------------------------------------- 1 | import {Dimensions} from 'react-native'; 2 | 3 | const x = Dimensions.get('window').width; 4 | const y = Dimensions.get('window').height; 5 | const xScreen = Dimensions.get('screen').width; 6 | const yScreen = Dimensions.get('screen').height; 7 | 8 | const appMetrics = { 9 | DEVICE_WIDTH: x, 10 | SCREEN_WIDTH: xScreen, 11 | DEVICE_HEIGTH: y, 12 | SCREEN_HEIGHT: yScreen, 13 | }; 14 | 15 | export default appMetrics; 16 | -------------------------------------------------------------------------------- /frontend/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 | -------------------------------------------------------------------------------- /frontend/src/appNavigation/NavigatorSelector.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {useSelector} from 'react-redux'; 3 | import AdminNavigator from './navigators/AdminNavigator'; 4 | import ClientNavigator from './navigators/ClientNavigator'; 5 | 6 | const NavigatorSelector = () => { 7 | const profile = useSelector(state => state.user.profile); 8 | if (profile.type === 'admin') { 9 | return ; 10 | } 11 | return ; 12 | }; 13 | 14 | export default NavigatorSelector; 15 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/user/actions.js: -------------------------------------------------------------------------------- 1 | export function updateProfileFailure() { 2 | return {type: '@user/UPDATE_PROFILE_FAILURE'}; 3 | } 4 | export function updateProfileRequest(data) { 5 | return {type: '@user/UPDATE_PROFILE_REQUEST', payload: {data}}; 6 | } 7 | export function completeProfileRequest(data) { 8 | return {type: '@user/COMPLETE_PROFILE_REQUEST', payload: {data}}; 9 | } 10 | export function updateProfileSuccess(profile) { 11 | return {type: '@user/UPDATE_PROFILE_SUCCESS', payload: {profile}}; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/components/Button/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {RectButton} from 'react-native-gesture-handler'; 3 | import {appColors} from '../../utils/appColors'; 4 | 5 | export const Container = styled(RectButton)` 6 | height: 46px; 7 | background: ${appColors.darkBlue}; 8 | border-radius: 4px; 9 | align-items: center; 10 | justify-content: center; 11 | `; 12 | 13 | export const Text = styled.Text` 14 | color: ${appColors.white}; 15 | font-weight: bold; 16 | font-size: 16px; 17 | `; 18 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/auth/actions.js: -------------------------------------------------------------------------------- 1 | export function signInRequest(data) { 2 | return {type: '@auth/SIGN_IN_REQUEST', payload: data}; 3 | } 4 | export function signInSuccess(token, user) { 5 | return {type: '@auth/SIGN_IN_SUCCESS', payload: {token, user}}; 6 | } 7 | export function signUpRequest(data) { 8 | return {type: '@auth/SIGN_UP_REQUEST', payload: data}; 9 | } 10 | export function signFailure() { 11 | return {type: '@auth/SIGN_FAILURE'}; 12 | } 13 | export function signOut() { 14 | return {type: '@auth/SIGN_OUT'}; 15 | } 16 | -------------------------------------------------------------------------------- /backend/controllers/card-controller.js: -------------------------------------------------------------------------------- 1 | const repository = require('../repositories/card-repository'); 2 | 3 | const _repo = new repository(); 4 | const ctrlBase = require('../bin/base/controller-base'); 5 | const validation = require('../bin/helpers/validation'); 6 | 7 | function cardController() {} 8 | 9 | cardController.prototype.get = async (req, res) => { 10 | ctrlBase.getMyAll(_repo, req, res); 11 | }; 12 | cardController.prototype.delete = async (req, res) => { 13 | ctrlBase.delete(_repo, req, res); 14 | }; 15 | 16 | module.exports = cardController; 17 | -------------------------------------------------------------------------------- /frontend/routes.js: -------------------------------------------------------------------------------- 1 | import {createAppContainer, createSwitchNavigator} from 'react-navigation'; 2 | import SignIn from './src/screens/SignIn/SignIn'; 3 | import SignUp from './src/screens/SignUp/SignUp'; 4 | import NavigatorSelector from './src/appNavigation/NavigatorSelector'; 5 | 6 | export default (isSigned = false) => 7 | createAppContainer( 8 | createSwitchNavigator( 9 | { 10 | Sign: createSwitchNavigator({SignIn, SignUp}), 11 | NavigatorSelector, 12 | }, 13 | {initialRouteName: isSigned ? 'NavigatorSelector' : 'Sign'}, 14 | ), 15 | ); 16 | -------------------------------------------------------------------------------- /backend/routes/user-router.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | const controller = require('../controllers/user-controller'); 5 | const auth = require('../middlewares/authentication'); 6 | 7 | const _ctrl = new controller(); 8 | 9 | router.post('/register', _ctrl.post); 10 | router.post('/authenticate', _ctrl.authenticate); 11 | router.put('/completeRegister', auth, _ctrl.completeRegister); 12 | router.get('/', auth, _ctrl.get); 13 | router.put('/:id', auth, _ctrl.put); 14 | router.delete('/:id', auth, _ctrl.delete); 15 | 16 | module.exports = router; 17 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/PaymentCart/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {appColors} from '../../../utils/appColors'; 3 | import Button from '../../../components/Button/Button'; 4 | 5 | export const Title = styled.Text` 6 | font-size: 20px; 7 | color: ${appColors.white}; 8 | font-weight: bold; 9 | align-self: center; 10 | margin-vertical: 15px; 11 | `; 12 | export const Container = styled.SafeAreaView` 13 | font-size: 20px; 14 | color: ${appColors.white}; 15 | font-weight: bold; 16 | align-self: center; 17 | `; 18 | 19 | export const SubmitButton = styled(Button)` 20 | margin-top: 5px; 21 | border-radius: 20px; 22 | `; 23 | -------------------------------------------------------------------------------- /frontend/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 | -------------------------------------------------------------------------------- /frontend/src/components/Button/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {ActivityIndicator} from 'react-native'; 3 | import PropTypes from 'prop-types'; 4 | import {Container, Text} from './styles'; 5 | import {appColors} from '../../utils/appColors'; 6 | 7 | export default function Button({children, loading, ...rest}) { 8 | return ( 9 | 10 | {loading ? ( 11 | 12 | ) : ( 13 | {children} 14 | )} 15 | 16 | ); 17 | } 18 | 19 | Button.propTypes = { 20 | children: PropTypes.string.isRequired, 21 | loading: PropTypes.bool, 22 | }; 23 | 24 | Button.defaultProps = { 25 | loading: false, 26 | }; 27 | -------------------------------------------------------------------------------- /backend/repositories/transaction-repository.js: -------------------------------------------------------------------------------- 1 | require('../models/transaction-model'); 2 | const base = require('../bin/base/repository-base'); 3 | 4 | class transactionRepository { 5 | constructor() { 6 | this._base = new base('Transaction'); 7 | } 8 | 9 | async getMyAll(user) { 10 | return await this._base.getMyAll(user); 11 | } 12 | 13 | async delete(id, user) { 14 | const model = await this._base.getById(id); 15 | if (model.userId.toString() === user._id) { 16 | return await this._base.delete(id); 17 | } 18 | return 'Operação Inválida'; 19 | } 20 | 21 | async create(data) { 22 | const transaction = await this._base.create(data); 23 | return transaction; 24 | } 25 | } 26 | module.exports = transactionRepository; 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Aula7DevDoido 2 | Código desenvolvido na aula 7 do canal do Dev Doido 3 | https://youtu.be/dP0QtPpsgYg 4 | # Descrição 5 | Mais um video da serie de como fazer um aplicativo React Native integrando a lib da PAGAR.ME com Craque Neto, Faustão e particiação especial do Zeca Camargo. Nesse projeto vocês irão: 6 | - Criar endpoint e tela de completar cadastro (cpf e telefone) - Tela de endereço de cobrança e autocomplete de cep usando a lib cep-promise 7 | - Tela de cartão de crédito utilizando o componente react-native-creditcard-input 8 | - Criptografia dos dados do cartão na comunicação com o backend 9 | - Integração com o backend desenvolvido na aula 3 10 | - Validação de formulários com o Yup e o Formik 11 | - useEffect,useState e useRef 12 | - action completeRegister no redux sagas 13 | - Homepage 14 | -------------------------------------------------------------------------------- /backend/repositories/card-repository.js: -------------------------------------------------------------------------------- 1 | require('../models/card-model'); 2 | const base = require('../bin/base/repository-base'); 3 | 4 | class cardRepository { 5 | constructor() { 6 | this._base = new base('Card'); 7 | } 8 | 9 | async getMyAll(user) { 10 | return await this._base.getMyAll(user); 11 | } 12 | 13 | async getById(id) { 14 | return await this._base.getById(id); 15 | } 16 | 17 | async delete(id, user) { 18 | const model = await this._base.getById(id); 19 | if (model.userId.toString() === user._id) { 20 | return await this._base.delete(id); 21 | } 22 | return 'Operação Inválida'; 23 | } 24 | 25 | async create(data) { 26 | const card = await this._base.create(data); 27 | return card; 28 | } 29 | } 30 | module.exports = cardRepository; 31 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /frontend/src/screens/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | import {useSelector} from 'react-redux'; 3 | import {Title} from './styles'; 4 | import Background from '../../components/Background/Background'; 5 | 6 | export default function Home({navigation}) { 7 | const profile = useSelector(state => state.user.profile); 8 | useEffect(() => { 9 | if (new Date(profile.payDay).getTime() < new Date().getTime()) { 10 | if (profile.cpf && profile.phone) { 11 | navigation.navigate('Payment'); 12 | } else { 13 | navigation.navigate('CompleteRegister'); 14 | } 15 | } 16 | }, [navigation, profile.cpf, profile.payDay, profile.phone]); 17 | 18 | return ( 19 | 20 | Homepage do Faustão 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /backend/bin/express.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const mongoose = require('mongoose'); 4 | const variables = require('./configuration/variables'); 5 | const userRouter = require('../routes/user-router'); 6 | const cardRouter = require('../routes/card-router'); 7 | const transactionRouter = require('../routes/transaction-router'); 8 | 9 | const app = express(); 10 | 11 | app.use(bodyParser.json()); 12 | app.use(bodyParser.urlencoded({ extended: false })); 13 | 14 | module.exports = app; 15 | 16 | mongoose.connect(variables.Database.connection, { 17 | useUnifiedTopology: true, 18 | useNewUrlParser: true, 19 | useCreateIndex: true, 20 | }); 21 | 22 | app.use('/api/user', userRouter); 23 | app.use('/api/transaction', transactionRouter); 24 | app.use('/api/card', cardRouter); 25 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DevDoido", 3 | "version": "1.0.0", 4 | "description": "Um bom projeto", 5 | "main": "server.js", 6 | "author": "Gustavo Miranda", 7 | "license": "MIT", 8 | "dependencies": { 9 | "bcryptjs": "^2.4.3", 10 | "body-parser": "^1.19.0", 11 | "express": "^4.17.1", 12 | "http": "^0.0.1-security", 13 | "jsonwebtoken": "^8.5.1", 14 | "moment": "^2.25.3", 15 | "mongoose": "^5.9.14", 16 | "pagarme": "^4.8.0", 17 | "react-native-crypto-js": "^1.0.0" 18 | }, 19 | "devDependencies": { 20 | "babel-eslint": "^10.1.0", 21 | "eslint": "^6.8.0", 22 | "eslint-config-airbnb-base": "^14.1.0", 23 | "eslint-config-prettier": "^6.11.0", 24 | "eslint-plugin-import": "^2.20.2", 25 | "eslint-plugin-prettier": "^3.1.3", 26 | "prettier": "^2.0.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frontend/ios/devdoidoTests/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 | -------------------------------------------------------------------------------- /frontend/src/utils/appColors.js: -------------------------------------------------------------------------------- 1 | export const appColors = { 2 | primary: '#8469e0', 3 | lightgreen: '#2ecc71', 4 | green: '#65bf50', 5 | secondary: '#171717', 6 | white30: 'rgba(255,255,255,0.3)', 7 | white20: 'rgba(255,255,255,0.2)', 8 | white10: 'rgba(255,255,255,0.1)', 9 | white40: 'rgba(255,255,255,0.4)', 10 | white50: 'rgba(255,255,255,0.5)', 11 | white60: 'rgba(255,255,255,0.6)', 12 | white90: 'rgba(255,255,255,0.9)', 13 | black: 'black', 14 | white: '#fff', 15 | gray: 'gray', 16 | ligthGray: '#D8D8D8', 17 | transparent: 'transparent', 18 | red: 'red', 19 | darkBlue: '#2769D3', 20 | filterBlue: '#3578E5', 21 | lightBlue: `rgba(53,120,229,0.6)`, 22 | extraLightBlue: `rgba(53,120,229,0.08)`, 23 | dark_gray: '#657786', 24 | light_gray: '#AAB8C2', 25 | exlight_gray: '#E1E8ED', 26 | exexlight_gray: '#F5F8FA', 27 | }; 28 | export default appColors; 29 | -------------------------------------------------------------------------------- /frontend/ios/devdoido-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 | -------------------------------------------------------------------------------- /backend/models/transaction-model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const schema = mongoose.Schema; 4 | const { ObjectId } = mongoose.Schema; 5 | 6 | const transactionModel = new schema( 7 | { 8 | transaction_id: { type: String }, 9 | status: { type: String }, 10 | authorization_code: { type: String }, 11 | risk_level: { type: String }, 12 | acquirer_id: { type: String }, 13 | userId: { type: ObjectId, ref: 'User' }, 14 | cardId: { type: ObjectId, ref: 'Card' }, 15 | ativo: { type: Boolean, required: true, default: true }, 16 | createdAt: { type: Date, default: Date.now }, 17 | }, 18 | { versionKey: false }, 19 | ); 20 | 21 | transactionModel.pre('save', (next) => { 22 | const agora = new Date(); 23 | if (!this.dataCriacao) this.dataCriacao = agora; 24 | next(); 25 | }); 26 | 27 | module.exports = mongoose.model('Transaction', transactionModel); 28 | -------------------------------------------------------------------------------- /backend/middlewares/authentication.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const variables = require('../bin/configuration/variables'); 3 | const usuario = require('../models/user-model'); 4 | 5 | module.exports = async (req, res, next) => { 6 | const authHeader = req.headers.authorization; 7 | const [, token] = authHeader.split(' '); 8 | if (token) { 9 | try { 10 | const decoded = await jwt.verify(token, variables.Security.secretKey); 11 | req.usuarioLogado = decoded; 12 | const userExiste = await usuario.findById(req.usuarioLogado.user._id); 13 | if (!userExiste) { 14 | res.status(401).send({ message: 'Usuario não existe' }); 15 | return; 16 | } 17 | next(); 18 | } catch (e) { 19 | res.status(401).send({ message: 'Token é inválido' }); 20 | } 21 | } else { 22 | res.status(401).send({ message: 'Token deve ser informado' }); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /backend/bin/helpers/validation.js: -------------------------------------------------------------------------------- 1 | class ValidationContract { 2 | constructor() { 3 | this._errors = []; 4 | } 5 | 6 | isNotArrayOrEmpty(value, message) { 7 | if (!value && value.length == 0) { 8 | this._errors.push({ message }); 9 | } 10 | } 11 | 12 | isTrue(value, message) { 13 | if (value) { 14 | this._errors.push({ message }); 15 | } 16 | } 17 | 18 | isRequired(value, message) { 19 | if (!value || value.length <= 0) { 20 | this._errors.push({ message }); 21 | } 22 | } 23 | 24 | isEmail(value, message) { 25 | const reg = new RegExp(/^\w+([-+,']\w+)*@\w+([-,]\w+)*\.\w+([-.]\w+)*$/); 26 | if (!reg.test(value)) { 27 | this._errors.push({ message }); 28 | } 29 | } 30 | 31 | errors() { 32 | return this._errors; 33 | } 34 | 35 | isValid() { 36 | return this._errors.length == 0; 37 | } 38 | } 39 | 40 | module.exports = ValidationContract; 41 | -------------------------------------------------------------------------------- /backend/bin/base/repository-base.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | class baseRepository { 4 | constructor(model) { 5 | this._model = mongoose.model(model); 6 | } 7 | 8 | async create(data) { 9 | const modelo = new this._model(data); 10 | const resultado = await modelo.save(); 11 | return resultado; 12 | } 13 | 14 | async update(id, data, usuarioLogado) { 15 | await this._model.findByIdAndUpdate(id, { $set: data }); 16 | const resultado = await this._model.findById(id); 17 | return resultado; 18 | } 19 | 20 | async getAll() { 21 | return await this._model.find({}); 22 | } 23 | 24 | async getMyAll(user) { 25 | return await this._model.find({ userId: user._id }); 26 | } 27 | 28 | async delete(id) { 29 | return await this._model.findByIdAndDelete(id); 30 | } 31 | 32 | async getById(id) { 33 | return await this._model.findById(id); 34 | } 35 | } 36 | 37 | module.exports = baseRepository; 38 | -------------------------------------------------------------------------------- /frontend/android/app/src/main/java/com/devdoido/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.devdoido; 2 | 3 | import com.facebook.react.ReactActivityDelegate; 4 | import com.facebook.react.ReactRootView; 5 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 6 | import com.facebook.react.ReactActivity; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "devdoido"; 17 | } 18 | 19 | @Override 20 | protected ReactActivityDelegate createReactActivityDelegate() { 21 | return new ReactActivityDelegate(this, getMainComponentName()) { 22 | @Override 23 | protected ReactRootView createRootView() { 24 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 25 | } 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/screens/Profile/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import Input from '../../components/Input/Input'; 3 | import Button from '../../components/Button/Button'; 4 | import {appColors} from '../../utils/appColors'; 5 | 6 | export const Container = styled.SafeAreaView` 7 | flex: 1; 8 | `; 9 | export const Title = styled.Text` 10 | font-size: 20px; 11 | color: ${appColors.white}; 12 | font-weight: bold; 13 | align-self: center; 14 | margin-top: 30px; 15 | `; 16 | export const Form = styled.ScrollView.attrs({ 17 | showsVerticalScrollIndicator: false, 18 | contentContainerStyle: {padding: 30}, 19 | })` 20 | align-self: stretch; 21 | `; 22 | 23 | export const FormInput = styled(Input)` 24 | margin-vertical: 5px; 25 | `; 26 | export const SubmitButton = styled(Button)` 27 | margin-top: 5px; 28 | `; 29 | export const Separator = styled.View` 30 | height: 1px; 31 | background: ${appColors.black}; 32 | margin: 20px 0 30px; 33 | `; 34 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/PaymentAddress/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {appColors} from '../../../utils/appColors'; 3 | import Input from '../../../components/Input/Input'; 4 | import Button from '../../../components/Button/Button'; 5 | 6 | export const Title = styled.Text` 7 | font-size: 20px; 8 | color: ${appColors.white}; 9 | font-weight: bold; 10 | align-self: center; 11 | margin-vertical: 15px; 12 | `; 13 | export const Container = styled.SafeAreaView` 14 | font-size: 20px; 15 | color: ${appColors.white}; 16 | font-weight: bold; 17 | align-self: center; 18 | margin-top: 30px; 19 | `; 20 | export const Form = styled.ScrollView.attrs({ 21 | showsVerticalScrollIndicator: false, 22 | contentContainerStyle: {padding: 5}, 23 | })` 24 | align-self: stretch; 25 | `; 26 | export const FormInput = styled(Input)` 27 | margin-bottom: 10px; 28 | `; 29 | 30 | export const SubmitButton = styled(Button)` 31 | margin-top: 5px; 32 | `; 33 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/auth/reducer.js: -------------------------------------------------------------------------------- 1 | import produce from 'immer'; 2 | 3 | const INITIAL_STATE = { 4 | token: null, 5 | signed: false, 6 | loading: false, 7 | }; 8 | export default function auth(state = INITIAL_STATE, action) { 9 | return produce(state, draft => { 10 | switch (action.type) { 11 | case '@auth/SIGN_IN_SUCCESS': { 12 | draft.token = action.payload.token; 13 | draft.signed = true; 14 | draft.loading = false; 15 | break; 16 | } 17 | case '@auth/SIGN_IN_REQUEST': { 18 | draft.loading = true; 19 | break; 20 | } 21 | case '@auth/SIGN_FAILURE': { 22 | draft.loading = false; 23 | break; 24 | } 25 | case '@auth/SIGN_OUT': { 26 | draft.token = null; 27 | draft.signed = false; 28 | break; 29 | } 30 | case '@auth/SIGN_UP_REQUEST': { 31 | draft.loading = true; 32 | break; 33 | } 34 | default: 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/CompleteRegister/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {appColors} from '../../../utils/appColors'; 3 | import Input from '../../../components/Input/Input'; 4 | import Button from '../../../components/Button/Button'; 5 | 6 | export const Title = styled.Text` 7 | font-size: 20px; 8 | color: ${appColors.white}; 9 | font-weight: bold; 10 | align-self: center; 11 | margin-vertical: 5px; 12 | `; 13 | export const Container = styled.SafeAreaView` 14 | font-size: 20px; 15 | color: ${appColors.white}; 16 | font-weight: bold; 17 | align-self: center; 18 | margin-top: 30px; 19 | `; 20 | export const Form = styled.ScrollView.attrs({ 21 | showsVerticalScrollIndicator: false, 22 | contentContainerStyle: {padding: 5}, 23 | })` 24 | align-self: stretch; 25 | `; 26 | export const FormInput = styled(Input)` 27 | margin-bottom: 10px; 28 | `; 29 | 30 | export const SubmitButton = styled(Button)` 31 | margin-top: 5px; 32 | border-radius: 4px; 33 | `; 34 | -------------------------------------------------------------------------------- /frontend/src/screens/SignUp/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {Platform} from 'react-native'; 3 | import Input from '../../components/Input/Input'; 4 | import Button from '../../components/Button/Button'; 5 | import {appColors} from '../../utils/appColors'; 6 | 7 | export const Container = styled.KeyboardAvoidingView.attrs({ 8 | enabled: Platform.OS === 'ios', 9 | behavior: 'padding', 10 | })` 11 | flex: 1; 12 | justify-content: center; 13 | align-items: center; 14 | padding: 0 30px; 15 | `; 16 | 17 | export const Form = styled.View` 18 | align-self: stretch; 19 | margin-top: 50px; 20 | `; 21 | export const FormInput = styled(Input)` 22 | margin-bottom: 10px; 23 | `; 24 | export const SubmitButton = styled(Button)` 25 | margin-top: 5px; 26 | `; 27 | export const SignLink = styled.TouchableOpacity` 28 | margin-top: 20px; 29 | `; 30 | export const SignLinkText = styled.Text` 31 | color: ${appColors.white}; 32 | font-weight: bold; 33 | font-size: 16px; 34 | `; 35 | -------------------------------------------------------------------------------- /frontend/src/screens/SignIn/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {Platform} from 'react-native'; 3 | import Input from '../../components/Input/Input'; 4 | import Button from '../../components/Button/Button'; 5 | import {appColors} from '../../utils/appColors'; 6 | 7 | export const Container = styled.KeyboardAvoidingView.attrs({ 8 | enabled: Platform.OS === 'ios', 9 | behavior: 'padding', 10 | })` 11 | flex: 1; 12 | justify-content: center; 13 | align-items: center; 14 | padding: 0 30px; 15 | `; 16 | 17 | export const Form = styled.View` 18 | align-self: stretch; 19 | margin-top: 50px; 20 | margin-bottom: 20px; 21 | `; 22 | export const FormInput = styled(Input)` 23 | margin-bottom: 10px; 24 | `; 25 | export const SubmitButton = styled(Button)` 26 | margin-top: 5px; 27 | `; 28 | export const SignLink = styled.TouchableOpacity` 29 | margin-top: 20px; 30 | `; 31 | export const SignLinkText = styled.Text` 32 | color: ${appColors.white}; 33 | font-weight: bold; 34 | font-size: 16px; 35 | `; 36 | -------------------------------------------------------------------------------- /backend/models/user-model.js: -------------------------------------------------------------------------------- 1 | 'user strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | 5 | const schema = mongoose.Schema; 6 | const { ObjectId } = mongoose.Schema; 7 | const moment = require('moment'); 8 | 9 | const userModel = new schema( 10 | { 11 | nome: { trim: true, index: true, required: true, type: String }, 12 | email: { type: String }, 13 | type: { type: String, default: 'client' }, 14 | cpf: { type: String }, 15 | phone: { type: String }, 16 | senha: { type: String }, 17 | ativo: { type: Boolean, required: true, default: true }, 18 | payDay: { type: Date, default: Date.now }, 19 | createdAt: { type: Date, default: Date.now }, 20 | }, 21 | { versionKey: false }, 22 | ); 23 | 24 | userModel.pre('save', (next) => { 25 | const agora = new Date(); 26 | const datav = new Date(moment().add(7, 'days')._d.toISOString()); 27 | if (!this.createdAt) this.createdAt = agora; 28 | if (!this.payDay) this.payDay = datav; 29 | next(); 30 | }); 31 | 32 | module.exports = mongoose.model('User', userModel); 33 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | -------------------------------------------------------------------------------- /backend/models/card-model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const schema = mongoose.Schema; 4 | const { ObjectId } = mongoose.Schema; 5 | 6 | const cardModel = new schema( 7 | { 8 | card_id: { type: String }, 9 | cardNumber: { type: String }, 10 | holder_name: { type: String }, 11 | name: { type: String }, 12 | brand: { type: String }, 13 | street: { type: String }, 14 | street_number: { type: String }, 15 | neighborhood: { type: String }, 16 | city: { type: String }, 17 | state: { type: String }, 18 | zipcode: { type: String }, 19 | phone: { type: String }, 20 | cpf: { type: String }, 21 | email: { type: String }, 22 | userId: { type: ObjectId, ref: 'User' }, 23 | ativo: { type: Boolean, required: true, default: true }, 24 | createdAt: { type: Date, default: Date.now }, 25 | }, 26 | { versionKey: false }, 27 | ); 28 | 29 | cardModel.pre('save', (next) => { 30 | const agora = new Date(); 31 | if (!this.dataCriacao) this.dataCriacao = agora; 32 | next(); 33 | }); 34 | 35 | module.exports = mongoose.model('Card', cardModel); 36 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/user/reducer.js: -------------------------------------------------------------------------------- 1 | import produce from 'immer'; 2 | 3 | const INITIAL_STATE = { 4 | profile: null, 5 | loading: false, 6 | }; 7 | 8 | export default function user(state = INITIAL_STATE, action) { 9 | return produce(state, draft => { 10 | switch (action.type) { 11 | case '@auth/SIGN_IN_SUCCESS': { 12 | draft.loading = false; 13 | draft.profile = action.payload.user; 14 | break; 15 | } 16 | case '@user/UPDATE_PROFILE_SUCCESS': { 17 | draft.loading = false; 18 | draft.profile = action.payload.profile; 19 | break; 20 | } 21 | case '@user/UPDATE_PROFILE_REQUEST': { 22 | draft.loading = true; 23 | break; 24 | } 25 | case '@user/COMPLETE_PROFILE_REQUEST': { 26 | draft.loading = true; 27 | break; 28 | } 29 | case '@user/UPDATE_PROFILE_FAILURE': { 30 | draft.loading = false; 31 | break; 32 | } 33 | case '@auth/SIGN_OUT': { 34 | draft.profile = null; 35 | break; 36 | } 37 | default: 38 | } 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /frontend/App.js: -------------------------------------------------------------------------------- 1 | import './src/config/reactotronConfig'; 2 | import React from 'react'; 3 | import {PersistGate} from 'redux-persist/integration/react'; 4 | import {Provider, useSelector} from 'react-redux'; 5 | import {StatusBar} from 'react-native'; 6 | import {Provider as PaperProvider} from 'react-native-paper'; 7 | import {darken} from 'polished'; 8 | import {appStore, appPersistor} from './src/appStore/appStore'; 9 | import createRouter from './routes'; 10 | import {appColors} from './src/utils/appColors'; 11 | 12 | function DevDoido() { 13 | const signed = useSelector(state => state.auth.signed); 14 | const Routes = createRouter(signed); 15 | return ; 16 | } 17 | 18 | const App = () => { 19 | return ( 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default App; 35 | -------------------------------------------------------------------------------- /frontend/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /frontend/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.5.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://www.jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /frontend/src/appStore/appStore.js: -------------------------------------------------------------------------------- 1 | import {persistReducer, persistStore} from 'redux-persist'; 2 | import AsyncStorage from '@react-native-community/async-storage'; 3 | import {createStore, compose, applyMiddleware, combineReducers} from 'redux'; 4 | import createSagaMiddleware from 'redux-saga'; 5 | import {createLogger} from 'redux-logger'; 6 | import auth from './appModules/auth/reducer'; 7 | import user from './appModules/user/reducer'; 8 | import appSagas from './appSagas'; 9 | 10 | const sagaMonitor = __DEV__ ? console.tron.createSagaMonitor() : null; 11 | const sagaMiddleware = createSagaMiddleware({sagaMonitor}); 12 | const middlewares = [sagaMiddleware, createLogger()]; 13 | 14 | const enhancer = __DEV__ 15 | ? compose(console.tron.createEnhancer(), applyMiddleware(...middlewares)) 16 | : applyMiddleware(...middlewares); 17 | 18 | const persistConfig = { 19 | key: 'devdoido', 20 | storage: AsyncStorage, 21 | whitelist: ['auth', 'user'], 22 | }; 23 | 24 | const rootReducer = combineReducers({auth, user}); 25 | const appStore = createStore( 26 | persistReducer(persistConfig, rootReducer), 27 | enhancer, 28 | ); 29 | 30 | const appPersistor = persistStore(appStore); 31 | 32 | sagaMiddleware.run(appSagas); 33 | 34 | export {appStore, appPersistor}; 35 | -------------------------------------------------------------------------------- /frontend/src/config/reactotronConfig.js: -------------------------------------------------------------------------------- 1 | import Reactotron, {overlay} from 'reactotron-react-native'; 2 | import {reactotronRedux} from 'reactotron-redux'; 3 | import sagaPlugin from 'reactotron-redux-saga'; 4 | import AsyncStorage from '@react-native-community/async-storage'; 5 | import {YellowBox} from 'react-native'; 6 | 7 | YellowBox.ignoreWarnings(['Remote debugger']); 8 | YellowBox.ignoreWarnings(['Unrecognized WebSocket']); 9 | YellowBox.ignoreWarnings([ 10 | 'Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?', 11 | ]); 12 | 13 | if (__DEV__) { 14 | const tron = Reactotron.configure() 15 | .useReactNative() 16 | .use(reactotronRedux()) 17 | .use(overlay()) 18 | .use(sagaPlugin()) 19 | .setAsyncStorageHandler(AsyncStorage) 20 | .connect(); 21 | tron.clear(); 22 | console.tron = tron; 23 | } else { 24 | const noop = () => undefined; 25 | console.tron = { 26 | configure: noop, 27 | connect: noop, 28 | use: noop, 29 | useReactNative: noop, 30 | clear: noop, 31 | log: noop, 32 | logImportant: noop, 33 | display: noop, 34 | error: noop, 35 | createEnhancer: noop, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true, 4 | }, 5 | extends: ['plugin:react/recommended', 'airbnb', 'prettier', 'prettier/react'], 6 | globals: { 7 | Atomics: 'readonly', 8 | SharedArrayBuffer: 'readonly', 9 | __DEV__: true, 10 | }, 11 | parser: 'babel-eslint', 12 | parserOptions: { 13 | ecmaFeatures: { 14 | jsx: true, 15 | }, 16 | ecmaVersion: 11, 17 | sourceType: 'module', 18 | }, 19 | plugins: ['react', 'prettier', 'import', 'react-hooks', 'jsx-a11y'], 20 | rules: { 21 | 'prettier/prettier': 'error', 22 | 'react/jsx-filename-extension': [ 23 | 'warn', 24 | { 25 | extensions: ['.jsx', '.js'], 26 | }, 27 | ], 28 | 'import/prefer-default-export': 'off', 29 | 'react/state-in-constructor': 'off', 30 | 'react/static-property-placement': 'off', 31 | 'react/jsx-props-no-spreading': 'off', 32 | 'react/prop-types': 'off', 33 | 'no-unused-vars': ['error', {argsIgnorePattern: '^_'}], 34 | 'react/jsx-one-expression-per-line': 'off', 35 | 'global-require': 'off', 36 | 'react-native/no-raw-text': 'off', 37 | 'no-param-reassign': 'off', 38 | 'no-underscore-dangle': 'off', 39 | camelcase: 'off', 40 | 'no-console': ['error', {allow: ['tron']}], 41 | 'react-hooks/rules-of-hooks': 'error', 42 | 'react-hooks/exhaustive-deps': 'warn', 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /frontend/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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.33.1 29 | -------------------------------------------------------------------------------- /frontend/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.devdoido", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.devdoido", 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 | -------------------------------------------------------------------------------- /frontend/src/appNavigation/navigators/AdminNavigator.js: -------------------------------------------------------------------------------- 1 | import {createAppContainer} from 'react-navigation'; 2 | import React from 'react'; 3 | import Icon from 'react-native-vector-icons/Octicons'; 4 | import LinearGradient from 'react-native-linear-gradient'; 5 | import {createDrawerNavigator} from 'react-navigation-drawer'; 6 | import Profile from '../../screens/Profile/Profile'; 7 | import appColors from '../../utils/appColors'; 8 | 9 | const drawerButton = navigation => ( 10 | { 16 | navigation.toggleDrawer(); 17 | }} 18 | /> 19 | ); 20 | 21 | export default createAppContainer( 22 | createDrawerNavigator( 23 | { 24 | Profile: { 25 | screen: Profile, 26 | navigationOptions: {drawerLabel: 'Meu perfil'}, 27 | }, 28 | }, 29 | { 30 | initialRouteName: 'Profile', 31 | headerMode: 'float', 32 | navigationOptions: ({navigation}) => ({ 33 | headerBackground: ( 34 | 40 | ), 41 | headerTintColor: appColors.white, 42 | title: 'Dev Doido', 43 | gesturesEnabled: false, 44 | headerLeft: drawerButton(navigation), 45 | headerTitleStyle: {color: appColors.white}, 46 | }), 47 | }, 48 | ), 49 | ); 50 | -------------------------------------------------------------------------------- /frontend/ios/devdoido-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 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | devdoido 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 | 57 | 58 | -------------------------------------------------------------------------------- /frontend/src/screens/SignIn/SignIn.js: -------------------------------------------------------------------------------- 1 | import React, {useRef, useState} from 'react'; 2 | import {useDispatch, useSelector} from 'react-redux'; 3 | import Background from '../../components/Background/Background'; 4 | import {signInRequest} from '../../appStore/appModules/auth/actions'; 5 | import { 6 | Container, 7 | Form, 8 | FormInput, 9 | SubmitButton, 10 | SignLinkText, 11 | SignLink, 12 | } from './styles'; 13 | 14 | export default function SignIn({navigation}) { 15 | const dispatch = useDispatch(); 16 | const passwordRef = useRef(); 17 | const [email, setEmail] = useState(''); 18 | const [senha, setSenha] = useState(''); 19 | const loading = useSelector(state => state.auth.loading); 20 | function handleSubmit() { 21 | dispatch(signInRequest({email, senha})); 22 | } 23 | return ( 24 | 25 | 26 |
27 | passwordRef.current.focus()} 35 | value={email} 36 | onChangeText={setEmail} 37 | /> 38 | 49 | 50 | Login 51 | 52 | 53 | navigation.navigate('SignUp')}> 54 | Ainda não tem conta? Cadastre-se aqui! 55 | 56 |
57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /frontend/ios/devdoidoTests/devdoidoTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface devdoidoTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation devdoidoTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /frontend/.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/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/\1' 40 | 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' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FlowFixMeProps 45 | suppress_type=$FlowFixMeState 46 | 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 50 | 51 | [lints] 52 | sketchy-null-number=warn 53 | sketchy-null-mixed=warn 54 | sketchy-number=warn 55 | untyped-type-import=warn 56 | nonstrict-import=warn 57 | deprecated-type=warn 58 | unsafe-getters-setters=warn 59 | inexact-spread=warn 60 | unnecessary-invariant=warn 61 | signature-verification-failure=warn 62 | deprecated-utility=error 63 | 64 | [strict] 65 | deprecated-type 66 | nonstrict-import 67 | sketchy-null 68 | unclear-type 69 | unsafe-getters-setters 70 | untyped-import 71 | untyped-type-import 72 | 73 | [version] 74 | ^0.113.0 75 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/user/sagas.js: -------------------------------------------------------------------------------- 1 | import {all, takeLatest, call, put} from 'redux-saga/effects'; 2 | import {Alert} from 'react-native'; 3 | import api from '../../../services/api'; 4 | import {updateProfileSuccess, updateProfileFailure} from './actions'; 5 | 6 | export function* updateProfile({payload}) { 7 | try { 8 | const { 9 | nome, 10 | _id, 11 | email, 12 | oldPassword, 13 | senha, 14 | senhaConfirmacao, 15 | } = payload.data; 16 | const profile = { 17 | nome, 18 | _id, 19 | email, 20 | oldPassword, 21 | senha, 22 | senhaConfirmacao, 23 | }; 24 | 25 | const response = yield call(api.put, `user/${profile._id}`, profile); 26 | if (response.data.message) { 27 | Alert.alert('Erro', response.data.message); 28 | yield put(updateProfileFailure()); 29 | } else if (response.data) { 30 | Alert.alert('Sucesso', 'Perfil atualizado com sucesso'); 31 | yield put(updateProfileSuccess(response.data)); 32 | } else { 33 | Alert.alert('Erro', 'Confira seus dados'); 34 | yield put(updateProfileFailure()); 35 | } 36 | } catch (err) { 37 | console.tron.log(err); 38 | Alert.alert('Erro', 'Confira seus dados'); 39 | yield put(updateProfileFailure()); 40 | } 41 | } 42 | export function* completeProfile({payload}) { 43 | try { 44 | const {cpf, phone} = payload.data; 45 | const profile = { 46 | cpf, 47 | phone, 48 | }; 49 | const response = yield call(api.put, `user/completeRegister`, profile); 50 | if (response.data.message) { 51 | Alert.alert('Erro', response.data.message); 52 | yield put(updateProfileFailure()); 53 | } else if (response.data) { 54 | Alert.alert('Sucesso', 'Perfil atualizado com sucesso'); 55 | yield put(updateProfileSuccess(response.data)); 56 | } else { 57 | Alert.alert('Erro', 'Confira seus dados'); 58 | yield put(updateProfileFailure()); 59 | } 60 | } catch (err) { 61 | console.tron.log(err); 62 | Alert.alert('Erro', 'Confira seus dados'); 63 | yield put(updateProfileFailure()); 64 | } 65 | } 66 | 67 | export default all([ 68 | takeLatest('@user/UPDATE_PROFILE_REQUEST', updateProfile), 69 | takeLatest('@user/COMPLETE_PROFILE_REQUEST', completeProfile), 70 | ]); 71 | -------------------------------------------------------------------------------- /frontend/src/components/Input/Input.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-nested-ternary */ 2 | import React, {forwardRef} from 'react'; 3 | import {TextInput} from 'react-native'; 4 | import Icon from 'react-native-vector-icons/MaterialIcons'; 5 | import PropTypes from 'prop-types'; 6 | import {TextInputMask} from 'react-native-masked-text'; 7 | import {Container} from './styles'; 8 | import {appColors} from '../../utils/appColors'; 9 | 10 | function Input({style, typeMask, typeInput, icon, ...rest}, ref) { 11 | return ( 12 | 13 | {icon && } 14 | {typeInput === 'mask' && typeMask === 'phone' ? ( 15 | 23 | ) : typeInput === 'mask' && typeMask === 'cpf' ? ( 24 | 31 | ) : typeInput === 'mask' && typeMask === 'cnpj' ? ( 32 | 39 | ) : typeInput === 'mask' && typeMask === 'cep' ? ( 40 | 48 | ) : ( 49 | 55 | )} 56 | 57 | ); 58 | } 59 | 60 | Input.propTypes = { 61 | icon: PropTypes.string, 62 | style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), 63 | }; 64 | 65 | Input.defaultProps = { 66 | icon: null, 67 | style: {}, 68 | }; 69 | 70 | export default forwardRef(Input); 71 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | #if DEBUG 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | static void InitializeFlipper(UIApplication *application) { 16 | FlipperClient *client = [FlipperClient sharedClient]; 17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 20 | [client addPlugin:[FlipperKitReactPlugin new]]; 21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 22 | [client start]; 23 | } 24 | #endif 25 | 26 | @implementation AppDelegate 27 | 28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 29 | { 30 | #if DEBUG 31 | InitializeFlipper(application); 32 | #endif 33 | 34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 35 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 36 | moduleName:@"devdoido" 37 | initialProperties:nil]; 38 | 39 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 40 | 41 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 42 | UIViewController *rootViewController = [UIViewController new]; 43 | rootViewController.view = rootView; 44 | self.window.rootViewController = rootViewController; 45 | [self.window makeKeyAndVisible]; 46 | return YES; 47 | } 48 | 49 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 50 | { 51 | #if DEBUG 52 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 53 | #else 54 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 55 | #endif 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /backend/bin/base/controller-base.js: -------------------------------------------------------------------------------- 1 | exports.post = async (repository, validationContract, req, res) => { 2 | try { 3 | const data = req.body; 4 | if (!validationContract.isValid()) { 5 | res 6 | .status(400) 7 | .send({ 8 | message: 'Existem dados inválidos na sua requisição', 9 | validation: validationContract.errors(), 10 | }) 11 | .end(); 12 | return; 13 | } 14 | const resultado = await repository.create(data, req); 15 | res.status(201).send(resultado); 16 | } catch (e) { 17 | res.status(500).send({ message: 'Internal server error', error: e }); 18 | } 19 | }; 20 | 21 | exports.put = async (repository, validationContract, req, res) => { 22 | try { 23 | const data = req.body; 24 | if (!validationContract.isValid()) { 25 | res 26 | .status(400) 27 | .send({ 28 | message: 'Existem dados inválidos na sua requisição', 29 | validation: validationContract.errors(), 30 | }) 31 | .end(); 32 | return; 33 | } 34 | const resultado = await repository.update( 35 | req.params.id, 36 | data, 37 | req.usuarioLogado.user, 38 | ); 39 | res.status(202).send(resultado); 40 | } catch (e) { 41 | res.status(500).send({ message: 'Internal server error', error: e }); 42 | } 43 | }; 44 | exports.get = async (repository, req, res) => { 45 | try { 46 | const resultado = await repository.getAll(); 47 | res.status(200).send(resultado); 48 | } catch (erro) { 49 | res.status(500).send({ message: 'Erro no processamento', error: erro }); 50 | } 51 | }; 52 | exports.getMyAll = async (repository, req, res) => { 53 | try { 54 | const resultado = await repository.getMyAll(req.usuarioLogado.user); 55 | res.status(200).send(resultado); 56 | } catch (erro) { 57 | res.status(500).send({ message: 'Erro no processamento', error: erro }); 58 | } 59 | }; 60 | exports.delete = async (repository, req, res) => { 61 | try { 62 | const { id } = req.params; 63 | if (id) { 64 | const resultado = await repository.delete(id, req.usuarioLogado); 65 | if (resultado !== 'Operação Inválida') { 66 | res.status(200).send({ message: 'Registro excluído com sucesso' }); 67 | } else { 68 | res.status(401).send({ message: 'Operação inválida' }); 69 | } 70 | } else { 71 | res.status(500).send({ message: 'O parametro id precisa ser informado' }); 72 | } 73 | } catch (e) { 74 | res.status(500).send({ message: 'Internal server error', error: e }); 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devdoido", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "and": "cd android && gradlew.bat clean && cd .. && react-native run-android", 7 | "reverse": "adb reverse tcp:8081 tcp:8081 && adb reverse tcp:9090 tcp:9090", 8 | "android": "react-native run-android", 9 | "ios": "react-native run-ios", 10 | "start": "react-native start", 11 | "test": "jest", 12 | "lint": "eslint ." 13 | }, 14 | "dependencies": { 15 | "@react-native-community/async-storage": "^1.11.0", 16 | "@react-native-community/masked-view": "^0.1.10", 17 | "axios": "^0.19.2", 18 | "cep-promise": "^3.0.9", 19 | "date-fns": "^2.14.0", 20 | "date-fns-tz": "^1.0.10", 21 | "formik": "^2.1.4", 22 | "immer": "^6.0.9", 23 | "neumorphism-ui": "^1.0.2", 24 | "polished": "^3.6.4", 25 | "prop-types": "^15.7.2", 26 | "react": "16.11.0", 27 | "react-native": "0.62.2", 28 | "react-native-credit-card-input": "^0.4.1", 29 | "react-native-crypto-js": "^1.0.0", 30 | "react-native-gesture-handler": "^1.6.1", 31 | "react-native-linear-gradient": "^2.5.6", 32 | "react-native-masked-text": "^1.13.0", 33 | "react-native-paper": "^3.10.1", 34 | "react-native-reanimated": "^1.9.0", 35 | "react-native-safe-area-context": "^3.0.3", 36 | "react-native-screens": "^2.8.0", 37 | "react-native-vector-icons": "^6.6.0", 38 | "react-navigation": "^4.3.9", 39 | "react-navigation-drawer": "^2.4.13", 40 | "react-navigation-stack": "^2.7.0", 41 | "react-redux": "^7.2.0", 42 | "redux": "^4.0.5", 43 | "redux-logger": "^3.0.6", 44 | "redux-persist": "^6.0.0", 45 | "redux-saga": "^1.1.3", 46 | "styled-components": "^5.1.1", 47 | "yup": "^0.29.1" 48 | }, 49 | "devDependencies": { 50 | "@babel/core": "^7.10.1", 51 | "@babel/runtime": "^7.10.1", 52 | "@react-native-community/eslint-config": "^1.1.0", 53 | "babel-eslint": "^10.1.0", 54 | "babel-jest": "^26.0.1", 55 | "eslint": "^6.8.0", 56 | "eslint-config-airbnb": "^18.1.0", 57 | "eslint-config-prettier": "^6.11.0", 58 | "eslint-plugin-import": "^2.20.2", 59 | "eslint-plugin-jsx-a11y": "^6.2.3", 60 | "eslint-plugin-prettier": "^3.1.3", 61 | "eslint-plugin-react": "^7.20.0", 62 | "eslint-plugin-react-hooks": "^2.5.1", 63 | "jest": "^26.0.1", 64 | "metro-react-native-babel-preset": "^0.59.0", 65 | "prettier": "^2.0.5", 66 | "react-test-renderer": "16.11.0", 67 | "reactotron-react-native": "^5.0.0", 68 | "reactotron-redux": "^3.1.3", 69 | "reactotron-redux-saga": "^4.2.3" 70 | }, 71 | "jest": { 72 | "preset": "react-native" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /frontend/src/appStore/appModules/auth/sagas.js: -------------------------------------------------------------------------------- 1 | import {takeLatest, call, put, all} from 'redux-saga/effects'; 2 | import {Alert} from 'react-native'; 3 | import AsyncStorage from '@react-native-community/async-storage'; 4 | import api from '../../../services/api'; 5 | import {signInSuccess, signFailure} from './actions'; 6 | 7 | export function* signIn({payload}) { 8 | try { 9 | const {email, senha} = payload; 10 | const senhaConfirmacao = senha; 11 | const response = yield call(api.post, 'user/authenticate', { 12 | email, 13 | senha, 14 | senhaConfirmacao, 15 | }); 16 | const {token, usuario} = response.data; 17 | AsyncStorage.setItem('user', JSON.stringify({usuario, token})); 18 | api.defaults.headers.Authorization = `Bearer ${token}`; 19 | yield put(signInSuccess(token, usuario)); 20 | } catch (e) { 21 | Alert.alert('Erro', 'Login falhou ai bixo, verifique usuário e senha'); 22 | yield put(signFailure()); 23 | } 24 | } 25 | export function* signUp({payload}) { 26 | try { 27 | const {email, senha, senhaConfirmacao, type, nome} = payload; 28 | if (type === 'admin') { 29 | Alert.alert('Erro', 'Você não pode ser o admin'); 30 | yield put(signFailure()); 31 | } 32 | 33 | const response = yield call(api.post, 'user/register', { 34 | email, 35 | senha, 36 | senhaConfirmacao, 37 | type, 38 | nome, 39 | }); 40 | if (response.status === 201) { 41 | Alert.alert('Sucesso', 'Cadastro realizado'); 42 | const responseSign = yield call(api.post, 'user/authenticate', { 43 | email, 44 | senha, 45 | senhaConfirmacao, 46 | }); 47 | const {token, usuario} = responseSign.data; 48 | AsyncStorage.setItem('user', JSON.stringify({usuario, token})); 49 | api.defaults.headers.Authorization = `Bearer ${token}`; 50 | yield put(signInSuccess(token, usuario)); 51 | } else { 52 | Alert.alert('Erro', 'Existem dados inválidos na sua requisição'); 53 | yield put(signFailure()); 54 | } 55 | } catch (e) { 56 | Alert.alert('Erro', 'Cadastro falhou ai bixo, verifique usuário e senha'); 57 | yield put(signFailure()); 58 | } 59 | } 60 | export function signOut() {} 61 | export function setToken({payload}) { 62 | if (!payload) return; 63 | if (payload.token === undefined) { 64 | if (payload.auth.token) { 65 | api.defaults.headers.Authorization = `Bearer ${payload.auth.token}`; 66 | } 67 | } else { 68 | const {token} = payload; 69 | if (token) { 70 | api.defaults.headers.Authorization = `Bearer ${token}`; 71 | } 72 | } 73 | } 74 | 75 | export default all([ 76 | takeLatest('persist/REHYDRATE', setToken), 77 | takeLatest('@auth/SIGN_UP_REQUEST', signUp), 78 | takeLatest('@auth/SIGN_IN_REQUEST', signIn), 79 | takeLatest('@auth/SIGN_OUT', signOut), 80 | ]); 81 | -------------------------------------------------------------------------------- /frontend/android/app/src/main/java/com/devdoido/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.devdoido; 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.facebook.react.ReactInstanceManager; 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, getReactNativeHost().getReactInstanceManager()); 48 | } 49 | 50 | /** 51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 53 | * 54 | * @param context 55 | * @param reactInstanceManager 56 | */ 57 | private static void initializeFlipper( 58 | Context context, ReactInstanceManager reactInstanceManager) { 59 | if (BuildConfig.DEBUG) { 60 | try { 61 | /* 62 | We use reflection here to pick up the class that initializes Flipper, 63 | since Flipper library is not available in release mode 64 | */ 65 | Class aClass = Class.forName("com.devdoido.ReactNativeFlipper"); 66 | aClass 67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 68 | .invoke(null, context, reactInstanceManager); 69 | } catch (ClassNotFoundException e) { 70 | e.printStackTrace(); 71 | } catch (NoSuchMethodException e) { 72 | e.printStackTrace(); 73 | } catch (IllegalAccessException e) { 74 | e.printStackTrace(); 75 | } catch (InvocationTargetException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /frontend/src/appNavigation/navigators/ClientNavigator.js: -------------------------------------------------------------------------------- 1 | import {createAppContainer} from 'react-navigation'; 2 | import React, {useEffect} from 'react'; 3 | import Icon from 'react-native-vector-icons/Octicons'; 4 | import {createStackNavigator} from 'react-navigation-stack'; 5 | import {darken} from 'polished'; 6 | import {useDispatch} from 'react-redux'; 7 | import LinearGradient from 'react-native-linear-gradient'; 8 | import {createDrawerNavigator} from 'react-navigation-drawer'; 9 | import appMetrics from '../../utils/appMetrics'; 10 | import {signOut} from '../../appStore/appModules/auth/actions'; 11 | import Profile from '../../screens/Profile/Profile'; 12 | import Home from '../../screens/Home/Home'; 13 | import PaymentAddress from '../../screens/Payment/PaymentAddress/PaymentAddress'; 14 | import PaymentCart from '../../screens/Payment/PaymentCart/PaymentCart'; 15 | import CompleteRegister from '../../screens/Payment/CompleteRegister/CompleteRegister'; 16 | import {appColors} from '../../utils/appColors'; 17 | 18 | function Logout() { 19 | const dispatch = useDispatch(); 20 | useEffect(() => { 21 | dispatch(signOut()); 22 | }, []); 23 | return <>; 24 | } 25 | 26 | const RootStack = createDrawerNavigator( 27 | { 28 | Home: { 29 | screen: Home, 30 | navigationOptions: () => ({drawerLabel: 'Inicio'}), 31 | }, 32 | Profile: { 33 | screen: Profile, 34 | navigationOptions: () => ({drawerLabel: 'Meu perfil'}), 35 | }, 36 | CompleteRegister: { 37 | screen: createStackNavigator({ 38 | CompleteRegister, 39 | PaymentAddress, 40 | PaymentCart, 41 | }), 42 | navigationOptions: () => ({drawerLabel: 'Completar registro'}), 43 | }, 44 | Payment: { 45 | screen: createStackNavigator({ 46 | PaymentAddress, 47 | PaymentCart, 48 | }), 49 | navigationOptions: () => ({drawerLabel: 'Pagamento'}), 50 | }, 51 | Logout: { 52 | screen: Logout, 53 | navigationOptions: () => ({drawerLabel: 'Sair'}), 54 | }, 55 | }, 56 | { 57 | initialRouteName: 'Home', 58 | headerMode: 'float', 59 | navigationOptions: ({navigation}) => ({ 60 | headerBackground: () => ( 61 | 65 | ), 66 | headerTintColor: appColors.white, 67 | title: 'Dev Doido', 68 | gesturesEnabled: true, 69 | headerLeft: () => ( 70 | { 76 | navigation.toggleDrawer(); 77 | }} 78 | /> 79 | ), 80 | headerTitleStyle: { 81 | paddingLeft: appMetrics.DEVICE_WIDTH / 5.5, 82 | color: appColors.white, 83 | }, 84 | }), 85 | }, 86 | ); 87 | 88 | export default createAppContainer( 89 | createStackNavigator({RootStack: {screen: RootStack}}), 90 | ); 91 | -------------------------------------------------------------------------------- /backend/repositories/user-repository.js: -------------------------------------------------------------------------------- 1 | require('../models/user-model'); 2 | const bcrypt = require('bcryptjs'); 3 | const jwt = require('jsonwebtoken'); 4 | const base = require('../bin/base/repository-base'); 5 | 6 | class userRepository { 7 | constructor() { 8 | this._base = new base('User'); 9 | this._projection = 'nome email payDay type cpf phone'; 10 | } 11 | 12 | async authenticate(Email, Senha, flag) { 13 | const user = await this._base._model.findOne({ email: Email }); 14 | const userR = await this._base._model.findOne( 15 | { email: Email }, 16 | this._projection, 17 | ); 18 | if (await bcrypt.compareSync(Senha, user.senha)) { 19 | return userR; 20 | } 21 | return null; 22 | } 23 | 24 | async IsEmailExiste(Email) { 25 | return await this._base._model.findOne({ email: Email }, this._projection); 26 | } 27 | 28 | async create(data, req) { 29 | const userCriado = await this._base.create(data); 30 | const userR = await this._base._model.findOne( 31 | { _id: userCriado._id }, 32 | this._projection, 33 | ); 34 | return userR; 35 | } 36 | 37 | async updatePayment(data, userid) { 38 | return await this._base.update(userid, { payDay: data }); 39 | } 40 | async completeRegister(data, userid) { 41 | await this._base.update(userid, data); 42 | const userR = await this._base._model.findOne( 43 | { _id: userid }, 44 | this._projection, 45 | ); 46 | return userR; 47 | } 48 | 49 | async update(id, data, usuarioLogado) { 50 | if (usuarioLogado._id === id) { 51 | if ( 52 | data.oldPassword !== data.senha && 53 | data.oldPassword && 54 | data.senha !== undefined && 55 | data.senhaConfirmacao !== undefined && 56 | data.senha === data.senhaConfirmacao 57 | ) { 58 | const user = await this._base._model.findOne({ _id: id }); 59 | if (await bcrypt.compareSync(data.oldPassword, user.senha)) { 60 | const salt = await bcrypt.genSaltSync(10); 61 | const _hashSenha = await bcrypt.hashSync(data.senha, salt); 62 | let { nome } = user; 63 | let { email } = user; 64 | if (data.email) { 65 | email = data.email; 66 | } 67 | if (data.nome) { 68 | nome = data.nome; 69 | } 70 | const usuarioAtualizado = await this._base.update(id, { 71 | nome, 72 | email, 73 | senha: _hashSenha, 74 | }); 75 | return this._base._model.findById( 76 | usuarioAtualizado._id, 77 | this._projection, 78 | ); 79 | } 80 | return { message: 'Senha inválida' }; 81 | } 82 | } else { 83 | return { message: 'Você não tem permissão para editar esse usuário' }; 84 | } 85 | } 86 | 87 | async getAll() { 88 | return await this._base._model.find({}, this._projection); 89 | } 90 | 91 | async delete(id) { 92 | return await this._base.delete(id); 93 | } 94 | } 95 | 96 | module.exports = userRepository; 97 | -------------------------------------------------------------------------------- /frontend/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 https://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 | -------------------------------------------------------------------------------- /frontend/android/app/src/debug/java/com/devdoido/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.devdoido; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | public class ReactNativeFlipper { 28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 29 | if (FlipperUtils.shouldEnableFlipper(context)) { 30 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 31 | 32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 33 | client.addPlugin(new ReactFlipperPlugin()); 34 | client.addPlugin(new DatabasesFlipperPlugin(context)); 35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 36 | client.addPlugin(CrashReporterPlugin.getInstance()); 37 | 38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 39 | NetworkingModule.setCustomClientBuilder( 40 | new NetworkingModule.CustomClientBuilder() { 41 | @Override 42 | public void apply(OkHttpClient.Builder builder) { 43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 44 | } 45 | }); 46 | client.addPlugin(networkFlipperPlugin); 47 | client.start(); 48 | 49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 50 | // Hence we run if after all native modules have been initialized 51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 52 | if (reactContext == null) { 53 | reactInstanceManager.addReactInstanceEventListener( 54 | new ReactInstanceManager.ReactInstanceEventListener() { 55 | @Override 56 | public void onReactContextInitialized(ReactContext reactContext) { 57 | reactInstanceManager.removeReactInstanceEventListener(this); 58 | reactContext.runOnNativeModulesQueueThread( 59 | new Runnable() { 60 | @Override 61 | public void run() { 62 | client.addPlugin(new FrescoFlipperPlugin()); 63 | } 64 | }); 65 | } 66 | }); 67 | } else { 68 | client.addPlugin(new FrescoFlipperPlugin()); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /frontend/ios/devdoido.xcodeproj/xcshareddata/xcschemes/devdoido.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /frontend/ios/devdoido.xcodeproj/xcshareddata/xcschemes/devdoido-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /frontend/ios/devdoido/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 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/PaymentCart/PaymentCart.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | import CryptoJS from 'react-native-crypto-js'; 3 | import {CreditCardInput} from 'react-native-credit-card-input'; 4 | import {Alert} from 'react-native'; 5 | import {useSelector, useDispatch} from 'react-redux'; 6 | import api from '../../../services/api'; 7 | import {completeProfileRequest} from '../../../appStore/appModules/user/actions'; 8 | import {Container, SubmitButton, Title} from './styles'; 9 | import Background from '../../../components/Background/Background'; 10 | 11 | export default function PaymentCart({navigation}) { 12 | const dispatch = useDispatch(); 13 | const [isValid, setIsValid] = useState(false); 14 | const [cart, setCart] = useState({}); 15 | const profile = useSelector(state => state.user.profile); 16 | async function handleSubmit() { 17 | if (isValid) { 18 | let expiration = parseInt(cart.expiry.replace('/', '')); 19 | if (expiration < 1000) { 20 | expiration = '0' + expiration; 21 | } 22 | console.tron.log(expiration); 23 | const numbercart = cart.number.toString().replace(/\s+/g, ''); 24 | const objToEncrypt = JSON.stringify({ 25 | card_number: numbercart, 26 | card_expiration_date: expiration, 27 | card_holder_name: cart.name, 28 | card_cvv: cart.cvc, 29 | }); 30 | const card_hash = CryptoJS.AES.encrypt( 31 | objToEncrypt, 32 | 'hdfudhuidfhudhudah9d8s8f9d8a98as9d8s9d89as', 33 | ).toString(); 34 | const state = navigation.getParam('state'); 35 | const complemento = navigation.getParam('complemento'); 36 | const street = navigation.getParam('street'); 37 | const street_number = navigation.getParam('street_number'); 38 | const city = navigation.getParam('city'); 39 | const zipcode = navigation.getParam('zipcode').replace('-', ''); 40 | const neighborhood = navigation.getParam('neighborhood'); 41 | const {cpf, phone, email} = profile; 42 | const obj = { 43 | city, 44 | name: cart.name, 45 | state, 46 | complemento, 47 | zipcode, 48 | card_hash, 49 | neighborhood, 50 | street, 51 | email, 52 | cpf, 53 | phone, 54 | street_number, 55 | }; 56 | try { 57 | const response = await api.post('transaction', obj); 58 | if (response.data) { 59 | Alert.alert( 60 | 'Pagamento feito com sucesso', 61 | 'Seu acesso à plataforma do faustão ta liberado', 62 | ); 63 | dispatch(completeProfileRequest({cpf, phone})); 64 | navigation.navigate('Home'); 65 | } 66 | } catch (e) { 67 | Alert.alert('Erro', 'Pagamento falhou'); 68 | } 69 | } 70 | } 71 | async function getForm(form) { 72 | if (form.valid) { 73 | setIsValid(true); 74 | setCart(form.values); 75 | } 76 | } 77 | 78 | return ( 79 | 80 | Detalhes do pagamento 81 | { 98 | getForm(form); 99 | }} 100 | /> 101 | 102 | Total: R$30 103 | handleSubmit()}> 104 | Confirmar pagamento 105 | 106 | 107 | 108 | ); 109 | } 110 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/CompleteRegister/CompleteRegister.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {useSelector, useDispatch} from 'react-redux'; 3 | import {Formik} from 'formik'; 4 | import * as Yup from 'yup'; 5 | import {Text, Alert} from 'react-native'; 6 | import {Title, Container, Form, FormInput, SubmitButton} from './styles'; 7 | import Background from '../../../components/Background/Background'; 8 | import {appColors} from '../../../utils/appColors'; 9 | import {completeProfileRequest} from '../../../appStore/appModules/user/actions'; 10 | 11 | const formSchema = Yup.object().shape({ 12 | cpf: Yup.string() 13 | .trim() 14 | .required('Obrigatório') 15 | .length(14, 'O CPF deve ter 11 dígitos'), 16 | phone: Yup.string() 17 | .trim() 18 | .required('Obrigatório') 19 | .length(16, 'o Celular deve ter no mínimo 13 dígitos'), 20 | }); 21 | 22 | export default function CompleteRegister({navigation}) { 23 | const dispatch = useDispatch(); 24 | const profile = useSelector(state => state.user.profile); 25 | const loading = useSelector(state => state.user.loading); 26 | const initialValues = {phone: profile?.phone, cpf: profile?.cpf}; 27 | function TestaCPF(strCPF) { 28 | let Soma; 29 | let Resto; 30 | Soma = 0; 31 | if (strCPF == '00000000000') return false; 32 | 33 | for (i = 1; i <= 9; i++) 34 | Soma += parseInt(strCPF.substring(i - 1, i)) * (11 - i); 35 | Resto = (Soma * 10) % 11; 36 | 37 | if (Resto == 10 || Resto == 11) Resto = 0; 38 | if (Resto != parseInt(strCPF.substring(9, 10))) return false; 39 | 40 | Soma = 0; 41 | for (i = 1; i <= 10; i++) 42 | Soma += parseInt(strCPF.substring(i - 1, i)) * (12 - i); 43 | Resto = (Soma * 10) % 11; 44 | 45 | if (Resto == 10 || Resto == 11) Resto = 0; 46 | if (Resto != parseInt(strCPF.substring(10, 11))) return false; 47 | return true; 48 | } 49 | const onSubmit = (values, isValid) => { 50 | const {cpf, phone} = values; 51 | if (cpf && cpf.length > 0 && phone && phone.length > 0) { 52 | const phoneFormatted = `${phone 53 | .replace('(', '') 54 | .replace(')', '') 55 | .replace('-', '')}`; 56 | const teste = TestaCPF( 57 | cpf.replace('.', '').replace('.', '').replace('-', ''), 58 | ); 59 | if (!teste) { 60 | Alert.alert('CPF inválido'); 61 | } 62 | if (isValid && teste) { 63 | dispatch(completeProfileRequest({cpf, phone: phoneFormatted})); 64 | if (new Date(profile.payDay).getTime() < new Date().getTime()) { 65 | if (!loading) { 66 | navigation.push('PaymentAddress'); 67 | } 68 | } 69 | } 70 | } 71 | }; 72 | 73 | return ( 74 | 75 | 76 | Completar cadastro 77 | 78 | {({ 79 | values, 80 | isValid, 81 | handleChange, 82 | setFieldTouched, 83 | touched, 84 | errors, 85 | }) => ( 86 |

87 | setFieldTouched('cpf')} 98 | onChangeText={handleChange('cpf')} 99 | /> 100 | {touched.cpf && errors.cpf && ( 101 | 107 | {errors.cpf} 108 | 109 | )} 110 | setFieldTouched('phone')} 121 | onChangeText={handleChange('phone')} 122 | /> 123 | {touched.phone && errors.phone && ( 124 | 130 | {errors.phone} 131 | 132 | )} 133 | onSubmit(values, isValid)}> 136 | Completar cadastro 137 | 138 | 139 | )} 140 | 141 | 142 | 143 | ); 144 | } 145 | -------------------------------------------------------------------------------- /frontend/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | def add_flipper_pods!(versions = {}) 5 | versions['Flipper'] ||= '~> 0.33.1' 6 | versions['DoubleConversion'] ||= '1.1.7' 7 | versions['Flipper-Folly'] ||= '~> 2.1' 8 | versions['Flipper-Glog'] ||= '0.3.6' 9 | versions['Flipper-PeerTalk'] ||= '~> 0.0.4' 10 | versions['Flipper-RSocket'] ||= '~> 1.0' 11 | 12 | pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug' 13 | pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug' 14 | pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 15 | pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug' 16 | pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug' 17 | 18 | # List all transitive dependencies for FlipperKit pods 19 | # to avoid them being linked in Release builds 20 | pod 'Flipper', versions['Flipper'], :configuration => 'Debug' 21 | pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug' 22 | pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug' 23 | pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug' 24 | pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug' 25 | pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug' 26 | pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug' 27 | pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug' 28 | pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug' 29 | pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug' 30 | pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug' 31 | pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug' 32 | pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug' 33 | pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 34 | end 35 | 36 | # Post Install processing for Flipper 37 | def flipper_post_install(installer) 38 | installer.pods_project.targets.each do |target| 39 | if target.name == 'YogaKit' 40 | target.build_configurations.each do |config| 41 | config.build_settings['SWIFT_VERSION'] = '4.1' 42 | end 43 | end 44 | end 45 | end 46 | 47 | target 'devdoido' do 48 | # Pods for devdoido 49 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 50 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 51 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 52 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 53 | pod 'React', :path => '../node_modules/react-native/' 54 | pod 'React-Core', :path => '../node_modules/react-native/' 55 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 56 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 57 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 58 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 59 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 60 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 61 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 62 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 63 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 64 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 65 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 66 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 67 | 68 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 69 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 70 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 71 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 72 | pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" 73 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 74 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true 75 | 76 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 77 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 78 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 79 | 80 | target 'devdoidoTests' do 81 | inherit! :complete 82 | # Pods for testing 83 | end 84 | 85 | use_native_modules! 86 | 87 | # Enables Flipper. 88 | # 89 | # Note that if you have use_frameworks! enabled, Flipper will not work and 90 | # you should disable these next few lines. 91 | add_flipper_pods! 92 | post_install do |installer| 93 | flipper_post_install(installer) 94 | end 95 | end 96 | 97 | target 'devdoido-tvOS' do 98 | # Pods for devdoido-tvOS 99 | 100 | target 'devdoido-tvOSTests' do 101 | inherit! :search_paths 102 | # Pods for testing 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /backend/controllers/user-controller.js: -------------------------------------------------------------------------------- 1 | const bcrypt = require('bcryptjs'); 2 | const jwt = require('jsonwebtoken'); 3 | const repository = require('../repositories/user-repository'); 4 | const validation = require('../bin/helpers/validation'); 5 | const ctrlBase = require('../bin/base/controller-base'); 6 | const variables = require('../bin/configuration/variables'); 7 | 8 | const _repo = new repository(); 9 | 10 | function userController() {} 11 | 12 | userController.prototype.post = async (req, res) => { 13 | const _validationContract = new validation(); 14 | _validationContract.isRequired(req.body.nome, 'Informe seu nome pentelho'); 15 | _validationContract.isRequired(req.body.email, 'Informe seu email pentelho'); 16 | _validationContract.isRequired(req.body.senha, 'Informe sua senha pentelho'); 17 | _validationContract.isRequired( 18 | req.body.senhaConfirmacao, 19 | 'Informe sua senha confirmação pentelho', 20 | ); 21 | _validationContract.isTrue( 22 | req.body.senhaConfirmacao !== req.body.senha, 23 | 'As senhas devem ser iguais pentelho', 24 | ); 25 | _validationContract.isEmail( 26 | req.body.email, 27 | 'Informe um email válido pentelho', 28 | ); 29 | 30 | try { 31 | const usuarioEmailExiste = await _repo.IsEmailExiste(req.body.email); 32 | if (usuarioEmailExiste) { 33 | _validationContract.isTrue( 34 | usuarioEmailExiste.nome != undefined, 35 | `Já existe o email ${req.body.email} cadastrado no banco de dados`, 36 | ); 37 | } 38 | const salt = await bcrypt.genSaltSync(10); 39 | req.body.senha = await bcrypt.hashSync(req.body.senha, salt); 40 | ctrlBase.post(_repo, _validationContract, req, res); 41 | } catch (e) { 42 | res.status(500).send({ message: 'Internal server error', error: e }); 43 | } 44 | }; 45 | userController.prototype.put = async (req, res) => { 46 | const _validationContract = new validation(); 47 | _validationContract.isRequired(req.body.nome, 'Informe seu nome pentelho'); 48 | _validationContract.isRequired(req.params.id, 'Informe seu id pentelho'); 49 | _validationContract.isRequired(req.body.email, 'Informe seu email pentelho'); 50 | _validationContract.isRequired(req.body.senha, 'Informe sua senha pentelho'); 51 | _validationContract.isRequired( 52 | req.body.senhaConfirmacao, 53 | 'Informe sua senha confirmação pentelho', 54 | ); 55 | _validationContract.isTrue( 56 | req.body.senhaConfirmacao !== req.body.senha, 57 | 'As senhas devem ser iguais pentelho', 58 | ); 59 | _validationContract.isEmail( 60 | req.body.email, 61 | 'Informe um email válido pentelho', 62 | ); 63 | 64 | try { 65 | const usuarioEmailExiste = await _repo.IsEmailExiste(req.body.email); 66 | if (usuarioEmailExiste) { 67 | _validationContract.isTrue( 68 | usuarioEmailExiste.nome != undefined && 69 | usuarioEmailExiste._id != req.params.id, 70 | `Já existe o email ${req.body.email} cadastrado no banco de dados`, 71 | ); 72 | } 73 | if (req.usuarioLogado.user._id.toString() === req.params.id) { 74 | ctrlBase.put(_repo, _validationContract, req, res); 75 | } else { 76 | res.status(401).send({ message: 'Você não tem permissão' }); 77 | } 78 | } catch (e) { 79 | res.status(500).send({ message: 'Internal server error', error: e }); 80 | } 81 | }; 82 | userController.prototype.completeRegister = async (req, res) => { 83 | try { 84 | const validationContract = new validation(); 85 | validationContract.isRequired(req.body.cpf, 'Informe seu cpf pentelho'); 86 | validationContract.isRequired(req.body.phone, 'Informe seu phone pentelho'); 87 | if (!validationContract.isValid()) { 88 | req 89 | .status(400) 90 | .send({ 91 | message: 'Existem dados inválido na sua requisição', 92 | validation: validationContract.errors(), 93 | }) 94 | .end(); 95 | return; 96 | } 97 | const data = req.body; 98 | const user = await _repo.completeRegister(data, req.usuarioLogado.user._id); 99 | res.status(200).send(user); 100 | } catch (e) { 101 | res.status(500).send({ message: 'Internal server error', error: e }); 102 | } 103 | }; 104 | userController.prototype.get = async (req, res) => { 105 | ctrlBase.get(_repo, req, res); 106 | }; 107 | userController.prototype.delete = async (req, res) => { 108 | _validationContract.isRequired(req.params.id, 'Informe seu id pentelho'); 109 | ctrlBase.delete(_repo, req, res); 110 | }; 111 | 112 | userController.prototype.authenticate = async (req, res) => { 113 | const _validationContract = new validation(); 114 | _validationContract.isRequired(req.body.email, 'Informe seu email pentelho'); 115 | _validationContract.isRequired(req.body.senha, 'Informe sua senha pentelho'); 116 | _validationContract.isRequired( 117 | req.body.senhaConfirmacao, 118 | 'Informe sua senha confirmação pentelho', 119 | ); 120 | _validationContract.isTrue( 121 | req.body.senhaConfirmacao !== req.body.senha, 122 | 'As senhas devem ser iguais pentelho', 123 | ); 124 | _validationContract.isEmail( 125 | req.body.email, 126 | 'Informe um email válido pentelho', 127 | ); 128 | if (!_validationContract.isValid()) { 129 | res.status(400).send({ 130 | message: 'Não foi possível efetuar o login', 131 | validation: _validationContract.errors(), 132 | }); 133 | return; 134 | } 135 | const usuarioEncontrado = await _repo.authenticate( 136 | req.body.email, 137 | req.body.senha, 138 | false, 139 | ); 140 | if (usuarioEncontrado == null) { 141 | res 142 | .status(404) 143 | .send({ message: 'Usuario ou senha informados são inválidos' }); 144 | } 145 | if (usuarioEncontrado) { 146 | res.status(200).send({ 147 | usuario: usuarioEncontrado, 148 | token: jwt.sign( 149 | { user: usuarioEncontrado }, 150 | variables.Security.secretKey, 151 | ), 152 | }); 153 | } else { 154 | res 155 | .status(404) 156 | .send({ message: 'Usuario ou senha informados são inválidos' }); 157 | } 158 | }; 159 | 160 | module.exports = userController; 161 | -------------------------------------------------------------------------------- /frontend/src/screens/Profile/Profile.js: -------------------------------------------------------------------------------- 1 | import React, {useRef} from 'react'; 2 | import {useDispatch, useSelector} from 'react-redux'; 3 | import {Formik} from 'formik'; 4 | import * as Yup from 'yup'; 5 | import {Text} from 'react-native'; 6 | import { 7 | Container, 8 | Form, 9 | FormInput, 10 | Title, 11 | SubmitButton, 12 | Separator, 13 | } from './styles'; 14 | import {updateProfileRequest} from '../../appStore/appModules/user/actions'; 15 | import Background from '../../components/Background/Background'; 16 | 17 | const formSchema = Yup.object().shape({ 18 | email: Yup.string().trim().email('Email inválido').required('Obrigatório'), 19 | nome: Yup.string().trim().required('Obrigatório'), 20 | oldPassword: Yup.string().trim().required('Obrigatório'), 21 | senha: Yup.string().trim().required('Obrigatório'), 22 | senhaConfirmacao: Yup.string() 23 | .trim() 24 | .required('Obrigatório') 25 | .test('passwords-match', 'As senhas devem ser iguais', function (value) { 26 | return this.parent.senha === value; 27 | }), 28 | }); 29 | 30 | export default function Profile({navigation}) { 31 | const profile = useSelector(state => state.user.profile); 32 | const loading = useSelector(state => state.user.loading); 33 | const initialValues = { 34 | email: profile.email, 35 | senha: '', 36 | nome: profile.nome, 37 | oldPassword: '', 38 | senhaConfirmacao: '', 39 | }; 40 | const dispatch = useDispatch(); 41 | const emailRef = useRef(); 42 | const passwordRef = useRef(); 43 | const oldPasswordRef = useRef(); 44 | const passwordConfirmationRef = useRef(); 45 | 46 | const onSubmit = (values, isValid) => { 47 | if (isValid) { 48 | const {nome, oldPassword, senha, senhaConfirmacao, email} = values; 49 | dispatch( 50 | updateProfileRequest({ 51 | nome, 52 | oldPassword, 53 | senha, 54 | senhaConfirmacao, 55 | email, 56 | _id: profile._id, 57 | }), 58 | ); 59 | } 60 | }; 61 | 62 | return ( 63 | 64 | 65 | Meu perfil 66 | 67 | {({ 68 | values, 69 | isValid, 70 | handleChange, 71 | setFieldTouched, 72 | touched, 73 | errors, 74 | }) => ( 75 |
76 | emailRef.current.focus()} 83 | value={values.nome} 84 | onBlur={() => setFieldTouched('nome')} 85 | onChangeText={handleChange('nome')} 86 | /> 87 | {touched.nome && errors.nome && ( 88 | 89 | {errors.nome} 90 | 91 | )} 92 | oldPasswordRef.current.focus()} 101 | value={values.email} 102 | onBlur={() => setFieldTouched('email')} 103 | onChangeText={handleChange('email')} 104 | /> 105 | {touched.email && errors.email && ( 106 | 107 | {errors.email} 108 | 109 | )} 110 | 111 | passwordRef.current.focus()} 119 | value={values.oldPassword} 120 | onBlur={() => setFieldTouched('oldPassword')} 121 | onChangeText={handleChange('oldPassword')} 122 | /> 123 | passwordConfirmationRef.current.focus()} 131 | value={values.senha} 132 | onBlur={() => setFieldTouched('senha')} 133 | onChangeText={handleChange('senha')} 134 | /> 135 | {touched.senha && errors.senha && ( 136 | 137 | {errors.senha} 138 | 139 | )} 140 | onSubmit(values, isValid)} 148 | value={values.senhaConfirmacao} 149 | onBlur={() => setFieldTouched('senhaConfirmacao')} 150 | onChangeText={handleChange('senhaConfirmacao')} 151 | /> 152 | {touched.senhaConfirmacao && errors.senhaConfirmacao && ( 153 | 154 | {errors.senhaConfirmacao} 155 | 156 | )} 157 | onSubmit(values, isValid)}> 160 | Atualizar perfil 161 | 162 | 163 | )} 164 |
165 |
166 |
167 | ); 168 | } 169 | -------------------------------------------------------------------------------- /frontend/src/screens/SignUp/SignUp.js: -------------------------------------------------------------------------------- 1 | import React, {useRef, useState} from 'react'; 2 | import {ScrollView, Text} from 'react-native'; 3 | import {useDispatch, useSelector} from 'react-redux'; 4 | import {Formik} from 'formik'; 5 | import * as Yup from 'yup'; 6 | import {signUpRequest} from '../../appStore/appModules/auth/actions'; 7 | import Background from '../../components/Background/Background'; 8 | import {appColors} from '../../utils/appColors'; 9 | import { 10 | Container, 11 | FormInput, 12 | Form, 13 | SubmitButton, 14 | SignLinkText, 15 | SignLink, 16 | } from './styles'; 17 | 18 | const formSchema = Yup.object().shape({ 19 | email: Yup.string().trim().email('Email inválido').required('Obrigatório'), 20 | nome: Yup.string().trim().required('Obrigatório'), 21 | senha: Yup.string().trim().required('Obrigatório'), 22 | senhaConfirmacao: Yup.string() 23 | .trim() 24 | .required('Obrigatório') 25 | .test('password-match', 'As senhas devem ser iguais', function (value) { 26 | return this.parent.senha === value; 27 | }), 28 | }); 29 | 30 | export default function SignUp({navigation}) { 31 | const dispatch = useDispatch(); 32 | const emailRef = useRef(); 33 | const passwordRef = useRef(); 34 | const passwordConfirmationRef = useRef(); 35 | const [type, setType] = useState('client'); 36 | const loading = useSelector(state => state.auth.loading); 37 | 38 | const initialValues = { 39 | email: '', 40 | senha: '', 41 | nome: '', 42 | senhaConfirmacao: '', 43 | }; 44 | const onSubmit = values => { 45 | const {email, nome, senha, senhaConfirmacao} = values; 46 | dispatch(signUpRequest({email, nome, senha, senhaConfirmacao, type})); 47 | }; 48 | return ( 49 | 50 | 51 | 52 | 53 | {({values, handleChange, setFieldTouched, touched, errors}) => ( 54 |
55 | setFieldTouched('nome')} 64 | onChangeText={handleChange('nome')} 65 | onSubmitEditing={() => emailRef.current.focus()} 66 | /> 67 | {touched.nome && errors.nome && ( 68 | 74 | {errors.nome} 75 | 76 | )} 77 | setFieldTouched('email')} 88 | onChangeText={handleChange('email')} 89 | onSubmitEditing={() => passwordRef.current.focus()} 90 | /> 91 | {touched.email && errors.email && ( 92 | 98 | {errors.email} 99 | 100 | )} 101 | setFieldTouched('senha')} 112 | onChangeText={handleChange('senha')} 113 | onSubmitEditing={() => 114 | passwordConfirmationRef.current.focus() 115 | } 116 | /> 117 | {touched.senha && errors.senha && ( 118 | 124 | {errors.senha} 125 | 126 | )} 127 | setFieldTouched('senhaConfirmacao')} 138 | onChangeText={handleChange('senhaConfirmacao')} 139 | onSubmitEditing={() => onSubmit(values)} 140 | /> 141 | {touched.senhaConfirmacao && errors.senhaConfirmacao && ( 142 | 148 | {errors.senhaConfirmacao} 149 | 150 | )} 151 | onSubmit(values)}> 154 | Cadastrar 155 | 156 | 157 | )} 158 |
159 | navigation.navigate('SignIn')}> 160 | Já tem conta? Entre aqui 161 | 162 |
163 |
164 |
165 | ); 166 | } 167 | -------------------------------------------------------------------------------- /frontend/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 | # https://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 or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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 | -------------------------------------------------------------------------------- /backend/controllers/transaction-controller.js: -------------------------------------------------------------------------------- 1 | const repository = require('../repositories/transaction-repository'); 2 | const repositoryCard = require('../repositories/card-repository'); 3 | const repositoryUser = require('../repositories/user-repository'); 4 | 5 | const _repo = new repository(); 6 | const _repoCard = new repositoryCard(); 7 | const _repoUser = new repositoryUser(); 8 | 9 | const ctrlBase = require('../bin/base/controller-base'); 10 | const validation = require('../bin/helpers/validation'); 11 | const pagarme = require('pagarme'); 12 | const variables = require('../bin/configuration/variables'); 13 | const CryptoJS = require('react-native-crypto-js'); 14 | const moment = require('moment'); 15 | 16 | function transactionController() {} 17 | 18 | transactionController.prototype.post = async (req, res) => { 19 | try { 20 | const _validationContract = new validation(); 21 | _validationContract.isRequired(req.body.cpf, 'Informe seu cpf pentelho'); 22 | const data = req.body; 23 | const encryption_key = variables.Pagarme.pagarmeKeyTest; 24 | const client = await pagarme.client.connect({ api_key: encryption_key }); 25 | if (data.card_id) { 26 | const card = await _repoCard.getById(data.card_id); 27 | const pagarmeTransaction = await client.transactions.create({ 28 | amount: 1, 29 | payment_method: 'credit_card', 30 | card_id: card.card_id, 31 | customer: { 32 | name: card.name, 33 | external_id: '#3333', 34 | email: card.email, 35 | type: 'individual', 36 | country: 'br', 37 | phone_numbers: [`+${card.phone}`], 38 | documents: [{ type: 'cpf', number: card.cpf }], 39 | }, 40 | billing: { 41 | name: card.name, 42 | address: { 43 | country: 'br', 44 | state: card.state, 45 | city: card.city, 46 | neighborhood: card.neighborhood, 47 | street: card.street, 48 | street_number: card.street_number, 49 | zipcode: card.zipcode, 50 | }, 51 | }, 52 | items: [ 53 | { 54 | id: '1', 55 | title: 'Parcela mensal do aplicativo do dev doido', 56 | unit_price: 30, 57 | quantity: 1, 58 | tangible: true, 59 | }, 60 | ], 61 | metadata: { idProduto: '1' }, 62 | }); 63 | const transaction = { 64 | status: pagarmeTransaction.status, 65 | authorization_code: pagarmeTransaction.authorization_code, 66 | risk_level: pagarmeTransaction.risk_level, 67 | card: card._id, 68 | userId: req.usuarioLogado.user._id, 69 | acquirer_id: pagarmeTransaction.acquirer_id, 70 | }; 71 | const transactionCreated = await _repo.create(transaction); 72 | const datav = new Date(moment().add(30, 'days')._d.toISOString()); 73 | await _repoUser.updatePayment(datav, req.usuarioLogado.user._id); 74 | res.status(200).send(transactionCreated); 75 | } else { 76 | const bytes = CryptoJS.AES.decrypt( 77 | data.card_hash, 78 | 'hdfudhuidfhudhudah9d8s8f9d8a98as9d8s9d89as', 79 | ); 80 | const decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); 81 | const cardToHash = { 82 | card_number: decryptedData.card_number, 83 | card_holder_name: decryptedData.card_holder_name, 84 | card_cvv: decryptedData.card_cvv, 85 | card_expiration_date: decryptedData.card_expiration_date, 86 | }; 87 | const cardHash = await client.security.encrypt(cardToHash); 88 | const pagarmeTransaction = await client.transactions.create({ 89 | amount: 6000, 90 | payment_method: 'credit_card', 91 | card_hash: cardHash, 92 | customer: { 93 | name: data.name, 94 | external_id: '#3311', 95 | email: data.email, 96 | type: 'individual', 97 | country: 'br', 98 | phone_numbers: [`+${data.phone}`], 99 | documents: [ 100 | { 101 | type: 'cpf', 102 | number: data.cpf, 103 | }, 104 | ], 105 | }, 106 | billing: { 107 | name: data.name, 108 | address: { 109 | country: 'br', 110 | state: data.state, 111 | city: data.city, 112 | neighborhood: data.neighborhood, 113 | street: data.street, 114 | street_number: data.street_number, 115 | zipcode: data.zipcode, 116 | }, 117 | }, 118 | items: [ 119 | { 120 | id: '1', 121 | title: 'Parcela mensal do aplicativo do dev doido', 122 | unit_price: 30, 123 | quantity: 1, 124 | tangible: true, 125 | }, 126 | ], 127 | metadata: { idProduto: '1' }, 128 | }); 129 | const cardAux = pagarmeTransaction.card; 130 | const card = { 131 | state: data.state, 132 | city: data.city, 133 | neighborhood: data.neighborhood, 134 | street: data.street, 135 | street_number: data.street_number, 136 | name: cardAux.holder_name, 137 | cpf: data.cpf, 138 | phone: data.phone, 139 | email: data.email, 140 | street_number: data.street_number, 141 | zipcode: data.zipcode, 142 | card_id: cardAux.id, 143 | userId: req.usuarioLogado.user._id, 144 | brand: cardAux.brand, 145 | holder_name: cardAux.holder_name, 146 | cardNumber: `${cardAux.first_digits}******${cardAux.last_digits}`, 147 | }; 148 | const cardCreated = await _repoCard.create(card); 149 | const transaction = { 150 | status: pagarmeTransaction.status, 151 | authorization_code: pagarmeTransaction.authorization_code, 152 | risk_level: pagarmeTransaction.risk_level, 153 | card: card._id, 154 | userId: req.usuarioLogado.user._id, 155 | acquirer_id: pagarmeTransaction.acquirer_id, 156 | }; 157 | const transactionCreated = await _repo.create(transaction); 158 | const datav = new Date(moment().add(30, 'days')._d.toISOString()); 159 | await _repoUser.updatePayment(datav, req.usuarioLogado.user._id); 160 | res.status(200).send(transactionCreated); 161 | } 162 | } catch (e) { 163 | let ero = ''; 164 | if (e.response && e.response.errors) { 165 | ero = e.response.errors; 166 | } else { 167 | ero = e.toString(); 168 | } 169 | res.status(500).send({ message: 'Internal server error', erro: ero }); // ,erro:e.response.errors[0] }); 170 | } 171 | }; 172 | 173 | transactionController.prototype.get = async (req, res) => { 174 | ctrlBase.getMyAll(_repo, req, res); 175 | }; 176 | transactionController.prototype.delete = async (req, res) => { 177 | ctrlBase.delete(_repo, req, res); 178 | }; 179 | 180 | module.exports = transactionController; 181 | /* 182 | const objtoencrypt = JSON.stringify({ 183 | card_number: "323232323323232", 184 | card_expiration_date: "32232", 185 | card_holder_name: 'Gustavo', 186 | card_cvv: '322', 187 | }); 188 | const cardHash = CryptoJS.AES.encrypt( 189 | objtoencrypt, 190 | 'hdfudhuidfhudhudah9d8s8f9d8a98as9d8s9d89as', 191 | ).toString(); 192 | */ 193 | -------------------------------------------------------------------------------- /frontend/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. If none specified and 19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is 20 | * // default. Can be overridden with ENTRY_FILE environment variable. 21 | * entryFile: "index.android.js", 22 | * 23 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 24 | * bundleCommand: "ram-bundle", 25 | * 26 | * // whether to bundle JS and assets in debug mode 27 | * bundleInDebug: false, 28 | * 29 | * // whether to bundle JS and assets in release mode 30 | * bundleInRelease: true, 31 | * 32 | * // whether to bundle JS and assets in another build variant (if configured). 33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 34 | * // The configuration property can be in the following formats 35 | * // 'bundleIn${productFlavor}${buildType}' 36 | * // 'bundleIn${buildType}' 37 | * // bundleInFreeDebug: true, 38 | * // bundleInPaidRelease: true, 39 | * // bundleInBeta: true, 40 | * 41 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 42 | * // for example: to disable dev mode in the staging build type (if configured) 43 | * devDisabledInStaging: true, 44 | * // The configuration property can be in the following formats 45 | * // 'devDisabledIn${productFlavor}${buildType}' 46 | * // 'devDisabledIn${buildType}' 47 | * 48 | * // the root of your project, i.e. where "package.json" lives 49 | * root: "../../", 50 | * 51 | * // where to put the JS bundle asset in debug mode 52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 53 | * 54 | * // where to put the JS bundle asset in release mode 55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 56 | * 57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 58 | * // require('./image.png')), in debug mode 59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 60 | * 61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 62 | * // require('./image.png')), in release mode 63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 64 | * 65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 69 | * // for example, you might want to remove it from here. 70 | * inputExcludes: ["android/**", "ios/**"], 71 | * 72 | * // override which node gets called and with what additional arguments 73 | * nodeExecutableAndArgs: ["node"], 74 | * 75 | * // supply additional arguments to the packager 76 | * extraPackagerArgs: [] 77 | * ] 78 | */ 79 | 80 | project.ext.react = [ 81 | enableHermes: false, // clean and rebuild if changing 82 | ] 83 | 84 | apply from: "../../node_modules/react-native/react.gradle" 85 | 86 | /** 87 | * Set this to true to create two separate APKs instead of one: 88 | * - An APK that only works on ARM devices 89 | * - An APK that only works on x86 devices 90 | * The advantage is the size of the APK is reduced by about 4MB. 91 | * Upload all the APKs to the Play Store and people will download 92 | * the correct one based on the CPU architecture of their device. 93 | */ 94 | def enableSeparateBuildPerCPUArchitecture = false 95 | 96 | /** 97 | * Run Proguard to shrink the Java bytecode in release builds. 98 | */ 99 | def enableProguardInReleaseBuilds = false 100 | 101 | /** 102 | * The preferred build flavor of JavaScriptCore. 103 | * 104 | * For example, to use the international variant, you can use: 105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 106 | * 107 | * The international variant includes ICU i18n library and necessary data 108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 109 | * give correct results when using with locales other than en-US. Note that 110 | * this variant is about 6MiB larger per architecture than default. 111 | */ 112 | def jscFlavor = 'org.webkit:android-jsc:+' 113 | 114 | /** 115 | * Whether to enable the Hermes VM. 116 | * 117 | * This should be set on project.ext.react and mirrored here. If it is not set 118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 119 | * and the benefits of using Hermes will therefore be sharply reduced. 120 | */ 121 | def enableHermes = project.ext.react.get("enableHermes", false); 122 | 123 | android { 124 | dexOptions { 125 | javaMaxHeapSize "4G" 126 | } 127 | compileSdkVersion rootProject.ext.compileSdkVersion 128 | 129 | compileOptions { 130 | sourceCompatibility JavaVersion.VERSION_1_8 131 | targetCompatibility JavaVersion.VERSION_1_8 132 | } 133 | 134 | defaultConfig { 135 | applicationId "com.devdoido" 136 | minSdkVersion rootProject.ext.minSdkVersion 137 | targetSdkVersion rootProject.ext.targetSdkVersion 138 | versionCode 1 139 | versionName "1.0" 140 | } 141 | splits { 142 | abi { 143 | reset() 144 | enable enableSeparateBuildPerCPUArchitecture 145 | universalApk false // If true, also generate a universal APK 146 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 147 | } 148 | } 149 | signingConfigs { 150 | debug { 151 | storeFile file('debug.keystore') 152 | storePassword 'android' 153 | keyAlias 'androiddebugkey' 154 | keyPassword 'android' 155 | } 156 | } 157 | buildTypes { 158 | debug { 159 | signingConfig signingConfigs.debug 160 | } 161 | release { 162 | // Caution! In production, you need to generate your own keystore file. 163 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 164 | signingConfig signingConfigs.debug 165 | minifyEnabled enableProguardInReleaseBuilds 166 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 167 | } 168 | } 169 | 170 | packagingOptions { 171 | pickFirst "lib/armeabi-v7a/libc++_shared.so" 172 | pickFirst "lib/arm64-v8a/libc++_shared.so" 173 | pickFirst "lib/x86/libc++_shared.so" 174 | pickFirst "lib/x86_64/libc++_shared.so" 175 | } 176 | 177 | // applicationVariants are e.g. debug, release 178 | applicationVariants.all { variant -> 179 | variant.outputs.each { output -> 180 | // For each separate APK per architecture, set a unique version code as described here: 181 | // https://developer.android.com/studio/build/configure-apk-splits.html 182 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 183 | def abi = output.getFilter(OutputFile.ABI) 184 | if (abi != null) { // null for the universal-debug, universal-release variants 185 | output.versionCodeOverride = 186 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 187 | } 188 | 189 | } 190 | } 191 | } 192 | 193 | dependencies { 194 | implementation fileTree(dir: "libs", include: ["*.jar"]) 195 | //noinspection GradleDynamicVersion 196 | implementation "com.facebook.react:react-native:+" // From node_modules 197 | 198 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 199 | 200 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { 201 | exclude group:'com.facebook.fbjni' 202 | } 203 | 204 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 205 | exclude group:'com.facebook.flipper' 206 | } 207 | 208 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { 209 | exclude group:'com.facebook.flipper' 210 | } 211 | 212 | if (enableHermes) { 213 | def hermesPath = "../../node_modules/hermes-engine/android/"; 214 | debugImplementation files(hermesPath + "hermes-debug.aar") 215 | releaseImplementation files(hermesPath + "hermes-release.aar") 216 | } else { 217 | implementation jscFlavor 218 | } 219 | } 220 | 221 | // Run this once to be able to run the application with BUCK 222 | // puts all compile dependencies into folder libs for BUCK to use 223 | task copyDownloadableDepsToLibs(type: Copy) { 224 | from configurations.compile 225 | into 'libs' 226 | } 227 | apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle"); 228 | 229 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 230 | -------------------------------------------------------------------------------- /frontend/src/screens/Payment/PaymentAddress/PaymentAddress.js: -------------------------------------------------------------------------------- 1 | import React, {useRef} from 'react'; 2 | import {useSelector} from 'react-redux'; 3 | import {Formik} from 'formik'; 4 | import * as Yup from 'yup'; 5 | import {Text, Alert} from 'react-native'; 6 | import cep from 'cep-promise'; 7 | import {Container, Form, FormInput, Title, SubmitButton} from './styles'; 8 | import Background from '../../../components/Background/Background'; 9 | import {appColors} from '../../../utils/appColors'; 10 | 11 | const formSchema = Yup.object().shape({ 12 | zipcode: Yup.string() 13 | .trim() 14 | .required('Obrigatório') 15 | .length(9, 'o cep deve ter pelo menos 8 dígitos'), 16 | street: Yup.string().trim().required('Obrigatório'), 17 | street_number: Yup.string().trim().required('Obrigatório'), 18 | city: Yup.string().trim().required('Obrigatório'), 19 | state: Yup.string().trim().required('Obrigatório'), 20 | neighborhood: Yup.string().trim().required('Obrigatório'), 21 | complemento: Yup.string().trim().required('Obrigatório'), 22 | }); 23 | 24 | export default function PaymentAddress({navigation}) { 25 | const profile = useSelector(state => state.user.profile); 26 | const loading = useSelector(state => state.user.loading); 27 | const initialValues = { 28 | zipcode: '', 29 | state: '', 30 | street: '', 31 | city: '', 32 | neighborhood: '', 33 | complemento: '', 34 | street_number: '', 35 | }; 36 | 37 | const streetRef = useRef(); 38 | const complementoRef = useRef(); 39 | const stateRef = useRef(); 40 | const cityRef = useRef(); 41 | const neighborhoodRef = useRef(); 42 | const streetnumberRef = useRef(); 43 | 44 | const onSubmit = async (values, isValid) => { 45 | if (isValid) { 46 | const { 47 | zipcode, 48 | state, 49 | street, 50 | city, 51 | neighborhood, 52 | street_number, 53 | complemento, 54 | } = values; 55 | 56 | navigation.push('PaymentCart', { 57 | zipcode, 58 | state, 59 | street, 60 | city, 61 | neighborhood, 62 | street_number, 63 | complemento, 64 | }); 65 | } 66 | }; 67 | 68 | const onChangeCep = async (setValues, values, txt) => { 69 | if (txt.length == 9) { 70 | setValues({...values, zipcode: txt}); 71 | try { 72 | const {state, city, street, neighborhood} = await cep(txt); 73 | setValues({...values, state, city, street, neighborhood, zipcode: txt}); 74 | } catch (e) { 75 | Alert.alert('CEP não foi encontrado'); 76 | } 77 | } else { 78 | setValues({...values, zipcode: txt}); 79 | } 80 | }; 81 | 82 | return ( 83 | 84 | 85 | Endereço de cobrança 86 | 87 | {({ 88 | values, 89 | handleChange, 90 | setFieldTouched, 91 | touched, 92 | isValid, 93 | errors, 94 | setValues, 95 | }) => ( 96 |
97 | 103 | CEP 104 | 105 | { 116 | streetnumberRef.current.focus(); 117 | }} 118 | value={values.zipcode} 119 | onBlur={() => setFieldTouched('zipcode')} 120 | onChangeText={txt => { 121 | onChangeCep(setValues, values, txt); 122 | }} 123 | /> 124 | {touched.zipcode && errors.zipcode && ( 125 | 131 | {errors.zipcode} 132 | 133 | )} 134 | 140 | Cidade 141 | 142 | { 151 | stateRef.current.focus(); 152 | }} 153 | value={values.city} 154 | onBlur={() => setFieldTouched('city')} 155 | onChangeText={handleChange('city')} 156 | /> 157 | {touched.city && errors.city && ( 158 | 164 | {errors.city} 165 | 166 | )} 167 | 173 | Estado 174 | 175 | { 184 | neighborhoodRef.current.focus(); 185 | }} 186 | value={values.state} 187 | onBlur={() => setFieldTouched('state')} 188 | onChangeText={handleChange('state')} 189 | /> 190 | {touched.state && errors.state && ( 191 | 197 | {errors.state} 198 | 199 | )} 200 | 206 | Bairro 207 | 208 | { 217 | neighborhoodRef.current.focus(); 218 | }} 219 | value={values.neighborhood} 220 | onBlur={() => setFieldTouched('neighborhood')} 221 | onChangeText={handleChange('neighborhood')} 222 | /> 223 | {touched.neighborhood && errors.neighborhood && ( 224 | 230 | {errors.neighborhood} 231 | 232 | )} 233 | 239 | Endereço 240 | 241 | { 250 | streetnumberRef.current.focus(); 251 | }} 252 | value={values.street} 253 | onBlur={() => setFieldTouched('street')} 254 | onChangeText={handleChange('street')} 255 | /> 256 | {touched.street && errors.street && ( 257 | 263 | {errors.street} 264 | 265 | )} 266 | 272 | Número 273 | 274 | { 283 | complementoRef.current.focus(); 284 | }} 285 | value={values.street_number} 286 | onBlur={() => setFieldTouched('street_number')} 287 | onChangeText={handleChange('street_number')} 288 | /> 289 | {touched.street_number && errors.street_number && ( 290 | 296 | {errors.street_number} 297 | 298 | )} 299 | 305 | Complemento 306 | 307 | { 316 | onSubmit(values, isValid); 317 | }} 318 | value={values.complemento} 319 | onBlur={() => setFieldTouched('complemento')} 320 | onChangeText={handleChange('complemento')} 321 | /> 322 | {touched.complemento && errors.complemento && ( 323 | 329 | {errors.complemento} 330 | 331 | )} 332 | onSubmit(values, isValid)}> 335 | Avançar 336 | 337 | 338 | )} 339 |
340 |
341 |
342 | ); 343 | } 344 | -------------------------------------------------------------------------------- /frontend/ios/devdoido.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 00E356F31AD99517003FC87E /* devdoidoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* devdoidoTests.m */; }; 11 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 12 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 14 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 15 | 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 16 | 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 17 | 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 18 | 2DCD954D1E0B4F2C00145EB5 /* devdoidoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* devdoidoTests.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A; 27 | remoteInfo = devdoido; 28 | }; 29 | 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7; 34 | remoteInfo = "devdoido-tvOS"; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 40 | 00E356EE1AD99517003FC87E /* devdoidoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = devdoidoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 00E356F21AD99517003FC87E /* devdoidoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = devdoidoTests.m; sourceTree = ""; }; 43 | 13B07F961A680F5B00A75B9A /* devdoido.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = devdoido.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = devdoido/AppDelegate.h; sourceTree = ""; }; 45 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = devdoido/AppDelegate.m; sourceTree = ""; }; 46 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 47 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = devdoido/Images.xcassets; sourceTree = ""; }; 48 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = devdoido/Info.plist; sourceTree = ""; }; 49 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = devdoido/main.m; sourceTree = ""; }; 50 | 2D02E47B1E0B4A5D006451C7 /* devdoido-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "devdoido-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 2D02E4901E0B4A5D006451C7 /* devdoido-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "devdoido-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 53 | ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 00E356EB1AD99517003FC87E /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | 2D02E4781E0B4A5D006451C7 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | 2D02E48D1E0B4A5D006451C7 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | 00E356EF1AD99517003FC87E /* devdoidoTests */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 00E356F21AD99517003FC87E /* devdoidoTests.m */, 92 | 00E356F01AD99517003FC87E /* Supporting Files */, 93 | ); 94 | path = devdoidoTests; 95 | sourceTree = ""; 96 | }; 97 | 00E356F01AD99517003FC87E /* Supporting Files */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 00E356F11AD99517003FC87E /* Info.plist */, 101 | ); 102 | name = "Supporting Files"; 103 | sourceTree = ""; 104 | }; 105 | 13B07FAE1A68108700A75B9A /* devdoido */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 109 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 110 | 13B07FB01A68108700A75B9A /* AppDelegate.m */, 111 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 112 | 13B07FB61A68108700A75B9A /* Info.plist */, 113 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 114 | 13B07FB71A68108700A75B9A /* main.m */, 115 | ); 116 | name = devdoido; 117 | sourceTree = ""; 118 | }; 119 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */, 123 | ED2971642150620600B7C4FE /* JavaScriptCore.framework */, 124 | ); 125 | name = Frameworks; 126 | sourceTree = ""; 127 | }; 128 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | ); 132 | name = Libraries; 133 | sourceTree = ""; 134 | }; 135 | 83CBB9F61A601CBA00E9B192 = { 136 | isa = PBXGroup; 137 | children = ( 138 | 13B07FAE1A68108700A75B9A /* devdoido */, 139 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 140 | 00E356EF1AD99517003FC87E /* devdoidoTests */, 141 | 83CBBA001A601CBA00E9B192 /* Products */, 142 | 2D16E6871FA4F8E400B85C8A /* Frameworks */, 143 | ); 144 | indentWidth = 2; 145 | sourceTree = ""; 146 | tabWidth = 2; 147 | usesTabs = 0; 148 | }; 149 | 83CBBA001A601CBA00E9B192 /* Products */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 13B07F961A680F5B00A75B9A /* devdoido.app */, 153 | 00E356EE1AD99517003FC87E /* devdoidoTests.xctest */, 154 | 2D02E47B1E0B4A5D006451C7 /* devdoido-tvOS.app */, 155 | 2D02E4901E0B4A5D006451C7 /* devdoido-tvOSTests.xctest */, 156 | ); 157 | name = Products; 158 | sourceTree = ""; 159 | }; 160 | /* End PBXGroup section */ 161 | 162 | /* Begin PBXNativeTarget section */ 163 | 00E356ED1AD99517003FC87E /* devdoidoTests */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "devdoidoTests" */; 166 | buildPhases = ( 167 | 00E356EA1AD99517003FC87E /* Sources */, 168 | 00E356EB1AD99517003FC87E /* Frameworks */, 169 | 00E356EC1AD99517003FC87E /* Resources */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | 00E356F51AD99517003FC87E /* PBXTargetDependency */, 175 | ); 176 | name = devdoidoTests; 177 | productName = devdoidoTests; 178 | productReference = 00E356EE1AD99517003FC87E /* devdoidoTests.xctest */; 179 | productType = "com.apple.product-type.bundle.unit-test"; 180 | }; 181 | 13B07F861A680F5B00A75B9A /* devdoido */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "devdoido" */; 184 | buildPhases = ( 185 | FD10A7F022414F080027D42C /* Start Packager */, 186 | 13B07F871A680F5B00A75B9A /* Sources */, 187 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 188 | 13B07F8E1A680F5B00A75B9A /* Resources */, 189 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | ); 195 | name = devdoido; 196 | productName = devdoido; 197 | productReference = 13B07F961A680F5B00A75B9A /* devdoido.app */; 198 | productType = "com.apple.product-type.application"; 199 | }; 200 | 2D02E47A1E0B4A5D006451C7 /* devdoido-tvOS */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "devdoido-tvOS" */; 203 | buildPhases = ( 204 | FD10A7F122414F3F0027D42C /* Start Packager */, 205 | 2D02E4771E0B4A5D006451C7 /* Sources */, 206 | 2D02E4781E0B4A5D006451C7 /* Frameworks */, 207 | 2D02E4791E0B4A5D006451C7 /* Resources */, 208 | 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | ); 214 | name = "devdoido-tvOS"; 215 | productName = "devdoido-tvOS"; 216 | productReference = 2D02E47B1E0B4A5D006451C7 /* devdoido-tvOS.app */; 217 | productType = "com.apple.product-type.application"; 218 | }; 219 | 2D02E48F1E0B4A5D006451C7 /* devdoido-tvOSTests */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "devdoido-tvOSTests" */; 222 | buildPhases = ( 223 | 2D02E48C1E0B4A5D006451C7 /* Sources */, 224 | 2D02E48D1E0B4A5D006451C7 /* Frameworks */, 225 | 2D02E48E1E0B4A5D006451C7 /* Resources */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */, 231 | ); 232 | name = "devdoido-tvOSTests"; 233 | productName = "devdoido-tvOSTests"; 234 | productReference = 2D02E4901E0B4A5D006451C7 /* devdoido-tvOSTests.xctest */; 235 | productType = "com.apple.product-type.bundle.unit-test"; 236 | }; 237 | /* End PBXNativeTarget section */ 238 | 239 | /* Begin PBXProject section */ 240 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 241 | isa = PBXProject; 242 | attributes = { 243 | LastUpgradeCheck = 1130; 244 | TargetAttributes = { 245 | 00E356ED1AD99517003FC87E = { 246 | CreatedOnToolsVersion = 6.2; 247 | TestTargetID = 13B07F861A680F5B00A75B9A; 248 | }; 249 | 13B07F861A680F5B00A75B9A = { 250 | LastSwiftMigration = 1120; 251 | }; 252 | 2D02E47A1E0B4A5D006451C7 = { 253 | CreatedOnToolsVersion = 8.2.1; 254 | ProvisioningStyle = Automatic; 255 | }; 256 | 2D02E48F1E0B4A5D006451C7 = { 257 | CreatedOnToolsVersion = 8.2.1; 258 | ProvisioningStyle = Automatic; 259 | TestTargetID = 2D02E47A1E0B4A5D006451C7; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "devdoido" */; 264 | compatibilityVersion = "Xcode 3.2"; 265 | developmentRegion = en; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | Base, 270 | ); 271 | mainGroup = 83CBB9F61A601CBA00E9B192; 272 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 273 | projectDirPath = ""; 274 | projectRoot = ""; 275 | targets = ( 276 | 13B07F861A680F5B00A75B9A /* devdoido */, 277 | 00E356ED1AD99517003FC87E /* devdoidoTests */, 278 | 2D02E47A1E0B4A5D006451C7 /* devdoido-tvOS */, 279 | 2D02E48F1E0B4A5D006451C7 /* devdoido-tvOSTests */, 280 | ); 281 | }; 282 | /* End PBXProject section */ 283 | 284 | /* Begin PBXResourcesBuildPhase section */ 285 | 00E356EC1AD99517003FC87E /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 293 | isa = PBXResourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 297 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | 2D02E4791E0B4A5D006451C7 /* Resources */ = { 302 | isa = PBXResourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | 2D02E48E1E0B4A5D006451C7 /* Resources */ = { 310 | isa = PBXResourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | /* End PBXResourcesBuildPhase section */ 317 | 318 | /* Begin PBXShellScriptBuildPhase section */ 319 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { 320 | isa = PBXShellScriptBuildPhase; 321 | buildActionMask = 2147483647; 322 | files = ( 323 | ); 324 | inputPaths = ( 325 | ); 326 | name = "Bundle React Native code and images"; 327 | outputPaths = ( 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | shellPath = /bin/sh; 331 | shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; 332 | }; 333 | 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | inputPaths = ( 339 | ); 340 | name = "Bundle React Native Code And Images"; 341 | outputPaths = ( 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | shellPath = /bin/sh; 345 | shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; 346 | }; 347 | FD10A7F022414F080027D42C /* Start Packager */ = { 348 | isa = PBXShellScriptBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | ); 352 | inputFileListPaths = ( 353 | ); 354 | inputPaths = ( 355 | ); 356 | name = "Start Packager"; 357 | outputFileListPaths = ( 358 | ); 359 | outputPaths = ( 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | shellPath = /bin/sh; 363 | shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; 364 | showEnvVarsInLog = 0; 365 | }; 366 | FD10A7F122414F3F0027D42C /* Start Packager */ = { 367 | isa = PBXShellScriptBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | ); 371 | inputFileListPaths = ( 372 | ); 373 | inputPaths = ( 374 | ); 375 | name = "Start Packager"; 376 | outputFileListPaths = ( 377 | ); 378 | outputPaths = ( 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | shellPath = /bin/sh; 382 | shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; 383 | showEnvVarsInLog = 0; 384 | }; 385 | /* End PBXShellScriptBuildPhase section */ 386 | 387 | /* Begin PBXSourcesBuildPhase section */ 388 | 00E356EA1AD99517003FC87E /* Sources */ = { 389 | isa = PBXSourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | 00E356F31AD99517003FC87E /* devdoidoTests.m in Sources */, 393 | ); 394 | runOnlyForDeploymentPostprocessing = 0; 395 | }; 396 | 13B07F871A680F5B00A75B9A /* Sources */ = { 397 | isa = PBXSourcesBuildPhase; 398 | buildActionMask = 2147483647; 399 | files = ( 400 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 401 | 13B07FC11A68108700A75B9A /* main.m in Sources */, 402 | ); 403 | runOnlyForDeploymentPostprocessing = 0; 404 | }; 405 | 2D02E4771E0B4A5D006451C7 /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */, 410 | 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */, 411 | ); 412 | runOnlyForDeploymentPostprocessing = 0; 413 | }; 414 | 2D02E48C1E0B4A5D006451C7 /* Sources */ = { 415 | isa = PBXSourcesBuildPhase; 416 | buildActionMask = 2147483647; 417 | files = ( 418 | 2DCD954D1E0B4F2C00145EB5 /* devdoidoTests.m in Sources */, 419 | ); 420 | runOnlyForDeploymentPostprocessing = 0; 421 | }; 422 | /* End PBXSourcesBuildPhase section */ 423 | 424 | /* Begin PBXTargetDependency section */ 425 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { 426 | isa = PBXTargetDependency; 427 | target = 13B07F861A680F5B00A75B9A /* devdoido */; 428 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; 429 | }; 430 | 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */ = { 431 | isa = PBXTargetDependency; 432 | target = 2D02E47A1E0B4A5D006451C7 /* devdoido-tvOS */; 433 | targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */; 434 | }; 435 | /* End PBXTargetDependency section */ 436 | 437 | /* Begin PBXVariantGroup section */ 438 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { 439 | isa = PBXVariantGroup; 440 | children = ( 441 | 13B07FB21A68108700A75B9A /* Base */, 442 | ); 443 | name = LaunchScreen.xib; 444 | path = devdoido; 445 | sourceTree = ""; 446 | }; 447 | /* End PBXVariantGroup section */ 448 | 449 | /* Begin XCBuildConfiguration section */ 450 | 00E356F61AD99517003FC87E /* Debug */ = { 451 | isa = XCBuildConfiguration; 452 | buildSettings = { 453 | BUNDLE_LOADER = "$(TEST_HOST)"; 454 | GCC_PREPROCESSOR_DEFINITIONS = ( 455 | "DEBUG=1", 456 | "$(inherited)", 457 | ); 458 | INFOPLIST_FILE = devdoidoTests/Info.plist; 459 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 460 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 461 | OTHER_LDFLAGS = ( 462 | "-ObjC", 463 | "-lc++", 464 | "$(inherited)", 465 | ); 466 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/devdoido.app/devdoido"; 469 | }; 470 | name = Debug; 471 | }; 472 | 00E356F71AD99517003FC87E /* Release */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | BUNDLE_LOADER = "$(TEST_HOST)"; 476 | COPY_PHASE_STRIP = NO; 477 | INFOPLIST_FILE = devdoidoTests/Info.plist; 478 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 480 | OTHER_LDFLAGS = ( 481 | "-ObjC", 482 | "-lc++", 483 | "$(inherited)", 484 | ); 485 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/devdoido.app/devdoido"; 488 | }; 489 | name = Release; 490 | }; 491 | 13B07F941A680F5B00A75B9A /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | CLANG_ENABLE_MODULES = YES; 496 | CURRENT_PROJECT_VERSION = 1; 497 | ENABLE_BITCODE = NO; 498 | GCC_PREPROCESSOR_DEFINITIONS = ( 499 | "$(inherited)", 500 | "FB_SONARKIT_ENABLED=1", 501 | ); 502 | INFOPLIST_FILE = devdoido/Info.plist; 503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 504 | OTHER_LDFLAGS = ( 505 | "$(inherited)", 506 | "-ObjC", 507 | "-lc++", 508 | ); 509 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; 510 | PRODUCT_NAME = devdoido; 511 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 512 | SWIFT_VERSION = 5.0; 513 | VERSIONING_SYSTEM = "apple-generic"; 514 | }; 515 | name = Debug; 516 | }; 517 | 13B07F951A680F5B00A75B9A /* Release */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 521 | CLANG_ENABLE_MODULES = YES; 522 | CURRENT_PROJECT_VERSION = 1; 523 | INFOPLIST_FILE = devdoido/Info.plist; 524 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 525 | OTHER_LDFLAGS = ( 526 | "$(inherited)", 527 | "-ObjC", 528 | "-lc++", 529 | ); 530 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; 531 | PRODUCT_NAME = devdoido; 532 | SWIFT_VERSION = 5.0; 533 | VERSIONING_SYSTEM = "apple-generic"; 534 | }; 535 | name = Release; 536 | }; 537 | 2D02E4971E0B4A5E006451C7 /* Debug */ = { 538 | isa = XCBuildConfiguration; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 541 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 542 | CLANG_ANALYZER_NONNULL = YES; 543 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 544 | CLANG_WARN_INFINITE_RECURSION = YES; 545 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 546 | DEBUG_INFORMATION_FORMAT = dwarf; 547 | ENABLE_TESTABILITY = YES; 548 | GCC_NO_COMMON_BLOCKS = YES; 549 | INFOPLIST_FILE = "devdoido-tvOS/Info.plist"; 550 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 551 | OTHER_LDFLAGS = ( 552 | "$(inherited)", 553 | "-ObjC", 554 | "-lc++", 555 | ); 556 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.devdoido-tvOS"; 557 | PRODUCT_NAME = "$(TARGET_NAME)"; 558 | SDKROOT = appletvos; 559 | TARGETED_DEVICE_FAMILY = 3; 560 | TVOS_DEPLOYMENT_TARGET = 9.2; 561 | }; 562 | name = Debug; 563 | }; 564 | 2D02E4981E0B4A5E006451C7 /* Release */ = { 565 | isa = XCBuildConfiguration; 566 | buildSettings = { 567 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 568 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 569 | CLANG_ANALYZER_NONNULL = YES; 570 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 571 | CLANG_WARN_INFINITE_RECURSION = YES; 572 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 573 | COPY_PHASE_STRIP = NO; 574 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 575 | GCC_NO_COMMON_BLOCKS = YES; 576 | INFOPLIST_FILE = "devdoido-tvOS/Info.plist"; 577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 578 | OTHER_LDFLAGS = ( 579 | "$(inherited)", 580 | "-ObjC", 581 | "-lc++", 582 | ); 583 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.devdoido-tvOS"; 584 | PRODUCT_NAME = "$(TARGET_NAME)"; 585 | SDKROOT = appletvos; 586 | TARGETED_DEVICE_FAMILY = 3; 587 | TVOS_DEPLOYMENT_TARGET = 9.2; 588 | }; 589 | name = Release; 590 | }; 591 | 2D02E4991E0B4A5E006451C7 /* Debug */ = { 592 | isa = XCBuildConfiguration; 593 | buildSettings = { 594 | BUNDLE_LOADER = "$(TEST_HOST)"; 595 | CLANG_ANALYZER_NONNULL = YES; 596 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 597 | CLANG_WARN_INFINITE_RECURSION = YES; 598 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 599 | DEBUG_INFORMATION_FORMAT = dwarf; 600 | ENABLE_TESTABILITY = YES; 601 | GCC_NO_COMMON_BLOCKS = YES; 602 | INFOPLIST_FILE = "devdoido-tvOSTests/Info.plist"; 603 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 604 | OTHER_LDFLAGS = ( 605 | "$(inherited)", 606 | "-ObjC", 607 | "-lc++", 608 | ); 609 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.devdoido-tvOSTests"; 610 | PRODUCT_NAME = "$(TARGET_NAME)"; 611 | SDKROOT = appletvos; 612 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/devdoido-tvOS.app/devdoido-tvOS"; 613 | TVOS_DEPLOYMENT_TARGET = 10.1; 614 | }; 615 | name = Debug; 616 | }; 617 | 2D02E49A1E0B4A5E006451C7 /* Release */ = { 618 | isa = XCBuildConfiguration; 619 | buildSettings = { 620 | BUNDLE_LOADER = "$(TEST_HOST)"; 621 | CLANG_ANALYZER_NONNULL = YES; 622 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 623 | CLANG_WARN_INFINITE_RECURSION = YES; 624 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 625 | COPY_PHASE_STRIP = NO; 626 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 627 | GCC_NO_COMMON_BLOCKS = YES; 628 | INFOPLIST_FILE = "devdoido-tvOSTests/Info.plist"; 629 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 630 | OTHER_LDFLAGS = ( 631 | "$(inherited)", 632 | "-ObjC", 633 | "-lc++", 634 | ); 635 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.devdoido-tvOSTests"; 636 | PRODUCT_NAME = "$(TARGET_NAME)"; 637 | SDKROOT = appletvos; 638 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/devdoido-tvOS.app/devdoido-tvOS"; 639 | TVOS_DEPLOYMENT_TARGET = 10.1; 640 | }; 641 | name = Release; 642 | }; 643 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | ALWAYS_SEARCH_USER_PATHS = NO; 647 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 648 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 649 | CLANG_CXX_LIBRARY = "libc++"; 650 | CLANG_ENABLE_MODULES = YES; 651 | CLANG_ENABLE_OBJC_ARC = YES; 652 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 653 | CLANG_WARN_BOOL_CONVERSION = YES; 654 | CLANG_WARN_COMMA = YES; 655 | CLANG_WARN_CONSTANT_CONVERSION = YES; 656 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 657 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 658 | CLANG_WARN_EMPTY_BODY = YES; 659 | CLANG_WARN_ENUM_CONVERSION = YES; 660 | CLANG_WARN_INFINITE_RECURSION = YES; 661 | CLANG_WARN_INT_CONVERSION = YES; 662 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 663 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 664 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 665 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 666 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 667 | CLANG_WARN_STRICT_PROTOTYPES = YES; 668 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 669 | CLANG_WARN_UNREACHABLE_CODE = YES; 670 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 671 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 672 | COPY_PHASE_STRIP = NO; 673 | ENABLE_STRICT_OBJC_MSGSEND = YES; 674 | ENABLE_TESTABILITY = YES; 675 | GCC_C_LANGUAGE_STANDARD = gnu99; 676 | GCC_DYNAMIC_NO_PIC = NO; 677 | GCC_NO_COMMON_BLOCKS = YES; 678 | GCC_OPTIMIZATION_LEVEL = 0; 679 | GCC_PREPROCESSOR_DEFINITIONS = ( 680 | "DEBUG=1", 681 | "$(inherited)", 682 | ); 683 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 684 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 685 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 686 | GCC_WARN_UNDECLARED_SELECTOR = YES; 687 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 688 | GCC_WARN_UNUSED_FUNCTION = YES; 689 | GCC_WARN_UNUSED_VARIABLE = YES; 690 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 691 | LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; 692 | LIBRARY_SEARCH_PATHS = ( 693 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", 694 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", 695 | "\"$(inherited)\"", 696 | ); 697 | MTL_ENABLE_DEBUG_INFO = YES; 698 | ONLY_ACTIVE_ARCH = YES; 699 | SDKROOT = iphoneos; 700 | }; 701 | name = Debug; 702 | }; 703 | 83CBBA211A601CBA00E9B192 /* Release */ = { 704 | isa = XCBuildConfiguration; 705 | buildSettings = { 706 | ALWAYS_SEARCH_USER_PATHS = NO; 707 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 708 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 709 | CLANG_CXX_LIBRARY = "libc++"; 710 | CLANG_ENABLE_MODULES = YES; 711 | CLANG_ENABLE_OBJC_ARC = YES; 712 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 713 | CLANG_WARN_BOOL_CONVERSION = YES; 714 | CLANG_WARN_COMMA = YES; 715 | CLANG_WARN_CONSTANT_CONVERSION = YES; 716 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 717 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 718 | CLANG_WARN_EMPTY_BODY = YES; 719 | CLANG_WARN_ENUM_CONVERSION = YES; 720 | CLANG_WARN_INFINITE_RECURSION = YES; 721 | CLANG_WARN_INT_CONVERSION = YES; 722 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 723 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 724 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 725 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 726 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 727 | CLANG_WARN_STRICT_PROTOTYPES = YES; 728 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 729 | CLANG_WARN_UNREACHABLE_CODE = YES; 730 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 731 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 732 | COPY_PHASE_STRIP = YES; 733 | ENABLE_NS_ASSERTIONS = NO; 734 | ENABLE_STRICT_OBJC_MSGSEND = YES; 735 | GCC_C_LANGUAGE_STANDARD = gnu99; 736 | GCC_NO_COMMON_BLOCKS = YES; 737 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 738 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 739 | GCC_WARN_UNDECLARED_SELECTOR = YES; 740 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 741 | GCC_WARN_UNUSED_FUNCTION = YES; 742 | GCC_WARN_UNUSED_VARIABLE = YES; 743 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 744 | LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; 745 | LIBRARY_SEARCH_PATHS = ( 746 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", 747 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", 748 | "\"$(inherited)\"", 749 | ); 750 | MTL_ENABLE_DEBUG_INFO = NO; 751 | SDKROOT = iphoneos; 752 | VALIDATE_PRODUCT = YES; 753 | }; 754 | name = Release; 755 | }; 756 | /* End XCBuildConfiguration section */ 757 | 758 | /* Begin XCConfigurationList section */ 759 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "devdoidoTests" */ = { 760 | isa = XCConfigurationList; 761 | buildConfigurations = ( 762 | 00E356F61AD99517003FC87E /* Debug */, 763 | 00E356F71AD99517003FC87E /* Release */, 764 | ); 765 | defaultConfigurationIsVisible = 0; 766 | defaultConfigurationName = Release; 767 | }; 768 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "devdoido" */ = { 769 | isa = XCConfigurationList; 770 | buildConfigurations = ( 771 | 13B07F941A680F5B00A75B9A /* Debug */, 772 | 13B07F951A680F5B00A75B9A /* Release */, 773 | ); 774 | defaultConfigurationIsVisible = 0; 775 | defaultConfigurationName = Release; 776 | }; 777 | 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "devdoido-tvOS" */ = { 778 | isa = XCConfigurationList; 779 | buildConfigurations = ( 780 | 2D02E4971E0B4A5E006451C7 /* Debug */, 781 | 2D02E4981E0B4A5E006451C7 /* Release */, 782 | ); 783 | defaultConfigurationIsVisible = 0; 784 | defaultConfigurationName = Release; 785 | }; 786 | 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "devdoido-tvOSTests" */ = { 787 | isa = XCConfigurationList; 788 | buildConfigurations = ( 789 | 2D02E4991E0B4A5E006451C7 /* Debug */, 790 | 2D02E49A1E0B4A5E006451C7 /* Release */, 791 | ); 792 | defaultConfigurationIsVisible = 0; 793 | defaultConfigurationName = Release; 794 | }; 795 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "devdoido" */ = { 796 | isa = XCConfigurationList; 797 | buildConfigurations = ( 798 | 83CBBA201A601CBA00E9B192 /* Debug */, 799 | 83CBBA211A601CBA00E9B192 /* Release */, 800 | ); 801 | defaultConfigurationIsVisible = 0; 802 | defaultConfigurationName = Release; 803 | }; 804 | /* End XCConfigurationList section */ 805 | }; 806 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 807 | } 808 | --------------------------------------------------------------------------------