瀏覽代碼

everythin is updated part 2

dmr1725 4 年之前
父節點
當前提交
42510c1fea

+ 1
- 1
Miupi Parser/Comunicaciones.json
文件差異過大導致無法顯示
查看文件


+ 1
- 1
client/.gitignore 查看文件

@@ -10,4 +10,4 @@ npm-debug.*
10 10
 web-build/
11 11
 
12 12
 # macOS
13
-.DS_Store
13
+.DS_Store

+ 135
- 96
client/App.js 查看文件

@@ -1,113 +1,152 @@
1
+// import { StatusBar } from 'expo-status-bar';
2
+// import React, {useState} from 'react';
3
+// import { StyleSheet, Text, View } from 'react-native';
4
+// import * as Google from "expo-google-app-auth";
5
+// import {SocialIcon, socialIcon} from 'react-native-elements'
6
+// import {createDrawerNavigator} from '@react-navigation/drawer'
7
+// import { NavigationContainer } from '@react-navigation/native';
8
+// import * as SecureStore from 'expo-secure-store';
9
+
10
+// import HomeScreen from './Screens/HomeScreen'
11
+// import NotificationsScreen from './Screens/NotificationScreen'
12
+// import SettingScreen from './Screens/SettingScreen'
13
+// import AddTakenCourse from './Screens/AddTakenCourse'
14
+// import MyCurriculum from './Screens/MyCurriculum'
15
+// import EnrollNextSemester from './Screens/EnrollNextSemester'
16
+
17
+
18
+// const Drawer = createDrawerNavigator()
19
+
20
+// const IOS_CLIENT_ID =
21
+//   "116415331974-tf6sehooctplmmn7j0gt831mdf1oqipl.apps.googleusercontent.com";
22
+
23
+// export default function App() {
24
+//   const [hasToken, setHasToken] = useState(false)
25
+  
26
+//   const signInWithGoogle = async ()=>{
27
+//     try {
28
+//       const result = await Google.logInAsync({
29
+//         iosClientId: IOS_CLIENT_ID,
30
+//         scopes: ["profile", "email"]
31
+//       })
32
+
33
+//       if (result.type == "success"){
34
+//         console.log(result.accessToken)
35
+
36
+//         try {
37
+//           // login user in backend
38
+//           let response = await fetch('http://5ce95b6ddcbd.ngrok.io/rest-auth/google/', {
39
+//             method: 'POST',
40
+//             headers: {
41
+//               'content-type': 'application/json'
42
+//             }, 
43
+//             body: JSON.stringify({
44
+//               access_token: `${result.accessToken}`
45
+//             })
46
+//           })
47
+
48
+//           // storing our token
49
+//           let responseJson = await response.json()
50
+//           if (responseJson){
51
+//             if (responseJson.key){
52
+//               await SecureStore.setItemAsync('token', responseJson.key)
53
+//             }
54
+//           }
55
+
56
+//           const token = await SecureStore.getItemAsync('token')
57
+
58
+//           // storing our id
59
+//           let id = await fetch('http://5ce95b6ddcbd.ngrok.io/api/get_user_id', {
60
+//             method: 'GET',
61
+//             headers: {
62
+//               'content-type': 'application/json',
63
+//               Authorization: `Token ${token}`
64
+//             }
65
+//           })
66
+//           let idJson = await id.json()
67
+//           if (idJson){
68
+//             if(idJson.user_id){
69
+//               idJson = idJson.user_id
70
+//               let id = idJson.toString()
71
+//               await SecureStore.setItemAsync('id', id)
72
+//             }
73
+//           }
74
+
75
+//         } catch(error){
76
+//           console.log(error)
77
+//         }
78
+
79
+//         setHasToken(true) // update states and redirect
80
+//       }
81
+
82
+//       else {
83
+//         console.log("no")
84
+//       }
85
+//     } catch(error){
86
+//       console.log(error)
87
+//     }
88
+//   }
89
+//   if (!hasToken){
90
+//     return (
91
+//       <View style={styles.container}>
92
+//         <SocialIcon title="Login With Google" button={true} type={"google"} onPress={signInWithGoogle}/>
93
+//       </View>
94
+//     );
95
+//   }
96
+
97
+//   return (
98
+//     <NavigationContainer>
99
+//         <Drawer.Navigator initialRouteName="Home">
100
+//           <Drawer.Screen name="Home" component={HomeScreen}/>
101
+//           <Drawer.Screen name="Notifications" component={NotificationsScreen} />
102
+//           <Drawer.Screen name="Settings" component={SettingScreen} />
103
+//           <Drawer.Screen name="Add Taken Courses" component={AddTakenCourse} />
104
+//           <Drawer.Screen name="My Curriculum" component={MyCurriculum} />
105
+//           <Drawer.Screen name="Enroll Next Semester" component={EnrollNextSemester} />
106
+
107
+//         </Drawer.Navigator>
108
+//     </NavigationContainer>
109
+//   )
110
+  
111
+// }
112
+
113
+// const styles = StyleSheet.create({
114
+//   container: {
115
+//     flex: 1,
116
+//     backgroundColor: '#fff',
117
+//     alignItems: 'center',
118
+//     justifyContent: 'center',
119
+//   },
120
+// });
1 121
 import { StatusBar } from 'expo-status-bar';
2 122
 import React, {useState} from 'react';
3
-import { StyleSheet, Text, View, Platform } from 'react-native';
123
+import { StyleSheet, Text, View } from 'react-native';
4 124
 import * as Google from "expo-google-app-auth";
5 125
 import {SocialIcon, socialIcon} from 'react-native-elements'
6 126
 import {createDrawerNavigator} from '@react-navigation/drawer'
7 127
 import { NavigationContainer } from '@react-navigation/native';
128
+import { createStackNavigator } from '@react-navigation/stack';
8 129
 import * as SecureStore from 'expo-secure-store';
9 130
 
10
-import HomeScreen from './Screens/HomeScreen'
11
-import NotificationsScreen from './Screens/NotificationScreen'
12
-import SettingScreen from './Screens/SettingScreen'
13
-import AddTakenCourse from './Screens/AddTakenCourse'
14
-import MyCurriculum from './Screens/MyCurriculum'
131
+import Login from './Screens/Login'
132
+import Logout from './Screens/Logout'
133
+import HomeScreen from './Screens/HomeScreen';
15 134
 
16
-const Drawer = createDrawerNavigator()
17 135
 
18
-console.log(Platform.OS)
19 136
 
20
-const IOS_CLIENT_ID =
21
-  "116415331974-tf6sehooctplmmn7j0gt831mdf1oqipl.apps.googleusercontent.com";
22 137
 
