Skip to content

Instantly share code, notes, and snippets.

@yutin1987
Last active July 10, 2017 03:45
Show Gist options
  • Save yutin1987/286fd05e2b71d41d95b66c978fa5184f to your computer and use it in GitHub Desktop.
Save yutin1987/286fd05e2b71d41d95b66c978fa5184f to your computer and use it in GitHub Desktop.
input
import React, { PropTypes, Component } from 'react';
import { StyleSheet, View, TouchableOpacity, Image } from 'react-native';
import { Input } from 'component';
import length from 'lodash/size';
import isArray from 'lodash/isArray';
import Cropper from 'react-native-cropper';
import color from 'color';
import size from 'size';
import Text from '../Text/Text';
import Icon from '../Icon/Icon';
const sh = StyleSheet.create({
viewport: {
flex: 1,
},
singleWrap: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 12,
},
multiWrap: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
justifyContent: 'space-between',
},
picture: {
flex: 1,
borderColor: color.textAssist,
borderWidth: 1,
marginBottom: 10,
},
insert: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
borderColor: color.textAssist,
borderWidth: 1,
marginBottom: 10,
},
insertText: {
marginTop: 5,
},
});
export default class InputPicture extends Component {
static displayName = 'InputPicture';
static propTypes = {
value: PropTypes.arrayOf(PropTypes.string),
tipShort: PropTypes.string,
maxSize: PropTypes.number,
pictureWidth: PropTypes.number,
pictureHeight: PropTypes.number,
onChange: PropTypes.func,
};
static defaultProps = {
name: '',
value: [],
placeholder: '',
maxSize: 1,
pictureWidth: 512,
pictureHeight: 512,
onChange: () => {},
}
state = {
box: 100,
picture: [],
}
onEdit = () => {
const { value } = this.props;
if (isArray(value) && length(value) > 0) {
this.setState({ picture: value });
}
};
onComplete = () => this.props.onChange(this.state.picture);
onLayout = (e) => {
const { width } = e.nativeEvent.layout;
this.setState({ box: (width - 10) / 2 });
}
onInsert = async () => {
const base64 = await this.getPhotoFromAlbum();
const { picture } = this.state;
if (base64) {
picture.push(`data:image/jpeg;base64, ${base64}`);
this.setState({ picture });
}
}
onModify = async (idx) => {
const base64 = await this.getPhotoFromAlbum();
const { picture } = this.state;
if (base64) {
picture[idx] = `data:image/jpeg;base64, ${base64}`;
this.setState({ picture });
}
}
getPhotoFromAlbum = async () => {
const { pictureWidth, pictureHeight } = this.props;
return await Cropper.getPhotoFromAlbum({ width: pictureWidth, height: pictureHeight });
}
render() {
const { maxSize, tipShort } = this.props;
const { box, picture } = this.state;
const surplus = maxSize - picture.length;
const scale = maxSize > 1 ? 1 : 1.5;
return (
<Input
{...this.props}
onEdit={this.onEdit}
onComplete={this.onComplete}
display={picture.length && `已選取${picture.length}張照片`}
tipShort={tipShort || `剩餘${surplus}張相片`}
>
<View style={maxSize > 1 ? sh.multiWrap : sh.singleWrap} onLayout={this.onLayout}>
{picture.map((uri, idx) => (
<View key={idx} style={{ width: box * scale, height: box * scale }}>
<TouchableOpacity style={sh.viewport} onPress={() => this.onModify(idx)}>
<Image style={sh.picture} source={{ uri }} />
</TouchableOpacity>
</View>
))}
{surplus > 0 &&
<View key="add" style={{ width: box * scale, height: box * scale }}>
<TouchableOpacity style={sh.insert} onPress={this.onInsert}>
<Icon name="photo" size={size.button} color={color.textAssist} />
<Text color={color.textAssist} style={sh.insertText}>新增照片</Text>
</TouchableOpacity>
</View>
}
</View>
</Input>
);
}
}
import React, { PropTypes, Component } from 'react';
import { StyleSheet, TextInput } from 'react-native';
import { Input } from 'component';
import color from 'color';
import size from 'size';
const sh = StyleSheet.create({
input: {
flex: 1,
fontSize: size.font.text,
color: color.text,
},
});
export default class InputText extends Component {
static displayName = 'InputText';
static propTypes = {
name: PropTypes.string,
value: PropTypes.string,
placeholder: PropTypes.string,
tipShort: PropTypes.string,
maxLength: PropTypes.number,
onChange: PropTypes.func,
};
static defaultProps = {
name: '',
value: '',
placeholder: '',
maxLength: 140,
onChange: () => {},
}
state = {
value: '',
}
onChange = (value) => this.setState({ value });
onEdit = () => this.setState({ value: this.props.value });
onComplete = () => this.props.onChange(this.state.value);
render() {
const { name, placeholder, maxLength, tipShort, value: propValue } = this.props;
const { value } = this.state;
const surplus = maxLength - (value || '').length;
return (
<Input
{...this.props}
onEdit={this.onEdit}
onComplete={this.onComplete}
display={propValue}
tipShort={tipShort || `剩餘${surplus}個字`}
>
<TextInput
style={sh.input}
autoFocus
multiline
maxLength={maxLength}
placeholder={placeholder || name}
value={value}
onChangeText={this.onChange}
/>
</Input>
);
}
}
import React, { PropTypes, Component } from 'react';
import { StyleSheet, Switch, View, Alert, TouchableOpacity } from 'react-native';
import { Input, InputTimeRange, Text, Label } from 'component';
import moment from 'moment-timezone';
import range from 'lodash/range';
import filter from 'lodash/filter';
import get from 'lodash/get';
import map from 'lodash/map';
import color from 'color';
import size from 'size';
const sh = StyleSheet.create({
placeholder: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
flexDirection: 'row',
borderTopColor: color.border,
borderTopWidth: StyleSheet.hairlineWidth,
alignItems: 'center',
height: size.itembar * 0.8,
},
buttonDisplay: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
buttonValue: {
marginTop: 3,
marginLeft: 5,
},
});
export default class InputWorktime extends Component {
static displayName = 'InputWorktime';
static propTypes = {
value: PropTypes.arrayOf(PropTypes.shape()),
name: PropTypes.string,
placeholder: PropTypes.string,
onChange: PropTypes.func,
};
static defaultProps = {
name: '',
value: [],
placeholder: '',
maxLength: 140,
onChange: () => {},
}
state = {
enable: [false, false, false, false, false, false, false],
timeRange: [{}, {}, {}, {}, {}, {}, {}],
}
onEdit = () => {
const { value } = this.props;
const { enable, timeRange } = this.state;
range(0, 7).forEach((day) => {
enable[day] = get(value, `[${day}].enable`, false);
timeRange[day] = {
start: get(value, `[${day}].start`, 0),
end: get(value, `[${day}].end`, 24 * 60),
};
});
this.setState({ enable, timeRange });
};
onComplete = () => {
const { enable, timeRange } = this.state;
this.props.onChange(
range(0, 7).map((day) => ({
enable: !!enable[day],
start: get(timeRange, `[${day}].start`, 0),
end: get(timeRange, `[${day}].end`, 24 * 60),
}))
);
};
onValueComplete = (day, value) => {
const { timeRange } = this.state;
timeRange[day] = value;
this.setState({ timeRange });
};
onSwitchChnage = (day, value) => {
const { enable } = this.state;
enable[day] = !!value;
this.setState({ enable });
}
onEditPress = (day, ref) => {
const { enable } = this.state;
if (enable[day]) return ref.onEdit();
return Alert.alert(
null,
`是否將${moment.weekdays(day)}設為營業日?`,
[
{ text: '取消' },
{
text: '設為營業日',
onPress: () => {
this.onSwitchChnage(day, true);
ref.onEdit();
},
},
]
);
}
renderButton = (data, state, ref) => {
const { day } = data;
const { enable } = this.state;
return (
<TouchableOpacity onPress={() => this.onEditPress(day, ref)}>
<View style={sh.button}>
<View style={sh.buttonDisplay}>
<Label color={color.primary}>{moment.weekdays(day)}</Label>
<Text style={sh.buttonValue} weight="light" color={color.textAssist}>
{enable[day] ? data.display || '24小時' : '休假日'}
</Text>
</View>
<Switch
value={!!enable[day]}
onValueChange={(value) => this.onSwitchChnage(day, value)}
/>
</View>
</TouchableOpacity>
);
}
render() {
const { name, placeholder, value } = this.props;
const { timeRange } = this.state;
return (
<Input
{...this.props}
onEdit={this.onEdit}
onComplete={this.onComplete}
display={
filter(map(
value || [],
(o, day) => (o.enable ? moment.weekdaysMin(day) : null)
), (o) => !!o).join(', ')
}
>
<View style={sh.placeholder}>
<Label>{placeholder || name}</Label>
</View>
{range(0, 7).map((day) => (
<InputTimeRange
key={day}
day={day}
disabled
name={`設定${moment.weekdays(day)}`}
value={timeRange[day]}
renderButton={this.renderButton}
onChange={(time) => this.onValueComplete(day, time)}
/>
))}
</Input>
);
}
}
import React, { Component, PropTypes } from 'react';
import { Animated, ScrollView } from 'react-native';
import {
NextButton,
NavigationView,
InputAddress,
InputPicture,
InputText,
InputWorktime,
Margin,
} from 'component';
export default class MemberRequisition extends Component {
static displayName = 'MemberRequisition';
static propTypes = {
nav: PropTypes.objectOf(PropTypes.func),
};
state = {
nickname: null,
picture: null,
provider: null,
address: null,
open: null,
}
onNicknameChange = (nickname) => this.setState({ nickname });
onPhotoChange = (picture) => this.setState({ picture });
onProviderChange = (provider) => this.setState({ provider });
onAddressChange = (address) => this.setState({ address });
onOpenChange = (open) => this.setState({ open });
nextAnimated = new Animated.Value(0);
render() {
const { nav } = this.props;
const { nickname, picture, provider, address, open } = this.state;
return (
<NavigationView
title="申請成為職人"
onLeftPress={nav.pop}
>
<ScrollView>
<Margin>
<InputText
name="撰寫職人名稱"
placeholder="希望顧客怎麼稱呼您?"
tip={'職人的名稱會公開顯示於Bunninn平台上,因此不建議使用全名或本名。\n\n可以是簡短容易記憶的暱稱,不建議超過四個字,顧客需要透過暱稱找到您。'}
tipTitle="簡短容易記憶"
value={nickname}
onChange={this.onNicknameChange}
/>
<InputPicture
name="上傳職人相片"
placeholder="有相片可以認識您嗎?"
value={picture}
onChange={this.onPhotoChange}
/>
<InputText
name="撰寫店名"
placeholder="您有個好記憶的店名嗎?"
value={provider}
onChange={this.onProviderChange}
/>
<InputAddress
name="撰寫店址"
placeholder="您的顧客該去哪裡找您?"
tipTitle="詳細的地址"
tipShort="詳細的地址有助於減少顧客找到您的時間"
tip={'詳細的地址有助於減少顧客找到您的時間,建議清楚告知幾號幾樓及櫃位號碼,如有公寓/大廈或商圈名稱會更棒。\n\n例如:臺北市大安區大安路1段77號東區地下街A03櫃'}
value={address}
onChange={this.onAddressChange}
/>
<InputWorktime
name="設定營業時段"
placeholder="星期幾可以與您預約?"
value={open}
onChange={this.onOpenChange}
/>
<NextButton>申請</NextButton>
</Margin>
</ScrollView>
</NavigationView>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment