diff --git a/.eslintrc b/.eslintrc index ed04c54..4bcbb4e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,8 +5,8 @@ "prettier/react" ], "rules": { - "react/prop-types": ["error", { "ignore": ["imageUri","onPress","children","style","predefinedStyle", "logger", "focused", "navigation","logout", "value","loggedIn","userToken","showActionSheetWithOptions", "MessagesKey", "initialsValue", "isModalVisible", "prevIsModalVisible", "initialsValue","toastRef", "myClasses", - "myClassesLookup"] }], + "react/prop-types": ["error", { "ignore": ["renderItem","isLoading","imageUri","onPress","children","style","predefinedStyle", "logger", "focused", "navigation","logout", "value","loggedIn","userToken","showActionSheetWithOptions", "MessagesKey", "initialsValue", "isModalVisible", "prevIsModalVisible", "initialsValue","toastRef", "myClasses", + "myClassesLookup","isFocused"] }], "no-fallthrough": "off", "jsx-a11y/anchor-is-valid": "off", "react/jsx-props-no-spreading": "off", diff --git a/App/Components/Calendar/Calendar.js b/App/Components/Calendar/Calendar.js index 62edd2e..482cc7a 100644 --- a/App/Components/Calendar/Calendar.js +++ b/App/Components/Calendar/Calendar.js @@ -162,7 +162,7 @@ class Calendar extends React.Component { return ( {this.renderDatePicker()} - + { + const { classHubHeaderHeight } = this.state; + const headerHub = classHubHeaderHeight.interpolate({ + inputRange: [ + toBaseDesignPx(297), + toBaseDesignPx(297) * 2, + toBaseDesignPx(297) * 3, + toBaseDesignPx(297) * 4, + ], + outputRange: [ + toBaseDesignPx(297), + toBaseDesignPx(297) / 2, + toBaseDesignPx(297) / 3, + constants.DEVICE.STATUS_BAR_HEIGHT, + ], + extrapolate: 'clamp', + useNativeDriver: true, + }); + + const headerHubOpacity = classHubHeaderHeight.interpolate({ + inputRange: [ + toBaseDesignPx(297), + toBaseDesignPx(297) * 2, + toBaseDesignPx(297) * 3, + toBaseDesignPx(297) * 4, + ], + outputRange: [OPACITY_VALUE, OPACITY_VALUE / 2, OPACITY_VALUE / 4, 0], + extrapolate: 'clamp', + useNativeDriver: true, + }); + return { headerHub, headerHubOpacity }; + }; + renderHeaderHub = () => { const { onBackArrowPress, @@ -23,8 +65,13 @@ class ClassHub extends React.PureComponent { subjectSection, subjectRoom, } = this.props; + const headerHubTransitions = this.handleInterpolateHeaderHub(); + const { headerHub, headerHubOpacity } = headerHubTransitions; + return ( - + - + ); }; @@ -123,10 +170,12 @@ class ClassHub extends React.PureComponent { }; renderRecentPosts = () => { + const { classHubHeaderHeight } = this.state; + const { posts, isFetchingPost, onRefreshPosts } = this.props; return ( - item.id} ListEmptyComponent={this.renderPostsEmpty} ItemSeparatorComponent={() => } + ListFooterComponent={() => } + onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: classHubHeaderHeight } } }])} /> ); }; diff --git a/App/Components/ClassInfoCard/ClassInfoCard.js b/App/Components/ClassInfoCard/ClassInfoCard.js index 5957c8d..b57a4b0 100644 --- a/App/Components/ClassInfoCard/ClassInfoCard.js +++ b/App/Components/ClassInfoCard/ClassInfoCard.js @@ -17,13 +17,14 @@ class ClassInfoCard extends React.Component { }; render() { - const { subject, schedule, onPress, disabled, titleStyle } = this.props; + const { subject, schedule, onPress, disabled, titleStyle, isLoading } = this.props; return ( diff --git a/App/Components/ClassInfoCard/ClassInfoCardLoadingState.js b/App/Components/ClassInfoCard/ClassInfoCardLoadingState.js new file mode 100644 index 0000000..8432f52 --- /dev/null +++ b/App/Components/ClassInfoCard/ClassInfoCardLoadingState.js @@ -0,0 +1,15 @@ +import React from 'react'; + +import InfoCard from '../Common/InfoCard'; + +class ClassInfoCardLoadingState extends React.Component { + renderClassInfoCardLoadingState = () => { + return ; + }; + + render() { + return this.renderClassInfoCardLoadingState(); + } +} + +export default ClassInfoCardLoadingState; diff --git a/App/Components/ClassInfoCard/index.js b/App/Components/ClassInfoCard/index.js index f5f8304..83719a9 100644 --- a/App/Components/ClassInfoCard/index.js +++ b/App/Components/ClassInfoCard/index.js @@ -1,3 +1,4 @@ import ClassInfoCard from './ClassInfoCard'; +import ClassInfoCardLoadingState from './ClassInfoCardLoadingState'; -export default ClassInfoCard; +export { ClassInfoCard as default, ClassInfoCardLoadingState }; diff --git a/App/Components/Common/Avatar/Avatar.js b/App/Components/Common/Avatar/Avatar.js index 940ac1d..2aaca65 100644 --- a/App/Components/Common/Avatar/Avatar.js +++ b/App/Components/Common/Avatar/Avatar.js @@ -12,7 +12,7 @@ import Text from '../Text'; class Avatar extends React.Component { renderAvatar = () => { - const { src, uri, initialsText, style, textStyle } = this.props; + const { src, uri, initialsText, style, textStyle, textBorderStyle } = this.props; if (src || uri) { return ( @@ -21,7 +21,10 @@ class Avatar extends React.Component { } return ( - + @@ -43,9 +46,14 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, + textBorderStyle: { + height: toBaseDesignPx(110), + width: toBaseDesignPx(110), + borderRadius: toBaseDesignPx(100), + }, textViewStyle: { - width: toBaseDesignPx(94), - height: toBaseDesignPx(94), + width: toBaseDesignPx(110), + height: toBaseDesignPx(110), alignItems: 'center', justifyContent: 'center', ...spacers.MR_0, @@ -55,7 +63,7 @@ const styles = StyleSheet.create({ }, textStyle: { color: colors.GRAY, - fontSize: RFValue(48), + fontSize: RFValue(40), textAlign: 'center', ...spacers.ML_1, ...spacers.MT_1, @@ -72,6 +80,7 @@ Avatar.defaultProps = { initialsText: null, style: null, textStyle: null, + textBorderStyle: null, }; Avatar.propTypes = { @@ -80,6 +89,7 @@ Avatar.propTypes = { initialsText: PropTypes.string, style: ViewPropTypes.style, textStyle: PropTypes.shape({}), + textBorderStyle: PropTypes.shape({}), }; export default Avatar; diff --git a/App/Components/Common/CalendarDatePicker/CalendarDatePicker.js b/App/Components/Common/CalendarDatePicker/CalendarDatePicker.js index fe2de26..85faece 100644 --- a/App/Components/Common/CalendarDatePicker/CalendarDatePicker.js +++ b/App/Components/Common/CalendarDatePicker/CalendarDatePicker.js @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import { StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import CalendarStrip from 'react-native-calendar-strip'; +import 'moment/locale/es'; // import CalendarStrip from 'react-native-slideable-calendar-strip'; import Moment from 'moment'; diff --git a/App/Components/Common/DropDown/DropDown.js b/App/Components/Common/DropDown/DropDown.js index f89db09..c76bd9d 100644 --- a/App/Components/Common/DropDown/DropDown.js +++ b/App/Components/Common/DropDown/DropDown.js @@ -1,3 +1,4 @@ +/* eslint-disable react/destructuring-assignment */ import React from 'react'; import { View, ViewPropTypes, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; @@ -14,21 +15,8 @@ import InLineComponent from '../InLineComponent'; import Icon, { ICON_TYPE, ICON_SIZE } from '../Icon'; class DropDownComponent extends React.Component { - constructor(props) { - super(props); - this.state = { - value: null, - }; - } - - componentDidMount() { - const { value } = this.props; - this.setState({ value }); - } - handleOptionChange = value => { const { onChange } = this.props; - this.setState({ value }); onChange(value); }; @@ -112,8 +100,16 @@ class DropDownComponent extends React.Component { }; render() { - const { style, placeholder, options, disabled, containerStyle, hasError, ...rest } = this.props; - const { value: valueFromState } = this.state; + const { + style, + placeholder, + options, + disabled, + containerStyle, + hasError, + value, + ...rest + } = this.props; const errorStyle = hasError ? styles.errorStyle : null; return ( @@ -134,7 +130,7 @@ class DropDownComponent extends React.Component { right: 15, }, }} - value={valueFromState} + value={value} useNativeAndroidPickerStyle={false} Icon={() => this.renderIcon()} {...rest} diff --git a/App/Components/Common/InfoCard/InfoCard.js b/App/Components/Common/InfoCard/InfoCard.js index 8448b1f..30ccafa 100644 --- a/App/Components/Common/InfoCard/InfoCard.js +++ b/App/Components/Common/InfoCard/InfoCard.js @@ -8,6 +8,7 @@ import { colors, toBaseDesignPx, spacers } from '../../../Core/Theme'; // Common import Text from '../Text'; +import InfoCardLoadingState from './InfoCardLoadingState'; class InfoCard extends React.Component { handleOnPress = () => { @@ -21,7 +22,12 @@ class InfoCard extends React.Component { }; render() { - const { children, title, style, titleStyle, disabled } = this.props; + const { children, title, style, titleStyle, disabled, isLoading } = this.props; + + if (isLoading) { + return ; + } + return ( {children} diff --git a/App/Components/Common/InfoCard/InfoCardLoadingState.js b/App/Components/Common/InfoCard/InfoCardLoadingState.js new file mode 100644 index 0000000..c65b467 --- /dev/null +++ b/App/Components/Common/InfoCard/InfoCardLoadingState.js @@ -0,0 +1,32 @@ +import React from 'react'; +import SvgAnimatedLinearGradient from 'react-native-svg-animated-linear-gradient'; + +import { Rect } from 'react-native-svg'; + +import { toBaseDesignPx, constants } from '../../../Core/Theme'; + +class SectionLoadingState extends React.Component { + renderSectionLoadingState = () => { + return ( + + + + ); + }; + + render() { + if (constants.isAndroid) { + return null; + } + return this.renderSectionLoadingState(); + } +} + +export default SectionLoadingState; diff --git a/App/Components/Common/InfoCard/index.js b/App/Components/Common/InfoCard/index.js index efe4fb6..a580f4b 100644 --- a/App/Components/Common/InfoCard/index.js +++ b/App/Components/Common/InfoCard/index.js @@ -1,3 +1,4 @@ import InfoCard from './InfoCard'; +import InfoCardLoadingState from './InfoCardLoadingState'; -export default InfoCard; +export { InfoCard as default, InfoCardLoadingState }; diff --git a/App/Components/Common/Link/Link.js b/App/Components/Common/Link/Link.js index 55f2629..a3f5dce 100644 --- a/App/Components/Common/Link/Link.js +++ b/App/Components/Common/Link/Link.js @@ -46,7 +46,7 @@ class Link extends React.Component { return ( - + ); diff --git a/App/Components/EventCalendar/EventCalendar.js b/App/Components/EventCalendar/EventCalendar.js index 6b3c97a..d3a105e 100644 --- a/App/Components/EventCalendar/EventCalendar.js +++ b/App/Components/EventCalendar/EventCalendar.js @@ -54,6 +54,7 @@ class EventCalendar extends React.Component { initialsText={initialsText} style={styles.avatarStyle} textStyle={styles.avatarTextStyle} + textBorderStyle={styles.textBorderStyle} /> { + return ( + + + + ); + }; + + render() { + if (constants.isAndroid) { + return null; + } + + return this.renderEventCalendarLoadingState(); + } +} + +export default EventCalendarLoadingState; diff --git a/App/Components/EventCalendar/index.js b/App/Components/EventCalendar/index.js index 9814769..c7b6852 100644 --- a/App/Components/EventCalendar/index.js +++ b/App/Components/EventCalendar/index.js @@ -1,3 +1,4 @@ import EventCalendar from './EventCalendar'; +import EventCalendarLoadingState from './EventCalendarLoadingState'; -export default EventCalendar; +export { EventCalendar as default, EventCalendarLoadingState }; diff --git a/App/Components/FileInput/FileInput.js b/App/Components/FileInput/FileInput.js index 964dff3..59cd724 100644 --- a/App/Components/FileInput/FileInput.js +++ b/App/Components/FileInput/FileInput.js @@ -11,6 +11,7 @@ import { fonts, colors, toBaseDesignPx, spacers } from '../../Core/Theme'; // Common import Text from '../Common/Text'; +import TextInput from '../Common/TextInput'; import InLineComponent from '../Common/InLineComponent'; import Icon, { ICON_TYPE, ICON_SIZE } from '../Common/Icon'; @@ -31,6 +32,7 @@ class FileInput extends React.Component { super(props); this.state = { value: [], + text: '', }; } @@ -56,7 +58,7 @@ class FileInput extends React.Component { }; pickDocument = async () => { - const { value } = this.state; + const { value, text } = this.state; const { onChange } = this.props; const newData = value; @@ -66,20 +68,24 @@ class FileInput extends React.Component { const nameseparator = name.split('.'); const [resultName, resultExtension] = nameseparator; - const index = newData.findIndex(x => x.name === resultName); + const index = newData.findIndex(x => x.fileURL === uri); if (index < 0) { const item = {}; item.id = null; item.name = name; item.fileURL = uri; + item.title = name; item.type = mime.lookup(resultExtension); item.extension = resultExtension; item.alias = resultName; + if (text.trim().length > 0) { + item.title = text.trim(); + item.extension = ''; + item.alias = text.trim(); + } newData.push(item); - this.setState({ value: newData }); + this.setState({ value: newData, text: '' }); onChange(newData); - } else { - // TO-DO documento repetido } }; @@ -88,7 +94,7 @@ class FileInput extends React.Component { const { onChange } = this.props; const newData = value; - const index = newData.findIndex(x => x.uri === id); + const index = newData.findIndex(x => x.fileURL === id); newData.splice(index, 1); this.setState({ value: newData }); @@ -147,13 +153,36 @@ class FileInput extends React.Component { render() { const { style, disabled, containerStyle, hasError } = this.props; - const { value } = this.state; + const { value, text } = this.state; const errorStyle = hasError ? styles.errorStyle : null; if (disabled) return null; return ( {this.renderLabel()} - + + this.setState({ text: txt })} + containerStyle={{ + borderBottomWidth: 0, + flex: 1, + }} + /> + + + + + + {}} ref={ref => { @@ -164,8 +193,8 @@ class FileInput extends React.Component { renderItem={({ item }) => { return ( @@ -176,14 +205,6 @@ class FileInput extends React.Component { extraData={this.state} showsHorizontalScrollIndicator={false} /> - - - ); diff --git a/App/Components/FileInput/FilePill.js b/App/Components/FileInput/FilePill.js index bb32229..33b388f 100644 --- a/App/Components/FileInput/FilePill.js +++ b/App/Components/FileInput/FilePill.js @@ -10,19 +10,20 @@ import { colors } from '../../Core/Theme'; import Text from '../Common/Text'; -const MAXLENGTH = 12; +const MAXLENGTH = 10; class FilePill extends React.Component { - trimText = () => { - const { documentType, documentText } = this.props; - - if (documentType && documentText.length > MAXLENGTH) { - return `${documentText.substring(0, MAXLENGTH)}...${documentType}`; + trimText = (text, type) => { + if (type && text.length > MAXLENGTH) { + return `${text.substring(0, MAXLENGTH)}...${type}`; + } + if (text.length > MAXLENGTH) { + return `${text.substring(0, MAXLENGTH)}...`; } - if (documentText.length > MAXLENGTH) { - return `${documentText.substring(0, MAXLENGTH)}...`; + if (type) { + return `${text.substring(0, MAXLENGTH)}.${type}`; } - return `${documentText}`; + return `${text.substring(0, MAXLENGTH)}`; }; handlePress = () => { @@ -31,10 +32,13 @@ class FilePill extends React.Component { }; render() { - const text = this.trimText(); + const { documentText, documentType } = this.props; + const text = this.trimText(documentText, documentType); return ( - + + + @@ -54,7 +58,7 @@ const styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', - maxWidth: 160, + maxWidth: 180, opacity: 0.7, }, closeContainer: { diff --git a/App/Components/Home/Home.js b/App/Components/Home/Home.js index 0820971..1f4d02c 100644 --- a/App/Components/Home/Home.js +++ b/App/Components/Home/Home.js @@ -11,7 +11,9 @@ import Section from '../Common/Section'; import LoadingState from '../LoadingState'; import Link from '../Common/Link'; import Event from '../SwipeableEventCalendar'; +import { EventCalendarLoadingState } from '../EventCalendar'; import Subject from '../SubjectCalendar'; +import LoadingList from '../LoadingList'; class Home extends React.Component { renderTodayTitle = () => { @@ -40,7 +42,7 @@ class Home extends React.Component { - + @@ -66,6 +68,10 @@ class Home extends React.Component { ); }; + renderEventCalendarLoadingState = item => { + return ; + }; + renderListEvents = () => { const { events } = this.props; @@ -117,7 +123,16 @@ class Home extends React.Component { }; renderEvents = () => { - const { events, subjects, onMyCalendarPress } = this.props; + const { events, subjects, onMyCalendarPress, isLoading } = this.props; + + if (isLoading) { + return ( + } + /> + ); + } if (Lodash.isEmpty(events) && Lodash.isEmpty(subjects)) { return ( @@ -142,7 +157,7 @@ class Home extends React.Component { }; render() { - const { renderSubjects, refreshing, onRefresh } = this.props; + const { renderSubjects, refreshing, onRefresh, isLoading } = this.props; return (
@@ -156,6 +171,7 @@ class Home extends React.Component {
} >
{this.renderEvents()}
diff --git a/App/Components/LoadingList/LoadingList.js b/App/Components/LoadingList/LoadingList.js new file mode 100644 index 0000000..79753d9 --- /dev/null +++ b/App/Components/LoadingList/LoadingList.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { FlatList } from 'react-native'; + +class LoadingList extends React.Component { + constructor(props) { + super(props); + this.state = { + data: [1, 2, 3, 4], + }; + } + + render() { + const { data } = this.state; + const { renderItem } = this.props; + + return ( + item} {...this.props} /> + ); + } +} + +export default LoadingList; diff --git a/App/Components/LoadingList/index.js b/App/Components/LoadingList/index.js new file mode 100644 index 0000000..f67ac9a --- /dev/null +++ b/App/Components/LoadingList/index.js @@ -0,0 +1,3 @@ +import LoadingList from './LoadingList'; + +export default LoadingList; diff --git a/App/Components/LoadingState/LoadingState.js b/App/Components/LoadingState/LoadingState.js index fe4a6c8..432bd2d 100644 --- a/App/Components/LoadingState/LoadingState.js +++ b/App/Components/LoadingState/LoadingState.js @@ -14,7 +14,9 @@ const SOURCE_ANIMATION_EMPTY_BOX = require('../../Core/Assets/Animations/emptyBo class LoadingState extends React.Component { componentDidMount() { - this.animation.play(); + if (this.animation) { + this.animation.play(); + } } getSize = () => { @@ -60,21 +62,30 @@ class LoadingState extends React.Component { render() { const loaderStyle = this.getSize(); const animationSrc = this.getAnimationSource(); + const { withoutLottie } = this.props; + + if (withoutLottie) { + return null; + } + return ; } } const LoadingStateModal = props => { - const { isVisible } = props; + const { isVisible, withoutLottie } = props; + const styleWithoutLottie = withoutLottie ? { backgroundColor: colors.TRANSPARENT } : null; + return ( - - + + ); @@ -87,6 +98,7 @@ const BaseLoadingState = { Modal: objProps => , NoEvents: objProps => , Empty: objProps => , + withoutLottie: objProps => , }; const styles = StyleSheet.create({ @@ -113,20 +125,24 @@ LoadingState.defaultProps = { size: null, noEventToday: false, isEmpty: false, + withoutLottie: false, }; LoadingState.propTypes = { size: PropTypes.string, noEventToday: PropTypes.bool, isEmpty: PropTypes.bool, + withoutLottie: PropTypes.bool, }; LoadingStateModal.defaultProps = { isVisible: false, + withoutLottie: false, }; LoadingStateModal.propTypes = { isVisible: PropTypes.bool, + withoutLottie: PropTypes.bool, }; export default BaseLoadingState; diff --git a/App/Components/Login/LoginForm.js b/App/Components/Login/LoginForm.js index 5287fc4..04e87d7 100644 --- a/App/Components/Login/LoginForm.js +++ b/App/Components/Login/LoginForm.js @@ -58,6 +58,8 @@ class LoginForm extends Component { }; renderForm = objForm => { + const { isLoading } = this.props; + return ( @@ -72,6 +74,7 @@ class LoginForm extends Component { onSubmitEditing={() => { this.passwordInput.focus(); }} + disabled={isLoading} /> { @@ -82,6 +85,7 @@ class LoginForm extends Component { containerStyle={styles.input} returnKeyType="done" secureTextEntry + disabled={isLoading} />