Skip to content

Instantly share code, notes, and snippets.

@maiordom
Created October 10, 2017 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maiordom/0989b2470dd0ee9e0a83a1b703b3aa4a to your computer and use it in GitHub Desktop.
Save maiordom/0989b2470dd0ee9e0a83a1b703b3aa4a to your computer and use it in GitHub Desktop.
// @flow
import * as ProfileService from '../services/Profile';
import constants from '../constants/Profile';
export const getUserProfile = () => (dispatch: Function, getState: Function) => {
const auth = getState().auth;
return ProfileService.getUserProfile({
Authorization: `${auth.tokenType} ${auth.accessToken}`,
}, {
include: 'master_cards',
})
.then((res: Object) => {
if (!res.error) {
dispatch({
type: constants.PROFILE_DATA_SET,
...res,
});
}
return res;
});
};
export const getMasterServices = (masterCardId: number) => (dispatch: Function) =>
ProfileService.getMasterServices({
filters: `[{"operator":"=","attribute":"master_card_id","value":"${masterCardId}"}]`,
}).then((res: Object) => {
if (!res.error) {
dispatch({
type: constants.PROFILE_MASTER_SERVICES_SET,
payload: { masterServices: res, masterCardId },
});
}
return res;
});
export const getAddresses = (masterCardId: number) => (dispatch: Function) =>
ProfileService.getAddresses({
filters: `[{"operator":"=","attribute":"master_card_id","value":${masterCardId}}]`,
include: 'timetables,schedules',
}).then((res: Object) => {
if (!res.error) {
dispatch({
type: constants.PROFILE_ADDRESSES_SET,
payload: { addresses: res, masterCardId },
});
}
return res;
});
export const selectMainMaster = (index: number) => (dispatch: Function) => {
dispatch({ type: constants.PROFILE_MAIN_SET, index });
};
// @flow
import React, { Component } from 'react';
import { View, Text, Image, StyleSheet, Platform } from 'react-native';
import { toPattern } from 'vanilla-masker';
import upperFirst from 'lodash/upperFirst';
import Input from '../Input';
import Switch from '../Switch';
import ButtonControl from '../ButtonControl';
import ActivityIndicator from '../../containers/ActivityIndicator';
import i18n from '../../i18n';
import vars from '../../vars';
const icons = Platform.select({
android: {
warning: require('../../icons/android/warning.png'),
},
});
type TState = {
errorFillPhoneNumber: boolean;
errorFillSalonName: boolean;
errorFillUsername: boolean;
hasError: boolean;
};
type TProps = {
actions: Object;
isSalonField: Object;
phoneField: Object;
salonNameField: Object;
usernameField: Object;
};
export default class MasterEditorGeneral extends Component<TProps, TState> {
state = {
errorFillPhoneNumber: false,
errorFillSalonName: false,
errorFillUsername: false,
hasError: false,
};
onChange = (value: string, modelName: string) => {
const sectionName = this.props[modelName].sectionName;
this.props.actions.setGeneralParam(modelName, value, sectionName);
if (this.state.hasError) {
this.validate();
}
};
onUsernameBlur = (value: string, modelName: string) => {
const sectionName = this.props[modelName].sectionName;
this.props.actions.setGeneralParam(modelName, upperFirst(value), sectionName);
};
onPhoneChange = (value: string, modelName: string) => {
const sectionName = this.props[modelName].sectionName;
value = value.replace(/[^0-9]+/g, '');
this.props.actions.setGeneralParam(modelName, upperFirst(value), sectionName);
};
formatPhone = (value: string) => {
let rawValue = value.replace(/[^0-9]+/g, '');
if (rawValue.length > 1 && rawValue[0] === '7') {
rawValue = rawValue.slice(1);
}
if (value === '+7 (') {
rawValue = '';
}
return toPattern(rawValue, {
pattern: '+7 (999) 999 99 99',
});
};
onNextPress = () => {
if (this.validate()) {
this.props.actions.createMaster().then((res) => {
if (res.result === 'success') {
this.props.actions.next();
}
});
}
};
validate() {
const {
usernameField,
isSalonField,
phoneField,
salonNameField,
} = this.props;
let validation = true;
const state = {};
if (!phoneField.value || phoneField.value && phoneField.value.length < 11) {
validation = false;
state.errorFillPhoneNumber = true;
} else {
state.errorFillPhoneNumber = false;
}
state.errorFillUsername = !usernameField.value;
state.errorFillSalonName = isSalonField.value && !salonNameField.value;
if (!usernameField.value
|| !phoneField.value
|| isSalonField.value && !salonNameField.value
) {
validation = false;
}
state.hasError = !validation;
this.setState(state);
return validation;
}
error = (text: string) => (
<View style={styles.error}>
<Text style={styles.errorText}>{text}</Text>
<Image style={styles.errorImage} source={icons.warning} />
</View>
);
render() {
const {
isSalonField,
phoneField,
salonNameField,
usernameField,
} = this.props;
const {
errorFillPhoneNumber,
errorFillSalonName,
errorFillUsername,
hasError,
} = this.state;
return (
<View style={styles.container}>
<ActivityIndicator position="absolute" />
<View style={styles.inner}>
<Input
{...usernameField}
debounce
onBlur={this.onUsernameBlur}
onChange={this.onChange}
/>
{errorFillUsername && (
this.error(i18n.fillField)
)}
<Input
{...phoneField}
debounce
formatValue={this.formatPhone}
keyboardType="phone-pad"
onChange={this.onPhoneChange}
/>
{errorFillPhoneNumber && (
this.error(i18n.fillPhoneNumber)
)}
<Switch
{...isSalonField}
onChange={this.onChange}
customStyles={{ container: styles.switcher }}
/>
<Input
{...salonNameField}
debounce
editable={isSalonField.value}
onChange={this.onChange}
/>
{errorFillSalonName && (
this.error(i18n.fillField)
)}
</View>
<ButtonControl
type={hasError && 'disabled'}
onPress={this.onNextPress}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
switcher: {
paddingLeft: 4,
},
inner: {
flex: 1,
paddingLeft: 12,
paddingRight: 12,
},
error: {
paddingLeft: 4,
flexDirection: 'row',
},
errorText: {
color: vars.color.red,
marginRight: 10,
},
errorImage: {
marginTop: 3,
},
});
import find from 'lodash/find';
import { makeReducer, groupServices } from '../utils';
import { intervalGroup } from '../store/Interval';
import type { TProfileData } from '../types/ProfileData';
import c from '../constants/Profile';
const intervalModel = intervalGroup();
export default makeReducer((state, action) => ({
[c.PROFILE_DATA_SET]: () => {
const { email, userId, masterCards } = action;
const profile: TProfileData = {
email,
masterCards,
userId,
};
state.profile = profile;
return state;
},
[c.PROFILE_MAIN_SET]: () => {
const { index } = action;
state.profile.masterCards.forEach((card, masterIndex) => {
card.isMain = masterIndex === index;
});
state.profile.masterCards = [...state.profile.masterCards];
return state;
},
[c.PROFILE_ADDRESSES_SET]: (state, { payload: { addresses, masterCardId } }) => {
const masterCard = find(state.profile.masterCards, { id: masterCardId });
if (masterCard) {
masterCard.addresses = addresses;
masterCard.status.addressesUploaded = true;
addresses.forEach(address => {
const interval = find(intervalModel.items, { id: address.timeTable.intervalType });
address.timeTable.intervalKey = interval.key;
});
}
return state;
},
[c.PROFILE_MASTER_SERVICES_SET]: (state, { payload: { masterServices, masterCardId } }) => {
const masterCard = find(state.profile.masterCards, { id: masterCardId });
masterCard.masterServices = groupServices(masterServices, state.dictionaries);
masterCard.status.masterServicesUploaded = true;
return state;
},
}));
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Actions } from 'react-native-router-flux';
import {
setDay,
setItemById,
toggleDeparture,
toggleExtension,
toggleManicure,
togglePedicure,
toggleService,
toggleWithdrawal,
} from '../../actions/Search';
import SearchForm from '../../components/SearchForm/SearchForm';
import NavBar from '../../components/NavBar';
const mapStateToProps = (state, ownProps) => ({
...state.searchForm,
leftButtonMenu: true,
sceneKey: ownProps.currentScene || state.scene.sceneKey,
});
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators({
onSearchLocation: Actions.masterLocation,
setDay,
setItemById,
toggleDeparture,
toggleExtension,
toggleManicure,
togglePedicure,
toggleService,
toggleWithdrawal,
}, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(NavBar(SearchForm));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment