Exibindo informações do imóvel com ModalRoute
Esse post é a decima primeira parte da série de posts “Clone AirBnB com AdonisJS, React Native e ReactJS” onde iremos construir do zero uma aplicação web com ReactJS e também uma aplicação mobile com React Native com dados servidos através de uma API REST feita com NodeJS utilizando o framework AdonisJS.
- Parte 1: Iniciando com AdonisJS: Autenticação JWT e API REST;
- Parte 2: Criando CRUD e relações em API REST no AdonisJS;
- Parte 3: Upload de imagens e geolocalização no AdonisJS;
- Parte 4: Iniciando com React Native: Navegação e Autenticação com JWT;
- Parte 5: Instalando o Mapbox e listando imóveis no React Native;
- Parte 6: Instalando a Câmera e realizando o cadastro de Imóveis;
- Parte 7: Listando em um Modal os dados detalhados dos Imóveis;
- Parte 8: Iniciando com ReactJS: Navegação e Autenticação com JWT;
- Parte 9: Instalando o Mapbox e listando os imóveis no ReactJS;
- Parte 10: Utilizando o ModalRoute e fazendo upload de imagens;
- Parte 11: Exibindo informações do imóvel com ModalRoute;
Estou aqui mais um dia, sobre o olhar atento dos Devs que programam. Não sou muito bom de rima rs.
Bom, hoje finalizaremos a série do AirBnB e para finaliza-la precisamos apenas exibir as informações das propriedades que estão no mapa. Não tem segredo, agora é só utilizar o que já temos, o ModalRoute, StyledComponent e por ai vai.
Página do imóvel
Assim como a página para adicionar um imóvel, na página para exibir informações dele, teremos uma página modal. Nela será exibida as demais informações, como título, endereço e imagens.
Quando falo de página, você já pensa naquela velha e boa estrutura já conhecida:
src/pages/
|--- Property/
|--- index.js
|--- styles.js
No styles.js
já defina os componentes com seus respectivos layouts:
import styled from "styled-components";
export const Images = styled.div`
width: 100%;
max-width: 660px;
font-size: 16px;
color: #777777;
text-align: center;
display: grid;
grid-template-columns: 100px 100px 100px;
grid-gap: 5px;
background-color: #fff;
color: #444;
&.without-images {
display: flex;
}
img {
width: 100px;
}
p {
margin-top: 15px;
border: none !important;
}
`;
export const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
padding: 10px 20px;
p {
margin-bottom: 15px;
padding: 10px;
width: 100%;
}
hr {
margin: 20px 0;
border: none;
border-bottom: 1px solid #cdcdcd;
width: 100%;
}
span {
color: #fc6963;
font-size: 20px;
}
`;
O Images
será o container das imagens, que é um grid de 3 colunas, já Container
engloba todo o conteúdo do Modal com suas respectivas estilizações.
No index.js
é necessário fazer os imports
:
import React, { Component, Fragment } from "react";
import { Container, Images } from "./styles";
import PropTypes from "prop-types";
import api from "../../services/api";
const intlMonetary = new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
minimumFractionDigits: 2
});
Além dos imports, já foi configurado o objeto Intl.NumberFormat
para transformar o price
em reais.
Agora será criado o componente, definido o propTypes
e alguns states
. Será definido também o que acontecerá no método componentDidMount
:
export default class Property extends Component {
static propTypes = {
match: PropTypes.shape({
params: PropTypes.shape({
id: PropTypes.string
})
}).isRequired
}
state = {
property: null,
loading: false
};
async componentDidMount() {
try {
const { id } = this.props.match.params;
this.setState({ loading: true });
const { data } = await api.get(`/properties/${id}`);
this.setState({ property: data });
} catch (err) {
console.log(err);
} finally {
this.setState({ loading: false });
}
}
// Mais
O componentDidMount
mais uma vez foi definido como assíncrono e dentro dele já inicia com o try/catch
. Foi resgatado dos parâmetros da url
o id
do imóvel, esse id
será usado pegar as informações do imóvel lá na API. Repare que no state
foi adicionado o loading
como true
e caso consiga resgatar da API o property
também é adicionado.
O catch
pegará algum erro, caso aconteça. Não é preciso jogar nada no state
pois se o property
for null
um erro será apresentado ao renderizar o imóvel.
O finally
será chamado quando tudo der certo ou quando tudo der errado, para finalizar o loading
.
Ainda no index.js
:
// ...
renderProperty() {
const { property } = this.state;
if (!property) {
return "Imóvel não encontrado!";
}
return (
<Fragment>
<h1>{property.title}</h1>
<hr />
<p>{property.address}</p>
<Images>
{property.images.map(image => (
<img src={image.url} alt={image.path} />
))}
</Images>
<span>{intlMonetary.format(property.price)}</span>
</Fragment>
);
}
// Mais
Por questão de organização e limpeza do código o render
do imóvel foi separado em um método, onde tem uma pequena verificação exibindo que ele não foi encontrado caso ocorra algum erro ou exibindo a estrutura de informações do imóvel caso tudo ocorra bem.
Por fim, adicione o render
:
// ...
render() {
const { loading } = this.state;
return (
<Container>
{loading ? <p>Carregando</p> : this.renderProperty()}
</Container>
);
}
}
No render
com o operador ternário exibe a mensagem “Carregando” ou o método de renderização do imóvel.
Exibindo a página
Agora resta você adicionar essa página lá no App, seguindo a mesma ideia da página AddProperty e também ajustar o Link lá no componente Properties
para chamar a nova página. No App/index.js
:
// ...
import Property from "../Property";
// ...
render() {
// ...
// Depois de
<ModalRoute
path={`${match.url}/properties/add`}
parentPath={match.url}
component={AddProperty}
/>
// Adicione
<ModalRoute
path={`${match.url}/property/:id`}
parentPath={match.url}
component={Property}
/>
}
// ...
Já finalizando, lá em App/components/Properties/index.js
:
// De
const Properties = ({ properties }) =>
// Para
const Properties = ({ properties, match }) =>
// ...
<Pin>
// De
<Link to="">{intlMonetary.format(property.price)}</Link>
// Para
<Link to={`${match.url}/property/${property.id}`}>
{intlMonetary.format(property.price)}
</Link>
</Pin>
// ...
Properties.propTypes = {
properties: ...,
// Adicione
match: PropTypes.shape({
url: PropTypes.string
}).isRequired
}
E teremos isso:
Goodbye
Devs mais queridos do Brasil, por hoje é isso!!
A série do AirBnB pode ser considerada finalizada agora que já exibe as informações do imóvel.
Fica aqui nossa salva de palmas para todos que participaram dessa série e esperamos que você tenha gostado * — *
Código aqui está aqui.
Ah, não se esqueça de deixar seu comentário e compartilhar com seus amigos devs.
Abraços