Skip to content

Commit

Permalink
✨ Applying Redux in the screen of get top tracks.
Browse files Browse the repository at this point in the history
  • Loading branch information
krrskl committed Jul 3, 2020
1 parent 9dd1951 commit 7fa7c0f
Show file tree
Hide file tree
Showing 16 changed files with 461 additions and 64 deletions.
52 changes: 46 additions & 6 deletions android/app/src/main/assets/index.android.bundle

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions android/app/src/main/res/raw/app.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "LastFMLevelOne",
"displayName": "LastFMLevelOne"
"name": "LastFMLevelTwoAndThree",
"displayName": "LastFMLevelTwoAndThree"
}
40 changes: 17 additions & 23 deletions app/components/Track-item.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, {Component} from 'react';
import {ListItem, Text} from 'react-native-elements';
import {Track} from 'app/core/models/Track.model';
import {Track} from './../core/models/Track.model';
import NumberFormat from 'react-number-format';
import {Navigation} from 'react-native-navigation';
import {connect} from 'react-redux';
import {goToTrackDetails} from './../core/store/effects/track.effects';

interface TrackItemProps {
track: Track;
goToTrackDetails: any;
}

export default class TrackItemComponent extends Component<TrackItemProps> {
class TrackItemComponent extends Component<TrackItemProps> {
constructor(props: any) {
super(props);
}
Expand All @@ -28,30 +31,21 @@ export default class TrackItemComponent extends Component<TrackItemProps> {
}
leftAvatar={{source: {uri: track.image[0]['#text']}}}
onPress={() => {
this.viewDetails(track);
this.props.goToTrackDetails(track);
}}
bottomDivider
chevron
/>
);
}

viewDetails(track: Track) {
Navigation.push('TracksScreen', {
component: {
name: 'TrackDetailsScreen',
id: 'TrackDetailsScreen',
passProps: {
track,
},
options: {
topBar: {
title: {
text: `Detalles de ${this.props.track.name}`,
},
},
},
},
});
}
}

const mapDispatchToProps = (dispatch: any) => {
return {
goToTrackDetails: (track: Track) => {
return dispatch(goToTrackDetails(track));
},
};
};

export default connect(null, mapDispatchToProps)(TrackItemComponent);
16 changes: 16 additions & 0 deletions app/core/config/configureStore.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {createStore, applyMiddleware} from 'redux';
import {composeWithDevTools} from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import Reducers from '../store/reducers';

const middleware = [thunk];

const configureStore = () => {
const store = createStore(
Reducers,
composeWithDevTools(applyMiddleware(...middleware)),
);
return store;
};

export default configureStore;
6 changes: 3 additions & 3 deletions app/core/models/Tracks-response.model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export interface Tracks {
}

export interface TracksAttr {
country: string;
country?: string;
page: string;
perPage: string;
perPage?: string;
totalPages: string;
total: string;
total?: string;
}
32 changes: 28 additions & 4 deletions app/core/navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,38 @@ import ArtistScreen from '../../screens/Artist/ArtistScreen';
import ArtistDetailsScreen from '../../screens/Artist-details/ArtistDetailsScreen';
import TracksScreen from '../../screens/Tracks/Tracks-screen';
import TrackDetailsScreen from '../../screens/Track-details/Track-details-screen';
import {Provider} from 'react-redux';
import configureStore from '../config/configureStore';

export function registerScreens() {
const store = configureStore();

/**
* Function for register the screens in the stack of React Native Navigation.
*
* @return
*/
export function registerScreens(): void {
Navigation.registerComponent('HomeScreen', () => HomeScreen);
Navigation.registerComponent('ArtistScreen', () => ArtistScreen);
Navigation.registerComponentWithRedux(
'ArtistScreen',
() => ArtistScreen,
Provider,
store,
);
Navigation.registerComponent(
'ArtistDetailsScreen',
() => ArtistDetailsScreen,
);
Navigation.registerComponent('TracksScreen', () => TracksScreen);
Navigation.registerComponent('TrackDetailsScreen', () => TrackDetailsScreen);
Navigation.registerComponentWithRedux(
'TracksScreen',
() => TracksScreen,
Provider,
store,
);
Navigation.registerComponentWithRedux(
'TrackDetailsScreen',
() => TrackDetailsScreen,
Provider,
store,
);
}
3 changes: 3 additions & 0 deletions app/core/store/actions/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as TrackActions from './track.actions';

export {TrackActions};
37 changes: 37 additions & 0 deletions app/core/store/actions/track.actions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {Track} from '../../models/Track.model';
import {TracksAttr} from './../../models/Tracks-response.model';

const TrackActionTypes = {
GET_TRACKS: '[TRACKS] Get tracks',
GET_TRACKS_SUCCESS: '[TRACKS] Get tracks success',
GET_TRACKS_FAILURE: '[TRACKS] Get tracks failure',

SET_TRACK: '[TRACKS] Set track',

NEXT_PAGE: '[TRACKS] Next page',
PREV_PAGE: '[TRACKS] Prev page',
};

export const getTracks = () => {
return {type: TrackActionTypes.GET_TRACKS};
};

export const getTracksSuccess = (tracks: Track[], paginator: TracksAttr) => {
return {type: TrackActionTypes.GET_TRACKS_SUCCESS, tracks, paginator};
};

export const getTracksFailure = (error: string) => {
return {type: TrackActionTypes.GET_TRACKS_FAILURE, error};
};

export const setTrack = (track: Track) => {
return {type: TrackActionTypes.SET_TRACK, track};
};

export const nextPage = (page: number) => {
return {type: TrackActionTypes.NEXT_PAGE, page};
};

export const prevPage = (page: number) => {
return {type: TrackActionTypes.PREV_PAGE, page};
};
68 changes: 68 additions & 0 deletions app/core/store/effects/track.effects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {TrackActions} from '../actions';
import {TrackService} from './../../services/track-service';
import {TracksResponse} from './../../models/Tracks-response.model';
import {Track} from './../../models/Track.model';
import {Navigation} from 'react-native-navigation';

const trackService = new TrackService();

export const fetchTracks = () => {
return (dispatch: any, getState: any) => {
dispatch({type: TrackActions.getTracks});

const {page, limit} = getState().tracksScreenStore.paginator;

trackService.getAllTopTracks(limit, page).then((resp) => {
const data: TracksResponse = resp.data;
dispatch({
type: TrackActions.getTracksSuccess,
tracks: data.tracks.track,
paginator: data.tracks['@attr'],
});
});
};
};

export const fetchNextPage = () => {
return (dispatch: any, getState: any) => {
let {page, totalPages} = getState().tracksScreenStore.paginator;

if (page < totalPages) {
page = parseInt(`${page}`, 10) + 1;

dispatch({type: TrackActions.nextPage, page});
dispatch(fetchTracks());
}
};
};

export const fetchPrevPage = () => {
return (dispatch: any, getState: any) => {
let {page} = getState().tracksScreenStore.paginator;
if (page > 1) {
page = parseInt(`${page}`, 10) - 1;

dispatch({type: TrackActions.nextPage, page});
dispatch(fetchTracks());
}
};
};

export const goToTrackDetails = (track: Track) => {
return (dispatch: any) => {
dispatch({type: TrackActions.setTrack, track});
Navigation.push('TracksScreen', {
component: {
name: 'TrackDetailsScreen',
id: 'TrackDetailsScreen',
options: {
topBar: {
title: {
text: `Detalles de ${track.name}`,
},
},
},
},
});
};
};
6 changes: 6 additions & 0 deletions app/core/store/reducers/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {combineReducers} from 'redux';
import trackReducer from './track.reducer';

const rootReducer = combineReducers({tracksScreenStore: trackReducer});

export default rootReducer;
65 changes: 65 additions & 0 deletions app/core/store/reducers/track.reducer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {Track} from './../../models/Track.model';
import {TrackActions} from '../actions';
import {TracksAttr} from './../../models/Tracks-response.model';

export interface TrackState {
tracks: Track[];
track: Track | null;
loading: boolean;
error: string;
limit: number;
paginator: TracksAttr;
}

const initialState: TrackState = {
tracks: [],
track: null,
loading: false,
error: '',
limit: 10,
paginator: {page: '1', totalPages: '0'},
};

export default function trackReducer(
state: TrackState = initialState,
action: any,
) {
switch (action.type) {
case TrackActions.getTracks:
return {
...state,
loading: true,
};

case TrackActions.getTracksSuccess:
const {tracks, paginator} = action;
return {
...state,
tracks: [...tracks],
paginator,
loading: false,
};

case TrackActions.getTracksFailure:
return {
...state,
loading: false,
erorr: action.error,
};

case TrackActions.setTrack:
return {
...state,
track: action.track,
};

case TrackActions.nextPage:
return {...state, paginator: {...state.paginator, page: action.page}};

case TrackActions.prevPage:
return {...state, paginator: {...state.paginator, page: action.page}};

default:
return state;
}
}
15 changes: 11 additions & 4 deletions app/screens/Track-details/Track-details-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import {Text, Badge, Card, Icon} from 'react-native-elements';
import {Track} from '../../core/models/Track.model';
import TrackDetailsStyles from './styles';
import NumberFormat from 'react-number-format';
import {connect} from 'react-redux';

interface TrackDetailsScreenProps {
track: Track | null;
}

export default class TrackDetailsScreen extends Component<
TrackDetailsScreenProps,
any
> {
class TrackDetailsScreen extends Component<TrackDetailsScreenProps, any> {
constructor(props: any) {
super(props);
}
Expand Down Expand Up @@ -70,3 +68,12 @@ export default class TrackDetailsScreen extends Component<
);
}
}

const mapStateToProps = (state: any) => {
const {tracksScreenStore} = state;
return {
track: tracksScreenStore.track,
};
};

export default connect(mapStateToProps)(TrackDetailsScreen);
Loading

0 comments on commit 7fa7c0f

Please sign in to comment.