Showing
38 changed files
with
663 additions
and
117 deletions
... | ... | @@ -30,9 +30,6 @@ moment.locale('es-ES') |
30 | 30 | |
31 | 31 | export default class App extends Component { |
32 | 32 | |
33 | - componentWillMount() { | |
34 | - } | |
35 | - | |
36 | 33 | render() { |
37 | 34 | // buscar solicitudes |
38 | 35 | // estadisticas |
... | ... | @@ -57,6 +54,9 @@ export default class App extends Component { |
57 | 54 | BuscarSolicitudes: { screen: BuscarSolicitudes }, |
58 | 55 | DetalleSolicitud: { screen: DetalleSolicitud } |
59 | 56 | }) |
57 | + const AyudaNavigator = createStackNavigator({ | |
58 | + Ayuda: { screen: Ayuda }, | |
59 | + }) | |
60 | 60 | |
61 | 61 | const DrawerNavigator = createDrawerNavigator({ |
62 | 62 | MisSolicitudes: { |
... | ... | @@ -84,7 +84,12 @@ export default class App extends Component { |
84 | 84 | }), |
85 | 85 | }, |
86 | 86 | Estadisticas: { screen: Estadisticas }, |
87 | - Ayuda: { screen: Ayuda }, | |
87 | + AyudaNavigator: { | |
88 | + screen: AyudaNavigator, | |
89 | + navigationOptions: () => ({ | |
90 | + title: 'Ayuda', | |
91 | + }) | |
92 | + } | |
88 | 93 | }, { |
89 | 94 | contentComponent: CustomDrawerContentComponent |
90 | 95 | }) | ... | ... |
1 | +import React, { Component } from 'react' | |
2 | +import { | |
3 | + View, | |
4 | +} from 'react-native' | |
5 | +import { connect } from 'react-redux' | |
6 | +import { Button } from 'react-native-elements' | |
7 | + | |
8 | +import { postValoracion } from '../../redux/actions/valoraciones' | |
9 | +import { postReporte } from '../../redux/actions/reportes' | |
10 | + | |
11 | +import css from './style' | |
12 | + | |
13 | +const SATISFECHO = 'SATISFECHO' | |
14 | +const NO_SATISFECHO = 'NO SATISFECHO' | |
15 | +const INFORMACION_NO_PUBLICADA = 'CONFIDENCIAL' | |
16 | +class BotonValoracion extends Component { | |
17 | + | |
18 | + render() { | |
19 | + if (this.props.mostrar) { | |
20 | + const solicitudId = this.props.solicitud.id | |
21 | + const usuario = this.props.usuario | |
22 | + const likeName = this.props.valoracion.data === SATISFECHO | |
23 | + ? 'ios-thumbs-up' | |
24 | + : 'ios-thumbs-up-outline' | |
25 | + | |
26 | + const dislikeName = this.props.valoracion.data === NO_SATISFECHO | |
27 | + ? 'ios-thumbs-down' | |
28 | + : 'ios-thumbs-down-outline' | |
29 | + | |
30 | + const reportName = this.props.reporte.data === INFORMACION_NO_PUBLICADA | |
31 | + ? 'ios-megaphone' | |
32 | + : 'ios-megaphone-outline' | |
33 | + | |
34 | + return ( | |
35 | + <View style={[css.buttonFooter]}> | |
36 | + <Button | |
37 | + onPress={() => this.props.postReporte(solicitudId, usuario, INFORMACION_NO_PUBLICADA)} | |
38 | + backgroundColor="white" | |
39 | + icon={{ | |
40 | + name: reportName, | |
41 | + size: 27, | |
42 | + color: 'red', | |
43 | + type: 'ionicon' | |
44 | + }} | |
45 | + /> | |
46 | + <Button | |
47 | + backgroundColor="white" | |
48 | + onPress={() => this.props.postValoracion(solicitudId, usuario, SATISFECHO)} | |
49 | + icon={{ | |
50 | + name: likeName, | |
51 | + size: 27, | |
52 | + color: 'red', | |
53 | + type: 'ionicon' | |
54 | + }} | |
55 | + /> | |
56 | + <Button | |
57 | + onPress={() => this.props.postValoracion(solicitudId, usuario, NO_SATISFECHO)} | |
58 | + backgroundColor="white" | |
59 | + icon={{ | |
60 | + name: dislikeName, | |
61 | + size: 27, | |
62 | + color: 'red', | |
63 | + type: 'ionicon' | |
64 | + }} | |
65 | + /> | |
66 | + </View> | |
67 | + ) | |
68 | + } | |
69 | + return <View /> | |
70 | + } | |
71 | +} | |
72 | + | |
73 | +const mapStateToProps = (state) => ({ | |
74 | + solicitud: state.solicitudes.current, | |
75 | + usuario: state.usuario.datos, | |
76 | + valoracion: state.valoracion, | |
77 | + reporte: state.reporte, | |
78 | +}) | |
79 | + | |
80 | +const mapDispatchToProps = (dispatch) => ({ | |
81 | + postValoracion: (solicitud, usuario, valoracion) => | |
82 | + dispatch(postValoracion(solicitud, usuario, valoracion)), | |
83 | + postReporte: (solicitud, usuario, valoracion) => | |
84 | + dispatch(postReporte(solicitud, usuario, valoracion)) | |
85 | +}) | |
86 | +export default connect(mapStateToProps, mapDispatchToProps)(BotonValoracion) | ... | ... |
... | ... | @@ -3,10 +3,12 @@ import { View, Image, Linking, TouchableOpacity } from 'react-native' |
3 | 3 | |
4 | 4 | import css from './style' |
5 | 5 | |
6 | +const innovandoImg = require('../../assets/logos/innovando.png') | |
7 | +const senaticsImg = require('../../assets/logos/senatics.png') | |
8 | + | |
6 | 9 | class FooterSenatics extends Component { |
7 | 10 | |
8 | 11 | myHandlePress = (link) => () => { |
9 | - console.log('pressed link') | |
10 | 12 | Linking.openURL(link) |
11 | 13 | } |
12 | 14 | |
... | ... | @@ -15,12 +17,12 @@ class FooterSenatics extends Component { |
15 | 17 | <View style={css.container}> |
16 | 18 | <View style={css.card} > |
17 | 19 | <TouchableOpacity onPress={this.myHandlePress('http://www.innovando.gov.py')}> |
18 | - <Image style={css.img} source={require('../../assets/logos/innovando.png')} /> | |
20 | + <Image style={css.img} source={innovandoImg} /> | |
19 | 21 | </TouchableOpacity> |
20 | 22 | </View> |
21 | 23 | <View style={css.card} > |
22 | 24 | <TouchableOpacity onPress={this.myHandlePress('https://www.senatics.gov.py')}> |
23 | - <Image style={css.img} source={require('../../assets/logos/senatics.png')} /> | |
25 | + <Image style={css.img} source={senaticsImg} /> | |
24 | 26 | </TouchableOpacity> |
25 | 27 | </View> |
26 | 28 | </View>) | ... | ... |
... | ... | @@ -3,19 +3,16 @@ import { Constants } from 'expo' |
3 | 3 | export const STATUS_BAR_HEIGHT = Constants.statusBarHeight |
4 | 4 | |
5 | 5 | // PROD |
6 | -export const AUTH_TOKEN = '730e9175-c76c-418a-a051-7e2834ed7fd7' | |
7 | -export const CLIENT_SECRET = 'deb7aa26038d0f44a35cd3e1d2f60b5c0e11192ddd0f9430c0d64a1101daa11f' | |
8 | -export const SENATICS_URL = 'https://informacionpublica.paraguay.gov.py:443/portal-core/rest/api' | |
9 | - | |
6 | +// export const SENATICS_URL = 'https://informacionpublica.paraguay.gov.py:443/portal-core/rest/api' | |
10 | 7 | // DEV |
11 | -// export const AUTH_TOKEN = '0496164f-8de1-449c-9ce9-af0e0a6ce9fe' | |
12 | -// export const CLIENT_SECRET = 'a66a1a98eb7059a5c3b446183e214cc2661326c2994b811cb06dd9d3d873a9e9' | |
13 | -// export const SENATICS_URL = 'http://192.168.0.26:2128/api' | |
14 | -export const BACKEND_URL = 'http://192.168.0.26:3000/api' | |
15 | -export const RENEW_INTERVAL = 1 * 1000 * 60 | |
16 | -export const TOKEN_EXPIRATION = 15 * 1000 * 60 | |
8 | +export const SENATICS_URL = 'http://192.168.0.26:2128/api' | |
9 | + | |
10 | +export const BACKEND_URL = 'http://192.168.0.26:3000' | |
17 | 11 | export const NOTIFICATION_ICON = 'http://ayuda.tesis-jmgo.cnc.una.py/img/jaikuaamina.icon.png' |
18 | 12 | export const INFO_PY_URL = 'https://informacionpublica.paraguay.gov.py/portal/' |
13 | +export const PORTAL_DENUNCIAS_URL = 'http://www.denuncias.gov.py' | |
14 | +export const TUTORIAL_AIF_URL = 'https://youtu.be/W8jG3md7YFg' | |
15 | +export const TUTORIAL_APP = `${BACKEND_URL}/index.html` | |
19 | 16 | |
20 | 17 | export const ESTADOS_SOLICITUDES = { |
21 | 18 | finalizados: [ | ... | ... |
... | ... | @@ -2629,13 +2629,12 @@ |
2629 | 2629 | } |
2630 | 2630 | }, |
2631 | 2631 | "buffer": { |
2632 | - "version": "4.9.1", | |
2633 | - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", | |
2634 | - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", | |
2632 | + "version": "5.1.0", | |
2633 | + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", | |
2634 | + "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==", | |
2635 | 2635 | "requires": { |
2636 | 2636 | "base64-js": "^1.0.2", |
2637 | - "ieee754": "^1.1.4", | |
2638 | - "isarray": "^1.0.0" | |
2637 | + "ieee754": "^1.1.4" | |
2639 | 2638 | } |
2640 | 2639 | }, |
2641 | 2640 | "buffer-alloc": { |
... | ... | @@ -5157,8 +5156,7 @@ |
5157 | 5156 | }, |
5158 | 5157 | "safe-buffer": { |
5159 | 5158 | "version": "5.1.1", |
5160 | - "bundled": true, | |
5161 | - "optional": true | |
5159 | + "bundled": true | |
5162 | 5160 | }, |
5163 | 5161 | "safer-buffer": { |
5164 | 5162 | "version": "2.1.2", |
... | ... | @@ -5250,8 +5248,7 @@ |
5250 | 5248 | }, |
5251 | 5249 | "yallist": { |
5252 | 5250 | "version": "3.0.2", |
5253 | - "bundled": true, | |
5254 | - "optional": true | |
5251 | + "bundled": true | |
5255 | 5252 | } |
5256 | 5253 | } |
5257 | 5254 | }, |
... | ... | @@ -9890,6 +9887,18 @@ |
9890 | 9887 | "html-entities": "^1.2.0", |
9891 | 9888 | "htmlparser2": "^3.9.0", |
9892 | 9889 | "stream": "0.0.2" |
9890 | + }, | |
9891 | + "dependencies": { | |
9892 | + "buffer": { | |
9893 | + "version": "4.9.1", | |
9894 | + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", | |
9895 | + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", | |
9896 | + "requires": { | |
9897 | + "base64-js": "^1.0.2", | |
9898 | + "ieee754": "^1.1.4", | |
9899 | + "isarray": "^1.0.0" | |
9900 | + } | |
9901 | + } | |
9893 | 9902 | } |
9894 | 9903 | }, |
9895 | 9904 | "react-native-safe-area-view": { |
... | ... | @@ -12613,9 +12622,9 @@ |
12613 | 12622 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" |
12614 | 12623 | }, |
12615 | 12624 | "uuid": { |
12616 | - "version": "3.0.1", | |
12617 | - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", | |
12618 | - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" | |
12625 | + "version": "3.2.1", | |
12626 | + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", | |
12627 | + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" | |
12619 | 12628 | }, |
12620 | 12629 | "uuid-js": { |
12621 | 12630 | "version": "0.7.5", |
... | ... | @@ -12833,6 +12842,13 @@ |
12833 | 12842 | "pegjs": "^0.10.0", |
12834 | 12843 | "simple-plist": "^0.2.1", |
12835 | 12844 | "uuid": "3.0.1" |
12845 | + }, | |
12846 | + "dependencies": { | |
12847 | + "uuid": { | |
12848 | + "version": "3.0.1", | |
12849 | + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", | |
12850 | + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" | |
12851 | + } | |
12836 | 12852 | } |
12837 | 12853 | }, |
12838 | 12854 | "xdl": { | ... | ... |
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | "preset": "jest-expo" |
21 | 21 | }, |
22 | 22 | "dependencies": { |
23 | + "buffer": "^5.1.0", | |
23 | 24 | "elliptic": "^6.4.0", |
24 | 25 | "expo": "^27.0.1", |
25 | 26 | "moment": "^2.22.2", |
... | ... | @@ -35,6 +36,7 @@ |
35 | 36 | "redux": "^4.0.0", |
36 | 37 | "redux-observable": "^0.19.0", |
37 | 38 | "redux-thunk": "^2.3.0", |
38 | - "rxjs": "^5.0.0" | |
39 | + "rxjs": "^5.0.0", | |
40 | + "uuid": "^3.2.1" | |
39 | 41 | } |
40 | 42 | } | ... | ... |
1 | +import EC from 'elliptic' | |
1 | 2 | import { tap } from 'ramda' |
2 | -import { SENATICS_URL } from '../../constants' | |
3 | +import uuid from 'uuid/v1' | |
4 | +import { Buffer } from 'buffer/' | |
5 | +import { ownPrivate } from '../../constants/keys' | |
6 | +import { BACKEND_URL } from '../../constants' | |
7 | + | |
8 | +const ec = new EC.ec('secp256k1') | |
9 | +const clientPriv = ec.keyFromPrivate(ownPrivate) | |
3 | 10 | |
4 | 11 | export const ACCESS_TOKEN_REQUESTED = 'ACCESS_TOKEN_REQUESTED' |
5 | 12 | export const accessTokenRequested = () => ({ |
... | ... | @@ -17,24 +24,19 @@ export const accessTokenReceived = (accessToken) => ({ |
17 | 24 | }) |
18 | 25 | |
19 | 26 | |
20 | -const ACCESS_TOKEN_URL = `${SENATICS_URL}/auth/token` | |
21 | -export const fetchToken = (token, secret) => (dispatch) => { | |
27 | +export const fetchToken = () => (dispatch) => { | |
22 | 28 | dispatch(accessTokenRequested()) |
23 | - | |
24 | - const payload = { | |
25 | - clientSecret: secret | |
26 | - } | |
27 | - | |
29 | + const nonce = uuid() | |
30 | + const firma = new Buffer(clientPriv.sign(nonce).toDER()).toString('hex') | |
28 | 31 | const options = { |
29 | - method: 'POST', | |
30 | - body: JSON.stringify(payload), | |
32 | + method: 'GET', | |
31 | 33 | headers: { |
32 | 34 | Accept: 'application/json', |
33 | 35 | 'Content-Type': 'application/json', |
34 | - Authorization: `Basic ${token}` | |
35 | 36 | }, |
36 | 37 | } |
37 | 38 | |
39 | + const ACCESS_TOKEN_URL = `${BACKEND_URL}/token/${nonce}/${firma}` | |
38 | 40 | const internal = () => fetch(ACCESS_TOKEN_URL, options) |
39 | 41 | .then(response => response.text()) |
40 | 42 | .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | ... | ... |
... | ... | @@ -6,9 +6,9 @@ import { fetchTipoRespuestas } from './tipoRespuestas' |
6 | 6 | import { comprobarExistenciaUsuarioLocal } from './usuario' |
7 | 7 | |
8 | 8 | export const INICIALIZAR_DATOS = 'INICIALIZAR_DATOS' |
9 | -export const inicializarDatos = (authToken, secret) => | |
9 | +export const inicializarDatos = () => | |
10 | 10 | (dispatch, getState) => |
11 | - dispatch(fetchToken(authToken, secret)) | |
11 | + dispatch(fetchToken()) | |
12 | 12 | .then(() => { |
13 | 13 | const accessToken = getState().autenticacion.token |
14 | 14 | return Promise.all([ | ... | ... |
1 | +import EC from 'elliptic' | |
1 | 2 | import { Permissions, Location } from 'expo' |
3 | +import { tap } from 'ramda' | |
4 | +import { Buffer } from 'buffer/' | |
5 | +import { ownPrivate } from '../../constants/keys' | |
6 | +import { BACKEND_URL } from '../../constants' | |
7 | + | |
8 | +const ec = new EC.ec('secp256k1') | |
9 | +const clientPriv = ec.keyFromPrivate(ownPrivate) | |
2 | 10 | |
3 | 11 | export const LOCATION_PERMISSION_REQUESTED = 'LOCATION_PERMISSION_REQUESTED' |
4 | 12 | export const locationPermissionRequested = () => ({ |
... | ... | @@ -6,8 +14,9 @@ export const locationPermissionRequested = () => ({ |
6 | 14 | }) |
7 | 15 | |
8 | 16 | export const LOCATION_PERMISSION_GRANTED = 'LOCATION_PERMISSION_GRANTED' |
9 | -export const locationPermissionGranted = () => ({ | |
10 | - type: LOCATION_PERMISSION_GRANTED | |
17 | +export const locationPermissionGranted = (solicitud) => ({ | |
18 | + type: LOCATION_PERMISSION_GRANTED, | |
19 | + solicitud | |
11 | 20 | }) |
12 | 21 | |
13 | 22 | export const LOCATION_PERMISSION_DENIED = 'LOCATION_PERMISSION_DENIED' |
... | ... | @@ -21,12 +30,12 @@ export const locationPermissionFailed = (error) => ({ |
21 | 30 | error |
22 | 31 | }) |
23 | 32 | |
24 | -export const requestLocationPermission = () => (dispatch) => { | |
33 | +export const requestLocationPermission = (solicitud) => (dispatch) => { | |
25 | 34 | dispatch(locationPermissionRequested()) |
26 | 35 | return Permissions.askAsync(Permissions.LOCATION) |
27 | 36 | .then(({ status }) => { |
28 | 37 | if (status === 'granted') { |
29 | - return dispatch(locationPermissionGranted()) | |
38 | + return dispatch(locationPermissionGranted(solicitud)) | |
30 | 39 | } |
31 | 40 | return dispatch(locationPermissionDenied()) |
32 | 41 | }) |
... | ... | @@ -40,9 +49,10 @@ export const locationRequested = () => ({ |
40 | 49 | }) |
41 | 50 | |
42 | 51 | export const LOCATION_RECEIVED = 'LOCATION_RECEIVED' |
43 | -export const locationReceived = (location) => ({ | |
52 | +export const locationReceived = ({ location, solicitud }) => ({ | |
44 | 53 | type: LOCATION_RECEIVED, |
45 | - location | |
54 | + location, | |
55 | + solicitud | |
46 | 56 | }) |
47 | 57 | |
48 | 58 | export const LOCATION_FAILED = 'LOCATION_FAILED' |
... | ... | @@ -51,9 +61,53 @@ export const locationFailed = (error) => ({ |
51 | 61 | error |
52 | 62 | }) |
53 | 63 | |
54 | -export const requestLocation = () => (dispatch) => { | |
64 | +export const requestLocation = (solicitud) => (dispatch) => { | |
55 | 65 | dispatch(locationRequested()) |
56 | 66 | Location.getCurrentPositionAsync({}) |
57 | - .then(location => dispatch(locationReceived(location))) | |
67 | + .then(location => dispatch(locationReceived({ location, solicitud }))) | |
58 | 68 | .catch(error => dispatch(locationFailed(error))) |
59 | 69 | } |
70 | + | |
71 | + | |
72 | +export const LOCATION_POSTED = 'LOCATION_POSTED' | |
73 | +export const locationPosted = () => ({ | |
74 | + type: LOCATION_POSTED | |
75 | +}) | |
76 | +export const LOCATION_POST_FAILED = 'LOCATION_POST_FAILED' | |
77 | +export const locationPostFailed = (error) => ({ | |
78 | + type: LOCATION_POST_FAILED, | |
79 | + error | |
80 | +}) | |
81 | +export const LOCATION_POST_SUCCESS = 'LOCATION_POST_SUCCESS' | |
82 | +export const locationPostSuccess = (result) => ({ | |
83 | + type: LOCATION_POST_SUCCESS, | |
84 | + result | |
85 | +}) | |
86 | + | |
87 | + | |
88 | +export const postLocation = (location, solicitud) => (dispatch) => { | |
89 | + dispatch(locationPosted()) | |
90 | + const message = JSON.stringify({ location, solicitud }) | |
91 | + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex') | |
92 | + const options = { | |
93 | + method: 'POST', | |
94 | + body: message, | |
95 | + headers: { | |
96 | + Accept: 'application/json', | |
97 | + 'Content-Type': 'application/json', | |
98 | + }, | |
99 | + } | |
100 | + | |
101 | + const url = `${BACKEND_URL}/solicitudes/ubicacion/${firma}` | |
102 | + | |
103 | + const internal = () => fetch(url, options) | |
104 | + .then(response => response.text()) | |
105 | + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | |
106 | + .then(JSON.parse) | |
107 | + .then(json => { | |
108 | + if (json.error) return dispatch(locationPostFailed(json.error)) | |
109 | + return dispatch(locationPostSuccess(json)) | |
110 | + }) | |
111 | + .catch(error => dispatch(locationPostFailed(error))) | |
112 | + return internal() | |
113 | +} | ... | ... |
jaikuaamina-app/redux/actions/reportes.js
0 → 100644
1 | +import EC from 'elliptic' | |
2 | +import { tap } from 'ramda' | |
3 | +import { Buffer } from 'buffer/' | |
4 | +import { BACKEND_URL } from '../../constants' | |
5 | +import { ownPrivate } from '../../constants/keys' | |
6 | + | |
7 | +const ec = new EC.ec('secp256k1') | |
8 | +const clientPriv = ec.keyFromPrivate(ownPrivate) | |
9 | + | |
10 | +export const REPORTE_REQUESTED = 'REPORTE_REQUESTED' | |
11 | +export const reporteRequested = () => ({ | |
12 | + type: REPORTE_REQUESTED | |
13 | +}) | |
14 | + | |
15 | +export const REPORTE_RECEIVED = 'REPORTE_RECEIVED' | |
16 | +export const reporteReceived = ({ reporte }) => ({ | |
17 | + type: REPORTE_RECEIVED, | |
18 | + reporte, | |
19 | +}) | |
20 | + | |
21 | +export const REPORTE_FAILED = 'REPORTE_FAILED' | |
22 | +export const reporteFailed = (error) => ({ | |
23 | + type: REPORTE_FAILED, | |
24 | + error | |
25 | +}) | |
26 | + | |
27 | +export const requestReporte = (id, email) => (dispatch) => { | |
28 | + dispatch(reporteRequested()) | |
29 | + const url = `${BACKEND_URL}/reportes/solicitud/${id}/usuario/${email}/` | |
30 | + const options = { | |
31 | + method: 'GET', | |
32 | + headers: { | |
33 | + Accept: 'application/json', | |
34 | + }, | |
35 | + } | |
36 | + | |
37 | + return fetch(url, options) | |
38 | + .then(response => response.text()) | |
39 | + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | |
40 | + .then(JSON.parse) | |
41 | + .then(json => dispatch(reporteReceived(json))) | |
42 | + .catch(error => dispatch(reporteFailed(error))) | |
43 | +} | |
44 | + | |
45 | + | |
46 | +export const REPORTE_POSTED = 'REPORTE_POSTED' | |
47 | +export const reportePosted = (reporte) => ({ | |
48 | + type: REPORTE_POSTED, | |
49 | + reporte | |
50 | +}) | |
51 | +export const REPORTE_POST_FAILED = 'REPORTE_POST_FAILED' | |
52 | +export const reportePostFailed = () => ({ | |
53 | + type: REPORTE_POST_FAILED | |
54 | +}) | |
55 | +export const REPORTE_POST_SUCCESS = 'REPORTE_POST_SUCCESS' | |
56 | +export const reportePostSuccess = (result) => ({ | |
57 | + type: REPORTE_POST_SUCCESS, | |
58 | + result | |
59 | +}) | |
60 | + | |
61 | + | |
62 | +export const postReporte = (solicitudId, usuario, reporte) => (dispatch) => { | |
63 | + dispatch(reportePosted(reporte)) | |
64 | + const message = JSON.stringify({ reporte, usuario }) | |
65 | + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex') | |
66 | + | |
67 | + const options = { | |
68 | + method: 'POST', | |
69 | + body: message, | |
70 | + headers: { | |
71 | + Accept: 'application/json', | |
72 | + 'Content-Type': 'application/json', | |
73 | + }, | |
74 | + } | |
75 | + | |
76 | + | |
77 | + const url = `${BACKEND_URL}/solicitudes/${solicitudId}/reporte/${firma}` | |
78 | + | |
79 | + const internal = () => fetch(url, options) | |
80 | + .then(response => response.text()) | |
81 | + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | |
82 | + .then(JSON.parse) | |
83 | + .then(json => { | |
84 | + if (json.error) return dispatch(reportePostFailed(json.error)) | |
85 | + return dispatch(reportePostSuccess(json)) | |
86 | + }) | |
87 | + .catch(error => dispatch(reportePostFailed(error))) | |
88 | + return internal() | |
89 | +} | ... | ... |
... | ... | @@ -100,8 +100,9 @@ export const fetchFlujo = (token, solicitudId) => ( |
100 | 100 | |
101 | 101 | |
102 | 102 | export const SOLICITUD_POSTED = 'SOLICITUD_POSTED' |
103 | -export const solicitudPosted = () => ({ | |
104 | - type: SOLICITUD_POSTED | |
103 | +export const solicitudPosted = (solicitud) => ({ | |
104 | + type: SOLICITUD_POSTED, | |
105 | + solicitud | |
105 | 106 | }) |
106 | 107 | export const SOLICITUD_POST_FAILED = 'SOLICITUD_POST_FAILED' |
107 | 108 | export const solicitudPostFailed = () => ({ |
... | ... | @@ -124,7 +125,7 @@ export const notifySolicitud = ({ titulo, institucion }) => () => |
124 | 125 | }) |
125 | 126 | |
126 | 127 | export const postSolicitud = (token, solicitud) => (dispatch) => { |
127 | - dispatch(solicitudPosted()) | |
128 | + dispatch(solicitudPosted(solicitud)) | |
128 | 129 | const options = { |
129 | 130 | method: 'POST', |
130 | 131 | body: JSON.stringify(solicitud), |
... | ... | @@ -142,7 +143,10 @@ export const postSolicitud = (token, solicitud) => (dispatch) => { |
142 | 143 | .then(response => response.text()) |
143 | 144 | .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) |
144 | 145 | .then(JSON.parse) |
145 | - .then(json => dispatch(solicitudPostSuccess(json))) | |
146 | + .then(json => { | |
147 | + if (json.error) return dispatch(solicitudPostFailed(json.error)) | |
148 | + return dispatch(solicitudPostSuccess(json)) | |
149 | + }) | |
146 | 150 | .catch(error => dispatch(solicitudPostFailed(error))) |
147 | 151 | return internal() |
148 | 152 | } | ... | ... |
1 | +import EC from 'elliptic' | |
2 | +import { tap } from 'ramda' | |
3 | +import { Buffer } from 'buffer/' | |
4 | +import { BACKEND_URL } from '../../constants' | |
5 | +import { ownPrivate } from '../../constants/keys' | |
6 | + | |
7 | +const ec = new EC.ec('secp256k1') | |
8 | +const clientPriv = ec.keyFromPrivate(ownPrivate) | |
9 | + | |
10 | +export const VALORACION_REQUESTED = 'VALORACION_REQUESTED' | |
11 | +export const valoracionRequested = () => ({ | |
12 | + type: VALORACION_REQUESTED | |
13 | +}) | |
14 | + | |
15 | +export const VALORACION_RECEIVED = 'VALORACION_RECEIVED' | |
16 | +export const valoracionReceived = ({ valoracion }) => ({ | |
17 | + type: VALORACION_RECEIVED, | |
18 | + valoracion, | |
19 | +}) | |
20 | + | |
21 | +export const VALORACION_FAILED = 'VALORACION_FAILED' | |
22 | +export const valoracionFailed = (error) => ({ | |
23 | + type: VALORACION_FAILED, | |
24 | + error | |
25 | +}) | |
26 | + | |
27 | +export const requestValoracion = (id, email) => (dispatch) => { | |
28 | + dispatch(valoracionRequested()) | |
29 | + const url = `${BACKEND_URL}/valoraciones/solicitud/${id}/usuario/${email}/` | |
30 | + const options = { | |
31 | + method: 'GET', | |
32 | + headers: { | |
33 | + Accept: 'application/json', | |
34 | + }, | |
35 | + } | |
36 | + | |
37 | + return fetch(url, options) | |
38 | + .then(response => response.text()) | |
39 | + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | |
40 | + .then(JSON.parse) | |
41 | + .then(json => dispatch(valoracionReceived(json))) | |
42 | + .catch(error => dispatch(valoracionFailed(error))) | |
43 | +} | |
44 | + | |
45 | + | |
46 | +export const VALORACION_POSTED = 'VALORACION_POSTED' | |
47 | +export const valoracionPosted = (valoracion) => ({ | |
48 | + type: VALORACION_POSTED, | |
49 | + valoracion | |
50 | +}) | |
51 | +export const VALORACION_POST_FAILED = 'VALORACION_POST_FAILED' | |
52 | +export const valoracionPostFailed = () => ({ | |
53 | + type: VALORACION_POST_FAILED | |
54 | +}) | |
55 | +export const VALORACION_POST_SUCCESS = 'VALORACION_POST_SUCCESS' | |
56 | +export const valoracionPostSuccess = (result) => ({ | |
57 | + type: VALORACION_POST_SUCCESS, | |
58 | + result | |
59 | +}) | |
60 | + | |
61 | + | |
62 | +export const postValoracion = (solicitudId, usuario, valoracion) => (dispatch) => { | |
63 | + dispatch(valoracionPosted(valoracion)) | |
64 | + const message = JSON.stringify({ valoracion, usuario }) | |
65 | + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex') | |
66 | + | |
67 | + const options = { | |
68 | + method: 'POST', | |
69 | + body: message, | |
70 | + headers: { | |
71 | + Accept: 'application/json', | |
72 | + 'Content-Type': 'application/json', | |
73 | + }, | |
74 | + } | |
75 | + | |
76 | + | |
77 | + const url = `${BACKEND_URL}/solicitudes/${solicitudId}/valoracion/${firma}` | |
78 | + | |
79 | + const internal = () => fetch(url, options) | |
80 | + .then(response => response.text()) | |
81 | + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) | |
82 | + .then(JSON.parse) | |
83 | + .then(json => { | |
84 | + if (json.error) return dispatch(valoracionPostFailed(json.error)) | |
85 | + return dispatch(valoracionPostSuccess(json)) | |
86 | + }) | |
87 | + .catch(error => dispatch(valoracionPostFailed(error))) | |
88 | + return internal() | |
89 | +} | ... | ... |
jaikuaamina-app/redux/epics/autenticacion.js
0 → 100644
... | ... | @@ -11,6 +11,10 @@ import { |
11 | 11 | } from './logger' |
12 | 12 | |
13 | 13 | import { |
14 | + renewToken | |
15 | +} from './autenticacion' | |
16 | + | |
17 | +import { | |
14 | 18 | askLocationOnPost, |
15 | 19 | getLocationOnGrant, |
16 | 20 | postLocationOnReceive, |
... | ... | @@ -28,5 +32,6 @@ export default combineEpics( |
28 | 32 | postLocationOnReceive, |
29 | 33 | searchDebounce, |
30 | 34 | changePage, |
31 | - getUserIfExists | |
35 | + getUserIfExists, | |
36 | + renewToken | |
32 | 37 | ) | ... | ... |
... | ... | @@ -5,19 +5,19 @@ import { |
5 | 5 | import { |
6 | 6 | requestLocation, |
7 | 7 | requestLocationPermission, |
8 | + postLocation, | |
8 | 9 | LOCATION_PERMISSION_GRANTED, |
9 | 10 | LOCATION_RECEIVED |
10 | 11 | } from '../actions/location' |
11 | 12 | |
12 | 13 | export const askLocationOnPost = (action$) => |
13 | 14 | action$.ofType(SOLICITUD_POSTED) |
14 | - .map(requestLocationPermission) | |
15 | + .map(action => requestLocationPermission(action.solicitud)) | |
15 | 16 | |
16 | 17 | export const getLocationOnGrant = (action$) => |
17 | 18 | action$.ofType(LOCATION_PERMISSION_GRANTED) |
18 | - .map(requestLocation) | |
19 | + .map(action => requestLocation(action.solicitud)) | |
19 | 20 | |
20 | 21 | export const postLocationOnReceive = (action$) => |
21 | 22 | action$.ofType(LOCATION_RECEIVED) |
22 | - .do(console.log) | |
23 | - .ignoreElements() | |
23 | + .map(action => postLocation(action.location, action.solicitud)) | ... | ... |
... | ... | @@ -29,8 +29,3 @@ export const searchDebounce = (action$, store) => |
29 | 29 | export const changePage = (action$, store) => |
30 | 30 | action$.ofType(CAMBIAR_PAGINA_SOLICITUD) |
31 | 31 | .map(() => fetchSolicitudes(getToken(store), getBusqueda(store))) |
32 | - | |
33 | -export const logAll = (action$) => | |
34 | - action$ | |
35 | - .do(console.log) | |
36 | - .ignoreElements() | ... | ... |
... | ... | @@ -3,6 +3,7 @@ import { merge } from 'ramda' |
3 | 3 | import { |
4 | 4 | REQUEST_FORMATOS, |
5 | 5 | RECEIVE_FORMATOS, |
6 | + ERROR_FORMATOS | |
6 | 7 | } from '../actions/formatos' |
7 | 8 | |
8 | 9 | |
... | ... | @@ -22,6 +23,10 @@ export default (state, action) => { |
22 | 23 | return merge( |
23 | 24 | state, |
24 | 25 | { loading: false, data: action.formatos, pages: action.pages }) |
26 | + case ERROR_FORMATOS: | |
27 | + return merge( | |
28 | + state, | |
29 | + { loading: false, data: [], pages: null }) | |
25 | 30 | default: |
26 | 31 | return state || formatos |
27 | 32 | } | ... | ... |
... | ... | @@ -9,6 +9,8 @@ import tipoRespuestas from './tipoRespuestas' |
9 | 9 | import usuario from './usuario' |
10 | 10 | import events from './events' |
11 | 11 | import auxiliares from './auxiliares' |
12 | +import valoracion from './valoraciones' | |
13 | +import reporte from './reportes' | |
12 | 14 | |
13 | 15 | |
14 | 16 | export default combineReducers({ |
... | ... | @@ -21,5 +23,7 @@ export default combineReducers({ |
21 | 23 | tipoRespuestas, |
22 | 24 | usuario, |
23 | 25 | events, |
24 | - auxiliares | |
26 | + auxiliares, | |
27 | + reporte, | |
28 | + valoracion | |
25 | 29 | }) | ... | ... |
jaikuaamina-app/redux/reducers/reportes.js
0 → 100644
1 | +import { merge } from 'ramda' | |
2 | + | |
3 | +import { | |
4 | + REPORTE_REQUESTED, | |
5 | + REPORTE_RECEIVED, | |
6 | + REPORTE_FAILED, | |
7 | + REPORTE_POST_SUCCESS, | |
8 | + REPORTE_POSTED, | |
9 | +} from '../actions/reportes' | |
10 | + | |
11 | + | |
12 | +const reporte = { | |
13 | + data: [], | |
14 | + loading: true, | |
15 | + error: null | |
16 | +} | |
17 | + | |
18 | +export default (state, action) => { | |
19 | + switch (action.type) { | |
20 | + case REPORTE_REQUESTED: | |
21 | + return merge(state, reporte) | |
22 | + case REPORTE_RECEIVED: | |
23 | + return merge(state, { loading: false, error: null, data: action.reporte }) | |
24 | + case REPORTE_POSTED: | |
25 | + return merge(state, { data: action.reporte }) | |
26 | + case REPORTE_POST_SUCCESS: | |
27 | + return merge(state, { data: action.result.reporte }) | |
28 | + case REPORTE_FAILED: | |
29 | + return merge(state, { loading: false, data: null, error: action.error }) | |
30 | + default: | |
31 | + return state || reporte | |
32 | + } | |
33 | +} | ... | ... |
1 | -import { merge, mergeAll, filter, contains, mergeDeepRight } from 'ramda' | |
1 | +import { | |
2 | + contains, | |
3 | + filter, | |
4 | + merge, | |
5 | + mergeDeepRight, | |
6 | + mergeAll, | |
7 | +} from 'ramda' | |
2 | 8 | |
3 | 9 | import { |
4 | 10 | SOLICITUDES_REQUESTED, |
5 | 11 | SOLICITUDES_RECEIVED, |
6 | 12 | SOLICITUDES_FAILED, |
7 | 13 | VER_DETALLE_SOLICITUD, |
8 | - FLUJOS_RECEIVED, FLUJOS_REQUESTED, | |
14 | + FLUJOS_RECEIVED, FLUJOS_REQUESTED, FLUJOS_FAILED, | |
9 | 15 | SOLICITUD_POST_SUCCESS, |
10 | 16 | SOLICITUD_POST_FAILED, |
11 | 17 | SOLICITUD_POSTED, |
... | ... | @@ -84,6 +90,9 @@ export default (state, action) => { |
84 | 90 | case FLUJOS_RECEIVED: |
85 | 91 | return merge(state, { flujos: { loading: false, datos: action.flujos } }) |
86 | 92 | |
93 | + case FLUJOS_FAILED: | |
94 | + return merge(state, { flujos: { loading: false, datos: [], error: action.error } }) | |
95 | + | |
87 | 96 | case SOLICITUD_POST_SUCCESS: |
88 | 97 | return merge(state, { post: { loading: false, error: null, result: action.result } }) |
89 | 98 | ... | ... |
... | ... | @@ -3,6 +3,7 @@ import { merge } from 'ramda' |
3 | 3 | import { |
4 | 4 | REQUEST_SOPORTES, |
5 | 5 | RECEIVE_SOPORTES, |
6 | + ERROR_SOPORTES | |
6 | 7 | } from '../actions/soportes' |
7 | 8 | |
8 | 9 | |
... | ... | @@ -22,6 +23,10 @@ export default (state, action) => { |
22 | 23 | return merge( |
23 | 24 | state, |
24 | 25 | { loading: false, data: action.soportes, pages: action.pages }) |
26 | + case ERROR_SOPORTES: | |
27 | + return merge( | |
28 | + state, | |
29 | + { loading: false, data: [], pages: null }) | |
25 | 30 | default: |
26 | 31 | return state || soportes |
27 | 32 | } | ... | ... |
... | ... | @@ -3,6 +3,7 @@ import { merge } from 'ramda' |
3 | 3 | import { |
4 | 4 | REQUEST_TIPO_RESPUESTAS, |
5 | 5 | RECEIVE_TIPO_RESPUESTAS, |
6 | + ERROR_TIPO_RESPUESTAS, | |
6 | 7 | } from '../actions/tipoRespuestas' |
7 | 8 | |
8 | 9 | |
... | ... | @@ -22,6 +23,10 @@ export default (state, action) => { |
22 | 23 | return merge( |
23 | 24 | state, |
24 | 25 | { loading: false, data: action.tipoRespuestas, pages: action.pages }) |
26 | + case ERROR_TIPO_RESPUESTAS: | |
27 | + return merge( | |
28 | + state, | |
29 | + { loading: false, data: [], pages: null }) | |
25 | 30 | default: |
26 | 31 | return state || tipoRespuestas |
27 | 32 | } | ... | ... |
1 | +import { merge } from 'ramda' | |
2 | + | |
3 | +import { | |
4 | + VALORACION_REQUESTED, | |
5 | + VALORACION_RECEIVED, | |
6 | + VALORACION_FAILED, | |
7 | + VALORACION_POSTED, | |
8 | + VALORACION_POST_SUCCESS | |
9 | +} from '../actions/valoraciones' | |
10 | + | |
11 | + | |
12 | +const valoracion = { | |
13 | + data: null, | |
14 | + loading: true, | |
15 | + error: null | |
16 | +} | |
17 | + | |
18 | +const toggle = (state, val) => { | |
19 | + if (state.valoracion === val) { | |
20 | + return null | |
21 | + } | |
22 | + return val | |
23 | +} | |
24 | + | |
25 | +export default (state, action) => { | |
26 | + switch (action.type) { | |
27 | + case VALORACION_REQUESTED: | |
28 | + return merge(state, valoracion) | |
29 | + case VALORACION_POSTED: | |
30 | + return merge(state, { data: toggle(state, action.valoracion) }) | |
31 | + case VALORACION_POST_SUCCESS: | |
32 | + return merge(state, { data: action.result.valoracion }) | |
33 | + case VALORACION_RECEIVED: | |
34 | + return merge(state, { loading: false, error: null, data: action.valoracion }) | |
35 | + case VALORACION_FAILED: | |
36 | + return merge(state, { loading: false, data: null, error: action.error }) | |
37 | + default: | |
38 | + return state || valoracion | |
39 | + } | |
40 | +} | ... | ... |
1 | -import 'moment/locale/es' | |
2 | 1 | import React, { Component } from 'react' |
3 | -import { View, Text } from 'react-native' | |
2 | +import { Button } from 'react-native-elements' | |
3 | +import { View, Text, Linking } from 'react-native' | |
4 | 4 | import { connect } from 'react-redux' |
5 | + | |
6 | +import { | |
7 | + PORTAL_DENUNCIAS_URL, | |
8 | + TUTORIAL_AIF_URL, | |
9 | + TUTORIAL_APP | |
10 | +} from '../../constants' | |
11 | + | |
5 | 12 | import css from './style' |
6 | 13 | // AIP Movil |
7 | 14 | |
8 | -class Estadistica extends Component { | |
9 | - static navigationOptions = () => ({ | |
15 | +class Ayuda extends Component { | |
16 | + static navigationOptions = ({ navigation }) => ({ | |
10 | 17 | title: 'Ayuda', |
11 | 18 | headerStyle: css.headerStyle, |
12 | - headerTitleStyle: css.headerTitleStyle | |
19 | + headerTitleStyle: css.headerTitleStyle, | |
20 | + headerLeft: | |
21 | + <Button | |
22 | + icon={{ name: 'menu', size: 27, color: 'white' }} | |
23 | + buttonStyle={{ backgroundColor: 'transparent' }} | |
24 | + onPress={() => navigation.toggleDrawer()} | |
25 | + /> | |
13 | 26 | }); |
27 | + myHandlePress = (link) => () => { | |
28 | + Linking.openURL(link) | |
29 | + } | |
14 | 30 | |
15 | 31 | |
16 | 32 | render() { |
17 | 33 | return ( |
18 | - <View style={[css.pane, css.fixStatusBar]}> | |
19 | - <Text> AYUDA </Text> | |
34 | + <View style={[css.pane, css.distribute]}> | |
35 | + <View> | |
36 | + <Text style={css.label}> | |
37 | + ¿Quieres saber más? | |
38 | + </Text> | |
39 | + <Button | |
40 | + buttonStyle={css.btn} | |
41 | + onPress={this.myHandlePress(TUTORIAL_AIF_URL)} | |
42 | + title="Ver Tutorial de Información Pública" | |
43 | + /> | |
44 | + </View> | |
45 | + <View> | |
46 | + <Text style={css.label}> | |
47 | + Aun no sé como usar la App | |
48 | + </Text> | |
49 | + <Button | |
50 | + buttonStyle={css.btn} | |
51 | + onPress={this.myHandlePress(TUTORIAL_APP)} | |
52 | + title="¿Cómo usar la App?" | |
53 | + /> | |
54 | + </View> | |
55 | + <View> | |
56 | + <Text style={css.label}> | |
57 | + No quiero información... Quiero Denunciar! | |
58 | + </Text> | |
59 | + <Button | |
60 | + buttonStyle={css.btn} | |
61 | + onPress={this.myHandlePress(PORTAL_DENUNCIAS_URL)} | |
62 | + title="Ir al Portal de Denuncias" | |
63 | + /> | |
64 | + </View> | |
20 | 65 | </View> |
21 | 66 | ) |
22 | 67 | } |
... | ... | @@ -28,4 +73,4 @@ const mapStateToProps = () => ({ |
28 | 73 | const mapDispatchToProps = () => ({ |
29 | 74 | }) |
30 | 75 | |
31 | -export default connect(mapStateToProps, mapDispatchToProps)(Estadistica) | |
76 | +export default connect(mapStateToProps, mapDispatchToProps)(Ayuda) | ... | ... |
1 | 1 | import { StyleSheet } from 'react-native' |
2 | 2 | import { merge } from 'ramda' |
3 | 3 | |
4 | -import styles from '../../common/styles' | |
4 | +import styles, { colors } from '../../common/styles' | |
5 | 5 | |
6 | 6 | export default merge(StyleSheet.create({ |
7 | - | |
7 | + distribute: { | |
8 | + justifyContent: 'space-evenly', | |
9 | + }, | |
10 | + btn: { | |
11 | + backgroundColor: colors.primary, | |
12 | + margin: 10, | |
13 | + }, | |
8 | 14 | }), styles) | ... | ... |
... | ... | @@ -35,8 +35,6 @@ const navegarSiguiente = (self, requeridos) => { |
35 | 35 | if (validateNext(requeridos)) { |
36 | 36 | self.props.navigation.dispatch(resetAction) |
37 | 37 | self.props.guardarUsuarioLocal(self.props.usuario) |
38 | - } else { | |
39 | - console.log('escribir mensajes de validacion') | |
40 | 38 | } |
41 | 39 | } |
42 | 40 | ... | ... |
... | ... | @@ -7,18 +7,25 @@ import { |
7 | 7 | } from 'react-native' |
8 | 8 | import { connect } from 'react-redux' |
9 | 9 | import { HeaderBackButton } from 'react-navigation' |
10 | -import { map } from 'ramda' | |
11 | - | |
10 | +import { map, contains } from 'ramda' | |
12 | 11 | import { Card, Divider, Text, Button } from 'react-native-elements' |
13 | 12 | import HTML from 'react-native-render-html' |
14 | 13 | |
15 | -import { INFO_PY_URL } from '../../constants' | |
14 | +import { INFO_PY_URL, ESTADOS_SOLICITUDES } from '../../constants' | |
16 | 15 | import { fetchFlujo } from '../../redux/actions/solicitudes' |
16 | +import { requestValoracion } from '../../redux/actions/valoraciones' | |
17 | +import { requestReporte } from '../../redux/actions/reportes' | |
18 | + | |
17 | 19 | import css from './style' |
18 | 20 | import DefaultIndicator from '../../components/DefaultIndicator' |
21 | +import BotonValoracion from '../../components/BotonValoracion' | |
19 | 22 | |
20 | 23 | const makeSolicitudURL = (solicitud) => `${INFO_PY_URL}/#!/ciudadano/solicitud/${solicitud.id}` |
21 | 24 | |
25 | +const esFinal = (solicitud) => contains( | |
26 | + solicitud.estado.nombre, | |
27 | + ESTADOS_SOLICITUDES.finalizados) | |
28 | + | |
22 | 29 | class PaginaDetalle extends Component { |
23 | 30 | static navigationOptions = ({ navigation }) => ({ |
24 | 31 | title: 'Detalles de solicitud', |
... | ... | @@ -37,6 +44,8 @@ class PaginaDetalle extends Component { |
37 | 44 | |
38 | 45 | componentDidMount() { |
39 | 46 | this.props.fetchFlujo(this.props.token, this.props.solicitud.id) |
47 | + this.props.requestValoracion(this.props.solicitud.id, this.props.miUsuario.mail) | |
48 | + this.props.requestReporte(this.props.solicitud.id, this.props.miUsuario.mail) | |
40 | 49 | } |
41 | 50 | |
42 | 51 | render() { |
... | ... | @@ -84,6 +93,11 @@ class PaginaDetalle extends Component { |
84 | 93 | </Card> |
85 | 94 | {props.flujos.loading ? spinner : flujos(props.flujos.datos)} |
86 | 95 | </ScrollView> |
96 | + <BotonValoracion | |
97 | + mostrar={esFinal(props.solicitud)} | |
98 | + reporte={props.reporte} | |
99 | + valoracion={props.valoracion} | |
100 | + /> | |
87 | 101 | </View> |
88 | 102 | ) |
89 | 103 | } |
... | ... | @@ -94,10 +108,15 @@ const mapStateToProps = (state) => ({ |
94 | 108 | token: state.autenticacion.token, |
95 | 109 | flujos: state.solicitudes.flujos, |
96 | 110 | usuario: state.solicitudes.current.usuario, |
111 | + miUsuario: state.usuario.datos, | |
112 | + valoracion: state.valoracion, | |
113 | + repote: state.reporte | |
97 | 114 | }) |
98 | 115 | |
99 | 116 | const mapDispatchToProps = dispatch => ({ |
100 | - fetchFlujo: (token, solicitudId) => dispatch(fetchFlujo(token, solicitudId)) | |
117 | + fetchFlujo: (token, solicitudId) => dispatch(fetchFlujo(token, solicitudId)), | |
118 | + requestValoracion: (solicitud, usuario) => dispatch(requestValoracion(solicitud, usuario)), | |
119 | + requestReporte: (solicitud, usuario) => dispatch(requestReporte(solicitud, usuario)) | |
101 | 120 | }) |
102 | 121 | |
103 | 122 | export default connect(mapStateToProps, mapDispatchToProps)(PaginaDetalle) | ... | ... |
... | ... | @@ -33,12 +33,10 @@ const makePicker = (onChange, dato, current) => ( |
33 | 33 | const validateNext = none(either(isNil, isEmpty)) |
34 | 34 | const navigateNext = (self, requeridos) => { |
35 | 35 | if (validateNext(requeridos)) { |
36 | - const pushAction = StackActions.push({ | |
37 | - routeName: 'ConfirmarSolicitud' | |
38 | - }) | |
39 | - self.props.navigation.dispatch(pushAction) | |
40 | - } else { | |
41 | - console.log('no pasar') | |
36 | + const pushAction = StackActions.push({ | |
37 | + routeName: 'ConfirmarSolicitud' | |
38 | + }) | |
39 | + self.props.navigation.dispatch(pushAction) | |
42 | 40 | } |
43 | 41 | } |
44 | 42 | ... | ... |
... | ... | @@ -7,9 +7,6 @@ import { connect } from 'react-redux' |
7 | 7 | import { NavigationActions, StackActions } from 'react-navigation' |
8 | 8 | import { all, not, identity } from 'ramda' |
9 | 9 | |
10 | - | |
11 | -import { AUTH_TOKEN, CLIENT_SECRET } from '../../constants' | |
12 | - | |
13 | 10 | import DefaultIndicator from '../../components/DefaultIndicator' |
14 | 11 | |
15 | 12 | import { inicializarDatos } from '../../redux/actions/inicio' |
... | ... | @@ -34,7 +31,7 @@ const goToUserDetails = StackActions.reset({ |
34 | 31 | class Splash extends Component { |
35 | 32 | |
36 | 33 | componentWillMount() { |
37 | - this.props.inicializarDatos(AUTH_TOKEN, CLIENT_SECRET) | |
34 | + this.props.inicializarDatos() | |
38 | 35 | } |
39 | 36 | |
40 | 37 | |
... | ... | @@ -81,7 +78,7 @@ const mapStateToProps = (state) => ({ |
81 | 78 | }) |
82 | 79 | |
83 | 80 | const mapDispatchToProps = (dispatch) => ({ |
84 | - inicializarDatos: (token, secret) => dispatch(inicializarDatos(token, secret)), | |
81 | + inicializarDatos: () => dispatch(inicializarDatos()), | |
85 | 82 | }) |
86 | 83 | |
87 | 84 | export default connect(mapStateToProps, mapDispatchToProps)(Splash) | ... | ... |
... | ... | @@ -1258,12 +1258,14 @@ |
1258 | 1258 | "balanced-match": { |
1259 | 1259 | "version": "1.0.0", |
1260 | 1260 | "bundled": true, |
1261 | - "dev": true | |
1261 | + "dev": true, | |
1262 | + "optional": true | |
1262 | 1263 | }, |
1263 | 1264 | "brace-expansion": { |
1264 | 1265 | "version": "1.1.11", |
1265 | 1266 | "bundled": true, |
1266 | 1267 | "dev": true, |
1268 | + "optional": true, | |
1267 | 1269 | "requires": { |
1268 | 1270 | "balanced-match": "^1.0.0", |
1269 | 1271 | "concat-map": "0.0.1" |
... | ... | @@ -1278,17 +1280,20 @@ |
1278 | 1280 | "code-point-at": { |
1279 | 1281 | "version": "1.1.0", |
1280 | 1282 | "bundled": true, |
1281 | - "dev": true | |
1283 | + "dev": true, | |
1284 | + "optional": true | |
1282 | 1285 | }, |
1283 | 1286 | "concat-map": { |
1284 | 1287 | "version": "0.0.1", |
1285 | 1288 | "bundled": true, |
1286 | - "dev": true | |
1289 | + "dev": true, | |
1290 | + "optional": true | |
1287 | 1291 | }, |
1288 | 1292 | "console-control-strings": { |
1289 | 1293 | "version": "1.1.0", |
1290 | 1294 | "bundled": true, |
1291 | - "dev": true | |
1295 | + "dev": true, | |
1296 | + "optional": true | |
1292 | 1297 | }, |
1293 | 1298 | "core-util-is": { |
1294 | 1299 | "version": "1.0.2", |
... | ... | @@ -1405,7 +1410,8 @@ |
1405 | 1410 | "inherits": { |
1406 | 1411 | "version": "2.0.3", |
1407 | 1412 | "bundled": true, |
1408 | - "dev": true | |
1413 | + "dev": true, | |
1414 | + "optional": true | |
1409 | 1415 | }, |
1410 | 1416 | "ini": { |
1411 | 1417 | "version": "1.3.5", |
... | ... | @@ -1417,6 +1423,7 @@ |
1417 | 1423 | "version": "1.0.0", |
1418 | 1424 | "bundled": true, |
1419 | 1425 | "dev": true, |
1426 | + "optional": true, | |
1420 | 1427 | "requires": { |
1421 | 1428 | "number-is-nan": "^1.0.0" |
1422 | 1429 | } |
... | ... | @@ -1431,6 +1438,7 @@ |
1431 | 1438 | "version": "3.0.4", |
1432 | 1439 | "bundled": true, |
1433 | 1440 | "dev": true, |
1441 | + "optional": true, | |
1434 | 1442 | "requires": { |
1435 | 1443 | "brace-expansion": "^1.1.7" |
1436 | 1444 | } |
... | ... | @@ -1438,12 +1446,14 @@ |
1438 | 1446 | "minimist": { |
1439 | 1447 | "version": "0.0.8", |
1440 | 1448 | "bundled": true, |
1441 | - "dev": true | |
1449 | + "dev": true, | |
1450 | + "optional": true | |
1442 | 1451 | }, |
1443 | 1452 | "minipass": { |
1444 | 1453 | "version": "2.2.4", |
1445 | 1454 | "bundled": true, |
1446 | 1455 | "dev": true, |
1456 | + "optional": true, | |
1447 | 1457 | "requires": { |
1448 | 1458 | "safe-buffer": "^5.1.1", |
1449 | 1459 | "yallist": "^3.0.0" |
... | ... | @@ -1462,6 +1472,7 @@ |
1462 | 1472 | "version": "0.5.1", |
1463 | 1473 | "bundled": true, |
1464 | 1474 | "dev": true, |
1475 | + "optional": true, | |
1465 | 1476 | "requires": { |
1466 | 1477 | "minimist": "0.0.8" |
1467 | 1478 | } |
... | ... | @@ -1542,7 +1553,8 @@ |
1542 | 1553 | "number-is-nan": { |
1543 | 1554 | "version": "1.0.1", |
1544 | 1555 | "bundled": true, |
1545 | - "dev": true | |
1556 | + "dev": true, | |
1557 | + "optional": true | |
1546 | 1558 | }, |
1547 | 1559 | "object-assign": { |
1548 | 1560 | "version": "4.1.1", |
... | ... | @@ -1554,6 +1566,7 @@ |
1554 | 1566 | "version": "1.4.0", |
1555 | 1567 | "bundled": true, |
1556 | 1568 | "dev": true, |
1569 | + "optional": true, | |
1557 | 1570 | "requires": { |
1558 | 1571 | "wrappy": "1" |
1559 | 1572 | } |
... | ... | @@ -1675,6 +1688,7 @@ |
1675 | 1688 | "version": "1.0.2", |
1676 | 1689 | "bundled": true, |
1677 | 1690 | "dev": true, |
1691 | + "optional": true, | |
1678 | 1692 | "requires": { |
1679 | 1693 | "code-point-at": "^1.0.0", |
1680 | 1694 | "is-fullwidth-code-point": "^1.0.0", | ... | ... |
jaikuaamina-server/public/index.html
0 → 100644
1 | +<!doctype html> | |
2 | +<html class="no-js" lang=""> | |
3 | + | |
4 | +<head> | |
5 | + <meta charset="utf-8"> | |
6 | + <meta http-equiv="x-ua-compatible" content="ie=edge"> | |
7 | + <title></title> | |
8 | + <meta name="description" content=""> | |
9 | + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
10 | + | |
11 | +</head> | |
12 | + | |
13 | +<body> | |
14 | + <p>Hello world! This is HTML5 Boilerplate.</p> | |
15 | +</body> | |
16 | + | |
17 | +</html> | ... | ... |
1 | -hola mundo |
Please
register
or
login
to post a comment