Parcourir la source

Notificaciones funcionando. Screen nuevo de confirmar. Si dice que no, se le notifica al cliente. Screen nuevo para citas.

ErnestoOrtiz2 il y a 3 ans
Parent
révision
c81205bc19
4 fichiers modifiés avec 508 ajouts et 40 suppressions
  1. 5
    0
      App.js
  2. 244
    0
      screens/main/Cita.js
  3. 255
    0
      screens/main/Confirm.js
  4. 4
    40
      screens/main/Home_page.js

+ 5
- 0
App.js Voir le fichier

@@ -24,6 +24,9 @@ import Calendario from './screens/main/Calendar';
24 24
 import Time from './screens/main/StateTime';
25 25
 import Search from './screens/main/Search';
26 26
 import Map from './screens/main/Map';
27
+import Confirm from './screens/main/Confirm';
28
+import Cita from './screens/main/Cita';
29
+
27 30
 
28 31
 
29 32
 if (firebase.apps.length === 0) {
@@ -97,6 +100,8 @@ export default class App extends Component {
97 100
             <Stack.Screen name = "StateTime" component={Time}/>
98 101
             <Stack.Screen name = "Search" component={Search}/>
99 102
             <Stack.Screen name = "Map" component={Map}/>
103
+            <Stack.Screen name = "Confirm" component={Confirm}/>
104
+            <Stack.Screen name = "Cita" component={Cita}/>
100 105
           </Stack.Navigator>
101 106
         </NavigationContainer>
102 107
       </Provider>

+ 244
- 0
screens/main/Cita.js Voir le fichier

@@ -0,0 +1,244 @@
1
+import React, {useState, useEffect, useRef} from 'react'
2
+import { Button, Text, View, StyleSheet, Dimensions} from 'react-native'
3
+import {FlatList, ListViewBase } from 'react-native'
4
+import {TouchableOpacity} from 'react-native-gesture-handler'
5
+import {List, Divider} from 'react-native-paper'
6
+import Loading from './Loading'
7
+import firebase from 'firebase';
8
+import { styles } from "../../config/styles";
9
+import { TextInput, TouchableWithoutFeedback, Keyboard, ImageBackground} from "react-native";
10
+
11
+import { connect } from 'react-redux'
12
+import { bindActionCreators } from 'redux' 
13
+import { fetchUser } from '../../redux/actions/index'
14
+
15
+import Constants from 'expo-constants';
16
+import * as Notifications from 'expo-notifications';
17
+
18
+Notifications.setNotificationHandler({
19
+  handleNotification: async () => ({
20
+    shouldShowAlert: true,
21
+    shouldPlaySound: true,
22
+    shouldSetBadge: false,
23
+  }),
24
+});
25
+
26
+
27
+export function Cita({navigation}) {
28
+  const [threads, setThreads] = useState([]);  
29
+  const [loading, setLoading] = useState(true);
30
+  const [appointments, setAppointments] = useState([]); 
31
+
32
+  const [expoPushToken, setExpoPushToken] = useState('');
33
+  const [notification, setNotification] = useState(false);
34
+  const notificationListener = useRef();
35
+  const responseListener = useRef();
36
+
37
+  useEffect(() => {
38
+    registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
39
+    notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
40
+      setNotification(notification);
41
+    });
42
+
43
+    responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
44
+      console.log(response);
45
+      navigation.navigate('Confirm');
46
+    });
47
+
48
+    const fire = firebase.firestore()
49
+    .collection('THREADS')
50
+    .where("members", "array-contains", firebase.auth().currentUser.uid)
51
+    .onSnapshot(querySnapshot => {
52
+      const threads = querySnapshot.docs.map(documentSnapshot => {
53
+        return{
54
+          _id:documentSnapshot.id,
55
+          name:'',
56
+          ...documentSnapshot.data()
57
+        };
58
+      });
59
+
60
+      setThreads(threads);
61
+      console.log(threads);
62
+
63
+      if(loading){
64
+        setLoading(false);
65
+      }
66
+    });
67
+
68
+    const cita = firebase.firestore().collection('APPOINTMENTS').where('Day', '==', 8).onSnapshot(snapShot => {
69
+      const appointments = snapShot.docs.map(docSnap => {
70
+        return{
71
+          _id:docSnap.id,
72
+          Day:'',
73
+          Month:'',
74
+          Time:'',
75
+          i_id:'',
76
+          uid1:'',
77
+          ...docSnap.data()
78
+        };
79
+      });
80
+      setAppointments(appointments);
81
+      console.log(appointments);
82
+    });
83
+      
84
+    return () => {
85
+      Notifications.removeNotificationSubscription(notificationListener.current);
86
+      Notifications.removeNotificationSubscription(responseListener.current);
87
+      fire();
88
+      cita();
89
+    }
90
+  }, []);
91
+  
92
+  if (loading) {
93
+    return <Loading />;
94
+  }
95
+
96
+  
97
+  function handleButtonPress() {
98
+      firebase.firestore()
99
+        .collection('THREADS')
100
+        .add({
101
+          name: 'PedroFecha',
102
+          members: [
103
+            firebase.auth().currentUser.uid,
104
+            '02yOZHxFcGUX4MNwjeEbAlCShdu1'
105
+          ]
106
+        })
107
+  }
108
+
109
+  const dimensions = Dimensions.get('window');
110
+  const screenWidth = dimensions.width;
111
+
112
+  
113
+  return (
114
+      <ImageBackground style={styles.stdcontainer} source={require('../../assets/yellow-white.jpg')}>
115
+        <FlatList style={{
116
+             flex: 1,
117
+             width: screenWidth,
118
+         }}
119
+          data={threads}
120
+          keyExtractor = {item => item._id}
121
+          ItemSeparatorComponent={() => <Divider />}
122
+          renderItem = {({item}) => (
123
+          <TouchableOpacity
124
+            onPress={() => navigation.navigate('Room', {thread: item})}
125
+          >
126
+            <List.Item
127
+              title={item.name}
128
+              titleNumberOfLines={1}
129
+              titleStyle={styles.listTitle}
130
+              descriptionStyle={styles.listDescription}
131
+              descriptionNumberOfLines={1}
132
+            />
133
+          </TouchableOpacity>
134
+        )}
135
+        />
136
+        <FlatList style={{
137
+             flex: 1,
138
+             width: screenWidth,
139
+         }}
140
+          data={appointments}
141
+          keyExtractor = {item => item._id}
142
+          ItemSeparatorComponent={() => <Divider />}
143
+          renderItem = {({item}) => (
144
+          <TouchableOpacity
145
+          onPress={async () => {
146
+            await sendPushNotification(expoPushToken); //item.push_token
147
+          }}
148
+          >
149
+            <List.Item
150
+              title={item.Month}
151
+              titleNumberOfLines={1}
152
+              titleStyle={styles.listTitle}
153
+              descriptionStyle={styles.listDescription}
154
+              descriptionNumberOfLines={1}
155
+            />
156
+            <List.Item
157
+              title={item.Day}
158
+              titleNumberOfLines={1}
159
+              titleStyle={styles.listTitle}
160
+              descriptionStyle={styles.listDescription}
161
+              descriptionNumberOfLines={1}
162
+            />
163
+            <List.Item
164
+              title={item.Time}
165
+              titleNumberOfLines={1}
166
+              titleStyle={styles.listTitle}
167
+              descriptionStyle={styles.listDescription}
168
+              descriptionNumberOfLines={1}
169
+            />
170
+          </TouchableOpacity>
171
+        )}
172
+        />
173
+      <Button
174
+        title ='Ver mapa'
175
+        onPress= {() => navigation.navigate('Map')}
176
+      />
177
+      <Button
178
+        title ='Logout'
179
+        onPress= {() => firebase.auth().signOut()}
180
+      />
181
+        </ImageBackground>
182
+    );
183
+  }
184
+// Can use this function below, OR use Expo's Push Notification Tool-> https://expo.dev/notifications
185
+async function sendPushNotification(expoPushToken) {
186
+  const message = {
187
+    to: expoPushToken,
188
+    sound: 'default',
189
+    title: 'Freehand',
190
+    body: 'Le solicitan una cita',
191
+    data: { someData: 'goes here' },
192
+  };
193
+
194
+  await fetch('https://exp.host/--/api/v2/push/send', {
195
+    method: 'POST',
196
+    headers: {
197
+      Accept: 'application/json',
198
+      'Accept-encoding': 'gzip, deflate',
199
+      'Content-Type': 'application/json',
200
+    },
201
+    body: JSON.stringify(message),
202
+  });
203
+}
204
+
205
+async function registerForPushNotificationsAsync() {
206
+  let token;
207
+  if (Constants.isDevice) {
208
+    const { status: existingStatus } = await Notifications.getPermissionsAsync();
209
+    let finalStatus = existingStatus;
210
+    if (existingStatus !== 'granted') {
211
+      const { status } = await Notifications.requestPermissionsAsync();
212
+      finalStatus = status;
213
+    }
214
+    if (finalStatus !== 'granted') {
215
+      alert('Failed to get push token for push notification!');
216
+      return;
217
+    }
218
+    token = (await Notifications.getExpoPushTokenAsync()).data;
219
+    console.log(token);
220
+  } else {
221
+    alert('Must use physical device for Push Notifications');
222
+  }
223
+
224
+  if (Platform.OS === 'android') {
225
+    Notifications.setNotificationChannelAsync('default', {
226
+      name: 'default',
227
+      importance: Notifications.AndroidImportance.MAX,
228
+      vibrationPattern: [0, 250, 250, 250],
229
+      lightColor: '#FF231F7C',
230
+    });
231
+  }
232
+
233
+  firebase.firestore().collection('Interprete').doc(firebase.auth().currentUser.uid).update({'push_token': token})
234
+  firebase.firestore().collection('Users').doc(firebase.auth().currentUser.uid).update({'push_token': token})
235
+
236
+  return token;
237
+}
238
+
239
+const mapStateToProps = (store) => ({
240
+  currentUser: store.userState.currentUser
241
+})
242
+const mapDispatchProps = (dispatch) => bindActionCreators({fetchUser}, dispatch);
243
+
244
+export default connect(mapStateToProps, mapDispatchProps)(Cita);

+ 255
- 0
screens/main/Confirm.js Voir le fichier

@@ -0,0 +1,255 @@
1
+import React, {useState, useEffect, useRef} from 'react'
2
+import { Button, Text, View, StyleSheet, Dimensions} from 'react-native'
3
+import {FlatList, ListViewBase } from 'react-native'
4
+import {TouchableOpacity} from 'react-native-gesture-handler'
5
+import {List, Divider} from 'react-native-paper'
6
+import Loading from './Loading'
7
+import firebase from 'firebase';
8
+import { styles } from "../../config/styles";
9
+import { TextInput, TouchableWithoutFeedback, Keyboard, ImageBackground} from "react-native";
10
+
11
+import { connect } from 'react-redux'
12
+import { bindActionCreators } from 'redux' 
13
+import { fetchUser } from '../../redux/actions/index'
14
+
15
+import Constants from 'expo-constants';
16
+import * as Notifications from 'expo-notifications';
17
+
18
+Notifications.setNotificationHandler({
19
+  handleNotification: async () => ({
20
+    shouldShowAlert: true,
21
+    shouldPlaySound: true,
22
+    shouldSetBadge: false,
23
+  }),
24
+});
25
+
26
+
27
+export function Confirm({navigation}) {
28
+  const [threads, setThreads] = useState([]);  
29
+  const [loading, setLoading] = useState(true);
30
+  const [appointments, setAppointments] = useState([]); 
31
+
32
+  const [expoPushToken, setExpoPushToken] = useState('');
33
+  const [notification, setNotification] = useState(false);
34
+  const notificationListener = useRef();
35
+  const responseListener = useRef();
36
+
37
+  useEffect(() => {
38
+    registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
39
+    notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
40
+      setNotification(notification);
41
+    });
42
+
43
+    responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
44
+      console.log(response);
45
+      navigation.navigate('Search');
46
+    });
47
+
48
+    const fire = firebase.firestore()
49
+    .collection('THREADS')
50
+    .where("members", "array-contains", firebase.auth().currentUser.uid)
51
+    .onSnapshot(querySnapshot => {
52
+      const threads = querySnapshot.docs.map(documentSnapshot => {
53
+        return{
54
+          _id:documentSnapshot.id,
55
+          name:'',
56
+          ...documentSnapshot.data()
57
+        };
58
+      });
59
+
60
+      setThreads(threads);
61
+      console.log(threads);
62
+
63
+      if(loading){
64
+        setLoading(false);
65
+      }
66
+    });
67
+
68
+    const cita = firebase.firestore().collection('APPOINTMENTS').where('Day', '==', 8).onSnapshot(snapShot => {
69
+      const appointments = snapShot.docs.map(docSnap => {
70
+        return{
71
+          _id:docSnap.id,
72
+          Day:'',
73
+          Month:'',
74
+          Time:'',
75
+          i_id:'',
76
+          uid1:'',
77
+          ...docSnap.data()
78
+        };
79
+      });
80
+      setAppointments(appointments);
81
+      console.log(appointments);
82
+    });
83
+      
84
+    return () => {
85
+      Notifications.removeNotificationSubscription(notificationListener.current);
86
+      Notifications.removeNotificationSubscription(responseListener.current);
87
+      fire();
88
+      cita();
89
+    }
90
+  }, []);
91
+  
92
+  if (loading) {
93
+    return <Loading />;
94
+  }
95
+
96
+  
97
+  function crearChat() {
98
+      firebase.firestore()
99
+        .collection('THREADS')
100
+        .add({
101
+          name: 'CHAT',
102
+          members: [
103
+            firebase.auth().currentUser.uid,
104
+            '02yOZHxFcGUX4MNwjeEbAlCShdu1'
105
+          ]
106
+        })
107
+  }
108
+
109
+  const dimensions = Dimensions.get('window');
110
+  const screenWidth = dimensions.width;
111
+
112
+  
113
+  return (
114
+      <ImageBackground style={styles.stdcontainer} source={require('../../assets/yellow-white.jpg')}>
115
+        <FlatList style={{
116
+             flex: 1,
117
+             width: screenWidth,
118
+         }}
119
+          data={threads}
120
+          keyExtractor = {item => item._id}
121
+          ItemSeparatorComponent={() => <Divider />}
122
+          renderItem = {({item}) => (
123
+          <TouchableOpacity
124
+            onPress={() => navigation.navigate('Room', {thread: item})}
125
+          >
126
+            <List.Item
127
+              title={item.name}
128
+              titleNumberOfLines={1}
129
+              titleStyle={styles.listTitle}
130
+              descriptionStyle={styles.listDescription}
131
+              descriptionNumberOfLines={1}
132
+            />
133
+          </TouchableOpacity>
134
+        )}
135
+        />
136
+        <FlatList style={{
137
+             flex: 1,
138
+             width: screenWidth,
139
+         }}
140
+          data={appointments}
141
+          keyExtractor = {item => item._id}
142
+          ItemSeparatorComponent={() => <Divider />}
143
+          renderItem = {({item}) => (
144
+          <TouchableOpacity
145
+          onPress={async () => {
146
+            await sendPushNotification(expoPushToken); //item.push_token
147
+          }}
148
+          >
149
+            <List.Item
150
+              title={item.Month}
151
+              titleNumberOfLines={1}
152
+              titleStyle={styles.listTitle}
153
+              descriptionStyle={styles.listDescription}
154
+              descriptionNumberOfLines={1}
155
+            />
156
+            <List.Item
157
+              title={item.Day}
158
+              titleNumberOfLines={1}
159
+              titleStyle={styles.listTitle}
160
+              descriptionStyle={styles.listDescription}
161
+              descriptionNumberOfLines={1}
162
+            />
163
+            <List.Item
164
+              title={item.Time}
165
+              titleNumberOfLines={1}
166
+              titleStyle={styles.listTitle}
167
+              descriptionStyle={styles.listDescription}
168
+              descriptionNumberOfLines={1}
169
+            />
170
+          </TouchableOpacity>
171
+        )}
172
+        />
173
+       <Button
174
+        title ='Ver mapa'
175
+        onPress= {() => navigation.navigate('Map')}
176
+      />
177
+      <Button
178
+        title="No disponible"
179
+        onPress={async () => {
180
+          await sendPushNotification(expoPushToken); //item.push_token
181
+          //Borrar Appointment de fb
182
+          navigation.navigate('Home');
183
+        }}
184
+      /> 
185
+      <Button
186
+        title ='Si'
187
+        onPress= {() => {
188
+            crearChat();
189
+            navigation.navigate('Home');
190
+        }}
191
+      />
192
+        </ImageBackground>
193
+    );
194
+  }
195
+// Can use this function below, OR use Expo's Push Notification Tool-> https://expo.dev/notifications
196
+async function sendPushNotification(expoPushToken) {
197
+  const message = {
198
+    to: expoPushToken,
199
+    sound: 'default',
200
+    title: 'Freehand',
201
+    body: 'Interprete no esta disponible',
202
+    data: { someData: 'goes here' },
203
+  };
204
+
205
+  await fetch('https://exp.host/--/api/v2/push/send', {
206
+    method: 'POST',
207
+    headers: {
208
+      Accept: 'application/json',
209
+      'Accept-encoding': 'gzip, deflate',
210
+      'Content-Type': 'application/json',
211
+    },
212
+    body: JSON.stringify(message),
213
+  });
214
+}
215
+
216
+async function registerForPushNotificationsAsync() {
217
+  let token;
218
+  if (Constants.isDevice) {
219
+    const { status: existingStatus } = await Notifications.getPermissionsAsync();
220
+    let finalStatus = existingStatus;
221
+    if (existingStatus !== 'granted') {
222
+      const { status } = await Notifications.requestPermissionsAsync();
223
+      finalStatus = status;
224
+    }
225
+    if (finalStatus !== 'granted') {
226
+      alert('Failed to get push token for push notification!');
227
+      return;
228
+    }
229
+    token = (await Notifications.getExpoPushTokenAsync()).data;
230
+    console.log(token);
231
+  } else {
232
+    alert('Must use physical device for Push Notifications');
233
+  }
234
+
235
+  if (Platform.OS === 'android') {
236
+    Notifications.setNotificationChannelAsync('default', {
237
+      name: 'default',
238
+      importance: Notifications.AndroidImportance.MAX,
239
+      vibrationPattern: [0, 250, 250, 250],
240
+      lightColor: '#FF231F7C',
241
+    });
242
+  }
243
+
244
+  firebase.firestore().collection('Interprete').doc(firebase.auth().currentUser.uid).update({'push_token': token})
245
+  firebase.firestore().collection('Users').doc(firebase.auth().currentUser.uid).update({'push_token': token})
246
+
247
+  return token;
248
+}
249
+
250
+const mapStateToProps = (store) => ({
251
+  currentUser: store.userState.currentUser
252
+})
253
+const mapDispatchProps = (dispatch) => bindActionCreators({fetchUser}, dispatch);
254
+
255
+export default connect(mapStateToProps, mapDispatchProps)(Confirm);

+ 4
- 40
screens/main/Home_page.js Voir le fichier

@@ -42,6 +42,7 @@ export function Home_page({navigation}) {
42 42
 
43 43
     responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
44 44
       console.log(response);
45
+      navigation.navigate('Confirm');
45 46
     });
46 47
 
47 48
     const fire = firebase.firestore()
@@ -115,34 +116,13 @@ export function Home_page({navigation}) {
115 116
              flex: 1,
116 117
              width: screenWidth,
117 118
          }}
118
-          data={threads}
119
-          keyExtractor = {item => item._id}
120
-          ItemSeparatorComponent={() => <Divider />}
121
-          renderItem = {({item}) => (
122
-          <TouchableOpacity
123
-            onPress={() => navigation.navigate('Room', {thread: item})}
124
-          >
125
-            <List.Item
126
-              title={item.name}
127
-              titleNumberOfLines={1}
128
-              titleStyle={styles.listTitle}
129
-              descriptionStyle={styles.listDescription}
130
-              descriptionNumberOfLines={1}
131
-            />
132
-          </TouchableOpacity>
133
-        )}
134
-        />
135
-        <FlatList style={{
136
-             flex: 1,
137
-             width: screenWidth,
138
-         }}
139 119
           data={appointments}
140 120
           keyExtractor = {item => item._id}
141 121
           ItemSeparatorComponent={() => <Divider />}
142 122
           renderItem = {({item}) => (
143 123
           <TouchableOpacity
144 124
           onPress={async () => {
145
-            await sendPushNotification(expoPushToken);
125
+            navigation.navigate('Cita')
146 126
           }}
147 127
           >
148 128
             <List.Item
@@ -169,22 +149,6 @@ export function Home_page({navigation}) {
169 149
           </TouchableOpacity>
170 150
         )}
171 151
         />
172
-      <Text>Your expo push token: {expoPushToken}</Text>
173
-      <View style={{ alignItems: 'center', justifyContent: 'center' }}>
174
-        <Text>Title: {notification && notification.request.content.title} </Text>
175
-        <Text>Body: {notification && notification.request.content.body}</Text>
176
-        <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text>
177
-      </View>
178
-      <Button
179
-        title="Press to Send Notification"
180
-        onPress={async () => {
181
-          await sendPushNotification(expoPushToken);
182
-        }}
183
-      /> 
184
-      <Button
185
-        title='CrearChat'
186
-        onPress={() => handleButtonPress()}
187
-      />
188 152
       <Button
189 153
         title ='Hacer Busqueda'
190 154
         onPress= {() => navigation.navigate('Search')}
@@ -201,8 +165,8 @@ async function sendPushNotification(expoPushToken) {
201 165
   const message = {
202 166
     to: expoPushToken,
203 167
     sound: 'default',
204
-    title: 'Original Title',
205
-    body: 'And here is the body!',
168
+    title: 'Freehand',
169
+    body: 'Le solicitan una cita',
206 170
     data: { someData: 'goes here' },
207 171
   };
208 172