Regions app working in RN

This commit is contained in:
Federico Kereki
2018-08-29 22:14:11 -03:00
parent 01b438322a
commit 43945d111c
14 changed files with 434 additions and 31 deletions
@@ -0,0 +1,63 @@
/* @flow */
import React from "react";
import PropTypes from "prop-types";
import { View, Text, Picker } from "react-native";
export class CountrySelect extends React.PureComponent<{
dispatch: ({}) => any
}> {
static propTypes = {
loading: PropTypes.bool.isRequired,
currentCountry: PropTypes.string.isRequired,
list: PropTypes.arrayOf(PropTypes.object).isRequired,
onSelect: PropTypes.func.isRequired,
getCountries: PropTypes.func.isRequired
};
componentDidMount() {
if (this.props.list.length === 0) {
this.props.getCountries();
}
}
onSelect = value => this.props.onSelect(value);
render() {
if (this.props.loading) {
return (
<View>
<Text>Loading countries...</Text>
</View>
);
} else {
const sortedCountries = [...this.props.list].sort(
(a, b) => (a.countryName < b.countryName ? -1 : 1)
);
return (
<View>
<Text>Country:</Text>
<Picker
onValueChange={this.onSelect}
prompt="Country"
selectedValue={this.props.currentCountry}
>
<Picker.Item
key={"00"}
label={"Select a country:"}
value={""}
/>
{sortedCountries.map(x => (
<Picker.Item
key={x.countryCode}
label={x.countryName}
value={x.countryCode}
/>
))}
</Picker>
</View>
);
}
}
}
@@ -0,0 +1,22 @@
/* @flow */
import { connect } from "react-redux";
import { CountrySelect } from "./countrySelect.component";
import { getCountries, getRegions } from "./world.actions";
const getProps = state => ({
list: state.countries,
currentCountry: state.currentCountry,
loading: state.loadingCountries
});
const getDispatch = dispatch => ({
getCountries: () => dispatch(getCountries()),
onSelect: c => dispatch(getRegions(c))
});
export const ConnectedCountrySelect = connect(
getProps,
getDispatch
)(CountrySelect);
+6
View File
@@ -0,0 +1,6 @@
/* @flow */
import { ConnectedCountrySelect } from "./countrySelect.connected.js";
import { ConnectedRegionsTable } from "./regionsTable.connected.js";
export { ConnectedCountrySelect, ConnectedRegionsTable };
+18
View File
@@ -0,0 +1,18 @@
/* @flow */
import React from "react";
import { View, StatusBar } from "react-native";
import { ConnectedCountrySelect, ConnectedRegionsTable } from ".";
export class Main extends React.PureComponent<> {
render() {
return (
<View>
<StatusBar hidden />
<ConnectedCountrySelect />
<ConnectedRegionsTable />
</View>
);
}
}
@@ -0,0 +1,44 @@
/* @flow */
import React from "react";
import PropTypes from "prop-types";
import { View, Text } from "react-native";
export class RegionsTable extends React.PureComponent<{
list: Array<{
regionCode: string,
regionName: string
}>
}> {
static propTypes = {
list: PropTypes.arrayOf(PropTypes.object).isRequired
};
static defaultProps = {
list: []
};
render() {
if (this.props.list.length === 0) {
return (
<View>
<Text>No regions.</Text>
</View>
);
} else {
const ordered = [...this.props.list].sort(
(a, b) => (a.regionName < b.regionName ? -1 : 1)
);
return (
<View>
{ordered.map(x => (
<View key={`${x.countryCode}-${x.regionCode}`>
<Text>{x.regionName}</Text>
</View>
))}
</View>
);
}
}
}
@@ -0,0 +1,12 @@
/* @flow */
import { connect } from "react-redux";
import { RegionsTable } from "./regionsTable.component";
const getProps = state => ({
list: state.regions,
loading: state.loadingRegions
});
export const ConnectedRegionsTable = connect(getProps)(RegionsTable);
+9
View File
@@ -0,0 +1,9 @@
/* @flow */
import axios from "axios";
export const getCountriesAPI = () =>
axios.get(`http://192.168.1.200:8080/countries`);
export const getRegionsAPI = country =>
axios.get(`http://192.168.1.200:8080/regions/${country}`);
+8
View File
@@ -0,0 +1,8 @@
/* @flow */
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { reducer } from "./world.reducer";
export const store = createStore(reducer, applyMiddleware(thunk));
+106
View File
@@ -0,0 +1,106 @@
/* @flow */
import { getCountriesAPI, getRegionsAPI } from "./serviceApi";
// Countries actions
export const COUNTRIES_REQUEST = "countries:request";
export const COUNTRIES_SUCCESS = "countries:success";
export const COUNTRIES_FAILURE = "countries:failure";
export type CountriesAction = {
type: string,
country?: string,
listOfCountries?: [object]
};
export const countriesRequest = () =>
({
type: COUNTRIES_REQUEST
}: CountriesActions);
export const countriesSuccess = (listOfCountries: []) =>
({
type: COUNTRIES_SUCCESS,
listOfCountries
}: CountriesActions);
export const countriesFailure = () =>
({
type: COUNTRIES_FAILURE
}: CountriesActions);
// Regions actions
export const REGIONS_REQUEST = "regions:request";
export const REGIONS_SUCCESS = "regions:success";
export const REGIONS_FAILURE = "regions:failure";
export type RegionsAction = {
type: string,
listOfRegions?: [object]
};
export const regionsRequest = (country: string) =>
({
type: REGIONS_REQUEST,
country
}: RegionsActions);
export const regionsSuccess = (listOfRegions: [{}]) =>
({
type: REGIONS_SUCCESS,
listOfRegions
}: RegionsActions);
export const regionsFailure = () =>
({
type: REGIONS_FAILURE
}: RegionsActions);
// Complex Actions:
export const getCountries = () => async dispatch => {
try {
dispatch(countriesRequest());
const result = await getCountriesAPI();
dispatch(countriesSuccess(result.data));
} catch (e) {
dispatch(countriesFailure());
}
};
export const getRegions = (country: string) => async dispatch => {
if (country) {
try {
dispatch(regionsRequest(country));
const result = await getRegionsAPI(country);
dispatch(regionsSuccess(result.data));
} catch (e) {
dispatch(regionsFailure());
}
} else {
dispatch(regionsFailure());
}
};
export const getRegions2 = (country: string) => async (
dispatch,
getState
) => {
if (country === getState().currentCountry) {
console.log("Hey! You are getting the same country as before!");
}
if (country) {
try {
dispatch(regionsRequest(country));
const result = await getRegionsAPI(country);
dispatch(regionsSuccess(result.data));
} catch (e) {
dispatch(regionsFailure());
}
} else {
dispatch(regionsFailure());
}
};
+74
View File
@@ -0,0 +1,74 @@
/* @flow */
import {
COUNTRIES_REQUEST,
COUNTRIES_SUCCESS,
COUNTRIES_FAILURE,
REGIONS_REQUEST,
REGIONS_SUCCESS,
REGIONS_FAILURE
} from "./world.actions";
import type { CountriesAction, RegionsAction } from "./world.actions";
// import type { CounterAction } from "./world.actions.js";
export const reducer = (
state: object = {
// initial state
loadingCountries: false,
currentCountry: "",
countries: [],
loadingRegions: false,
regions: []
},
action: CountriesAction | RegionsAction
) => {
switch (action.type) {
case COUNTRIES_REQUEST:
return {
...state,
loadingCountries: true,
countries: []
};
case COUNTRIES_SUCCESS:
return {
...state,
loadingCountries: false,
countries: action.listOfCountries
};
case COUNTRIES_FAILURE:
return {
...state,
loadingCountries: false,
countries: []
};
case REGIONS_REQUEST:
return {
...state,
loadingRegions: true,
currentCountry: action.country,
regions: []
};
case REGIONS_SUCCESS:
return {
...state,
loadingRegions: false,
regions: action.listOfRegions
};
case REGIONS_FAILURE:
return {
...state,
loadingRegions: false,
regions: []
};
default:
return state;
}
};