Como pode ser observado nos últimos códigos postados, o grupo decidiu considerar uma tecnologia diferente do Android: utilizou-se o Javascript para abranger uma gama maior de usuários. Ao invés de arriscar que o usuário use o aplicativo e o desinstale de seu smartphone, busca-se por uma solução mais atrativa e que faça diferença na vida de quem está preocupado com o impactos ambientais. Portanto:
Tecnologias envolvidas: Javascript/react para criação de um aplicativo web
Público-alvo: as pessoas preocupadas com os impactos ambientais. Tendo ainda como estratégia de aproximação: parcerias com instituições não governamentais e gamification através do conhecimento.
GitHub link for project of Iglu app: https://github.com/gustavo-depaula/iglu
#SpaceApps #SpaceAppsSP #FatecOsasco
import React, {Component} from 'react'; | |
import 'bulma/css/bulma.css' | |
import { Spring } from 'react-spring' | |
class BottomInfo extends Component { | |
state = { toggle: true } | |
toggle = () => this.setState(state => ({ toggle: !state.toggle })) | |
render () { | |
return ( | |
<Spring | |
from={{h: '10vh', w: '90%'}} | |
to={{ | |
h: this.state.toggle ? '15vh' : '100vh', | |
w: this.state.toggle ? '90%' : '100%' | |
}} | |
toggle={this.toggle} // Additional props will be spread over the child | |
children={({h, w, toggle}) => { | |
return ( | |
<div style={{ | |
display: 'flex', | |
justifyContent: 'center' | |
}}> | |
<div | |
onClick={toggle} | |
style={{ | |
borderRadius: '5px 5px 0 0', | |
backgroundColor: 'white', | |
position: 'absolute', | |
width: w, | |
zIndex: toggle ? 5 : 0, | |
height: h, | |
bottom: '-20px', | |
padding: '15px 20px' | |
}} | |
> | |
<h3 className="title is-4" style={{ | |
fontWeight: 100 | |
}}> | |
O que é a Criosfera? | |
</h3> | |
</div> | |
</div> | |
) | |
}} | |
/> | |
) | |
} | |
} | |
export default BottomInfo; |
import React from 'react' | |
import { Link } from 'react-router-dom' | |
import { cities } from '../data' | |
function CityItem ({ name, slug }) { | |
return ( | |
<Link to={`/cities/${slug}`}> | |
<div className='columns' style={{ | |
borderBottom: '1px solid #ddd', | |
padding: '16px 12px' | |
}}> | |
<div className='column'> | |
<div style={{ | |
display: 'inline', | |
padding: '15px 20px' | |
}}> | |
<i className='fas fa-map-pin' /> | |
</div> | |
<div style={{ display: 'inline' }}> | |
<h3 className='title is-4' style={{ | |
display: 'inline', | |
fontWeight: 100 | |
}}> | |
{name} | |
</h3> | |
</div> | |
</div> | |
</div> | |
</Link> | |
) | |
} | |
function CitiesList ({ searchTerm = '' }) { | |
return ( | |
<div style={{ | |
overflow: 'scroll' | |
}}> | |
{cities.filter(city => city.name.toUpperCase().includes(searchTerm.toUpperCase())).map((city, index) => ( | |
<CityItem key={index} name={city.name} slug={city.value} /> | |
))} | |
</div> | |
) | |
} | |
export default CitiesList |
import React from 'react' | |
import { Link } from 'react-router-dom' | |
import { Map } from '../App' | |
import { cities } from '../data' | |
function CityPage ({ match, ...props }) { | |
const city = cities.find(city => city.value === match.params.city) | |
return ( | |
<> | |
<Map | |
center={[121.450496, 31.165072]} | |
style='mapbox://styles/mapbox/light-v9' | |
containerStyle={{ | |
height: '200px', | |
width: '100vw' | |
}} | |
zoom={[7]} | |
/> | |
<div style={{ | |
padding: '20px' | |
}}> | |
<Link to='/'>voltar</Link> | |
<h1 className='title'>{city.name}</h1> | |
{city.data.map((data, index) => ( | |
<div key={index} style={{ paddingBottom: '15px' }}> | |
<p style={{ fontWeight: 'bold' }}>{data.title}</p> | |
<p style={{ textAlign: 'justify', textJustify: 'inter-word' }}>{data.value}</p> | |
</div> | |
))} | |
</div> | |
</> | |
) | |
} | |
export default CityPage |
import React from 'react' | |
import BottomInfo from '../components/bottom-info' | |
import SearchBox from '../components/search-box' | |
import { Map } from '../App' | |
function MainPage() { | |
return ( | |
<div> | |
<SearchBox /> | |
<BottomInfo /> | |
<Map | |
style='mapbox://styles/mapbox/light-v9' | |
containerStyle={{ | |
height: '100vh', | |
width: '100vw' | |
}} | |
zoom={[1]} | |
/> | |
</div> | |
) | |
} | |
export default MainPage |
import React from 'react'; | |
import { Spring } from 'react-spring' | |
import CitiesList from './cities-list' | |
const activatedStyles = { | |
width: '100%', | |
height: '100vh', | |
left: '0', | |
top: '0', | |
icon: 'fas fa-chevron-left' | |
} | |
const defaultStyles = { | |
width: '90%', | |
height: '4vh', //56px | |
left: '20px', | |
top: '21px', | |
icon: 'fas fa-bars' | |
} | |
class SearchBox extends React.Component { | |
state = { fullscreen: false, searchTerm: '' } | |
activate = () => this.setState({fullscreen: true}) | |
close = () => this.setState({fullscreen: false}) | |
handleSearchTerm = (event) => this.setState({searchTerm: event.target.value}); | |
render () { | |
return ( | |
<Spring | |
from={defaultStyles} | |
to={this.state.fullscreen ? activatedStyles : defaultStyles} | |
children={ | |
({toggle, ...styles}) => ( | |
<div style={{ | |
...styles, | |
borderRadius: this.state.fullscreen ? '0' : '5px', | |
position: 'absolute', | |
zIndex: this.state.fullscreen ? 10 : 2, | |
backgroundColor: 'white' | |
}}> | |
<div className="field is-horizontal"> | |
<div className="field-body"> | |
<div className="field is-expanded"> | |
<div className="field has-addons"> | |
<p className="control"> | |
{this.state.fullscreen && | |
<a className="button" onClick={this.close} style={{ | |
borderColor: 'white', | |
borderRadius: this.state.fullscreen ? '0' : '5px 0 0 5px', | |
height: '56px', | |
fontSize: '21px', | |
fontWeight: '300', | |
boxShadow: '-2px 4px 7px 0px rgba(0, 0, 0, 0.25)', | |
}}> | |
<i className='fas fa-chevron-left'/> | |
</a> | |
} | |
{!this.state.fullscreen && | |
<a className="button" onClick={this.close} style={{ | |
borderColor: 'white', | |
borderRadius: this.state.fullscreen ? '0' : '5px 0 0 5px', | |
height: '56px', | |
fontSize: '21px', | |
fontWeight: '300', | |
boxShadow: '-2px 4px 7px 0px rgba(0, 0, 0, 0.25)', | |
}}> | |
<i className='fas fa-bars'/> | |
</a> | |
} | |
</p> | |
<p className="control is-expanded"> | |
<input className="input" type="text" onChange={this.handleSearchTerm} onFocus={this.activate} placeholder="Onde?" style={{ | |
borderColor: 'white', | |
borderRadius: this.state.fullscreen ? '0' : '0 5px 5px 0', | |
height: '56px', | |
fontSize: '21px', | |
fontWeight: '300', | |
boxShadow: '2px 4px 7px 0px rgba(0, 0, 0, 0.25)', | |
}} /> | |
</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
{this.state.fullscreen && <CitiesList searchTerm={this.state.searchTerm}/>} | |
</div> | |
) | |
} | |
/> | |
) | |
} | |
} | |
export default SearchBox; |
Definição dos elementos de gamification:
-> Formas de ganhar pontos
1 ponto:
5 pontos:
10 pontos:
30 pontos:
-> Ranking
-> Níveis
O que é criosfera?
Compreende os lugares da Terra que a água é encontrada em estado sólido (gelo ou neve).
São definidas de acordo os seus componentes:
– Água congelada – Lençóis de gelo – Neve e solo congelado (permafrost)
Ideia e público-alvo
- Aplicativo educativo que utiliza conceitos de gamification para aproximar a criosfera ao cotidiano da população mundial
- Comunidades que são diretamente afetadas pela criosfera, pessoas que possuem um smartphone e com acesso à Internet
Metodologia de desenvolvimento
- Coleta de informações dos sites da Nasa disponibilizados - Prototipação evolutiva de software
Funcionalidades do app
- Mapeamento dos componentes da crioesfera mais próximos ao usuário
- Exibição das características biológicas e físicas da criosfera
- Atribuição de pontuação e conquistas (gamification) conforme o usuário avança pelo appTecnologias envolvidas
- Java (aplicativo para Android) - Ferramenta Adobe XD CC para prototipação das telas do app e Figma
Referência
SpaceApps is a NASA incubator innovation program.