├── assets ├── icon.png ├── splash.png ├── favicon.png └── adaptive-icon.png ├── babel.config.js ├── src ├── data │ └── Profile.js ├── components │ ├── Title │ │ ├── styles.js │ │ └── index.jsx │ └── TouchButton │ │ ├── styles.js │ │ └── index.jsx ├── models │ └── user │ │ ├── User.js │ │ └── UserRepository.js ├── screens │ ├── Home │ │ ├── styles.js │ │ └── index.jsx │ ├── Form │ │ ├── styles.js │ │ └── index.jsx │ ├── Profile │ │ ├── styles.js │ │ └── index.jsx │ └── Users │ │ ├── styles.js │ │ └── index.jsx └── routes │ ├── index.jsx │ ├── stack.routes.jsx │ ├── drawer.routes.jsx │ └── tab.routes.jsx ├── App.jsx ├── .gitignore ├── app.json ├── package.json ├── LICENSE └── README.md /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FelipeSantos92Dev/rn-models/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FelipeSantos92Dev/rn-models/HEAD/assets/splash.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FelipeSantos92Dev/rn-models/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FelipeSantos92Dev/rn-models/HEAD/assets/adaptive-icon.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /src/data/Profile.js: -------------------------------------------------------------------------------- 1 | export const user = { 2 | id: 1513, 3 | name: "Felipe Santos", 4 | email: "felipesantos@dev.com", 5 | age: 32, 6 | }; 7 | -------------------------------------------------------------------------------- /App.jsx: -------------------------------------------------------------------------------- 1 | import "react-native-gesture-handler"; 2 | 3 | import Routes from "./src/routes"; 4 | 5 | export default function App() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/Title/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | title: { 5 | fontSize: 24, 6 | fontWeight: "bold", 7 | }, 8 | }); 9 | 10 | export default styles; 11 | -------------------------------------------------------------------------------- /src/components/Title/index.jsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | 3 | import styles from "./styles"; 4 | 5 | const Title = ({ title }) => { 6 | return ( 7 | 8 | {title} 9 | 10 | ); 11 | }; 12 | 13 | export default Title; 14 | -------------------------------------------------------------------------------- /src/models/user/User.js: -------------------------------------------------------------------------------- 1 | export default class User { 2 | constructor(name, email, age) { 3 | this.id = this.generateId(); 4 | this.name = name; 5 | this.email = email; 6 | this.age = age; 7 | } 8 | 9 | generateId() { 10 | return Math.floor(Math.random() * 1000); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/components/TouchButton/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | title: { 5 | fontSize: 24, 6 | fontWeight: "bold", 7 | }, 8 | button: { 9 | marginTop: 20, 10 | padding: 10, 11 | backgroundColor: "#C9D4FF", 12 | borderRadius: 5, 13 | }, 14 | }); 15 | 16 | export default styles; 17 | -------------------------------------------------------------------------------- /src/screens/Home/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | alignItems: "center", 7 | marginTop: 50, 8 | }, 9 | button: { 10 | marginTop: 20, 11 | padding: 10, 12 | backgroundColor: "#C9D4FF", 13 | borderRadius: 5, 14 | }, 15 | }); 16 | 17 | export default styles; 18 | -------------------------------------------------------------------------------- /src/screens/Home/index.jsx: -------------------------------------------------------------------------------- 1 | import { Text, View } from "react-native"; 2 | 3 | import styles from "./styles"; 4 | import Title from "../../components/Title"; 5 | 6 | export default function Home() { 7 | return ( 8 | 9 | 10 | 11 | <View> 12 | <Text>Tela de apresentação do app</Text> 13 | </View> 14 | </View> 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/screens/Form/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | marginTop: 50, 7 | alignItems: "center", 8 | }, 9 | button: { 10 | marginTop: 20, 11 | padding: 10, 12 | backgroundColor: "#C9D4FF", 13 | borderRadius: 5, 14 | }, 15 | userInput: { 16 | padding: 8, 17 | borderBottomColor: "black", 18 | borderBottomWidth: 1, 19 | }, 20 | }); 21 | 22 | export default styles; 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # Expo 7 | .expo/ 8 | dist/ 9 | web-build/ 10 | 11 | # Native 12 | *.orig.* 13 | *.jks 14 | *.p8 15 | *.p12 16 | *.key 17 | *.mobileprovision 18 | 19 | # Metro 20 | .metro-health-check* 21 | 22 | # debug 23 | npm-debug.* 24 | yarn-debug.* 25 | yarn-error.* 26 | 27 | # macOS 28 | .DS_Store 29 | *.pem 30 | 31 | # local env files 32 | .env*.local 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | -------------------------------------------------------------------------------- /src/routes/index.jsx: -------------------------------------------------------------------------------- 1 | import { NavigationContainer } from "@react-navigation/native"; 2 | import { StatusBar } from "expo-status-bar"; 3 | 4 | import StackRoutes from "./stack.routes"; 5 | import TabRoutes from "./tab.routes"; 6 | import DrawerRoutes from "./drawer.routes"; 7 | 8 | export default function Routes() { 9 | return ( 10 | <NavigationContainer> 11 | {/* <StackRoutes /> */} 12 | <TabRoutes /> 13 | {/* <DrawerRoutes /> */} 14 | <StatusBar style="auto" /> 15 | </NavigationContainer> 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/TouchButton/index.jsx: -------------------------------------------------------------------------------- 1 | import { View, TouchableOpacity } from "react-native"; 2 | import { useNavigation } from "@react-navigation/native"; 3 | 4 | import styles from "./styles"; 5 | import Title from "../Title"; 6 | 7 | const TouchButton = ({ route, title, data }) => { 8 | const navigation = useNavigation(); 9 | 10 | return ( 11 | <View> 12 | <TouchableOpacity 13 | style={styles.button} 14 | onPress={() => navigation.navigate(route, { data })} 15 | > 16 | <Title title={title} /> 17 | </TouchableOpacity> 18 | </View> 19 | ); 20 | }; 21 | 22 | export default TouchButton; 23 | -------------------------------------------------------------------------------- /src/routes/stack.routes.jsx: -------------------------------------------------------------------------------- 1 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 2 | 3 | import Home from "../screens/Home"; 4 | import Profile from "../screens/Profile"; 5 | import Form from "../screens/Form"; 6 | 7 | const Stack = createNativeStackNavigator(); 8 | 9 | const StackRoutes = () => { 10 | return ( 11 | <Stack.Navigator screenOptions={{ headerShown: false }}> 12 | <Stack.Screen name="Home" component={Home} /> 13 | <Stack.Screen name="Profile" component={Profile} /> 14 | <Stack.Screen name="Form" component={Form} /> 15 | </Stack.Navigator> 16 | ); 17 | }; 18 | 19 | export default StackRoutes; 20 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "rn-boilerplate", 4 | "slug": "rn-boilerplate", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "assetBundlePatterns": [ 15 | "**/*" 16 | ], 17 | "ios": { 18 | "supportsTablet": true 19 | }, 20 | "android": { 21 | "adaptiveIcon": { 22 | "foregroundImage": "./assets/adaptive-icon.png", 23 | "backgroundColor": "#ffffff" 24 | } 25 | }, 26 | "web": { 27 | "favicon": "./assets/favicon.png" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-boilerplate", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web" 10 | }, 11 | "dependencies": { 12 | "@react-navigation/bottom-tabs": "^6.5.19", 13 | "@react-navigation/drawer": "^6.6.14", 14 | "@react-navigation/native": "^6.1.16", 15 | "@react-navigation/native-stack": "^6.9.25", 16 | "expo": "~50.0.11", 17 | "expo-status-bar": "~1.11.1", 18 | "react": "18.2.0", 19 | "react-native": "0.73.4", 20 | "react-native-safe-area-context": "4.8.2", 21 | "react-native-screens": "~3.29.0", 22 | "react-native-gesture-handler": "~2.14.0", 23 | "react-native-reanimated": "~3.6.2" 24 | }, 25 | "devDependencies": { 26 | "@babel/core": "^7.20.0" 27 | }, 28 | "private": true 29 | } 30 | -------------------------------------------------------------------------------- /src/models/user/UserRepository.js: -------------------------------------------------------------------------------- 1 | import { user } from "../../data/Profile"; 2 | import User from "./User"; 3 | 4 | class UsersRepository { 5 | constructor() { 6 | this.users = []; 7 | } 8 | 9 | getAll() { 10 | return this.users; 11 | } 12 | 13 | get(id) { 14 | return this.users.find((user) => user.id === id); 15 | } 16 | 17 | add(user) { 18 | this.users.push(user); 19 | } 20 | 21 | remove(id) { 22 | this.users = this.users.filter((user) => user.id !== id); 23 | } 24 | 25 | update(id, name, email, age) { 26 | const user = this.get(id); 27 | 28 | if (user) { 29 | user.name = name; 30 | user.email = email; 31 | user.age = age; 32 | } 33 | return user; 34 | } 35 | } 36 | 37 | const usersRepository = new UsersRepository(); 38 | const newUser = new User(user.name, user.email, parseInt(user.age) || 0); 39 | 40 | usersRepository.add(newUser); 41 | 42 | export default usersRepository; 43 | -------------------------------------------------------------------------------- /src/screens/Profile/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | alignItems: "center", 7 | marginTop: 50, 8 | }, 9 | button: { 10 | marginTop: 20, 11 | padding: 10, 12 | backgroundColor: "#C9D4FF", 13 | borderRadius: 5, 14 | }, 15 | user: { 16 | marginTop: 20, 17 | padding: 10, 18 | backgroundColor: "#C9D4FF", 19 | borderRadius: 5, 20 | }, 21 | userDetail: { 22 | marginBottom: 10, 23 | }, 24 | userActions: { 25 | flexDirection: "row", 26 | gap: 10, 27 | justifyContent: "center", 28 | }, 29 | editButton: { 30 | padding: 5, 31 | borderRadius: 5, 32 | backgroundColor: "#4CAF50", 33 | marginRight: 5, 34 | minWidth: 70, 35 | alignItems: "center", 36 | }, 37 | deleteButton: { 38 | padding: 5, 39 | borderRadius: 5, 40 | backgroundColor: "#FF6347", 41 | minWidth: 70, 42 | alignItems: "center", 43 | }, 44 | text: { 45 | fontSize: 16, 46 | }, 47 | }); 48 | 49 | export default styles; 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Felipe Santos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 18 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, 19 | WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, 20 | OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/screens/Users/styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | marginTop: 50, 7 | alignItems: "center", 8 | }, 9 | userItem: { 10 | flexDirection: "row", 11 | justifyContent: "space-between", 12 | gap: 10, 13 | alignItems: "center", 14 | padding: 10, 15 | borderBottomWidth: 1, 16 | borderBottomColor: "#ccc", 17 | }, 18 | userDetailButton: { 19 | padding: 10, 20 | borderRadius: 5, 21 | backgroundColor: "#f0f0f0", 22 | marginRight: 10, 23 | }, 24 | userActions: { 25 | flexDirection: "row", 26 | gap: 10, 27 | }, 28 | userName: { 29 | fontSize: 16, 30 | color: "#333", 31 | fontWeight: "bold", 32 | }, 33 | editButton: { 34 | padding: 5, 35 | borderRadius: 5, 36 | backgroundColor: "#4CAF50", 37 | marginRight: 5, 38 | minWidth: 70, 39 | alignItems: "center", 40 | }, 41 | detailsButton: { 42 | padding: 5, 43 | borderRadius: 5, 44 | backgroundColor: "#ADD8E6", 45 | minWidth: 70, 46 | alignItems: "center", 47 | }, 48 | }); 49 | 50 | export default styles; 51 | -------------------------------------------------------------------------------- /src/screens/Profile/index.jsx: -------------------------------------------------------------------------------- 1 | import { Text, TouchableOpacity, View } from "react-native"; 2 | import { useNavigation } from "@react-navigation/native"; 3 | 4 | import styles from "./styles"; 5 | import Title from "../../components/Title"; 6 | 7 | import usersRepository from "../../models/user/UserRepository"; 8 | 9 | export default function Profile({ route }) { 10 | const navigation = useNavigation(); 11 | const { data } = route.params; 12 | 13 | const editUser = () => { 14 | navigation.navigate("Form", { user: data, edit: true }); 15 | }; 16 | 17 | const deleteUser = () => { 18 | usersRepository.remove(data.id); 19 | navigation.navigate("Users"); 20 | }; 21 | 22 | return ( 23 | <View style={styles.container}> 24 | <Title title="Profile" /> 25 | 26 | {data ? ( 27 | <Text>Detalhes do usuário</Text> 28 | ) : ( 29 | <Text>Selecione um usuário para exibir seus detalhes</Text> 30 | )} 31 | 32 | <View style={styles.user}> 33 | <View style={styles.userDetail}> 34 | <Text style={styles.text}>{data.name}</Text> 35 | <Text style={styles.text}>{data.email}</Text> 36 | <Text style={styles.text}>{data.age}</Text> 37 | </View> 38 | 39 | <View style={styles.userActions}> 40 | <TouchableOpacity style={styles.editButton} onPress={editUser}> 41 | <Text>Editar</Text> 42 | </TouchableOpacity> 43 | <TouchableOpacity style={styles.deleteButton} onPress={deleteUser}> 44 | <Text>Excluir</Text> 45 | </TouchableOpacity> 46 | </View> 47 | </View> 48 | </View> 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /src/screens/Users/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Text, TouchableOpacity, View } from "react-native"; 3 | import { useNavigation, useIsFocused } from "@react-navigation/native"; 4 | 5 | import styles from "./styles"; 6 | import Title from "../../components/Title"; 7 | import usersRepository from "../../models/user/UserRepository"; 8 | 9 | export default function Users() { 10 | const navigation = useNavigation(); 11 | const isFocused = useIsFocused(); 12 | const [allUsers, setAllUsers] = useState([]); 13 | 14 | useEffect(() => { 15 | if (isFocused) { 16 | const users = usersRepository.getAll(); 17 | setAllUsers(users); 18 | } 19 | }, [isFocused]); 20 | 21 | return ( 22 | <View style={styles.container}> 23 | <Title title="Users" /> 24 | <Text>Tela de listagem de todos os usuários</Text> 25 | 26 | {allUsers.length > 0 ? ( 27 | <View style={styles.userList}> 28 | {allUsers.map((user) => ( 29 | <View key={user.id} style={styles.userItem}> 30 | <View> 31 | <Text style={styles.userName}>{user.name}</Text> 32 | </View> 33 | 34 | <View style={styles.userActions}> 35 | <TouchableOpacity 36 | style={styles.detailsButton} 37 | onPress={() => navigation.navigate("Profile", { data: user })} 38 | > 39 | <Text>Detalhes</Text> 40 | </TouchableOpacity> 41 | </View> 42 | </View> 43 | ))} 44 | </View> 45 | ) : ( 46 | <Text>Não há usuários cadastrados</Text> 47 | )} 48 | </View> 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /src/routes/drawer.routes.jsx: -------------------------------------------------------------------------------- 1 | import { createDrawerNavigator } from "@react-navigation/drawer"; 2 | import { Feather } from "@expo/vector-icons"; 3 | 4 | import Home from "../screens/Home"; 5 | import Profile from "../screens/Profile"; 6 | import Form from "../screens/Form"; 7 | import { user } from "../data/Profile"; 8 | 9 | const Drawer = createDrawerNavigator(); 10 | 11 | const DrawerRoutes = () => { 12 | return ( 13 | <Drawer.Navigator screenOptions={{ headerShown: true }}> 14 | <Drawer.Screen 15 | name="Home" 16 | component={Home} 17 | options={{ 18 | headerTitle: "", 19 | drawerIcon: ({ focused }) => ( 20 | <Feather 21 | name="home" 22 | size={24} 23 | color={focused ? "#131313" : "#D6D6D6"} 24 | /> 25 | ), 26 | drawerLabel: "Inicial", 27 | drawerActiveTintColor: "#131313", 28 | drawerInactiveTintColor: "#D6D6D6", 29 | }} 30 | /> 31 | <Drawer.Screen 32 | name="Profile" 33 | component={Profile} 34 | initialParams={{ data: user }} 35 | options={{ 36 | headerTitle: "", 37 | drawerIcon: ({ focused }) => ( 38 | <Feather 39 | name="user" 40 | size={24} 41 | color={focused ? "#131313" : "#D6D6D6"} 42 | /> 43 | ), 44 | drawerLabel: "Perfil", 45 | drawerActiveTintColor: "#131313", 46 | drawerInactiveTintColor: "#D6D6D6", 47 | }} 48 | /> 49 | <Drawer.Screen 50 | name="Form" 51 | component={Form} 52 | options={{ 53 | headerTitle: "", 54 | drawerIcon: ({ focused }) => ( 55 | <Feather 56 | name="list" 57 | size={24} 58 | color={focused ? "#131313" : "#D6D6D6"} 59 | /> 60 | ), 61 | drawerLabel: "Categorias", 62 | drawerActiveTintColor: "#131313", 63 | drawerInactiveTintColor: "#D6D6D6", 64 | }} 65 | /> 66 | </Drawer.Navigator> 67 | ); 68 | }; 69 | 70 | export default DrawerRoutes; 71 | -------------------------------------------------------------------------------- /src/screens/Form/index.jsx: -------------------------------------------------------------------------------- 1 | import { Text, TextInput, TouchableOpacity, View } from "react-native"; 2 | import { useNavigation } from "@react-navigation/native"; 3 | import { useState, useEffect } from "react"; 4 | 5 | import styles from "./styles"; 6 | import Title from "../../components/Title"; 7 | 8 | import usersRepository from "../../models/user/UserRepository"; 9 | import User from "../../models/user/User"; 10 | 11 | export default function Form({ route }) { 12 | let { user, edit } = route.params; 13 | 14 | const [name, setName] = useState(""); 15 | const [email, setEmail] = useState(""); 16 | const [age, setAge] = useState(""); 17 | const [isUpdate, setIsUpdate] = useState(edit); 18 | 19 | const navigation = useNavigation(); 20 | 21 | useEffect(() => { 22 | if (edit) { 23 | setName(user.name); 24 | setEmail(user.email); 25 | setAge(String(user.age)); 26 | setIsUpdate(true); 27 | } else { 28 | clearInputs(); 29 | } 30 | }, [user, edit]); 31 | 32 | const handleUserAction = () => { 33 | if (isUpdate) { 34 | usersRepository.update(user.id, name, email, parseInt(age) || 0); 35 | clearInputs(); 36 | } else { 37 | const newUser = new User(name, email, parseInt(age) || 0); 38 | usersRepository.add(newUser); 39 | clearInputs(); 40 | } 41 | navigation.navigate("Users"); 42 | }; 43 | 44 | const clearInputs = () => { 45 | setIsUpdate(false); 46 | edit = false; 47 | setName(""); 48 | setEmail(""); 49 | setAge(""); 50 | }; 51 | 52 | return ( 53 | <View style={styles.container}> 54 | <Title title={isUpdate ? "Editar Usuário" : "Novo Usuário"} /> 55 | <TextInput 56 | placeholder="Digite o nome do usuário" 57 | style={styles.userInput} 58 | onChangeText={setName} 59 | value={name} 60 | /> 61 | <TextInput 62 | placeholder="Digite o email do usuário" 63 | style={styles.userInput} 64 | onChangeText={setEmail} 65 | value={email} 66 | /> 67 | <TextInput 68 | placeholder="Digite a idade do usuário" 69 | style={styles.userInput} 70 | onChangeText={setAge} 71 | value={age} 72 | keyboardType="numeric" 73 | /> 74 | 75 | <TouchableOpacity style={styles.button} onPress={handleUserAction}> 76 | <Text>{isUpdate ? "Salvar Alterações" : "Criar Usuário"}</Text> 77 | </TouchableOpacity> 78 | 79 | {isUpdate && ( 80 | <TouchableOpacity style={styles.button} onPress={clearInputs}> 81 | <Text>Cancelar Edição</Text> 82 | </TouchableOpacity> 83 | )} 84 | </View> 85 | ); 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Expo Boilerplate 2 | 3 | Este repositório serve como um boilerplate para iniciar projetos em React Native utilizando o Expo. Ele está configurado com três principais estratégias de navegação - Stack, Drawer e Bottom Tabs Navigation - e inclui um exemplo de passagem de dados entre telas para facilitar o desenvolvimento de aplicações mais complexas. 4 | 5 | ## Status do desenvolvimento 6 | 7 | - [x] Configuração do ambiente 8 | - [x] Estrutura de pastas 9 | - [x] Estrutura de navegação 10 | - [x] Exemplo de passagem de dados entre telas 11 | 12 | ## Iniciando o projeto 13 | 14 | Aqui estão as instruções detalhadas para configurar o ambiente de desenvolvimento e começar a trabalhar com este boilerplate em sua máquina local. 15 | 16 | ### Pré-requisitos 17 | 18 | Para utilizar este boilerplate, é essencial ter o ambiente NodeJS/React Native já configurado. Caso ainda não tenha realizado essa configuração, siga as orientações disponíveis [neste link](https://www.notion.so/Windows-f715073fc7c446dbaaee2bc313f8741c) para preparar seu ambiente. 19 | 20 | ### Configuração e Instalação 21 | 22 | 1. **Fork do Repositório:** Primeiramente, faça um fork deste repositório para sua conta no GitHub. 23 | 24 | 2. **Clone Local:** Depois, clone o repositório forkado para sua máquina. 25 | 26 | 3. **Instale as Dependências:** Entre na pasta do projeto e instale as dependências necessárias. 27 | 28 | 4. **Inicie o Projeto:** Com as dependências instaladas, inicie o projeto. 29 | 30 | 5. **Dispositivo ou Emulador:** Finalmente, abra o projeto em seu dispositivo físico ou em um emulador. 31 | 32 | ## Estrutura de arquivos 33 | 34 | O projeto segue uma organização lógica de arquivos, facilitando a manutenção e a compreensão do código: 35 | 36 | ``` 37 | react-native-expo-boilerplate/ 38 | ├── src/ 39 | │ ├── components/ 40 | │ ├── data/ 41 | │ ├── routes/ 42 | │ ├── screens/ 43 | └── App.jsx 44 | ``` 45 | 46 | ## Tecnologias 47 | 48 | - [React Native](https://reactnative.dev/) 49 | - [Expo](https://expo.dev/) 50 | - [React Navigation](https://reactnavigation.org/) 51 | 52 | ## Contribuindo 53 | 54 | Contribuições são sempre bem-vindas para melhorar o boilerplate. Veja como você pode contribuir: 55 | 56 | 1. **Fork:** Inicie fazendo um fork do projeto. 57 | 2. **Branch de Feature:** Crie uma branch para sua feature: `git checkout -b minha-feature`. 58 | 3. **Commit:** Faça commits das suas alterações: `git commit -m "feat: minha feature"`. 59 | 4. **Push:** Envie suas alterações para o GitHub: `git push origin minha-feature`. 60 | 5. **Pull Request:** Abra um pull request para a branch principal. 61 | 62 | ## Licença 63 | 64 | Este projeto está licenciado sob a licença MIT - consulte o arquivo [LICENSE](LICENSE) para mais detalhes. 65 | 66 | ## Contato 67 | 68 | Se você tiver alguma dúvida sobre o projeto, sinta-se à vontade para me contatar em [meu e-mail](mailto:dev.felipesantos@gmail.com) ou pelo meu [LinkedIn](https://www.linkedin.com/in/92felipesantos). 69 | -------------------------------------------------------------------------------- /src/routes/tab.routes.jsx: -------------------------------------------------------------------------------- 1 | import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; 2 | import { Feather } from "@expo/vector-icons"; 3 | 4 | import Home from "../screens/Home"; 5 | import Profile from "../screens/Profile"; 6 | import Form from "../screens/Form"; 7 | import Users from "../screens/Users"; 8 | import { user } from "../data/Profile"; 9 | 10 | import usersRepository from "../models/user/UserRepository"; 11 | 12 | const users = usersRepository.getAll(); 13 | 14 | const Tab = createBottomTabNavigator(); 15 | 16 | const TabRoutes = () => { 17 | return ( 18 | <Tab.Navigator 19 | screenOptions={{ headerShown: false }} 20 | initialRouteName="Home" 21 | > 22 | <Tab.Screen 23 | name="Home" 24 | component={Home} 25 | options={{ 26 | tabBarIcon: ({ focused }) => ( 27 | <Feather 28 | name="home" 29 | size={24} 30 | color={focused ? "#131313" : "#D6D6D6"} 31 | /> 32 | ), 33 | tabBarLabel: "Inicial", 34 | tabBarActiveTintColor: "#131313", 35 | tabBarInactiveTintColor: "#D6D6D6", 36 | }} 37 | /> 38 | 39 | <Tab.Screen 40 | name="Users" 41 | component={Users} 42 | initialParams={{ users }} 43 | options={{ 44 | tabBarIcon: ({ focused }) => ( 45 | <Feather 46 | name="users" 47 | size={24} 48 | color={focused ? "#131313" : "#D6D6D6"} 49 | /> 50 | ), 51 | tabBarLabel: "Usuários", 52 | tabBarActiveTintColor: "#131313", 53 | tabBarInactiveTintColor: "#D6D6D6", 54 | }} 55 | /> 56 | 57 | <Tab.Screen 58 | name="Profile" 59 | component={Profile} 60 | initialParams={{ data: user }} 61 | options={{ 62 | tabBarItemStyle: { 63 | display: "none", 64 | }, 65 | tabBarIcon: ({ focused }) => ( 66 | <Feather 67 | name="user" 68 | size={24} 69 | color={focused ? "#131313" : "#D6D6D6"} 70 | /> 71 | ), 72 | tabBarLabel: "Perfil", 73 | tabBarActiveTintColor: "#131313", 74 | tabBarInactiveTintColor: "#D6D6D6", 75 | }} 76 | /> 77 | 78 | <Tab.Screen 79 | name="Form" 80 | component={Form} 81 | initialParams={{ user: null, edit: false }} 82 | options={{ 83 | tabBarIcon: ({ focused }) => ( 84 | <Feather 85 | name="list" 86 | size={24} 87 | color={focused ? "#131313" : "#D6D6D6"} 88 | /> 89 | ), 90 | tabBarLabel: "Cadastro", 91 | tabBarActiveTintColor: "#131313", 92 | tabBarInactiveTintColor: "#D6D6D6", 93 | }} 94 | /> 95 | </Tab.Navigator> 96 | ); 97 | }; 98 | 99 | export default TabRoutes; 100 | --------------------------------------------------------------------------------