23
-const ANDROID_CLIENT_ID = 
24
-  "116415331974-72n6g689k4me386dod763gi31vpuh71a.apps.googleusercontent.com";
25
-  // 116415331974-72n6g689k4me386dod763gi31vpuh71a.apps.googleusercontent.com
26 138
 export default function App() {
27
-  const [hasToken, setHasToken] = useState(false)
28
-  
29
-  const signInWithGoogle = async ()=>{
30
-    try {
31
-      const result = await Google.logInAsync({
32
-        iosClientId: IOS_CLIENT_ID,
33
-        androidClientId: ANDROID_CLIENT_ID,
34
-        scopes: ["profile", "email"]
35
-      })
36
-
37
-      if (result.type == "success"){
38
-        console.log(result.accessToken)
39
-
40
-        try {
41
-          // login user in backend
42
-          let response = await fetch('http://8c4029a33a9a.ngrok.io/rest-auth/google/', {
43
-            method: 'POST',
44
-            headers: {
45
-              'content-type': 'application/json'
46
-            }, 
47
-            body: JSON.stringify({
48
-              access_token: `${result.accessToken}`
49
-            })
50
-          })
51
-
52
-          // storing our token
53
-          let responseJson = await response.json()
54
-          if (responseJson){
55
-            if (responseJson.key){
56
-              await SecureStore.setItemAsync('token', responseJson.key)
57
-            }
58
-          }
59
-
60
-          const token = await SecureStore.getItemAsync('token')
61
-
62
-          // storing our id
63
-          let id = await fetch('http://8c4029a33a9a.ngrok.io/api/get_user_id', {
64
-            method: 'GET',
65
-            headers: {
66
-              'content-type': 'application/json',
67
-              Authorization: `Token ${token}`
68
-            }
69
-          })
70
-          let idJson = await id.json()
71
-          if (idJson){
72
-            if(idJson.user_id){
73
-              idJson = idJson.user_id
74
-              let id = idJson.toString()
75
-              await SecureStore.setItemAsync('id', id)
76
-            }
77
-          }
78
-
79
-        } catch(error){
80
-          console.log(error)
81
-        }
82
-
83
-        setHasToken(true) // update states and redirect
84
-      }
85
-
86
-      else {
87
-        console.log("no")
88
-      }
89
-    } catch(error){
90
-      console.log(error)
91
-    }
92
-  }
93
-  if (!hasToken){
94
-    return (
95
-      <View style={styles.container}>
96
-        <SocialIcon title="Login With Google" button={true} type={"google"} onPress={signInWithGoogle}/>
97
-      </View>
98
-    );
99
-  }
100
-
139
+  const Stack = createStackNavigator();
101 140
   return (
102
-    <NavigationContainer>
103
-        <Drawer.Navigator initialRouteName="Home">
104
-          <Drawer.Screen name="Home" component={HomeScreen}/>
105
-          <Drawer.Screen name="Notifications" component={NotificationsScreen} />
106
-          <Drawer.Screen name="Settings" component={SettingScreen} />
107
-          <Drawer.Screen name="Add Taken Courses" component={AddTakenCourse} />
108
-          <Drawer.Screen name="My Curriculum" component={MyCurriculum} />
109
-        </Drawer.Navigator>
110
-    </NavigationContainer>
141
+   <NavigationContainer>
142
+      <Stack.Navigator
143
+        screenOptions={{headerShown: false}}
144
+        initialRouteName = "Login"
145
+    >
146
+        <Stack.Screen name = "Login" component={Login}/>
147
+        <Stack.Screen name = "Logout" component={Logout}/>
148
+     </Stack.Navigator>
149
+   </NavigationContainer>
111 150
   )
112 151
   
113 152
 }

+ 12
- 6
client/Screens/AddTakenCourse.js 查看文件

@@ -1,6 +1,6 @@
1 1
 import axios from "axios";
2 2
 import React, { useState } from "react";
3
-import { FlatList, StatusBar, StyleSheet, Text, TouchableOpacity, TextInput, View, Button, ActivityIndicator } from "react-native";
3
+import { FlatList, StatusBar, StyleSheet, Text, TouchableOpacity, TextInput, View, Button, ActivityIndicator, Alert } from "react-native";
4 4
 import * as SecureStore from 'expo-secure-store';
5 5
 import Modal from 'react-native-modal';
6 6
 import {Picker} from '@react-native-community/picker';
@@ -38,6 +38,7 @@ const AddTakenCourse = () => {
38 38
 
39 39
   const toggle = ()=>{
40 40
     setModalVisible(!modalVisible)
41
+    setSelectedId(null)
41 42
   }
42 43
 
43 44
   const addCourse = async ()=>{
@@ -51,7 +52,7 @@ const AddTakenCourse = () => {
51 52
 
52 53
       let response = await axios({
53 54
         method: 'POST',
54
-        url: 'http://8c4029a33a9a.ngrok.io/api/add_taken_course',
55
+        url: 'http://da0406585426.ngrok.io/api/add_taken_course',
55 56
         headers: {
56 57
           'content-type': 'application/json',
57 58
           Authorization: `Token ${token}`
@@ -65,7 +66,7 @@ const AddTakenCourse = () => {
65 66
         }
66 67
       })
67 68
 
68
-      console.log(response.data)
69
+      console.log(response.data.msg)
69 70
 
70 71
       setAnimating(true)
71 72
 
@@ -73,8 +74,14 @@ const AddTakenCourse = () => {
73 74
         setAnimating(false)
74 75
         setModalVisible(false)
75 76
         setSelectedId(null)
76
-        setData([])
77
+        setData([]) // courses will disappear because data would be empty
77 78
       }, 3000)
79
+
80
+      setTimeout(()=>{
81
+        Alert.alert(response.data.msg)
82
+     }, 5000)
83
+
84
+
78 85
   }
79 86
 
80 87
 
@@ -85,7 +92,7 @@ const AddTakenCourse = () => {
85 92
       const token = await SecureStore.getItemAsync('token')
86 93
       const response = await axios({
87 94
           method: 'GET',
88
-          url: `http://8c4029a33a9a.ngrok.io/api/find_course?code=${text}`,
95
+          url: `http://da0406585426.ngrok.io/api/find_course?code=${text}`,
89 96
           headers: {
90 97
             'content-type': 'application/json',
91 98
             Authorization: `Token ${token}`
@@ -172,7 +179,6 @@ const AddTakenCourse = () => {
172 179
                     onValueChange={(itemValue, itemIndex) => setSemester(itemValue) }>
173 180
                     <Picker.Item label="1" value="1" />
174 181
                     <Picker.Item label="2" value="2" />
175
-                    <Picker.Item label="3" value="3" />
176 182
                 </Picker>
177 183
             </View>
178 184
            <View style={{flex: 1, justifyContent: 'center'}}>

+ 260
- 0
client/Screens/CurrentCourses.js 查看文件

@@ -0,0 +1,260 @@
1
+import React, {useState, useEffect} from 'react';
2
+import { FlatList, StatusBar, StyleSheet, Text, TouchableOpacity, TextInput, View, Button, ActivityIndicator, Alert, ScrollView, RefreshControl } from "react-native";
3
+import axios from 'axios'
4
+import * as SecureStore from 'expo-secure-store';
5
+import Modal from 'react-native-modal';
6
+
7
+const Item = ({ item, onPress, style }) => (
8
+    <TouchableOpacity onPress={onPress} style={[styles.item, style]}>
9
+      <Text style={styles.title}>{`${item.code}`}</Text>
10
+    </TouchableOpacity>
11
+);
12
+  
13
+ // separates results, taken from https://stackoverflow.com/questions/60350768/how-to-make-search-bar-with-dropdown-list-in-react-native
14
+const renderSeparator = () => {
15
+    return (
16
+      <View
17
+        style={{
18
+          height: 1,
19
+          width: '100%',
20
+          backgroundColor: '#CED0CE',
21
+        }}
22
+      />
23
+    );
24
+};
25
+
26
+
27
+
28
+const CurrentCourses = () =>{
29
+    const [courses, setCourses] = useState(null)
30
+    const [refreshing, setRefreshing] = useState(false)
31
+    const [selectedId, setSelectedId] = useState(null); // course_id
32
+    const [animating, setAnimating] = useState('')
33
+    const [modalVisible, setModalVisible] = useState(false)
34
+    const [code, setCode] = useState(null)
35
+    const [days, setDays] = useState(null)
36
+    const [courseName, setCourseName] = useState(null)
37
+    const [prof, setProf] = useState(null)
38
+    const [rooms, setRooms] = useState(null)
39
+    const [section, setSection] = useState(null)
40
+    const [hours, setHours] = useState(null)
41
+    const [year, setYear] = useState(null)
42
+    const [semestre, setSemestre] = useState(null)
43
+
44
+    
45
+    const toggle = ()=>{
46
+        setModalVisible(!modalVisible)
47
+        setSelectedId(null)
48
+    }
49
+
50
+
51
+    const getMyCurrentCourses = async()=>{
52
+        const token = await SecureStore.getItemAsync('token')
53
+        let id = await SecureStore.getItemAsync('id')
54
+        let user_id = parseInt(id)
55
+
56
+        try {
57
+            let response = await axios(`http://da0406585426.ngrok.io/api/get_current_courses`, {
58
+                method: 'POST',
59
+                headers: {
60
+                    'content-type': 'application/json',
61
+                    Authorization: `Token ${token}`
62
+                },
63
+                data:{
64
+                    user_id: user_id
65
+                }
66
+            })
67
+
68
+            
69
+            if(response.data.list){
70
+                setCourses(response.data.list)
71
+            }
72
+            else{
73
+                setCourses(response.data.msg)
74
+            }
75
+             console.log(courses)
76
+           } catch(error){
77
+               console.log(error)
78
+           }
79
+    }
80
+
81
+    const deleteOneCourse = async()=>{
82
+        const token = await SecureStore.getItemAsync('token')
83
+        let id = await SecureStore.getItemAsync('id')
84
+        let user_id = parseInt(id)
85
+        console.log(semestre)
86
+        console.log(year)
87
+
88
+        try {
89
+            let response = await axios(`http://da0406585426.ngrok.io/api/delete_course`, {
90
+                method: 'DELETE',
91
+                headers: {
92
+                    'content-type': 'application/json',
93
+                    Authorization: `Token ${token}`
94
+                },
95
+                data:{
96
+                    user_id: user_id,
97
+                    course_id: selectedId,
98
+                    year: year,
99
+                    semestre: semestre
100
+                }
101
+            })
102
+
103
+            setAnimating(true)
104
+      
105
+            // after 3 seconds, the courses, the modal and the activity indicator will disappear
106
+            setTimeout(()=>{
107
+                setAnimating(false)
108
+                setModalVisible(false)
109
+                setSelectedId(null)
110
+            }, 3000)
111
+
112
+            setTimeout(()=>{
113
+                Alert.alert(response.data.msg)
114
+            }, 5000) 
115
+
116
+            getMyCurrentCourses() // get current courses again
117
+            setSection(null)
118
+            setDays(null)
119
+            setHours(null)
120
+            setRooms(null)
121
+            setProf(null)
122
+            
123
+           
124
+           } catch(error){
125
+               console.log(error)
126
+        }
127
+
128
+    }
129
+
130
+    const onRefresh = React.useCallback(async ()=>{
131
+        setRefreshing(true)
132
+        getMyCurrentCourses()
133
+        setRefreshing(false)
134
+
135
+    }, [refreshing])
136
+
137
+
138
+
139
+
140
+    useEffect(()=>{
141
+        console.log('dimelo')
142
+        getMyCurrentCourses()
143
+    },[])
144
+
145
+    const renderItem = ({ item }) => {
146
+        const backgroundColor = item.id === selectedId ? "#e60505" : "#fafbfc";
147
+        return (
148
+          <Item
149
+            item={item}
150
+            onPress={() => {
151
+              setSelectedId(item.id)
152
+              if(item.section === undefined){
153
+                setCourseName(item.name)
154
+                setCode(item.code)
155
+                setYear(item.year)
156
+                setSemestre(item.semestre)
157
+                setModalVisible(true)
158
+              }
159
+              else{
160
+                setCourseName(item.name)
161
+                setCode(item.code)
162
+                setYear(item.year)
163
+                setSemestre(item.semestre)
164
+                setSection(item.section)
165
+                setDays(item.dias)
166
+                setHours(item.horarios)
167
+                setRooms(item.salones)
168
+                setProf(item.prof)
169
+                setModalVisible(true)
170
+              }
171
+            }}
172
+            style={{ backgroundColor }}
173
+          />
174
+        );
175
+      };
176
+
177
+    // if student does not have courses currently, return this
178
+    if(courses === null || courses === 'No tienes cursos'){
179
+        return (
180
+          <ScrollView
181
+          refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh}/>}
182
+          >
183
+              <Text>No tienes cursos</Text>
184
+          </ScrollView>    
185
+        )
186
+    }
187
+    return (
188
+        <View style={styles.container}>
189
+           <FlatList
190
+                    data={courses}
191
+                    renderItem={renderItem}
192
+                    keyExtractor={(item) => item.id.toString()}
193
+                    extraData={selectedId}
194
+                    ItemSeparatorComponent={renderSeparator}
195
+                    refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh}/>}
196
+            />
197
+            <Modal isVisible={modalVisible} 
198
+            >
199
+            <View style={styles.modalItem}>
200
+                <Text></Text>
201
+                <Text style={styles.course_info}>Name: {courseName}</Text>
202
+                <Text style={styles.course_info}>Code: {code}</Text>
203
+                <Text style={styles.course_info}>{section === null ? '' : 'Section '+ section} </Text>
204
+                <Text style={styles.course_info}>{prof === null ? '' : 'Prof:' + prof} </Text>
205
+                <Text style={styles.course_info}>{days === null ? '' : 'Days: ' + days} </Text>
206
+                <Text style={styles.course_info}>{hours === null ? '' : 'Hours: '+ hours} </Text>
207
+                <Text style={styles.course_info}>{rooms === null ? '' : 'Rooms: ' + rooms} </Text>
208
+                <ActivityIndicator size="small" color="0000ff" animating={animating}/>
209
+                <Button title="Delete Course" onPress={deleteOneCourse}/>
210
+                <Button title="Close" onPress={toggle}/>
211
+            </View>
212
+        </Modal>
213
+            
214
+
215
+        </View>
216
+    );
217
+}
218
+
219
+export default CurrentCourses
220
+
221
+const styles = StyleSheet.create({
222
+    container: {
223
+      flex: 1,
224
+      marginTop: StatusBar.currentHeight || 0,
225
+    },
226
+    item: {
227
+      padding: 10,
228
+      marginVertical: 8,
229
+      marginHorizontal: 16,
230
+    },
231
+    title: {
232
+      fontSize: 15,
233
+    },
234
+    searchBar: {
235
+      height: 40, 
236
+      borderColor: '#000', 
237
+      borderWidth: 1 
238
+    },
239
+    modalItem: {
240
+      // width: '30%', // is 30% of container width
241
+      margin: 60, // 300
242
+      backgroundColor: 'white',
243
+      borderRadius:20,
244
+      height: 270
245
+    },
246
+    course_info: {
247
+        fontWeight: 'bold',
248
+        fontSize: 13
249
+    }
250
+    
251
+  });
252
+
253
+// const styles = StyleSheet.create({
254
+//     container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
255
+//     head: {  height: 40,  backgroundColor: '#e82020'  },
256
+//     wrapper: { flexDirection: 'row' },
257
+//     title: { flex: 1, backgroundColor: '#e82020' },
258
+//     row: {  height: 28  },
259
+//     text: { textAlign: 'center', fontSize:10 },
260
+//   });

+ 268
- 0
client/Screens/EditGrades.js 查看文件

@@ -0,0 +1,268 @@
1
+import React, {useState, useEffect} from 'react';
2
+import { FlatList, StatusBar, StyleSheet, Text, TouchableOpacity, TextInput, View, Button, ActivityIndicator, Alert, ScrollView, RefreshControl } from "react-native";
3
+import axios from 'axios'
4
+import * as SecureStore from 'expo-secure-store';
5
+import Modal from 'react-native-modal';
6
+import {Picker} from '@react-native-community/picker';
7
+
8
+const Item = ({ item, onPress, style }) => (
9
+    <TouchableOpacity onPress={onPress} style={[styles.item, style]}>
10
+      <Text style={styles.title}>{`${item.code}: ${item.grade}`}</Text>
11
+    </TouchableOpacity>
12
+);
13
+  
14
+ // separates results, taken from https://stackoverflow.com/questions/60350768/how-to-make-search-bar-with-dropdown-list-in-react-native
15
+const renderSeparator = () => {
16
+    return (
17
+      <View
18
+        style={{
19
+          height: 1,
20
+          width: '100%',
21
+          backgroundColor: '#CED0CE',
22
+        }}
23
+      />
24
+    );
25
+};
26
+
27
+
28
+
29
+const CurrentCourses = () =>{
30
+    const [courses, setCourses] = useState(null)
31
+    const [refreshing, setRefreshing] = useState(false)
32
+    const [selectedId, setSelectedId] = useState(null); // course_id
33
+    const [animating, setAnimating] = useState('')
34
+    const [modalVisible, setModalVisible] = useState(false)
35
+    const [year, setYear] = useState(null)
36
+    const [semestre, setSemestre] = useState(null)
37
+    const [grade, setGrade] = useState('A')
38
+
39
+    
40
+    const toggle = ()=>{
41
+        setModalVisible(!modalVisible)
42
+        setSelectedId(null)
43
+    }
44
+
45
+
46
+    const getAllMyCourses = async()=>{
47
+        const token = await SecureStore.getItemAsync('token')
48
+        let id = await SecureStore.getItemAsync('id')
49
+        let user_id = parseInt(id)
50
+        console.log(user_id)
51
+
52
+        try {
53
+            let response = await axios(`http://da0406585426.ngrok.io/api/get_all_courses_user_has_taken?user_id=${user_id}`, {
54
+                method: 'GET',
55
+                headers: {
56
+                    'content-type': 'application/json',
57
+                    Authorization: `Token ${token}`
58
+                }
59
+            })
60
+
61
+            // console.log(response.data.list)
62
+            setCourses(response.data.list)
63
+
64
+           } catch(error){
65
+               console.log(error)
66
+           }
67
+    }
68
+
69
+    const deleteOneCourse = async()=>{
70
+        const token = await SecureStore.getItemAsync('token')
71
+        let id = await SecureStore.getItemAsync('id')
72
+        let user_id = parseInt(id)
73
+
74
+        try {
75
+            let response = await axios(`http://da0406585426.ngrok.io/api/delete_course`, {
76
+                method: 'DELETE',
77
+                headers: {
78
+                    'content-type': 'application/json',
79
+                    Authorization: `Token ${token}`
80
+                },
81
+                data:{
82
+                    user_id: user_id,
83
+                    course_id: selectedId,
84
+                    year: year,
85
+                    semestre: semestre
86
+                }
87
+            })
88
+
89
+            setAnimating(true)
90
+      
91
+            // after 3 seconds, the courses, the modal and the activity indicator will disappear
92
+            setTimeout(()=>{
93
+                setAnimating(false)
94
+                setModalVisible(false)
95
+                setSelectedId(null)
96
+            }, 3000)
97
+
98
+            setTimeout(()=>{
99
+                Alert.alert(response.data.msg)
100
+            }, 5000) 
101
+
102
+            getAllMyCourses() // get current courses again
103
+            
104
+            
105
+           
106
+           } catch(error){
107
+               console.log(error)
108
+        }
109
+
110
+    }
111
+
112
+    const updateGrade = async()=>{
113
+        const token = await SecureStore.getItemAsync('token')
114
+        let id = await SecureStore.getItemAsync('id')
115
+        let user_id = parseInt(id)
116
+        console.log(semestre)
117
+        console.log(year)
118
+
119
+        try {
120
+            let response = await axios(`http://da0406585426.ngrok.io/api/update_grade_and_gpa`, {
121
+                method: 'PATCH',
122
+                headers: {
123
+                    'content-type': 'application/json',
124
+                    Authorization: `Token ${token}`
125
+                },
126
+                data:{
127
+                    user_id: user_id,
128
+                    course_id: selectedId,
129
+                    year: year,
130
+                    semestre: semestre,
131
+                    grade: grade
132
+                }
133
+            })
134
+
135
+            setAnimating(true)
136
+      
137
+            // after 3 seconds, the courses, the modal and the activity indicator will disappear
138
+            setTimeout(()=>{
139
+                setAnimating(false)
140
+                setModalVisible(false)
141
+                setSelectedId(null)
142
+            }, 3000)
143
+
144
+            setTimeout(()=>{
145
+                Alert.alert(response.data.msg)
146
+            }, 5000) 
147
+
148
+            getAllMyCourses() // get current courses again
149
+            
150
+            
151
+           
152
+           } catch(error){
153
+               console.log(error)
154
+        }
155
+
156
+    }
157
+
158
+    const onRefresh = React.useCallback(async ()=>{
159
+        setRefreshing(true)
160
+        getAllMyCourses()
161
+        setRefreshing(false)
162
+
163
+    }, [refreshing])
164
+
165
+
166
+
167
+
168
+    useEffect(()=>{
169
+        getAllMyCourses()
170
+    },[])
171
+
172
+    const renderItem = ({ item }) => {
173
+        const backgroundColor = item.course_id === selectedId ? "#e60505" : "#fafbfc";
174
+        return (
175
+          <Item
176
+            item={item}
177
+            onPress={() => {
178
+              setModalVisible(true)
179
+              setSelectedId(item.course_id)
180
+              setYear(item.year)
181
+              setSemestre(item.semestre)
182
+              setGrade(item.grade)
183
+            }}
184
+            style={{ backgroundColor }}
185
+          />
186
+        );
187
+      };
188
+
189
+    // if student does not have courses currently, return this
190
+    if(courses === null || courses.length === 0){
191
+        return (
192
+            <ScrollView
193
+            refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh}/>}
194
+            >
195
+                <Text>No tienes cursos</Text>
196
+            </ScrollView>    
197
+        )
198
+    }
199
+    // console.log(grade)
200
+    return (
201
+        <View style={styles.container}>
202
+           <FlatList
203
+                    data={courses}
204
+                    renderItem={renderItem}
205
+                    keyExtractor={(item) => item.course_id.toString()}
206
+                    extraData={selectedId}
207
+                    ItemSeparatorComponent={renderSeparator}
208
+                    refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh}/>}
209
+            />
210
+            <Modal isVisible={modalVisible} 
211
+            >
212
+            <View style={styles.modalItem}>
213
+                <Button title= "Update grade" onPress={updateGrade} />
214
+                <Picker
215
+                    selectedValue={grade}
216
+                    style={{ width: 50}}
217
+                    onValueChange={(itemValue, itemIndex) => setGrade(itemValue) }>
218
+                    <Picker.Item label="A" value="A" />
219
+                    <Picker.Item label="B" value="B" />
220
+                    <Picker.Item label="C" value="C" />
221
+                    <Picker.Item label="D" value="D" />
222
+                    <Picker.Item label="F" value="F" />
223
+                </Picker>
224
+                <ActivityIndicator size="small" color="0000ff" animating={animating}/>
225
+                <Button title="Delete Course" onPress={deleteOneCourse}/>
226
+                <Button title="Close" onPress={toggle}/>
227
+            </View>
228
+        </Modal>
229
+            
230
+
231
+        </View>
232
+    );
233
+}
234
+
235
+export default CurrentCourses
236
+
237
+const styles = StyleSheet.create({
238
+    container: {
239
+      flex: 1,
240
+      marginTop: StatusBar.currentHeight || 0,
241
+    },
242
+    item: {
243
+      padding: 10,
244
+      marginVertical: 8,
245
+      marginHorizontal: 16,
246
+    },
247
+    title: {
248
+      fontSize: 15,
249
+    },
250
+    searchBar: {
251
+      height: 40, 
252
+      borderColor: '#000', 
253
+      borderWidth: 1 
254
+    },
255
+    modalItem: {
256
+      // width: '30%', // is 30% of container width
257
+      margin: 60, // 300
258
+      backgroundColor: 'white',
259
+      borderRadius:20,
260
+      height: 340
261
+    },
262
+    course_info: {
263
+        fontWeight: 'bold',
264
+        fontSize: 13
265
+    }
266
+    
267
+  });
268
+

+ 205
- 0
client/Screens/EnrollNextSemester.js 查看文件

@@ -0,0 +1,205 @@
1
+import axios from "axios";
2
+import React, { useState } from "react";
3
+import { FlatList, StatusBar, StyleSheet, Text, TouchableOpacity, TextInput, View, Button, ActivityIndicator, Alert } from "react-native";
4
+import * as SecureStore from 'expo-secure-store';
5
+import Modal from 'react-native-modal';
6
+
7
+
8
+const Item = ({ item, onPress, style }) => (
9
+  <TouchableOpacity onPress={onPress} style={[styles.item, style]}>
10
+    <Text style={styles.title}>{`${item.code}-${item.section}`}</Text>
11
+  </TouchableOpacity>
12
+);
13
+
14
+// separates results, taken from https://stackoverflow.com/questions/60350768/how-to-make-search-bar-with-dropdown-list-in-react-native
15
+const renderSeparator = () => {
16
+    return (
17
+      <View
18
+        style={{
19
+          height: 1,
20
+          width: '100%',
21
+          backgroundColor: '#CED0CE',
22
+        }}
23
+      />
24
+    );
25
+};
26
+
27
+
28
+const EnrollNextSemester = () => {
29
+  const [text, setText] = useState('')
30
+  const [selectedId, setSelectedId] = useState(null);
31
+  const [data, setData] = useState([])
32
+  const [modalVisible, setModalVisible] = useState(false)
33
+  const [animating, setAnimating] = useState('')
34
+  const [isSummer, setIsSummer] = useState('false')
35
+  const [code, setCode] = useState('')
36
+  const [creditos, setCreditos] = useState('')
37
+  const [days, setDays] = useState('')
38
+  const [courseName, setCourseName] = useState('')
39
+  const [prof, setProf] = useState('')
40
+  const [rooms, setRooms] = useState('')
41
+  const [section, setSection] = useState('')
42
+  const [hours, setHours] = useState('')
43
+
44
+  const toggle = ()=>{
45
+    setModalVisible(!modalVisible)
46
+    setSelectedId(null)
47
+  }
48
+
49
+  // add course (enroll) to your next semester
50
+  const enrollCourse = async ()=>{
51
+      const token = await SecureStore.getItemAsync('token')
52
+      let id = await SecureStore.getItemAsync('id')
53
+      let user_id = parseInt(id)
54
+
55
+
56
+      let response = await axios({
57
+        method: 'POST',
58
+        url: 'http://da0406585426.ngrok.io/api/matricular_prox_semestre',
59
+        headers: {
60
+          'content-type': 'application/json',
61
+          Authorization: `Token ${token}`
62
+        },
63
+        data: {
64
+          user_id: user_id,
65
+          course_id: selectedId,
66
+          isSummer: isSummer
67
+        }
68
+      })
69
+      console.log(response.data.msg)
70
+    //   setMsg(response.data.msg)
71
+
72
+      setAnimating(true)
73
+      
74
+      // after 3 seconds, the courses, the modal and the activity indicator will disappear
75
+      setTimeout(()=>{
76
+        setAnimating(false)
77
+        setModalVisible(false)
78
+        setSelectedId(null)
79
+        setData([]) // courses will disappear because data would be empty
80
+      }, 3000)
81
+
82
+      setTimeout(()=>{
83
+          Alert.alert(response.data.msg)
84
+      }, 5000)
85
+
86
+  }
87
+
88
+
89
+
90
+  const searchCourses = async(text)=>{
91
+      let courses = []
92
+      setText(text)
93
+      const token = await SecureStore.getItemAsync('token')
94
+      const response = await axios({
95
+          method: 'GET',
96
+          url: `http://da0406585426.ngrok.io/api/select_course_prox_semestre?code=${text}`,
97
+          headers: {
98
+            'content-type': 'application/json',
99
+            Authorization: `Token ${token}`
100
+          }
101
+
102
+      })
103
+      // looping through our response data and creating a course object to append it to the courses array
104
+      response.data.list.map((course)=>{
105
+        let oneCourse = {'id': course.id, 'name': course.name,'code': course.code, 'creditos': course.creditos, 'prof': course.prof, 'section': course.section, 'hours': course.hours, 'days': course.days, 'rooms': course.rooms}
106
+        courses.push(oneCourse)
107
+      })
108
+
109
+      setData(courses)
110
+    //   console.log(courses)
111
+  }
112
+
113
+  const renderItem = ({ item }) => {
114
+    const backgroundColor = item.id === selectedId ? "#e60505" : "#fafbfc";
115
+    return (
116
+      <Item
117
+        item={item}
118
+        onPress={() => {
119
+          setSelectedId(item.id)
120
+          setCourseName(item.name)
121
+          setCode(item.code)
122
+          setCreditos(item.creditos)
123
+          setSection(item.section)
124
+          setDays(item.days)
125
+          setHours(item.hours)
126
+          setRooms(item.rooms)
127
+          setProf(item.prof)
128
+          setModalVisible(true)
129
+        }}
130
+        style={{ backgroundColor }}
131
+      />
132
+    );
133
+  };
134
+
135
+
136
+  return (
137
+    <View style={{flex: 1, padding: 10}}>
138
+       <TextInput
139
+        style={styles.searchBar}
140
+        placeholder="Search for a course that you want to enroll for next semester"
141
+        onChangeText={text=>searchCourses(text)}
142
+        // onChangeText={text=>setText(text)}
143
+      />
144
+      <FlatList
145
+        data={data}
146
+        renderItem={renderItem}
147
+        keyExtractor={(item) => item.id.toString()}
148
+        extraData={selectedId}
149
+        ItemSeparatorComponent={renderSeparator}
150
+      />
151
+      <Modal isVisible={modalVisible} 
152
+        >
153
+            <View style={styles.modalItem}>
154
+                <Text></Text>
155
+                <Text style={styles.course_info}>Name: {courseName}</Text>
156
+                <Text style={styles.course_info}>Code: {code}</Text>
157
+                <Text style={styles.course_info}>Credits: {creditos}</Text>
158
+                <Text style={styles.course_info}>Section: {section}</Text>
159
+                <Text style={styles.course_info}>Prof: {prof}</Text>
160
+                <Text style={styles.course_info}>Days: {days}</Text>
161
+                <Text style={styles.course_info}>Hours: {hours}</Text>
162
+                <Text style={styles.course_info}>Rooms: {rooms}</Text>
163
+                <ActivityIndicator size="small" color="0000ff" animating={animating}/>
164
+                <Button title="Enroll" onPress={enrollCourse}/>
165
+                <Button title="Close" onPress={toggle}/>
166
+            </View>
167
+        </Modal>
168
+    </View>
169
+  );
170
+};
171
+
172
+
173
+const styles = StyleSheet.create({
174
+  container: {
175
+    flex: 1,
176
+    marginTop: StatusBar.currentHeight || 0,
177
+  },
178
+  item: {
179
+    padding: 10,
180
+    marginVertical: 8,
181
+    marginHorizontal: 16,
182
+  },
183
+  title: {
184
+    fontSize: 15,
185
+  },
186
+  searchBar: {
187
+    height: 40, 
188
+    borderColor: '#000', 
189
+    borderWidth: 1 
190
+  },
191
+  modalItem: {
192
+    // width: '30%', // is 30% of container width
193
+    margin: 60, // 300
194
+    backgroundColor: 'white',
195
+    borderRadius:20,
196
+    height: 270
197
+  },
198
+  course_info: {
199
+      fontWeight: 'bold',
200
+      fontSize: 13
201
+  }
202
+  
203
+});
204
+
205
+export default EnrollNextSemester;

