mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 07:54:57 -06:00
unknown quantity UI
This commit is contained in:
parent
96e24881fc
commit
b958515311
10 changed files with 92 additions and 61 deletions
|
|
@ -18,7 +18,8 @@
|
||||||
"__DEV__": true
|
"__DEV__": true
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"react/display-name": 1
|
"react/display-name": 1,
|
||||||
|
"react/prop-types": 0
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"react": {
|
"react": {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,15 @@
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data
|
||||||
|
android:host="wheresthetp.auth0.com"
|
||||||
|
android:pathPrefix="/android/${applicationId}/callback"
|
||||||
|
android:scheme="${applicationId}" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import { pure } from 'recompose';
|
import { pure } from 'recompose';
|
||||||
import ProductRecord from '../records/ProductRecord';
|
import ProductRecord from '../records/ProductRecord';
|
||||||
import typeof PlaceRecord from '../records/PlaceRecord';
|
|
||||||
import theme from '../ui-theme';
|
import theme from '../ui-theme';
|
||||||
import { Link } from 'react-router-native';
|
import { Link } from 'react-router-native';
|
||||||
import { routeWithTitle } from '../helpers/RouteHelpers';
|
import { routeWithTitle } from '../helpers/RouteHelpers';
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,12 @@
|
||||||
// @flow
|
import React from 'react';
|
||||||
import React, { Component } from 'react';
|
import { View, FlatList } from 'react-native';
|
||||||
import { View } from 'react-native';
|
|
||||||
import { type SetSeq } from 'immutable';
|
import { type SetSeq } from 'immutable';
|
||||||
import ProductRecord from '../records/ProductRecord';
|
import ProductRecord from '../records/ProductRecord';
|
||||||
import { compose, pure } from 'recompose';
|
import { compose, pure } from 'recompose';
|
||||||
import { pipe } from 'ramda';
|
import { pipe } from 'ramda';
|
||||||
import { withFilter } from '../enhancers/filterEnhancers';
|
import { withFilter } from '../enhancers/filterEnhancers';
|
||||||
import FilterRecord from '../records/FilterRecord';
|
|
||||||
import { compareQuantity } from '../helpers/QuantityHelpers';
|
import { compareQuantity } from '../helpers/QuantityHelpers';
|
||||||
|
|
||||||
// promote this somewhere?
|
|
||||||
type homomorph<T> = T => T;
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
filter: FilterRecord,
|
|
||||||
productsSeq: SetSeq<ProductRecord>,
|
|
||||||
children: (product: ProductRecord) => Component<*, *, *>,
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByDistance = (productsSeq: SetSeq<ProductRecord>): SetSeq<ProductRecord> => {
|
const sortByDistance = (productsSeq: SetSeq<ProductRecord>): SetSeq<ProductRecord> => {
|
||||||
return productsSeq.sort((left, right) => left.distance - right.distance);
|
return productsSeq.sort((left, right) => left.distance - right.distance);
|
||||||
};
|
};
|
||||||
|
|
@ -33,7 +22,7 @@ const sortByQuantity = (productsSeq: SetSeq<ProductRecord>): SetSeq<ProductRecor
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSortBy = (filter: FilterRecord): homomorph<*> => {
|
const getSortBy = filter => {
|
||||||
switch (filter.orderby) {
|
switch (filter.orderby) {
|
||||||
case 'quantity':
|
case 'quantity':
|
||||||
return sortByQuantity;
|
return sortByQuantity;
|
||||||
|
|
@ -47,7 +36,7 @@ const getSortBy = (filter: FilterRecord): homomorph<*> => {
|
||||||
const intoArray = (productsSeq: SetSeq<ProductRecord>): Array<ProductRecord> =>
|
const intoArray = (productsSeq: SetSeq<ProductRecord>): Array<ProductRecord> =>
|
||||||
productsSeq ? productsSeq.toArray() : [];
|
productsSeq ? productsSeq.toArray() : [];
|
||||||
|
|
||||||
const ProductList = (props: Props) => {
|
const ProductList = props => {
|
||||||
const { filter, productsSeq, children } = props;
|
const { filter, productsSeq, children } = props;
|
||||||
|
|
||||||
if (!productsSeq) {
|
if (!productsSeq) {
|
||||||
|
|
@ -59,7 +48,15 @@ const ProductList = (props: Props) => {
|
||||||
intoArray
|
intoArray
|
||||||
)(productsSeq);
|
)(productsSeq);
|
||||||
|
|
||||||
return <View style={{ flexShrink: 2 }}>{items.map(children)}</View>;
|
return (
|
||||||
|
<View style={{ flexShrink: 2 }}>
|
||||||
|
<FlatList
|
||||||
|
data={items}
|
||||||
|
renderItem={({ item }) => children(item)}
|
||||||
|
keyExtractor={item => item.id}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
|
|
||||||
47
js/components/QuantityTile.js
Normal file
47
js/components/QuantityTile.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, Text, Button } from 'react-native';
|
||||||
|
import RouterButton from 'react-router-native-button';
|
||||||
|
import { SubText } from './ItemTile';
|
||||||
|
import { getQuantityLabelText } from '../helpers/QuantityHelpers';
|
||||||
|
import { loginWithBackto } from '../helpers/RouteHelpers';
|
||||||
|
import moment from 'moment';
|
||||||
|
import theme from '../ui-theme';
|
||||||
|
|
||||||
|
const QuantityPanel = ({ style, isAuthed, product, onUpdatePress }) => (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
...style,
|
||||||
|
flexBasis: 50,
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}>
|
||||||
|
{product.quantity ? (
|
||||||
|
<>
|
||||||
|
<Text style={{ fontSize: 42, color: 'black' }}>
|
||||||
|
{getQuantityLabelText(product.quantity)}
|
||||||
|
</Text>
|
||||||
|
<SubText>
|
||||||
|
Last updated at {moment(product.lastupdated).format('h:mm A on MMM D, YYYY')}
|
||||||
|
</SubText>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Text style={{ fontSize: 24, color: 'black', flex: 1, flexWrap: 'wrap' }}>
|
||||||
|
Be the first to update the amount of this product.
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{isAuthed && (
|
||||||
|
<Button title="Update amount" onPress={onUpdatePress} color={theme.palette.primaryColor} />
|
||||||
|
)}
|
||||||
|
{!isAuthed && (
|
||||||
|
<RouterButton
|
||||||
|
title="Update Amount"
|
||||||
|
to={loginWithBackto(`/product/${product.id}?loginAction=open-quantity-modal`)}
|
||||||
|
color={theme.actionButton.speedDialActionIcon.backgroundColor}
|
||||||
|
style={{ fontSize: 20, fontWeight: 500 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default QuantityPanel;
|
||||||
|
|
@ -11,4 +11,4 @@ export const BASE_URL = '192.168.1.247:3000';
|
||||||
|
|
||||||
export const GoogleAPIKey = 'AIzaSyBfMm1y6JayCbXrQmgAG1R3ka4ZOJno_5E';
|
export const GoogleAPIKey = 'AIzaSyBfMm1y6JayCbXrQmgAG1R3ka4ZOJno_5E';
|
||||||
|
|
||||||
export const auth0ClientId = 'y3jfovcuWnEhdisNaA666rxsf4hyZrUa';
|
export const auth0ClientId = '4p1BPIX4L6iwTv5gl3ZpHpU4Ye5YatQ3';
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { Divider, Icon } from 'react-native-material-ui';
|
||||||
import { getBackTo } from '../helpers/RouteHelpers';
|
import { getBackTo } from '../helpers/RouteHelpers';
|
||||||
import ResetPasswordButton from '../components/ResetPasswordButton';
|
import ResetPasswordButton from '../components/ResetPasswordButton';
|
||||||
|
|
||||||
const auth0ErrToStr = (message) => {
|
const auth0ErrToStr = message => {
|
||||||
if (typeof message === 'string') {
|
if (typeof message === 'string') {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
@ -24,9 +24,9 @@ type Props = {
|
||||||
error: string,
|
error: string,
|
||||||
setError: (err: string) => void,
|
setError: (err: string) => void,
|
||||||
email: string,
|
email: string,
|
||||||
setEmail: (string) => void,
|
setEmail: string => void,
|
||||||
password: string,
|
password: string,
|
||||||
setPassword: (string) => void,
|
setPassword: string => void,
|
||||||
router: {
|
router: {
|
||||||
route: {
|
route: {
|
||||||
location: {
|
location: {
|
||||||
|
|
@ -43,7 +43,7 @@ type Props = {
|
||||||
deauthUser: () => void,
|
deauthUser: () => void,
|
||||||
createUser: () => void,
|
createUser: () => void,
|
||||||
isNewUser: boolean,
|
isNewUser: boolean,
|
||||||
setIsNewUser: (boolean) => void,
|
setIsNewUser: boolean => void,
|
||||||
resetPassword: () => void,
|
resetPassword: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -83,7 +83,9 @@ const LoginPageComponent = ({
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Text style={{ fontSize: 36, fontWeight: '700', marginTop: 32, marginBottom: 16 }}>Sign In</Text>
|
<Text style={{ fontSize: 36, fontWeight: '700', marginTop: 32, marginBottom: 16 }}>
|
||||||
|
Sign In
|
||||||
|
</Text>
|
||||||
|
|
||||||
<View style={{ flexDirection: 'row', padding: 16, paddingBottom: 0 }}>
|
<View style={{ flexDirection: 'row', padding: 16, paddingBottom: 0 }}>
|
||||||
<View style={{ flex: 1, flexDirection: 'column' }}>
|
<View style={{ flex: 1, flexDirection: 'column' }}>
|
||||||
|
|
@ -160,7 +162,7 @@ export default compose(
|
||||||
withState('password', 'setPassword', ''),
|
withState('password', 'setPassword', ''),
|
||||||
withState('isNewUser', 'setIsNewUser', false),
|
withState('isNewUser', 'setIsNewUser', false),
|
||||||
withHandlers({
|
withHandlers({
|
||||||
checkAuth: (props) => async () => {
|
checkAuth: props => async () => {
|
||||||
const isLoggedIn = await AuthManager.checkIsAuthed();
|
const isLoggedIn = await AuthManager.checkIsAuthed();
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
const backTo = getBackTo(props);
|
const backTo = getBackTo(props);
|
||||||
|
|
@ -175,6 +177,8 @@ export default compose(
|
||||||
await AuthManager.authenticate({ email, password });
|
await AuthManager.authenticate({ email, password });
|
||||||
checkAuth();
|
checkAuth();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
debugger;
|
||||||
setError('You have entered an invalid email or password. Please try again.');
|
setError('You have entered an invalid email or password. Please try again.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, Image, Text, View } from 'react-native';
|
import { Image, View } from 'react-native';
|
||||||
import theme from '../ui-theme';
|
import theme from '../ui-theme';
|
||||||
import { StrongText, SubText } from '../components/ItemTile';
|
import { StrongText, SubText } from '../components/ItemTile';
|
||||||
import typeof ProductRecord from '../records/ProductRecord';
|
import typeof ProductRecord from '../records/ProductRecord';
|
||||||
|
|
@ -21,10 +20,7 @@ import Carousel from 'react-native-looped-carousel';
|
||||||
import CountBadge from '../components/CountBadge';
|
import CountBadge from '../components/CountBadge';
|
||||||
import { routeWithTitle, loginWithBackto } from '../helpers/RouteHelpers';
|
import { routeWithTitle, loginWithBackto } from '../helpers/RouteHelpers';
|
||||||
import { Link } from 'react-router-native';
|
import { Link } from 'react-router-native';
|
||||||
import moment from 'moment';
|
|
||||||
import { withUpdateQuantity } from '../enhancers/quantityEnhancers';
|
import { withUpdateQuantity } from '../enhancers/quantityEnhancers';
|
||||||
import { getQuantityLabelText } from '../helpers/QuantityHelpers';
|
|
||||||
import RouterButton from 'react-router-native-button';
|
|
||||||
import QuantityModal from '../modals/QuantityModal';
|
import QuantityModal from '../modals/QuantityModal';
|
||||||
import { identity, pathOr } from 'ramda';
|
import { identity, pathOr } from 'ramda';
|
||||||
import Spinner from 'react-native-loading-spinner-overlay';
|
import Spinner from 'react-native-loading-spinner-overlay';
|
||||||
|
|
@ -35,6 +31,7 @@ import { withAuthed } from '../enhancers/authEnhancers';
|
||||||
import { withFaves } from '../enhancers/favesEnhancer';
|
import { withFaves } from '../enhancers/favesEnhancer';
|
||||||
import debounce from '../helpers/debounce';
|
import debounce from '../helpers/debounce';
|
||||||
import { withCurrentPath, withReplaceRoute } from '../enhancers/routeEnhancers';
|
import { withCurrentPath, withReplaceRoute } from '../enhancers/routeEnhancers';
|
||||||
|
import QuantityTile from '../components/QuantityTile';
|
||||||
|
|
||||||
const { productDetails: style } = theme;
|
const { productDetails: style } = theme;
|
||||||
|
|
||||||
|
|
@ -144,35 +141,12 @@ export const ProductDetail = (props: Props) => {
|
||||||
</View>
|
</View>
|
||||||
</Link>
|
</Link>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<QuantityTile
|
||||||
style={{
|
product={product}
|
||||||
flexBasis: 100,
|
isAuthed={isAuthed}
|
||||||
flexGrow: 1,
|
onUpdatePress={toggleQuantityModal}
|
||||||
...contentTileStyle,
|
style={contentTileStyle}
|
||||||
flexDirection: 'column',
|
/>
|
||||||
justifyContent: 'space-between',
|
|
||||||
}}>
|
|
||||||
<Text style={{ fontSize: 42, color: 'black' }}>
|
|
||||||
{getQuantityLabelText(product.quantity)}
|
|
||||||
</Text>
|
|
||||||
<SubText>
|
|
||||||
Last updated at {moment(product.lastupdated).format('h:mm A on MMM D, YYYY')}
|
|
||||||
</SubText>
|
|
||||||
{isAuthed && (
|
|
||||||
<Button
|
|
||||||
title="Update quantity"
|
|
||||||
onPress={toggleQuantityModal}
|
|
||||||
color={theme.palette.primaryColor}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!isAuthed && (
|
|
||||||
<RouterButton
|
|
||||||
title="Log in to update quantity"
|
|
||||||
to={loginWithBackto(`/product/${product.id}?loginAction=open-quantity-modal`)}
|
|
||||||
color={theme.actionButton.speedDialActionIcon.backgroundColor}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
<View style={{ flex: 1, ...contentTileStyle }}>
|
<View style={{ flex: 1, ...contentTileStyle }}>
|
||||||
{isAuthed && isFave ? (
|
{isAuthed && isFave ? (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ const ProductList = props => {
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onPulldown} />}>
|
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onPulldown} />}>
|
||||||
<ProductsList productsSeq={productsSeq}>
|
<ProductsList productsSeq={productsSeq}>
|
||||||
{product => <ProductTile key={product.id} product={product} />}
|
{product => <ProductTile product={product} />}
|
||||||
</ProductsList>
|
</ProductsList>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ export default {
|
||||||
fontSize: 25,
|
fontSize: 25,
|
||||||
color: COLOR.black,
|
color: COLOR.black,
|
||||||
},
|
},
|
||||||
pressHighlightColor: COLOR.pink500,
|
pressHighlightColor: primaryColor,
|
||||||
},
|
},
|
||||||
countBadge: {
|
countBadge: {
|
||||||
backgroundColor: '#00506C',
|
backgroundColor: '#00506C',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue