mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 09:44:55 -06:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9c40c27811
8 changed files with 116 additions and 157 deletions
2
.prettierrc
Normal file
2
.prettierrc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
printWidth: 100;
|
||||
parser: flow;
|
||||
|
|
@ -1,111 +1,60 @@
|
|||
// @flow
|
||||
import { memoize } from 'ramda';
|
||||
|
||||
// TODO open a websoket and create observable from it
|
||||
const DUMMY_DATA = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Big John Cookies',
|
||||
placeId: 'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
|
||||
latitude: 30.270667599999996,
|
||||
longitude: -97.7532464,
|
||||
distance: 0.5,
|
||||
quantity: 'alot',
|
||||
category: 'desserts',
|
||||
images: [
|
||||
'https://s-media-cache-ak0.pinimg.com/564x/e7/5f/08/e75f08b00c0bc7f2b01b3d1a636389f6.jpg',
|
||||
'http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
|
||||
],
|
||||
thumbImage: 'http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jelly Filled Donuts',
|
||||
placeId: 'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
latitude: 30.263963300000004,
|
||||
longitude: -97.742308,
|
||||
distance: 1.0,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: ['https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg'],
|
||||
thumbImage: 'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Spelt Brownies',
|
||||
placeId: 'ChIJG44vBQi1RIYRvWGHdYUolZY',
|
||||
latitude: 30.265019100000004,
|
||||
longitude: -97.7419085,
|
||||
distance: 1.7,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: ['http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg'],
|
||||
thumbImage: 'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Oatmeal Raisin Cookies',
|
||||
placeId: 'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
|
||||
latitude: 30.270667599999996,
|
||||
longitude: -97.7532464,
|
||||
distance: 0.5,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: ['http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg'],
|
||||
thumbImage: 'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Donuts with Sprinkles',
|
||||
placeId: 'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
latitude: 30.263963300000004,
|
||||
longitude: -97.742308,
|
||||
distance: 1.0,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: ['https://dannivee.files.wordpress.com/2013/10/img_1950.jpg'],
|
||||
thumbImage: 'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Powdered Donuts',
|
||||
placeId: 'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
latitude: 30.263963300000004,
|
||||
longitude: -97.742308,
|
||||
distance: 1.0,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: [
|
||||
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
|
||||
],
|
||||
thumbImage:
|
||||
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Snickerdoodles',
|
||||
placeId: 'ChIJr3szW6a1RIYRkM7LRpnBIO0',
|
||||
latitude: 30.266898599999998,
|
||||
longitude: -97.73798459999999,
|
||||
quantity: 'few',
|
||||
category: 'desserts',
|
||||
images: ['http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg'],
|
||||
thumbImage: 'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Pizza',
|
||||
placeId: 'ChIJr3szW6a1RIYRkM7LRpnBIO0',
|
||||
latitude: 30.266898599999998,
|
||||
longitude: -97.73798459999999,
|
||||
quantity: 'few',
|
||||
category: 'entrees',
|
||||
images: ['http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg'],
|
||||
thumbImage: 'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
|
||||
},
|
||||
];
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
export const getFoodItemsForLocation = (location: Location) => {
|
||||
return Promise.resolve(DUMMY_DATA);
|
||||
export type FoodItemsFilter = {
|
||||
radius?: number,
|
||||
};
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
export type RawFoodItem = {
|
||||
id: string,
|
||||
name: string,
|
||||
place_id: string,
|
||||
category: string,
|
||||
images: string,
|
||||
thumbimage: string,
|
||||
latitude: number,
|
||||
longitude: number,
|
||||
distance: number,
|
||||
};
|
||||
|
||||
export type FoodItemsForLocation = {
|
||||
orderby: string,
|
||||
filter: FoodItemsFilter,
|
||||
fooditems: Array<RawFoodItem>,
|
||||
};
|
||||
|
||||
export const getFoodItemsForLocation = memoize(
|
||||
async ({ pos: { coords: { latitude, longitude } } }: { pos: Position }): Promise<FoodItemsForLocation> => {
|
||||
try {
|
||||
return fetch('http://192.168.122.1:3000/fooditems', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
lat: latitude,
|
||||
lng: longitude,
|
||||
orderby: 'distance',
|
||||
filter: {
|
||||
radius: 10,
|
||||
},
|
||||
}),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(json => ({
|
||||
...json,
|
||||
loading: false,
|
||||
error: null,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error(error); // eslint-disable-line no-console
|
||||
return {
|
||||
orderby: 'distance',
|
||||
filter: {},
|
||||
fooditems: [],
|
||||
loading: false,
|
||||
error: error,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,30 +8,36 @@ import theme from '../ui-theme';
|
|||
import { Link } from 'react-router-native';
|
||||
import { routeWithTitle } from '../helpers/RouteHelpers';
|
||||
import { TileBox, StrongText, SubText, Thumbnail } from './ItemTile';
|
||||
import { withPlace } from '../enhancers/placeEnhancers';
|
||||
|
||||
export default pure(({ foodItem, place = {} }: { foodItem: FoodItemRecord, place: PlaceRecord }) => {
|
||||
if (!foodItem || !place) {
|
||||
return <View />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={routeWithTitle(`/foodItem/${foodItem.id || ''}`, foodItem.name)}
|
||||
underlayColor={theme.itemTile.pressHighlightColor}
|
||||
>
|
||||
<View>
|
||||
<TileBox>
|
||||
<Thumbnail thumb={foodItem.thumbImage} />
|
||||
<View style={{ paddingTop: 15 }}>
|
||||
<StrongText>
|
||||
{foodItem.name || ''}
|
||||
</StrongText>
|
||||
<SubText>
|
||||
{`${place.name || ''} - ${foodItem.distance} mi`}
|
||||
</SubText>
|
||||
</View>
|
||||
</TileBox>
|
||||
</View>
|
||||
</Link>
|
||||
);
|
||||
const PlaceNameAndDistance = withPlace(({ place = {}, distance = 999.9 }: { place: PlaceRecord, distance: number }) => {
|
||||
return <SubText>{`${place.name || 'Loading...'} - ${parseFloat(distance).toFixed(1)} mi`}</SubText>;
|
||||
});
|
||||
|
||||
export default pure(
|
||||
({ foodItem }: { foodItem: FoodItemRecord }) => {
|
||||
if (!foodItem) {
|
||||
return <View />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={routeWithTitle(`/foodItem/${foodItem.id || ''}`, foodItem.name)}
|
||||
underlayColor={theme.itemTile.pressHighlightColor}
|
||||
>
|
||||
<View>
|
||||
<TileBox>
|
||||
<Thumbnail thumb={foodItem.thumbImage} />
|
||||
<View style={{ paddingTop: 15 }}>
|
||||
<StrongText>{foodItem.name || ''}</StrongText>
|
||||
<PlaceNameAndDistance
|
||||
placeId={foodItem.placeId}
|
||||
distance={foodItem.distance}
|
||||
/>
|
||||
</View>
|
||||
</TileBox>
|
||||
</View>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ export const withFoodItemsAsSeq = mapPropsStream(props$ =>
|
|||
);
|
||||
|
||||
export const withFoodItemIdFromRoute = withProps((props: { match: { params: { id: string } } }) => {
|
||||
const id = path(['match', 'params', 'id'], props) || 0;
|
||||
return { foodItemId: +id };
|
||||
const id: string = path(['match', 'params', 'id'], props) || '';
|
||||
return { foodItemId: id };
|
||||
});
|
||||
|
||||
export const withFoodItem = compose(
|
||||
|
|
|
|||
|
|
@ -6,13 +6,10 @@ import { ActionButton } from 'react-native-material-ui';
|
|||
import { routeWithTitle } from '../helpers/RouteHelpers';
|
||||
import FoodItemList from '../components/FoodItemList';
|
||||
import typeof FoodItemRecord from '../records/FoodItemRecord';
|
||||
import { withPlaceForFoodItem } from '../enhancers/placeEnhancers';
|
||||
|
||||
import theme from '../ui-theme';
|
||||
|
||||
const FoodItemWithPlace = withPlaceForFoodItem(FoodItemTile);
|
||||
|
||||
const renderFoodItem = (foodItem: FoodItemRecord) => <FoodItemWithPlace key={foodItem.id} foodItem={foodItem} />;
|
||||
const renderFoodItem = (foodItem: FoodItemRecord) => <FoodItemTile key={foodItem.id} foodItem={foodItem} />;
|
||||
|
||||
export default class FoodList extends Component {
|
||||
static displayName = 'FoodList';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@flow
|
||||
import { fromJS, List, Record } from 'immutable';
|
||||
import { type RawFoodItem } from '../apis/FoodItemsApi';
|
||||
|
||||
export const QUANTITY_NONE: 'none' = 'none';
|
||||
export const QUANTITY_FEW: 'few' = 'few';
|
||||
|
|
@ -20,7 +21,7 @@ export type Category =
|
|||
export const CATEGORIES = [CATEGORY_BEVERAGES, CATEGORY_DESSERTS, CATEGORY_ENTREES, CATEGORY_OTHER];
|
||||
|
||||
export type FoodItem = {
|
||||
id: ?number,
|
||||
id: ?string,
|
||||
name: string,
|
||||
placeId: ?number,
|
||||
latitude: number,
|
||||
|
|
@ -34,7 +35,7 @@ export type FoodItem = {
|
|||
};
|
||||
|
||||
const FoodRecordDefaults: FoodItem = {
|
||||
id: null,
|
||||
id: '',
|
||||
name: '',
|
||||
placeId: null,
|
||||
latitude: 0,
|
||||
|
|
@ -49,10 +50,12 @@ const FoodRecordDefaults: FoodItem = {
|
|||
|
||||
const FoodItemRecord = Record(FoodRecordDefaults, 'FoodItemRecord');
|
||||
|
||||
export const createFoodItem = (foodItemRaw: Object) => {
|
||||
export const createFoodItem = (foodItemRaw: RawFoodItem) => {
|
||||
return new FoodItemRecord({
|
||||
...foodItemRaw,
|
||||
images: fromJS(foodItemRaw.images),
|
||||
images: fromJS((foodItemRaw.images || '').split(',')),
|
||||
placeId: foodItemRaw.place_id,
|
||||
thumbImage: foodItemRaw.thumbimage,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import { createFoodItem } from '../records/FoodItemRecord';
|
|||
import { setById } from '../helpers/ImmutableHelpers';
|
||||
import { Map } from 'immutable';
|
||||
import location$ from './LocationStream';
|
||||
import { getFoodItemsForLocation } from '../apis/FoodItemsApi';
|
||||
import { getFoodItemsForLocation, type FoodItemsForLocation } from '../apis/FoodItemsApi';
|
||||
|
||||
export default location$.mergeMap(getFoodItemsForLocation).map(foodItems => {
|
||||
return foodItems.map(createFoodItem).reduce(setById, new Map());
|
||||
});
|
||||
export default location$
|
||||
.mergeMap(pos => getFoodItemsForLocation({ pos }))
|
||||
.map(({ fooditems = [] }: FoodItemsForLocation) => {
|
||||
return fooditems.map(createFoodItem).reduce(setById, new Map());
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,18 +16,18 @@ import { setById } from '../helpers/ImmutableHelpers';
|
|||
*/
|
||||
const safeGetPlaceDetails = memoize((placeId: string): Promise<?GooglePlaceObj> => {
|
||||
return getPlaceDetails(placeId).catch(error => {
|
||||
console.log(error); // eslint-disable-line no-console
|
||||
console.error(error); // eslint-disable-line no-console
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
export default foodItems$
|
||||
.map((foodItems: Map<string, FoodItemRecord>): Array<string> => {
|
||||
return foodItems.map(foodItem => foodItem.placeId).toArray();
|
||||
const Places$ = foodItems$
|
||||
.mergeMap((foodItems: Map<string, FoodItemRecord>): Observable<string> => {
|
||||
return Observable.from(foodItems.toArray().map(foodItem => foodItem.placeId));
|
||||
})
|
||||
.mergeMap((placeIds: Array<string>): Observable<Array<Promise<?GooglePlaceObj>>> => {
|
||||
return Observable.forkJoin(placeIds.map(safeGetPlaceDetails));
|
||||
})
|
||||
.map((places: Array<GooglePlaceObj>): Map<string, PlaceRecord> => {
|
||||
return places.map(buildPlaceRecord).reduce(setById, new Map());
|
||||
});
|
||||
.distinct()
|
||||
.mergeMap(safeGetPlaceDetails)
|
||||
.map(buildPlaceRecord)
|
||||
.scan(setById, new Map());
|
||||
|
||||
export default Places$;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue