diff --git a/App.js b/App.js
index d19757c..57f9f55 100644
--- a/App.js
+++ b/App.js
@@ -10,6 +10,7 @@ export default class App extends React.Component {
+
)
}
}
diff --git a/actions/index.js b/actions/index.js
index 38170a1..2aa48db 100644
--- a/actions/index.js
+++ b/actions/index.js
@@ -3,6 +3,26 @@ import types from '../lib/actionTypes'
let actions = {
// GENERAL
+ enrollStudent: (student, courseId) => {
+ return {
+ type: types.ENROLL_STUDENT,
+ student,
+ courseId,
+ }
+ },
+ unenrollStudent: (studentId, courseId) => {
+ return {
+ type: types.UNENROLL_STUDENT,
+ studentId,
+ courseId,
+ }
+ },
+ updateLocale: (locale) => {
+ return {
+ type: types.UPDATE_LOCALE,
+ locale
+ }
+ },
receiveStandardError: (error) => {
return {
type: types.RECEIVE_STANDARD_ERROR,
@@ -71,6 +91,44 @@ let actions = {
courseId
}
},
+ updateStudentAttendanceStats: (attendances, curAttendances, courseId) => {
+ return {
+ type: types.UPDATE_STUDENT_ATTENDANCE_STATS,
+ attendances,
+ curAttendances,
+ courseId
+ }
+ },
+
+ // Sessions
+ requestSessions: (courseId) => {
+ return {
+ type: types.REQUEST_SESSIONS,
+ courseId
+ }
+ },
+ receiveSessionsSuccess: (sessions, courseId) => {
+ return {
+ type: types.RECEIVE_SESSIONS_SUCCESS,
+ sessions,
+ courseId
+ }
+ },
+
+ // Course Teachers
+ requestCourseTeachers: (courseId) => {
+ return {
+ type: types.REQUEST_COURSE_TEACHERS,
+ courseId
+ }
+ },
+ receiveCourseTeachersSuccess: (courseTeachers, courseId) => {
+ return {
+ type: types.RECEIVE_COURSE_TEACHERS_SUCCESS,
+ courseTeachers,
+ courseId
+ }
+ },
// ATTENDANCES
requestAttendances: (courseId, date) => {
diff --git a/components/AttendanceCard/AttendanceCard.js b/components/AttendanceCard/AttendanceCard.js
index 328d350..207bd8b 100644
--- a/components/AttendanceCard/AttendanceCard.js
+++ b/components/AttendanceCard/AttendanceCard.js
@@ -2,6 +2,7 @@ import React from 'react';
import { Image, View, Text, StyleSheet, Button, TouchableHighlight } from 'react-native';
import styles from './styles'
import Dropdown from '../Dropdown'
+import PropTypes from 'prop-types'
import { textStyles } from '../../styles/textStyles';
class AttendanceCard extends React.Component {
@@ -57,7 +58,7 @@ class AttendanceCard extends React.Component {
source={require('../../icons/comment_active.png')}
/>
)
- }
+ }
return (
{this.props.name}
-
-
-
- {this.renderSelect()}
- this.props.setModal(this.props.index, this.props.attendance.comment)}
- underlayColor='transparent'>
- {this.renderCommentButton(this.props.attendance.comment)}
-
+
+
+
+ {this.renderSelect()}
+ this.props.setModal(this.props.attendance.comment)}
+ underlayColor='transparent'>
+ {this.renderCommentButton(this.props.attendance.comment)}
+
+
)
@@ -89,11 +91,11 @@ class AttendanceCard extends React.Component {
}
AttendanceCard.propTypes = {
- attendance: React.PropTypes.object.isRequired,
- name: React.PropTypes.string.isRequired,
- index: React.PropTypes.number.isRequired,
- setModal: React.PropTypes.func.isRequired,
- setType: React.PropTypes.func.isRequired,
+ attendance: PropTypes.object.isRequired,
+ name: PropTypes.string.isRequired,
+ index: PropTypes.number.isRequired,
+ setModal: PropTypes.func.isRequired,
+ setType: PropTypes.func.isRequired,
};
export default AttendanceCard;
diff --git a/components/AttendanceCard/styles.js b/components/AttendanceCard/styles.js
index dff0ad3..0aa82d7 100644
--- a/components/AttendanceCard/styles.js
+++ b/components/AttendanceCard/styles.js
@@ -3,25 +3,32 @@ import { StyleSheet } from 'react-native';
export default StyleSheet.create({
container: {
flexDirection: 'row',
+ flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 24,
},
nameContainer: {
flexDirection: 'row',
- flex: 1,
+ flex: 0.5,
},
spaceContainer:{
- flex: 0.1,
+ flex: 0.01,
+ },
+ leftOuterContainer: {
+ flex: 0.49,
},
leftContainer: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 16,
- flex: 1,
},
attendanceButton: {
- width: 116,
+ width: 100,
+ height: 40,
+ },
+ attendanceContainer: {
+ width: 100,
height: 40,
},
commentButton: {
diff --git a/components/Button/Button.js b/components/Button/Button.js
index 46b46a0..6ca8b94 100644
--- a/components/Button/Button.js
+++ b/components/Button/Button.js
@@ -24,12 +24,12 @@ export default class StyledButton extends React.Component {
>{this.props.text}
);
}
- if (this.props.noPaddingPrimaryButtonSmall) {
+ if (this.props.editButton) {
return (
);
}
@@ -38,7 +38,7 @@ export default class StyledButton extends React.Component {
);
}
@@ -65,7 +65,7 @@ export default class StyledButton extends React.Component {
);
}
diff --git a/components/Button/styles.js b/components/Button/styles.js
index f845496..8400e5c 100644
--- a/components/Button/styles.js
+++ b/components/Button/styles.js
@@ -22,13 +22,13 @@ const buttonStyles = StyleSheet.create({
marginBottom: 8,
},
- noPaddingPrimaryButtonSmall: {
- backgroundColor: colors.primaryYellow,
- borderColor: colors.primaryYellow,
+ editButton: {
+ backgroundColor: '#CFD8DC',
+ borderColor: '#CFD8DC',
width: 85,
- height: 37,
+ height: 32,
marginLeft: 10,
- marginBottom: -10,
+ marginBottom: 0,
},
clearButtonSmall: {
@@ -74,7 +74,7 @@ const buttonStyles = StyleSheet.create({
enrollSmall: {
backgroundColor: colors.courseBlue,
borderColor: colors.courseBlue,
- width: 140,
+ width: 120,
height: 36,
},
diff --git a/components/Collapse/Collapse.js b/components/Collapse/Collapse.js
index 7639ce8..0d9d1ee 100644
--- a/components/Collapse/Collapse.js
+++ b/components/Collapse/Collapse.js
@@ -2,6 +2,7 @@ import React from 'react';
import { View, TouchableHighlight } from 'react-native';
import { commonStyles } from '../../styles/styles';
import styles from './styles';
+import PropTypes from 'prop-types'
import Collapsible from 'react-native-collapsible';
class Collapse extends React.Component {
@@ -24,10 +25,10 @@ class Collapse extends React.Component {
Collapse.propTypes = {
- setCollapsed: React.PropTypes.func.isRequired,
- header: React.PropTypes.object.isRequired,
- isCollapsed: React.PropTypes.bool.isRequired,
- headerStyle: React.PropTypes.object,
+ setCollapsed: PropTypes.func.isRequired,
+ header: PropTypes.object.isRequired,
+ isCollapsed: PropTypes.bool.isRequired,
+ headerStyle: PropTypes.object,
};
export default Collapse;
diff --git a/components/CourseCard/CourseCard.js b/components/CourseCard/CourseCard.js
index ff12473..cd4ea0d 100644
--- a/components/CourseCard/CourseCard.js
+++ b/components/CourseCard/CourseCard.js
@@ -6,6 +6,9 @@ import PropTypes from 'prop-types';
import { cardStyles } from './styles';
import { textStyles } from '../../styles/textStyles';
import colors from '../../styles/colors';
+import { FontAwesome } from '@expo/vector-icons';
+import I18n from '../../lib/i18n/i18n';
+
/**
* @prop course_id - course ID
@@ -29,20 +32,26 @@ class CourseCard extends React.Component {
4: colors.courseBrown
}
const colorKey = this.props.index % 5
- let syncText = this.props.synced ? "" : "Not Synced"
+ const unsyncedAttendances = (
+
+ {I18n.t('unsyncedattendances', {locale: this.props.locale})}
+
+ )
+ let syncText = this.props.synced ? (I18n.t('lastsynced', {locale: this.props.locale}) + ": " + this.props.last_synced) : unsyncedAttendances
return (
this.props.onSelectCourse(this.props.course_id, colorKey)}
underlayColor='transparent'>
{this.props.title}
- {this.props.numStudents} Students
+ 5 {I18n.t('students', {locale: this.props.locale})}
{syncText}
+
this.props.onTakeAttendance(this.props.course_id, this.props.title)}
- text='Take Attendance'
+ text={I18n.t('takeattendance', {locale: this.props.locale})}
clearButtonSmall>
diff --git a/components/CourseCard/styles.js b/components/CourseCard/styles.js
index 44d454b..0a7e81d 100644
--- a/components/CourseCard/styles.js
+++ b/components/CourseCard/styles.js
@@ -9,7 +9,9 @@ const cardStyles = StyleSheet.create({
},
topContainer: {
flex: 1,
- height: 100,
+ // height: 100,
+ paddingRight: 8,
+ paddingBottom: 8,
backgroundColor: 'transparent'
},
bottomContainer: {
diff --git a/components/Dropdown/Dropdown.js b/components/Dropdown/Dropdown.js
index 660fa01..ccb6d52 100644
--- a/components/Dropdown/Dropdown.js
+++ b/components/Dropdown/Dropdown.js
@@ -2,6 +2,7 @@ import React from 'react';
import { View, Text, StyleSheet, Button, TextInput, Modal, TouchableHighlight } from 'react-native';
import { Select, Option } from 'react-native-chooser';
import styles from './styles';
+import PropTypes from 'prop-types'
import { textStyles } from '../../styles/textStyles';
class Dropdown extends React.Component {
@@ -57,11 +58,11 @@ class Dropdown extends React.Component {
}
Dropdown.propTypes = {
- onSelect: React.PropTypes.func.isRequired,
- value: React.PropTypes.any.isRequired,
- options: React.PropTypes.object.isRequired,
- defaultText: React.PropTypes.string.isRequired,
- styles: React.PropTypes.object,
+ onSelect: PropTypes.func.isRequired,
+ value: PropTypes.any.isRequired,
+ options: PropTypes.object.isRequired,
+ defaultText: PropTypes.string.isRequired,
+ styles: PropTypes.object,
};
export default Dropdown;
diff --git a/components/SearchResultCard/SearchResultCard.js b/components/SearchResultCard/SearchResultCard.js
index 9984f08..0a42fac 100644
--- a/components/SearchResultCard/SearchResultCard.js
+++ b/components/SearchResultCard/SearchResultCard.js
@@ -19,7 +19,7 @@ class SearchResultCard extends React.Component {
render() {
return (
- this.props.onSelectStudent(this.props.student.id)}
+ this.props.onSelectStudent(this.props.student)}
underlayColor='transparent'>
{ navigation.navigate('TeacherProfile') }}>
-
),
headerStyle: {},
headerTintColor: '',
+ gesturesEnabled: false,
}),
},
TeacherProfile : {
screen: TeacherProfileScreen,
navigationOptions: ({navigation}) => ({
headerTitle: 'Profile',
- headerRight: ( { navigation.navigate('EditTeacherProfile') }}>
),
@@ -89,6 +90,11 @@ export const HomeStack = StackNavigator({
screen: EditCourseScreen,
navigationOptions: {
headerTitle: 'Edit Course',
+ headerStyle: {
+ backgroundColor: '#f5f5f6',
+ borderBottomColor: 'transparent',
+ },
+ headerTintColor: colors.textDark,
},
},
StudentProfile : {
@@ -112,7 +118,6 @@ export const HomeStack = StackNavigator({
screen: AttendanceSummaryScreen,
navigationOptions: ({navigation}) => ({
headerTitle: 'Attendance Summary',
- headerRight: (
this.props.navigation.navigate('StudentPersonalDetails',
- { refreshStudents: this.props.navigation.state.params.refreshStudents,
- course_id: this.state.course_id,
+ { course_id: this.state.course_id,
navbarColor: this.state.navbarColor,
newStudent: true })}
text="+ Create Student"
@@ -88,17 +87,7 @@ class SearchStudentResultScreen extends React.Component {
}
render() {
- let results;
- if (this.props.isLoading) {
- results = (
-
- )
- } else {
- results = this._renderSearchResults();
- }
+ results = this._renderSearchResults();
return (
diff --git a/screens/students/SearchStudentScreen.js b/screens/students/SearchStudentScreen.js
index 68b939c..ef891b4 100644
--- a/screens/students/SearchStudentScreen.js
+++ b/screens/students/SearchStudentScreen.js
@@ -27,9 +27,9 @@ class SearchStudentScreen extends React.Component {
this.setState({students: responseData});
this.props.navigation.navigate('SearchStudentResults', {
students: responseData,
- refreshStudents: this.props.navigation.state.params.refreshStudents,
- course_id: this.state.course_id,
+ course_id: this.state.course_id,
navbarColor: this.state.navbarColor,
+ parentKey: this.props.navigation.state.key,
})
}
getRequest(APIRoutes.searchStudentPath(), successFunc, standardError, params=params);
@@ -43,9 +43,10 @@ class SearchStudentScreen extends React.Component {
this.props.navigation.navigate('StudentPersonalDetails',
- { refreshStudents: this.props.navigation.state.params.refreshStudents,
+ {
course_id: this.state.course_id,
navbarColor: this.state.navbarColor,
+ parentKey: this.props.navigation.state.key,
newStudent: true })}
text="+ Create Student"
secondaryButtonLarge
diff --git a/screens/students/StudentContactInfoScreen.js b/screens/students/StudentContactInfoScreen.js
index ca43b50..78dec89 100644
--- a/screens/students/StudentContactInfoScreen.js
+++ b/screens/students/StudentContactInfoScreen.js
@@ -15,7 +15,8 @@ class StudentContactInfoScreen extends React.Component {
course_id: this.props.navigation.state.params.course_id,
navbarColor: this.props.navigation.state.params.navbarColor,
newStudent: this.props.navigation.state.params.newStudent,
- savedFields: this.props.navigation.state.params.savedFields
+ savedFields: this.props.navigation.state.params.savedFields,
+ parentKey: this.props.navigation.state.params.parentKey,
}
}
@@ -29,7 +30,7 @@ class StudentContactInfoScreen extends React.Component {
navbarColor: this.state.navbarColor,
});
}
- putRequest(APIRoutes.getStudentPath(studentId),
+ putRequest(APIRoutes.getStudentPath(studentId),
successFunc, standardError, params=params);
}
@@ -41,7 +42,7 @@ class StudentContactInfoScreen extends React.Component {
navbarColor: this.state.navbarColor,
newStudent: this.state.newStudent,
savedFields: joined,
- refreshStudents: this.props.navigation.state.params.refreshStudents,
+ parentKey: this.state.parentKey,
});
}
@@ -67,7 +68,7 @@ class StudentContactInfoScreen extends React.Component {
phone_2={navProps.phone_2}
email={navProps.email}
newStudent={this.state.newStudent}
- onSaveStudent={this._handleUpdateStudent}
+ onSaveStudent={this._handleUpdateStudent}
/>
)
diff --git a/screens/students/StudentExtraInfoScreen.js b/screens/students/StudentExtraInfoScreen.js
index c2f31e4..fbc7814 100644
--- a/screens/students/StudentExtraInfoScreen.js
+++ b/screens/students/StudentExtraInfoScreen.js
@@ -2,9 +2,11 @@ import React from 'react';
import { View } from 'react-native';
import { APIRoutes } from '../../config/routes';
import { postRequest, putRequest } from '../../lib/requests';
-import { standardError } from '../../lib/alerts';
+import { standardError, alert } from '../../lib/alerts';
import PropTypes from 'prop-types';
import StudentExtraInfoForm from '../../components/Form/StudentExtraInfoForm';
+import { connect } from 'react-redux';
+import actions from '../../actions';
class StudentExtraInfoScreen extends React.Component {
constructor(props) {
@@ -15,7 +17,8 @@ class StudentExtraInfoScreen extends React.Component {
course_id: this.props.navigation.state.params.course_id,
navbarColor: this.props.navigation.state.params.navbarColor,
newStudent: this.props.navigation.state.params.newStudent,
- savedFields: this.props.navigation.state.params.savedFields
+ savedFields: this.props.navigation.state.params.savedFields,
+ parentKey: this.props.navigation.state.params.parentKey,
}
}
@@ -23,23 +26,23 @@ class StudentExtraInfoScreen extends React.Component {
const studentId = this.props.navigation.state.params.student.id;
const successFunc = (responseData) => {
this.props.navigation.navigate('StudentProfile', {
- refreshStudents: this.props.navigation.state.params.refreshStudents,
studentId: studentId,
courseId: this.state.course_id,
navbarColor: this.state.navbarColor,
});
}
- putRequest(APIRoutes.getStudentPath(studentId),
+ putRequest(APIRoutes.getStudentPath(studentId),
successFunc, standardError, params=params);
}
_handleEnrollStudent(student) {
const successFunc = (responseData) => {
- this.props.navigation.state.params.refreshStudents();
- this.props.navigation.navigate('ViewCourse', {
- course_id: this.state.course_id,
+ this.props.enrollStudent(this.state.student, this.state.course_id)
+ this.props.navigation.navigate('ViewCourse', {
+ courseId: this.state.course_id,
navbarColor: this.state.navbarColor,
});
+ alert("Success!", "Student Successfully Enrolled")
}
const p = {
@@ -80,7 +83,7 @@ class StudentExtraInfoScreen extends React.Component {
primary_language={navProps.primary_language}
past_dream_participant={navProps.past_dream_participant}
newStudent={this.state.newStudent}
- onSaveStudent={this._handleUpdateStudent}
+ onSaveStudent={this._handleUpdateStudent}
/>
)
@@ -88,4 +91,10 @@ class StudentExtraInfoScreen extends React.Component {
}
}
-export default StudentExtraInfoScreen;
+const mapDispatchToProps = (dispatch) => {
+ return {
+ enrollStudent: (student, courseId) => dispatch(actions.enrollStudent(student, courseId)),
+ }
+}
+
+export default connect(null, mapDispatchToProps)(StudentExtraInfoScreen);
diff --git a/screens/students/StudentPersonalDetailsScreen.js b/screens/students/StudentPersonalDetailsScreen.js
index 3ea7528..fd0bc0d 100644
--- a/screens/students/StudentPersonalDetailsScreen.js
+++ b/screens/students/StudentPersonalDetailsScreen.js
@@ -15,6 +15,7 @@ class StudentPersonalDetailsScreen extends React.Component {
course_id: this.props.navigation.state.params.course_id,
newStudent: this.props.navigation.state.params.newStudent,
navbarColor: this.props.navigation.state.params.navbarColor,
+ parentKey: this.props.navigation.state.params.parentKey,
}
}
@@ -22,13 +23,12 @@ class StudentPersonalDetailsScreen extends React.Component {
const studentId = this.props.navigation.state.params.student.id;
const successFunc = (responseData) => {
this.props.navigation.navigate('StudentProfile', {
- refreshStudents: this.props.navigation.state.params.refreshStudents,
studentId: studentId,
courseId: this.state.course_id,
navbarColor: this.state.navbarColor,
});
}
- putRequest(APIRoutes.getStudentPath(studentId),
+ putRequest(APIRoutes.getStudentPath(studentId),
successFunc, standardError, params=params);
}
@@ -38,7 +38,7 @@ class StudentPersonalDetailsScreen extends React.Component {
navbarColor: this.state.navbarColor,
newStudent: this.state.newStudent,
savedFields: params,
- refreshStudents: this.props.navigation.state.params.refreshStudents,
+ parentKey: this.state.parentKey,
});
}
@@ -63,7 +63,7 @@ class StudentPersonalDetailsScreen extends React.Component {
is_active={navProps.is_active}
sex={navProps.sex}
newStudent={this.state.newStudent}
- onSaveStudent={this._handleUpdateStudent}
+ onSaveStudent={this._handleUpdateStudent}
/>
)
diff --git a/screens/students/StudentProfilePreviewScreen.js b/screens/students/StudentProfilePreviewScreen.js
index d6ae32b..2937ddb 100644
--- a/screens/students/StudentProfilePreviewScreen.js
+++ b/screens/students/StudentProfilePreviewScreen.js
@@ -6,56 +6,50 @@ import { colors } from '../../styles/colors';
import { getRequest, deleteRequest, postRequest } from '../../lib/requests';
import { APIRoutes } from '../../config/routes';
import { formViewStyles } from '../../styles/formViewStyles';
-import { standardError } from '../../lib/alerts';
+import { frontendError, alert } from '../../lib/alerts';
import {formStyles} from "../../components/Form/styles";
import StyledButton from '../../components/Button/Button';
+import { connect } from 'react-redux';
+import actions from '../../actions';
+
+
class StudentProfilePreviewScreen extends React.Component {
constructor(props) {
super(props);
this._renderStudent = this._renderStudent.bind(this);
- this._fetchStudent = this._fetchStudent.bind(this);
this._handleEnrollStudent = this._handleEnrollStudent.bind(this);
+ //THis state updating is 100% for convenience tbh. bad practice
this.state = {
- isLoading : true,
- studentId: this.props.navigation.state.params.studentId,
+ student: this.props.navigation.state.params.student,
course_id: this.props.navigation.state.params.course_id,
navbarColor: this.props.navigation.state.params.navbarColor,
- student: { }
+ parentKey: this.props.navigation.state.params.parentKey,
}
}
_handleEnrollStudent() {
+ if(this.props.studentIds.includes(this.state.student.id)) {
+ console.log("Student is already enrolled");
+ frontendError("This student is already enrolled.");
+ this.props.navigation.goBack(this.state.parentKey)
+ return;
+ }
const successFunc = (responseData) => {
- this.props.navigation.state.params.refreshStudents();
- this.props.navigation.navigate('ViewCourse', {
- course_id: this.state.course_id,
- navbarColor: this.state.navbarColor,
- });
+ alert("Success!", "Student Successfully Enrolled")
+ this.props.navigation.goBack(this.state.parentKey)
}
const p = {
- student_id: this.state.studentId,
+ student_id: this.state.student.id,
course_id: this.state.course_id
}
-
- postRequest(APIRoutes.getCoursesStudentsPath(), successFunc, standardError, params=p);
- }
-
- componentDidMount() {
- this._fetchStudent(this.state.studentId);
- }
-
- _fetchStudent(studentId) {
- const { navigate } = this.props.navigation;
- const successFunc = (responseData) => {
- this.setState({ student: responseData, isLoading: false });
- }
-
- getRequest(APIRoutes.getStudentPath(studentId), successFunc, standardError);
+ this.props.enrollStudent(this.state.student, this.state.course_id)
+ //TODO: What if this post request fails? Add graceful failing!
+ postRequest(APIRoutes.getCoursesStudentsPath(), successFunc, () => frontendError("Student Enrollment Failed"), params=p);
}
_renderStudent() {
@@ -122,17 +116,7 @@ class StudentProfilePreviewScreen extends React.Component {
render() {
const { navigate } = this.props.navigation;
- let students;
- if (this.state.isLoading) {
- student = (
-
- )
- } else {
- student = this._renderStudent()
- }
+ student = this._renderStudent()
return (
{ student }
@@ -148,4 +132,19 @@ const viewStyles = StyleSheet.create({
},
});
-export default StudentProfilePreviewScreen;
+const mapStateToProps = (state, props) => {
+ // Get course and date associated with this attendance screen
+ const course = state.courses.find((course) => course.id === props.navigation.state.params.course_id);
+ return {
+ ...props.navigation.state.params,
+ studentIds: course.students.map((student) => {return student.id}),
+ };
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ enrollStudent: (student, courseId) => dispatch(actions.enrollStudent(student, courseId)),
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(StudentProfilePreviewScreen);
diff --git a/screens/students/StudentProfileScreen.js b/screens/students/StudentProfileScreen.js
index c3330ba..33428a3 100644
--- a/screens/students/StudentProfileScreen.js
+++ b/screens/students/StudentProfileScreen.js
@@ -1,296 +1,321 @@
import React from 'react';
-import { Image, Button, Text, View, ScrollView } from 'react-native';
+import { Image, Button, Text, View, ScrollView, StyleSheet} from 'react-native';
import { textStyles } from '../../styles/textStyles';
import { commonStyles } from '../../styles/styles';
-import { colors } from '../../styles/colors';
+import colors from '../../styles/colors';
import { getRequest, deleteRequest, putRequest } from '../../lib/requests';
import { APIRoutes } from '../../config/routes';
import { formViewStyles } from '../../styles/formViewStyles';
import { standardError, confirmDelete } from '../../lib/alerts';
import StyledButton from '../../components/Button/Button';
+import { connect } from 'react-redux';
+import actions from '../../actions';
+
+
class StudentProfileScreen extends React.Component {
constructor(props) {
super(props);
this._renderStudent = this._renderStudent.bind(this);
- this._fetchStudent = this._fetchStudent.bind(this);
this._handleUpdateStudent = this._handleUpdateStudent.bind(this);
this._deleteEnrollment = this._deleteEnrollment.bind(this);
-
- this.state = {
- student : { },
- isLoading : true,
- studentId: this.props.navigation.state.params.studentId,
- courseId: this.props.navigation.state.params.courseId,
- navbarColor: this.props.navigation.state.params.navbarColor
- }
- }
-
- componentDidMount() {
- this._fetchStudent(this.state.studentId);
}
- _fetchStudent(studentId) {
- const { navigate } = this.props.navigation;
- const successFunc = (responseData) => {
- this.setState({ student: responseData, isLoading: false });
- }
-
- getRequest(APIRoutes.getStudentPath(studentId), successFunc, standardError);
+ calculatePercentages(attendance_stats) {
+ const total = attendance_stats.num_present + attendance_stats.num_late + attendance_stats.num_absent;
+ // var present = (attendance_stats.num_present / total) * 100;
+ // var late = (attendance_stats.num_late / total) * 100;
+ // var absent = (attendance_stats.num_absent / total) * 100;
+ var present = `${attendance_stats.num_present} / ${total}`
+ var late = `${attendance_stats.num_late} / ${total}`
+ var absent = `${attendance_stats.num_absent} / ${total}`
+ // return {present: present.toFixed(1), late: late.toFixed(1), absent: absent.toFixed(1)};
+ return {present: present, late: late, absent: absent};
}
_deleteEnrollment() {
var params = {
- student_id: this.state.studentId,
- course_id: this.state.courseId
+ student_id: this.props.student.id,
+ course_id: this.props.courseId
}
const successFunc = (responseData) => {
- // this.props.navigation.state.params.refreshStudents();
- this.props.navigation.navigate('ViewCourse', {
- course_id: this.state.courseId,
- navbarColor: this.state.navbarColor
- });
+ this.props.unenrollStudent(this.props.student.id, this.props.courseId);
+ this.props.navigation.goBack();
}
+ //TODO: What happens if this function fails. Are we still offline first? HAndle this!!!
deleteRequest(APIRoutes.getCoursesStudentsPath(), successFunc, standardError, params=params);
}
_handleUpdateStudent(params) {
const successFunc = (responseData) => {
- // this.props.navigation.state.params.refreshStudent();
+ this.props.navigation.state.params.refreshStudent();
this.props.navigation.navigate('Courses');
}
- putRequest(APIRoutes.getStudentPath(this.state.studentId), successFunc, standardError, params=params);
+ putRequest(APIRoutes.getStudentPath(this.props.student.id), successFunc, standardError, params=params);
}
- _renderStudent() {
- const { navigate } = this.props.navigation;
- return(
-
-
-
-
- {this.state.student.first_name} {this.state.student.last_name} - {this.state.student.dream_id}
-
-
-
-
-
-
- Personal Information
-
-
- navigate('StudentPersonalDetails', {
- refreshStudent: this._fetchStudent(this.state.studentId),
- newStudent: false,
- student: this.state.student,
- navbarColor: this.state.navbarColor
- })}
- text='Edit'
- noPaddingPrimaryButtonSmall
- />
-
-
-
-
-
-
-
- Nickname
-
-
- {this.state.student.nickname}
-
-
-
-
-
- Birthday
-
-
- {this.state.student.birthday}
-
-
-
-
-
- Active Participant?
-
-
- {this.state.student.is_active}
-
-
-
-
-
- Sex
-
-
- {this.state.student.sex}
-
-
-
-
-
-
- Contact Information
-
-
- navigate('StudentContactInfo', {
- refreshStudent: this._fetchStudent(this.state.studentId),
- newStudent: false,
- student: this.state.student,
- navbarColor: this.state.navbarColor})}
- text='Edit'
- noPaddingPrimaryButtonSmall
- />
-
-
-
+ _renderAttendanceStats() {
+ if(!this.props.student || !this.props.student.attendance_stats) {
+ return;
+ }
+ const attendanceStats = this.calculatePercentages(this.props.student.attendance_stats)
+ return (
+
+
+
+ {attendanceStats.present}
+ Present
+
+
+
+ {attendanceStats.absent}
+ Absent
+
+
+
+ {attendanceStats.late}
+ Late
+
+
+
+ )
-
-
- Address
-
-
- {this.state.student.address}
-
-
+ }
-
-
- Phone Numbers
-
-
- {this.state.student.phone} {"\n"}
- {this.state.student.phone_2}
-
+ _renderPersonalInfo() {
+ return (
+
+
+
+
+ Personal Information
+
+
+
+
+
-
-
- Name on Facebook
-
-
- {this.state.student.facebook_name}
-
-
+
+
+ Birthday
+
+
+ {this.props.student.birthday}
+
+
-
-
- Email Address
-
-
- {this.state.student.email}
-
-
+
+
+ Active Participant?
+
+
+ {this.props.student.is_active}
+
+
-
-
- Primary Contact Name
-
-
- {this.state.student.primary_contact}
-
-
-
-
-
- Primary Contact Phone Number
-
-
- {this.state.student.primary_contact_phone}
-
-
+
+
+ Sex
+
+
+ {this.props.student.sex}
+
+
+
+ )
+ }
-
-
+ _renderContactInfo() {
+ return(
+
+
+
- Extra Information
+ Contact Information
navigate('StudentExtraInfo', {
- refreshStudent: this._fetchStudent(this.state.studentId),
- newStudent: false,
- student: this.state.student,
- navbarColor: this.state.navbarColor})}
text='Edit'
- noPaddingPrimaryButtonSmall
+ editButton
/>
-
+
-
-
- Notes
-
-
- {this.state.student.notes}
-
-
+
+
+ Address
+
+
+ {this.props.student.address}
+
+
-
-
- Level (Montessori Only)
-
-
- {this.state.student.level}
-
-
+
+
+ Phone Numbers
+
+
+ {this.props.student.phone} {"\n"}
+ {this.props.student.phone_2}
+
+
-
-
- Primary Language
-
-
- {this.state.student.primary_language}
-
-
+
+
+ Name on Facebook
+
+
+ {this.props.student.facebook_name}
+
+
-
-
- Document Type
-
-
- {this.state.student.document_type}
-
+
+
+ Email Address
+
+
+ {this.props.student.email}
+
+
+
+
+
+ Primary Contact Name
+
+
+ {this.props.student.primary_contact}
+
+
+
+
+
+ Primary Contact Phone Number
+
+
+ {this.props.student.primary_contact_phone}
+
+
+
+ )
+ }
+
+ _renderExtraInfo() {
+ return(
+
+
+
+
+ Extra Information
+
+
+
+
+
+
+
+
+ Notes
+
+
+ {this.props.student.notes}
+
+
+
+
+
+ Level (Montessori Only)
+
+
+ {this.props.student.level}
+
+
+
+
+
+ Primary Language
+
+
+ {this.props.student.primary_language}
+
+
+
+
+
+ Document Type
+
+
+ {this.props.student.document_type}
+
+
+
+
+
+ Participated in DREAM before?
+
+
+ {this.props.student.past_dream_participant}
+
+
+
+ )
+ }
+
+ _renderStudent() {
+ const { navigate } = this.props.navigation;
+ if (!this.props.student ) {
+ return;
+ }
+ attendance_stats = this._renderAttendanceStats()
+ personal_info = this._renderPersonalInfo()
+ contact_info = this._renderContactInfo()
+ extra_info = this._renderExtraInfo()
-
-
- Participated in DREAM before?
-
-
- {this.state.student.past_dream_participant}
-
+ return(
+
+
+
+
+
+ {this.props.student.first_name} {this.props.student.last_name}
+
+
+ {this.props.student.nickname}
+
+
+
-
-
);
}
render() {
const { navigate } = this.props.navigation;
- let students;
- if (this.state.isLoading) {
- student = (
-
- )
- } else {
- student = this._renderStudent()
- }
+ student = this._renderStudent()
return (
{ student }
@@ -299,4 +324,34 @@ class StudentProfileScreen extends React.Component {
}
}
-export default StudentProfileScreen;
+const mapStateToProps = (state, props) => {
+ // Get course and date associated with this attendance screen
+ const course = state.courses.find((course) => course.id === props.navigation.state.params.courseId);
+ console.log('state.courses');
+ console.log(state.courses);
+ console.log('courseID');
+ console.log(props.navigation.state.params.courseId);
+ console.log('course.students');
+ console.log(course.students);
+ const student = course.students.find((student) => student.id === props.navigation.state.params.studentId);
+ return {
+ ...props.navigation.state.params,
+ student: student,
+ };
+}
+
+const viewStyles = StyleSheet.create({
+ outer: {
+ margin: 24,
+ marginBottom: 8
+ },
+})
+
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ unenrollStudent: (studentId, courseId) => dispatch(actions.unenrollStudent(studentId, courseId)),
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(StudentProfileScreen);
diff --git a/screens/teachers/TeacherProfileScreen.js b/screens/teachers/TeacherProfileScreen.js
index 5f5fafc..4f8d8f2 100644
--- a/screens/teachers/TeacherProfileScreen.js
+++ b/screens/teachers/TeacherProfileScreen.js
@@ -3,6 +3,7 @@ import { Image, Button, Text, View, ScrollView } from 'react-native';
import { connect } from 'react-redux';
import actions from '../../actions';
+import I18n from '../../lib/i18n/i18n';
import { colors } from '../../styles/colors';
import { textStyles } from '../../styles/textStyles';
@@ -42,7 +43,7 @@ class TeacherProfileScreen extends React.Component {
- Dream ID
+ {I18n.t('dreamid', {locale: this.props.locale})}
{this.props.teacher.dream_id}
@@ -51,7 +52,7 @@ class TeacherProfileScreen extends React.Component {
- Email
+ {I18n.t('email', {locale: this.props.locale})}
{this.props.teacher.email}
@@ -60,16 +61,29 @@ class TeacherProfileScreen extends React.Component {
- Phone Number
+ {I18n.t('phonenumber', {locale: this.props.locale})}
{this.props.teacher.phone}
-
+
+
+
+ {I18n.t('currentlanguage', {locale: this.props.locale})}
+
+
+ {this.props.locale == "en" ? "English" : "Español"}
+
+
+ this.props.updateLocale(this.props.locale == "en" ? "es" : "en")}
+ text={I18n.t('changelanguage', {locale: this.props.locale})}
+ linkButton
+ />
@@ -115,15 +129,23 @@ const fetchTeacher = (teacher) => {
}
}
+const updateLocale = (locale) => {
+ return (dispatch) => {
+ dispatch(actions.updateLocale(locale));
+ }
+}
+
const mapStateToProps = (state) => {
return {
teacher: state.teacher,
- isLoading: state.isLoading.value,
+ isLoading: state.config.isLoading,
+ locale: state.config.locale,
};
}
const mapDispatchToProps = (dispatch) => {
return {
+ updateLocale: (locale) => dispatch(updateLocale(locale)),
fetchTeacher: (teacher) => dispatch(fetchTeacher(teacher)),
logout: () => dispatch(actions.logout()),
}
diff --git a/styles/styles.js b/styles/styles.js
index 939a16a..f8807b7 100644
--- a/styles/styles.js
+++ b/styles/styles.js
@@ -24,7 +24,7 @@ const commonStyles = StyleSheet.create({
alignSelf: 'center',
},
divider: {
- borderBottomWidth: 1,
+ borderBottomWidth: 1,
borderBottomColor: '#E6E6E6'
}
});