Esse projeto foi construído durante o Next Level Week 1. A semana é um curso elaborado pela RocketSeat, na qual semana desenvolvemos um backend express, uma aplicação web com ReactJS e uma app mobile com React Native. Meus maiores aprendizados dessa semana foram:
- TypeScript
- Validação de dados com Celebrate
- Upload de arquivos com Multer.js
- Seeds e Migrations Knex.js
- React-native-maps
- React-leaflet para renderização de mapa
- Consumir APIs externas
- Boas práticas de programação =)
import MapView, { Marker } from 'react-native-maps'
<View style={styles.mapContainer}>
{initialPosition[0] !== 0 && ( ## validação de loading da posição inicial
<MapView style={styles.map} ## Renderização do mapa
loadingEnabled={initialPosition[0] === 0}
initialRegion={{
latitude: initialPosition[0],
longitude: initialPosition[1],
latitudeDelta: 0.020,
longitudeDelta: 0.020,
}}>
{points.map(point => (
## Criação dos pontos de marcação no mapa
<Marker
key={String(point.id)}
style={styles.mapMarker}
coordinate={{
latitude: point.latitude,
longitude: point.longitude,
}}
onPress={() => {HandleNavigateToDetail(point.id)}}
>
<View style={styles.mapMarkerContainer}>
<Image style={styles.mapMarkerImage} source={{ uri: point.image_url }} />
<Text style={styles.mapMarkerTitle}> {point.name} </Text>
</View>
</Marker>
))}
</MapView>
)}
</View> import { Map, TileLayer, Marker } from 'react-leaflet';
<Map center={initialPosition} zoom={15} onclick={handleMapClick}>
<TileLayer
attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker
position={selectedPosition}
/>
</Map> ## Routes.ts
import {celebrate, Joi} from 'celebrate';
## Upload de arquivo e a validação dos campos são feitos na rota da api
routes.post(
'/points',
upload.single('image'),
celebrate({
body: Joi.object().keys({
name: Joi.string().required(),
email: Joi.string().required().email(),
whatsapp: Joi.string().required(),
latitude: Joi.number().required(),
longitude: Joi.number().required(),
city: Joi.string().required(),
uf: Joi.string().required().max(2),
items: Joi.string().required(),
})
}),
pointsControllers.create
); ## Server.ts
import path from 'path';
import {errors} from 'celebrate';
app.use('/uploads', express.static(path.resolve(__dirname,'..', 'uploads'))) //Path dos arquivos salvos.
app.use(errors()); ##Usado para reportar erros de validação
## Multer.ts
## Configuração do Multer.js para upload de arquivo
import multer from 'multer';
import path from 'path';
import crypto from 'crypto';
export default{
storage: multer.diskStorage({
destination: path.resolve(__dirname,'..','..', 'uploads'), ##Diretório onde o arquivo será salvo.
filename(request, file, callback){ ##renomeação do arquivo
const hash = crypto.randomBytes(6).toString('hex');
const fileName = `${hash}-${file.originalname}`;
callback(null, fileName);
},
})
} ## Migrations com relacionamento
import Knex from 'knex';
## Script de criação
export async function up(knex: Knex) {
return knex.schema.createTable('point_items', table => {
table.increments('id').primary(); ## Autoincremento do campo
table.integer('point_id')
.notNullable()
.references('id') ## Realacionamento com a tabela Points
.inTable('points');
table.integer('item_id')
.notNullable()
.references('id') ## Realacionamento com a tabela Items
.inTable('items');
})
};
## Script de drop
export async function down(knex: Knex) {
return knex.schema.dropTable('point_items');
}; ## Seeds de inserção na tabela items
import Knex from "knex"
export async function seed(Knex: Knex){
await Knex('items').insert([
{ title:'Lâmpadas', image:'lampadas.svg'},
{ title:'Pilhas e Baterias', image:'baterias.svg'},
{ title:'Papéis e Papelao', image:'papeis-papelao.svg'},
{ title:'Resíduos Eletrônicos', image:'eletronicos.svg'},
{ title:'Resíduos Orgânicos', image:'organicos.svg'},
{ title:'Óleo de cozinha', image:'oleo.svg'},
])
}
