This commit is contained in:
Jay 2017-07-05 13:45:46 +08:00
parent 9f9f8affe0
commit f03870e882
12 changed files with 238 additions and 74 deletions

View File

@ -6,48 +6,16 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import {
AppRegistry, AppRegistry
StyleSheet,
Text,
View
} from 'react-native'; } from 'react-native';
import MainApp from './src'
export default class BuyWhat extends Component { export default class BuyWhat extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <MainApp dev='android' />
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
); );
} }
} }
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('BuyWhat', () => BuyWhat); AppRegistry.registerComponent('BuyWhat', () => BuyWhat);

View File

@ -1,5 +1,15 @@
{ {
"images" : [ "images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{ {
"idiom" : "iphone", "idiom" : "iphone",
"size" : "29x29", "size" : "29x29",

View File

@ -36,7 +36,13 @@ export const removeDialog = () => ({
export const getStoreList = () => dispatch => { export const getStoreList = () => dispatch => {
dispatch(toggleLoading(1)) dispatch(toggleLoading(1))
fetch(`${apiUrl}/store`, genRequest()) fetch(`${apiUrl}/store`, genRequest())
.then(response => response.json()) .then(response => {
if(response.status == 404) return {
status: 0,
message: 'api not found'
}
return response.json()
})
.then(json => { .then(json => {
dispatch(toggleLoading(0)) dispatch(toggleLoading(0))
if (json.status != 1) return dispatch(addDialog(json.message)) if (json.status != 1) return dispatch(addDialog(json.message))
@ -50,7 +56,13 @@ export const getStoreList = () => dispatch => {
export const getItems = (id) => dispatch => { export const getItems = (id) => dispatch => {
dispatch(toggleLoading(1)) dispatch(toggleLoading(1))
fetch(`${apiUrl}/item/${id}`, genRequest()) fetch(`${apiUrl}/item/${id}`, genRequest())
.then(response => response.json()) .then(response => {
if(response.status == 404) return {
status: 0,
message: 'api not found'
}
return response.json()
})
.then(json => { .then(json => {
dispatch(toggleLoading(0)) dispatch(toggleLoading(0))
if(json.status != 1) return dispatch(addDialog(json.message)) if(json.status != 1) return dispatch(addDialog(json.message))
@ -67,6 +79,10 @@ export const clearStore = () => ({
export const clearItems = () => ({ export const clearItems = () => ({
type: 'clear_items' type: 'clear_items'
}) })
export const setStore = (id) => ({
type: 'set_store',
id
})
export const toPage = (page = 0) => ({ export const toPage = (page = 0) => ({
type: 'page', type: 'page',

54
src/components/Dialog.js Normal file
View File

@ -0,0 +1,54 @@
import React from 'react';
import { View, Text, Button, TouchableOpacity, Dimensions } from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const Dialog = ({ show, obj, onButtonPress }) => {
if (!show) return null;
return (
<View style={{
position: 'absolute',
top: 0,
left: 0,
width,
height,
justifyContent: 'center',
alignItems: 'center',
zIndex: 500,
backgroundColor: 'rgba(0,0,0,0.4)'
}}>
<View style={{
width: width * 0.7,
backgroundColor: '#fff',
minHeight: 100,
borderRadius: 10
}}>
<View style={{
alignItems: 'center',
paddingTop: 10,
flex: 1
}}>
<Text>{obj}</Text>
</View>
<View style={{
borderTopColor: '#000',
borderTopWidth: 1,
borderStyle: 'solid'
}}>
<TouchableOpacity style={{
alignItems: 'center',
justifyContent: 'center',
paddingTop: 5,
paddingBottom: 5,
paddingLeft: 10,
paddingRight: 10
}} onPress={() => onButtonPress()}>
<Text>OK</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
export default Dialog;

View File

@ -7,8 +7,74 @@ const ds = new ListView.DataSource({
} }
}) })
export default ItemsPage = ({ dev, show, list, refresh, getList, backPage }) => { const defState = () => ({
if (!show) return null show: false,
list: [],
id: '',
result: null
})
const shuffle = (array) => {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
export default class ItemsPage extends React.Component {
constructor(props) {
super(props)
this.state = defState()
this.refreshList = this.refreshList.bind(this)
this.randomItem = this.randomItem.bind(this)
}
refreshList() {
let { getList } = this.props
getList(this.state.id)
}
randomItem() {
let ls = shuffle([...this.state.list])
this.setState({
result: ls[0] || null
})
}
componentWillReceiveProps(nextProps) {
if (this.state.show !== nextProps.show) {
this.setState({
show: nextProps.show,
result: null
})
}
if (this.state.id !== nextProps.sid) {
this.setState({ id: nextProps.sid }, () => {
this.refreshList()
})
}
this.setState({
list: nextProps.list
})
}
render() {
let { dev, list, refresh, getList, backPage } = this.props
if (!this.state.show) return null
console.log('Items') console.log('Items')
return ( return (
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
@ -23,8 +89,25 @@ export default ItemsPage = ({ dev, show, list, refresh, getList, backPage }) =>
<Text style={{ fontSize: 20 }}>&lt;&lt;Back</Text> <Text style={{ fontSize: 20 }}>&lt;&lt;Back</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<View style={{
height: 30,
margin: 10,
alignContent: 'center',
alignItems: 'center'
}}>
<TouchableOpacity onPress={() => this.randomItem()}>
<Text style={{ fontSize: 25 }}>Random!!</Text>
</TouchableOpacity>
</View>
<View style={{
height: 25,
padding: 5,
alignItems: 'center'
}}>
{this.state.result != null ? <Text>結果: {this.state.result.name} / {this.state.result.price}</Text> : null}
</View>
<ListView <ListView
refreshControl={<RefreshControl refreshing={refresh} onRefresh={getList} />} refreshControl={<RefreshControl refreshing={refresh} onRefresh={this.refreshList} />}
enableEmptySections={true} enableEmptySections={true}
dataSource={ds.cloneWithRows(list)} dataSource={ds.cloneWithRows(list)}
renderRow={data => { renderRow={data => {
@ -35,3 +118,4 @@ export default ItemsPage = ({ dev, show, list, refresh, getList, backPage }) =>
</View> </View>
) )
} }
}

View File

@ -16,7 +16,8 @@ const Item = ({ name, onClick }) => {
flexDirection: 'column' flexDirection: 'column'
}}> }}>
<Text style={{ <Text style={{
fontSize: 20 fontSize: 30,
backgroundColor: '#eee'
}}>{name}</Text> }}>{name}</Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>

View File

@ -14,6 +14,12 @@ export default StoreList = ({dev, show, list, refresh, getList, loadItems}) => {
console.log('Store', list) console.log('Store', list)
return ( return (
<View style={{flex: 1}}> <View style={{flex: 1}}>
<View style={{height: 30}}>
<Text style={{
fontSize: 25,
alignSelf: 'center'
}}>請選擇店家</Text>
</View>
<ListView <ListView
refreshControl={<RefreshControl refreshing={refresh} onRefresh={getList} />} refreshControl={<RefreshControl refreshing={refresh} onRefresh={getList} />}
enableEmptySections={true} enableEmptySections={true}

17
src/containers/Dialog.js Normal file
View File

@ -0,0 +1,17 @@
import React from 'react';
import { connect } from 'react-redux';
import Dialog from '../components/Dialog';
import { removeDialog } from '../actions';
const mapStateToProps = (state) => ({
obj: state.ui.dialog[0] || null,
show: state.ui.dialog.length > 0
});
const mapDispatchToProps = (dispatch, ownProps) => ({
onButtonPress: () => {
dispatch(removeDialog());
}
});
export default connect(mapStateToProps, mapDispatchToProps)(Dialog);

View File

@ -1,17 +1,18 @@
import {connect} from 'react-redux' import {connect} from 'react-redux'
import ItemsPage from '../components/ItemsPage' import ItemsPage from '../components/ItemsPage'
import {toPage, getStoreList, clearItems} from '../actions' import {toPage, getStoreList, clearItems, getItems} from '../actions'
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
dev: state.sys.dev, dev: state.sys.dev,
show: state.ui.page == 1, show: state.ui.page == 1,
refresh: state.ui.loading, refresh: state.ui.loading,
list: state.sys.items || [] list: state.sys.items || [],
sid: state.sys.sid
}) })
const mapDispatchToProps = (dispatch, ownProps) => ({ const mapDispatchToProps = (dispatch, ownProps) => ({
getList: () => { getList: (id) => {
dispatch(getItems()) dispatch(getItems(id))
}, },
backPage: () => { backPage: () => {
dispatch(clearItems()) dispatch(clearItems())

View File

@ -1,6 +1,6 @@
import {connect} from 'react-redux' import {connect} from 'react-redux'
import StoreList from '../components/StoreList' import StoreList from '../components/StoreList'
import {getStoreList, getItems, toPage, clearStore} from '../actions' import {getStoreList, getItems, toPage, clearStore, setStore} from '../actions'
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
dev: state.sys.dev, dev: state.sys.dev,
@ -15,6 +15,7 @@ const mapDispatchToProps = (dispatch, ownProps) => ({
}, },
loadItems: (id) => { loadItems: (id) => {
dispatch(clearStore()) dispatch(clearStore())
dispatch(setStore(id))
dispatch(toPage(1)) dispatch(toPage(1))
dispatch(getItems(id)) dispatch(getItems(id))
} }

View File

@ -3,12 +3,13 @@ import {createStore, applyMiddleware} from 'redux'
import reducers from './reducers' import reducers from './reducers'
import {Provider, connect} from 'react-redux' import {Provider, connect} from 'react-redux'
import thunk from 'redux-thunk' import thunk from 'redux-thunk'
import {View, Text} from 'react-native' import {View, Text, Platform} from 'react-native'
import {SetDev, getStoreList} from './actions' import {SetDev, getStoreList} from './actions'
// import pages // import pages
import StoreList from './containers/StoreList' import StoreList from './containers/StoreList'
import ItemsPage from './containers/ItemsPage' import ItemsPage from './containers/ItemsPage'
import Dialog from './containers/Dialog'
const middleware = [thunk] const middleware = [thunk]
@ -21,7 +22,10 @@ store.subscribe(() => {
const VV = (props) => { const VV = (props) => {
console.log(props) console.log(props)
return ( return (
<View style={{flex: 1}}> <View style={{
flex: 1,
paddingTop: Platform.OS === 'ios' ? 20 : 0
}}>
{ {
props.children props.children
} }
@ -34,8 +38,6 @@ const CView = connect()(VV)
class Main extends React.Component { class Main extends React.Component {
componentDidMount(){ componentDidMount(){
let {dev} = this.props
store.dispatch(SetDev(dev))
store.dispatch(getStoreList()) store.dispatch(getStoreList())
} }
@ -45,6 +47,7 @@ class Main extends React.Component {
<CView> <CView>
<StoreList /> <StoreList />
<ItemsPage /> <ItemsPage />
<Dialog />
</CView> </CView>
</Provider> </Provider>
) )

View File

@ -1,6 +1,7 @@
const stateDefault = () => ({ const stateDefault = () => ({
dev: '', dev: '',
store: [], store: [],
sid: '',
items: [] items: []
}) })
@ -16,6 +17,8 @@ export default sysReducer = (state = stateDefault(), action) => {
return { ...state, items: [] } return { ...state, items: [] }
case 'items': case 'items':
return { ...state, items: action.list } return { ...state, items: action.list }
case 'set_store':
return { ...state, sid: action.id }
default: default:
return state return state
} }