mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 07:24:56 -06:00
add food item name modal
This commit is contained in:
parent
27ad3d5769
commit
38035c6f5c
5 changed files with 214 additions and 19 deletions
|
|
@ -12,6 +12,7 @@ import List from './pages/List';
|
|||
import FoodItemDetail from './pages/FoodItemDetail';
|
||||
import PlaceDetail from './pages/PlaceDetail';
|
||||
import Drawer from 'react-native-drawer';
|
||||
import CreateFoodItem from './pages/CreateFoodItem';
|
||||
|
||||
setObservableConfig(rxjsconfig);
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ export default class App extends Component {
|
|||
<Route path="/list/:type" component={List} />
|
||||
<Route path="/foodItem/:id" component={FoodItemDetail} />
|
||||
<Route path="/place/:id" component={PlaceDetail} />
|
||||
<Route path="/createFoodItem" component={CreateFoodItem} />
|
||||
</View>
|
||||
</Drawer>
|
||||
</ThemeProvider>
|
||||
|
|
|
|||
39
js/components/FoodItemList.js
Normal file
39
js/components/FoodItemList.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { Seq } from 'immutable';
|
||||
import FoodItemRecord, { type FoodItem } from '../records/FoodItemRecord';
|
||||
import { pure, compose } from 'recompose';
|
||||
import { memoize } from 'ramda';
|
||||
import { withFoodItemsAsSeq } from '../enhancers/foodItemEnhancers';
|
||||
|
||||
const matchString = memoize((match = '', str = '') => str.toLowerCase().includes(match.toLowerCase()));
|
||||
|
||||
const textFilter = (filter?: string = '', foodItemsSeq: Seq<FoodItem>) => {
|
||||
return foodItemsSeq.filter((foodItem: typeof FoodItemRecord) => {
|
||||
return matchString(filter, foodItem.name);
|
||||
});
|
||||
};
|
||||
|
||||
class FoodItemList extends Component {
|
||||
static displayName = 'FoodItemList';
|
||||
|
||||
props: {
|
||||
filter: string,
|
||||
foodItemsSeq: Seq<FoodItem>,
|
||||
renderFoodItem: (foodItem: typeof FoodItemRecord) => Component,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { filter, foodItemsSeq, renderFoodItem } = this.props;
|
||||
return (
|
||||
<View>
|
||||
{textFilter(filter, foodItemsSeq).map(renderFoodItem)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const enhance = compose(pure, withFoodItemsAsSeq);
|
||||
|
||||
export default enhance(FoodItemList);
|
||||
70
js/modals/FoodItemNameModal.js
Normal file
70
js/modals/FoodItemNameModal.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import { View, TextInput, TouchableOpacity } from 'react-native';
|
||||
import Modal from '../components/Modal';
|
||||
import { Divider, Icon } from 'react-native-material-ui';
|
||||
import FoodItemList from '../components/FoodItemList';
|
||||
import FoodItemRecord from '../records/FoodItemRecord';
|
||||
import { withPlaceForFoodItem } from '../enhancers/placeEnhancers';
|
||||
import { NameAndPlace } from '../components/ItemTile';
|
||||
import { type Place } from '../records/PlaceRecord';
|
||||
|
||||
const FoodItemWithPlace = withPlaceForFoodItem(
|
||||
({ foodItem, place }: { foodItem: typeof FoodItemRecord, place: Place }) => {
|
||||
return <NameAndPlace name={foodItem.name} place={place.name} />;
|
||||
}
|
||||
);
|
||||
|
||||
class NameModal extends Component {
|
||||
static displayName = 'NameModal';
|
||||
|
||||
props: {
|
||||
isVisible: boolean,
|
||||
onClose: () => void,
|
||||
};
|
||||
|
||||
state: {
|
||||
text: string,
|
||||
};
|
||||
|
||||
state = {
|
||||
text: '',
|
||||
};
|
||||
|
||||
setText = (text: string) => {
|
||||
this.setState({ text });
|
||||
};
|
||||
|
||||
renderFoodItem = (foodItem: typeof FoodItemRecord) => {
|
||||
return (
|
||||
<TouchableOpacity key={foodItem.id} onPress={() => this.setText(foodItem.name)}>
|
||||
<FoodItemWithPlace foodItem={foodItem} />
|
||||
<Divider />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isVisible, onClose } = this.props;
|
||||
return (
|
||||
<Modal isVisible={isVisible}>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<Icon name="search" style={{ marginTop: 10 }} />
|
||||
<TextInput
|
||||
style={{ flex: 1, height: 40 }}
|
||||
onChangeText={this.setText}
|
||||
value={this.state.text}
|
||||
placeholder="search"
|
||||
/>
|
||||
<TouchableOpacity onPress={onClose}>
|
||||
<Icon name="close" style={{ marginTop: 10 }} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Divider />
|
||||
<FoodItemList filter={this.state.text} renderFoodItem={this.renderFoodItem} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NameModal;
|
||||
67
js/pages/CreateFoodItem.js
Normal file
67
js/pages/CreateFoodItem.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import theme from '../ui-theme';
|
||||
import { Divider } from 'react-native-material-ui';
|
||||
import FoodItemRecord from '../records/FoodItemRecord';
|
||||
import NameModal from '../modals/FoodItemNameModal';
|
||||
|
||||
const fieldStyle = {
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
};
|
||||
|
||||
const fieldNameStyle = {
|
||||
fontSize: 18,
|
||||
};
|
||||
|
||||
class CreateFoodItem extends Component {
|
||||
static displayName = 'CreateFoodItem';
|
||||
|
||||
state: {
|
||||
foodItem: typeof FoodItemRecord,
|
||||
modals: {
|
||||
name: boolean,
|
||||
},
|
||||
};
|
||||
|
||||
state = {
|
||||
foodItem: new FoodItemRecord(),
|
||||
modalsVisible: {
|
||||
name: false,
|
||||
},
|
||||
};
|
||||
|
||||
setName = (name: string) => {
|
||||
this.setState(({ foodItem }) => foodItem.set('name', name));
|
||||
};
|
||||
|
||||
toggleModal = (modalName: string) => () => {
|
||||
this.setState(state => {
|
||||
return {
|
||||
...state,
|
||||
modalsVisible: {
|
||||
...state.modalsVisible,
|
||||
[modalName]: !state.modalsVisible[modalName],
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { foodItem, modalsVisible } = this.state;
|
||||
return (
|
||||
<View style={{ ...theme.page.container, backgroundColor: 'white', padding: 10 }}>
|
||||
<TouchableOpacity style={fieldStyle} onPress={this.toggleModal('name')}>
|
||||
<Text style={fieldNameStyle}>
|
||||
{foodItem.name || 'Name'}
|
||||
</Text>
|
||||
<Divider />
|
||||
</TouchableOpacity>
|
||||
<NameModal isVisible={modalsVisible.name} onClose={this.toggleModal('name')} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CreateFoodItem;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { View, ScrollView } from 'react-native';
|
||||
import theme from '../ui-theme';
|
||||
import { withFoodItemsAsSeq } from '../enhancers/foodItemEnhancers';
|
||||
|
|
@ -7,30 +7,47 @@ import { pure, compose } from 'recompose';
|
|||
import { FoodItemTile } from '../components/ItemTile';
|
||||
import { type FoodItem } from '../records/FoodItemRecord';
|
||||
import { type Seq } from 'immutable';
|
||||
import { ActionButton } from 'react-native-material-ui';
|
||||
import { routeWithTitle } from '../helpers/RouteHelpers';
|
||||
|
||||
const { shape, func } = PropTypes;
|
||||
|
||||
const enhance = compose(pure, withFoodItemsAsSeq);
|
||||
const FoodItemList = enhance(({ foodItemsSeq }: { foodItemsSeq: Seq<FoodItem> }) => {
|
||||
return (
|
||||
<View>
|
||||
{foodItemsSeq.map((foodItem: FoodItem, index: number) => {
|
||||
return <FoodItemTile key={index} foodItem={foodItem} />;
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
export const FoodItemList = enhance(({ foodItemsSeq }: { foodItemsSeq: Seq<FoodItem> }) => {
|
||||
return (
|
||||
<View>
|
||||
{foodItemsSeq.map((foodItem: FoodItem, index: number) => {
|
||||
return <FoodItemTile key={index} foodItem={foodItem} />;
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
class Food extends Component {
|
||||
static displayName = 'Food';
|
||||
static displayName = 'Food';
|
||||
static contextTypes = {
|
||||
router: shape({
|
||||
history: shape({
|
||||
push: func.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={theme.page.container}>
|
||||
<ScrollView>
|
||||
<FoodItemList />
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
addFoodItem = () => {
|
||||
const newRoute = routeWithTitle('/createFoodItem', 'Add a Food Item');
|
||||
this.context.router.history.push(newRoute);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={theme.page.container}>
|
||||
<ScrollView>
|
||||
<FoodItemList />
|
||||
</ScrollView>
|
||||
<ActionButton icon="add" onPress={this.addFoodItem} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Food;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue