Permalink
Browse files

REFACTOR: added normalizr to expose reviews w/out restaurant

  • Loading branch information...
toranb committed Jun 8, 2018
1 parent a03f639 commit ed929eb1eef56a1e16b57c31b30fbc2fb55aa082
@@ -1,9 +1,9 @@
import { connect } from 'ember-redux';
import { RootState } from '../types/index';
import { getSelectedRestaurant } from '../reducers/restaurants';
import { getReviews } from '../reducers/restaurants';

const stateToComputed = (state: RootState) => ({
restaurant: getSelectedRestaurant(state)
reviews: getReviews(state)
});

export default connect(stateToComputed)();
@@ -1,30 +1,46 @@
import _ from 'lodash';
import reselect from 'reselect';
import { RootState, Dictionary } from '../types/index';
import { Restaurant, RestaurantState } from '../types/restaurants';
import { Review, Restaurant, RestaurantState } from '../types/restaurants';
import { TRANSFORM_LIST, TRANSFORM_DETAIL, DetailAction, ListAction } from '../actions/restaurants';
import { normalize, schema } from 'normalizr';

const { createSelector } = reselect;

const reviewSchema = new schema.Entity('reviews');
const restaurantSchema = new schema.Entity('restaurants', {
reviews: [reviewSchema]
});

const initialState = {
all: undefined,
selectedId: undefined
selectedId: undefined,
reviews: undefined
};

type Action = ListAction | DetailAction;

export default ((state: RestaurantState, action: Action): RestaurantState => {
switch(action.type) {
case TRANSFORM_LIST: {
const restaurants = _.keyBy(action.response, (restaurant: Restaurant) => restaurant.id);
const merged = _.extend({}, state.all, restaurants);
return Object.assign({}, state, {all: merged});
const normalized = normalize(action.response, [restaurantSchema]);
const { restaurants, reviews } = normalized.entities;
const merged = _.extend({}, state.all, _.keyBy(restaurants, (r: Restaurant) => r.id));
const mergedReviews = _.extend({}, state.reviews, _.keyBy(reviews, (r: Review) => r.id));
return Object.assign({}, state, {
all: merged,
reviews: mergedReviews
});
}
case TRANSFORM_DETAIL: {
const restaurant = {[action.response.id]: action.response};
const merge = _.extend({}, state.all, restaurant);
const normalized = normalize(restaurant, [restaurantSchema]);
const { restaurants, reviews } = normalized.entities;
const merge = _.extend({}, state.all, restaurants);
const mergeReviews = _.extend({}, state.reviews, _.keyBy(reviews, (r: Review) => r.id));
return Object.assign({}, state, {
all: merge,
reviews: mergeReviews,
selectedId: action.response.id
});
}
@@ -36,6 +52,7 @@ export default ((state: RestaurantState, action: Action): RestaurantState => {

const all = (state: RootState) => state.restaurants.all;
const selectedId = (state: RootState) => state.restaurants.selectedId;
const reviews = (state: RootState) => state.restaurants.reviews;

export const getRestaurants = createSelector(
all,
@@ -47,3 +64,13 @@ export const getSelectedRestaurant = createSelector(
selectedId,
(all: Dictionary<Restaurant>, selectedId: number) => _.get(all, selectedId)
);

export const getReviews = createSelector(
reviews,
getSelectedRestaurant,
(reviews: Dictionary<Review>, selectedRestaurant: Restaurant) => {
return _.map(selectedRestaurant.reviews, (reviewId: number) => {
return _.get(reviews, reviewId);
});
}
);
@@ -1,5 +1,5 @@
<ul>
{{#each @restaurant.reviews as |review|}}
{{#each @reviews as |review|}}
<li>{{review.rating}} ★</li>
{{else}}
<li>no reviews</li>
@@ -1 +1 @@
{{yield restaurant}}
{{yield reviews}}
@@ -1,3 +1,3 @@
<RestaurantItem as |restaurant|>
<RestaurantDetail @restaurant={{restaurant}} />
<RestaurantItem as |reviews|>
<RestaurantDetail @reviews={{reviews}} />
</RestaurantItem>
@@ -1,12 +1,19 @@
import { Dictionary } from './index';

export interface Review {
id: number;
rating: number;
}

export interface Restaurant {
id: number;
name: string;
reviews: Array<number>;
}

export interface RestaurantState {
all: Dictionary<Restaurant>;
reviews: Dictionary<Review>;
selectedId: number;
}

@@ -35,6 +35,7 @@
"ember-cli-htmlbars-inline-precompile": "^1.0.0",
"ember-cli-inject-live-reload": "^1.4.1",
"ember-cli-mirage": "^0.4.7",
"ember-cli-normalizr-shim": "^1.0.0",
"ember-cli-qunit": "^4.1.1",
"ember-cli-shims": "^1.2.0",
"ember-cli-sri": "^2.1.0",
@@ -55,6 +56,7 @@
"ember-welcome-page": "^3.0.0",
"eslint-plugin-ember": "^5.0.0",
"loader.js": "^4.2.3",
"normalizr": "3.2.2",
"qunit-dom": "^0.6.2",
"redux": "3.7.2",
"redux-thunk": "2.2.0",
@@ -24,6 +24,7 @@
"redux": ["node_modules/redux/index.d.ts"],
"fetch": ["node_modules/ember-fetch/index.d.ts"],
"reselect": ["node_modules/reselect/lib/index.d.ts"],
"normalizr": ["node_modules/normalizr/index.d.ts"],
"guides/*": [
"app/*"
],

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

0 comments on commit ed929eb

Please sign in to comment.