+ 3
- 3
client/Screens/HomeScreen.js 查看文件

@@ -2,8 +2,7 @@ import * as React from 'react';
2 2
 import { Button, View } from 'react-native';
3 3
 import * as SecureStore from 'expo-secure-store';
4 4
 import Axios from 'axios';
5
-
6
-
5
+import Logout from './Logout'
7 6
 
8 7
 
9 8
 function HomeScreen({ navigation }) {
@@ -13,7 +12,7 @@ function HomeScreen({ navigation }) {
13 12
     console.log(token, id)
14 13
 
15 14
     let response = await Axios({
16
-      url: 'http://8c4029a33a9a.ngrok.io/api/hello',
15
+      url: 'http://da0406585426.ngrok.io/api/hello',
17 16
       method: 'GET',
18 17
       headers: {
19 18
           Authorization: `Token ${token}`
@@ -27,6 +26,7 @@ function HomeScreen({ navigation }) {
27 26
   
28 27
     return (
29 28
       <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
29
+        {/* <Text>Welcome to Companion App!</Text> */}
30 30
         <Button
31 31
           onPress={() => navigation.navigate('Notifications')}
32 32
           title="Go to notifications"

+ 126
- 0
client/Screens/Login.js 查看文件

@@ -0,0 +1,126 @@
1
+import { StatusBar } from 'expo-status-bar';
2
+import React, {useState} from 'react';
3
+import { StyleSheet, Text, View } from 'react-native';
4
+import * as Google from "expo-google-app-auth";
5
+import {SocialIcon, socialIcon} from 'react-native-elements'
6
+import {createDrawerNavigator} from '@react-navigation/drawer'
7
+import { NavigationContainer } from '@react-navigation/native';
8
+import * as SecureStore from 'expo-secure-store';
9
+
10
+import HomeScreen from './HomeScreen'
11
+import NotificationsScreen from './NotificationScreen'
12
+import SettingScreen from './SettingScreen'
13
+import AddTakenCourse from './AddTakenCourse'
14
+import MyCurriculum from './MyCurriculum'
15
+import EnrollNextSemester from './EnrollNextSemester'
16
+import Logout from './Logout'
17
+import CurrentCourses from './CurrentCourses'
18
+import EditGrades from './EditGrades'
19
+import UpdateSemYear from './UpdateSemYear'
20
+
21
+
22
+const Drawer = createDrawerNavigator()
23
+
24
+const IOS_CLIENT_ID =
25
+  "116415331974-tf6sehooctplmmn7j0gt831mdf1oqipl.apps.googleusercontent.com";
26
+
27
+export default function Login() {
28
+  const [hasToken, setHasToken] = useState(false)
29
+  
30
+  const signInWithGoogle = async ()=>{
31
+    try {
32
+      const result = await Google.logInAsync({
33
+        iosClientId: IOS_CLIENT_ID,
34
+        scopes: ["profile", "email"]
35
+      })
36
+
37
+      if (result.type == "success"){
38
+        console.log(result.accessToken)
39
+
40
+        try {
41
+          // login user in backend
42
+          let response = await fetch('http://da0406585426.ngrok.io/rest-auth/google/', {
43
+            method: 'POST',
44
+            headers: {
45
+              'content-type': 'application/json'
46
+            }, 
47
+            body: JSON.stringify({
48
+              access_token: `${result.accessToken}`
49
+            })
50
+          })
51
+
52
+          // storing our token
53
+          let responseJson = await response.json()
54
+          if (responseJson){
55
+            if (responseJson.key){
56
+              await SecureStore.setItemAsync('token', responseJson.key)
57
+            }
58
+          }
59
+
60
+          const token = await SecureStore.getItemAsync('token')
61
+
62
+          // storing our id
63
+          let id = await fetch('http://da0406585426.ngrok.io/api/get_user_id', {
64
+            method: 'GET',
65
+            headers: {
66
+              'content-type': 'application/json',
67
+              Authorization: `Token ${token}`
68
+            }
69
+          })
70
+          let idJson = await id.json()
71
+          if (idJson){
72
+            if(idJson.user_id){
73
+              idJson = idJson.user_id
74
+              let id = idJson.toString()
75
+              await SecureStore.setItemAsync('id', id)
76
+            }
77
+          }
78
+
79
+        } catch(error){
80
+          console.log(error)
81
+        }
82
+
83
+        setHasToken(true) // update states and redirect
84
+      }
85
+
86
+      else {
87
+        console.log("no")
88
+      }
89
+    } catch(error){
90
+      console.log(error)
91
+    }
92
+  }
93
+  if (!hasToken){
94
+    return (
95
+      <View style={styles.container}>
96
+        <SocialIcon title="Login With Google" button={true} type={"google"} onPress={signInWithGoogle}/>
97
+      </View>
98
+    );
99
+  }
100
+
101
+  return (
102
+    <Drawer.Navigator initialRouteName="Home">
103
+      <Drawer.Screen name="Home" component={HomeScreen}/>
104
+      <Drawer.Screen name="Notifications" component={NotificationsScreen} />
105
+      {/* <Drawer.Screen name="Settings" component={SettingScreen} /> */}
106
+      <Drawer.Screen name="Add Taken Courses" component={AddTakenCourse} />
107
+      <Drawer.Screen name="My Curriculum" component={MyCurriculum} />
108
+      <Drawer.Screen name="Enroll Next Semester" component={EnrollNextSemester} />
109
+      <Drawer.Screen name="Update Grades" component={EditGrades} />
110
+      <Drawer.Screen name="Current Courses" component={CurrentCourses} />
111
+      <Drawer.Screen name="Set your semester and year" component={UpdateSemYear} />
112
+      <Drawer.Screen name="Logout" component={Logout} />
113
+
114
+   </Drawer.Navigator>
115
+  )
116
+  
117
+}
118
+
119
+const styles = StyleSheet.create({
120
+  container: {
121
+    flex: 1,
122
+    backgroundColor: '#fff',
123
+    alignItems: 'center',
124
+    justifyContent: 'center',
125
+  },
126
+});

+ 21
- 0
client/Screens/Logout.js 查看文件

@@ -0,0 +1,21 @@
1
+import * as React from 'react';
2
+import { Button, View } from 'react-native';
3
+import * as SecureStore from 'expo-secure-store';
4
+
5
+function Logout({ navigation }) {
6
+  return (
7
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
8
+      <Button onPress={
9
+        ()=>{
10
+          SecureStore.deleteItemAsync('token')
11
+          SecureStore.deleteItemAsync('id')
12
+          navigation.push('Login')
13
+
14
+        }
15
+      } title="LOGOUT" />
16
+    </View>
17
+  );
18
+}
19
+export default Logout
20
+
21
+// navigation.navigate('Login', {screen: 'Login'})

+ 8
- 5
client/Screens/MyCurriculum.js 查看文件

@@ -1,7 +1,7 @@
1 1
 import React, {useState, useEffect} from 'react';
2
-import { View, StyleSheet, Text } from 'react-native';
2
+import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';
3 3
 import axios from 'axios'
4
-import { Table, Row, Rows, TableWrapper, Col } from 'react-native-table-component';
4
+import { Table, Row, Rows, TableWrapper, Col, Cell } from 'react-native-table-component';
5 5
 import {Picker} from '@react-native-community/picker'
6 6
 import * as SecureStore from 'expo-secure-store';
7 7
 
@@ -20,7 +20,7 @@ const MyCurriculum = () =>{
20 20
         let user_id = parseInt(id)
21 21
 
22 22
         try {
23
-            let response = await axios('http://8c4029a33a9a.ngrok.io/api/see_gpa', {
23
+            let response = await axios('http://da0406585426.ngrok.io/api/see_gpa', {
24 24
                 method: 'POST',
25 25
                 headers: {
26 26
                     Authorization: `Token ${token}`
@@ -43,7 +43,7 @@ const MyCurriculum = () =>{
43 43
         let numbers = []
44 44
 
45 45
         try {
46
-            let response = await axios(`http://8c4029a33a9a.ngrok.io/api/get_all_courses_by_semester?user_id=${user_id}&year=${year}&semestre=${semester}`, {
46
+            let response = await axios(`http://da0406585426.ngrok.io/api/get_all_courses_by_semester?user_id=${user_id}&year=${year}&semestre=${semester}`, {
47 47
                 method: 'GET',
48 48
                 headers: {
49 49
                     'content-type': 'application/json',
@@ -70,6 +70,9 @@ const MyCurriculum = () =>{
70 70
            }
71 71
     }
72 72
 
73
+
74
+
75
+
73 76
     useEffect(()=>{
74 77
         console.log('dimelo')
75 78
         getMyCurriculum()
@@ -127,5 +130,5 @@ const styles = StyleSheet.create({
127 130
     wrapper: { flexDirection: 'row' },
128 131
     title: { flex: 1, backgroundColor: '#e82020' },
129 132
     row: {  height: 28  },
130
-    text: { textAlign: 'center', fontSize:10 }
133
+    text: { textAlign: 'center', fontSize:10 },
131 134
   });

+ 2
- 3
client/Screens/SettingScreen.js 查看文件

@@ -15,7 +15,7 @@ export default function SettingScreen() {
15 15
         let user_id = parseInt(id)
16 16
 
17 17
        try {
18
-        let response = await axios(`http://8c4029a33a9a.ngrok.io/api/get_faculty_name?id=${user_id}`, {
18
+        let response = await axios(`http://0e86feab4a8f.ngrok.io/api/get_faculty_name?id=${user_id}`, {
19 19
             method: 'GET',
20 20
             headers: {
21 21
                 'content-type': 'application/json',
@@ -43,7 +43,7 @@ export default function SettingScreen() {
43 43
         try {
44 44
             let response = await axios({
45 45
                 method: 'PATCH',
46
-                url: 'http://8c4029a33a9a.ngrok.io/api/update_faculty',
46
+                url: 'http://0e86feab4a8f.ngrok.io/api/update_faculty',
47 47
                 headers: {
48 48
                     Authorization: `Token ${token}`
49 49
                 },
@@ -61,7 +61,6 @@ export default function SettingScreen() {
61 61
     console.log(faculty)
62 62
     return(
63 63
         <View style={styles.container}>
64
-            {/* <DisplayFaculty/> */}
65 64
             <View style={{textAlignVertical: 'top'}}>
66 65
                 <Text style={{ fontSize: 12, fontWeight: "bold" , height:30 }}>
67 66
                     You currently belong to the faculty: {currentFaculty}

+ 144
- 0
client/Screens/UpdateSemYear.js 查看文件

@@ -0,0 +1,144 @@
1
+import axios from "axios";
2
+import React, { useState, useEffect } from "react";
3
+import { StatusBar, StyleSheet, Text, View, Button, Alert } from "react-native";
4
+import * as SecureStore from 'expo-secure-store';
5
+import Modal from 'react-native-modal';
6
+import {Picker} from '@react-native-community/picker';
7
+
8
+
9
+
10
+const UpdateSemYear = () => {
11
+  
12
+  const [year, setYear] = useState('1')
13
+  const [semester, setSemester] = useState('1')
14
+  const [modalVisible, setModalVisible] = useState(false)
15
+  
16
+    const updateSemesterAndYear = async()=>{
17
+        const token = await SecureStore.getItemAsync('token')
18
+        let id = await SecureStore.getItemAsync('id')
19
+        let user_id = parseInt(id)
20
+    
21
+
22
+        let response = await axios({
23
+        method: 'PATCH',
24
+        url: 'http://da0406585426.ngrok.io/api/update_year_and_semester',
25
+        headers: {
26
+            'content-type': 'application/json',
27
+            Authorization: `Token ${token}`
28
+        },
29
+        data: {
30
+            user_id: user_id,
31
+            year: year,
32
+            semester: semester
33
+        }
34
+        })
35
+        console.log(response.data)
36
+
37
+        getSemesterAndYear()
38
+        toggle()
39
+
40
+    }
41
+ 
42
+
43
+  const getSemesterAndYear = async ()=>{
44
+      const token = await SecureStore.getItemAsync('token')
45
+      let id = await SecureStore.getItemAsync('id')
46
+      let user_id = parseInt(id)
47
+     
48
+
49
+      let response = await axios({
50
+        method: 'POST',
51
+        url: 'http://da0406585426.ngrok.io/api/get_year_and_semester',
52
+        headers: {
53
+          'content-type': 'application/json',
54
+          Authorization: `Token ${token}`
55
+        },
56
+        data: {
57
+          user_id: user_id,
58
+        }
59
+      })
60
+
61
+      setYear(response.data.msg.year)
62
+      setSemester(response.data.msg.semestre)
63
+
64
+
65
+  }
66
+
67
+  const toggle = ()=>{
68
+    setModalVisible(!modalVisible)
69
+  }
70
+
71
+  useEffect(()=>{
72
+    getSemesterAndYear()
73
+},[])
74
+
75
+
76
+  console.log(year)
77
+  return (
78
+    <View style={{flex: 1, padding: 10}}>
79
+       <Text style={styles.title}>Your current year is {year} and current semester is {semester}</Text>
80
+       <Button title="Change Year and Semester" onPress={toggle}/>
81
+       <Modal 
82
+            isVisible={modalVisible}
83
+        >
84
+        <View style={styles.modalItem}>
85
+                    <Text>Year</Text>
86
+                    <Picker
87
+                        selectedValue={year}
88
+                        style={{ width: 50}}
89
+                        onValueChange={(itemValue, itemIndex) => setYear(itemValue) }>
90
+                        <Picker.Item label="1" value="1" />
91
+                        <Picker.Item label="2" value="2" />
92
+                        <Picker.Item label="3" value="3" />
93
+                        <Picker.Item label="4" value="4" />
94
+                        <Picker.Item label="5" value="5" />
95
+                        <Picker.Item label="6" value="6" />
96
+                    </Picker>
97
+                </View>
98
+                <View style={styles.modalItem}>
99
+                    <Text>Semester</Text>
100
+                    <Picker
101
+                        selectedValue={semester}
102
+                        style={{ width: 50}}
103
+                        onValueChange={(itemValue, itemIndex) => setSemester(itemValue) }>
104
+                        <Picker.Item label="1" value="1" />
105
+                        <Picker.Item label="2" value="2" />
106
+                    </Picker>
107
+            </View>
108
+            <Button title="Submit" onPress={updateSemesterAndYear}/>
109
+            <Button title="Close" onPress={toggle}/>
110
+
111
+       </Modal>
112
+    </View>
113
+  );
114
+};
115
+
116
+
117
+const styles = StyleSheet.create({
118
+  container: {
119
+    flex: 1,
120
+    marginTop: StatusBar.currentHeight || 0,
121
+  },
122
+  item: {
123
+    padding: 10,
124
+    marginVertical: 8,
125
+    marginHorizontal: 16,
126
+  },
127
+  title: {
128
+    fontSize: 15,
129
+    fontWeight: 'bold'
130
+  },
131
+  searchBar: {
132
+    height: 40, 
133
+    borderColor: '#000', 
134
+    borderWidth: 1 
135
+  },
136
+  modalItem: {
137
+    // width: '30%', // is 30% of container width
138
+    margin: 8, // 300
139
+    backgroundColor: 'white'
140
+}
141
+  
142
+});
143
+
144
+export default UpdateSemYear;

+ 2
- 1
client/debug.log 查看文件

@@ -1 +1,2 @@
1
-[1130/124344.155:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
1
+[1117/174912.971:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
2
+[1214/193105.148:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)

二進制
organizar/__pycache__/organizar.cpython-38.pyc 查看文件


+ 7
- 2
organizar/organizar.py 查看文件

@@ -1,7 +1,6 @@
1 1
 import os, sys
2 2
 import json
3 3
 
4
-
5 4
 path1 = "C:/Users/diego/Documents/companion_app/primer_sem"
6 5
 path2 = "C:/Users/diego/Documents/companion_app/segundo_sem"
7 6
 path3 = "C:/Users/diego/Documents/companion_app/Miupi Parser"
@@ -33,7 +32,6 @@ def orderFiles3(files1, files2, files3):
33 32
         files3.append({'file': files2[i]['file'], 'num': files1[i]['num']})
34 33
     return files3
35 34
 
36
-
37 35
 def orderFilesProxSemestre(files):
38 36
     """ 
39 37
     Organizing all the files from Miupi Parser to a single array. The array will contain each directory of each file
@@ -51,3 +49,10 @@ files3 = []
51 49
 files3 = orderFiles3(files1, files2, files3)
52 50
 proxSemFiles = orderFilesProxSemestre([])
53 51
 
52
+
53
+
54
+
55
+
56
+               
57
+            
58
+