Commit 8046d829 authored by Phuengton Chummuel's avatar Phuengton Chummuel

add notification

parent 23fb75a0
......@@ -137,6 +137,7 @@ android {
}
dependencies {
compile project(':react-native-picker')
compile project(':realm')
compile project(':react-native-push-notification')
compile ('com.google.android.gms:play-services-gcm:11.4.2') {
......
......@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
......@@ -31,6 +32,7 @@
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
......@@ -3,6 +3,7 @@ package com.pillminder;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.beefe.picker.PickerViewPackage;
import io.realm.react.RealmReactPackage;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
import co.apptailor.googlesignin.RNGoogleSigninPackage;
......@@ -30,6 +31,7 @@ public class MainApplication extends Application implements ReactApplication {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new PickerViewPackage(),
new RealmReactPackage(),
new ReactNativePushNotificationPackage(),
new RNGoogleSigninPackage(),
......
rootProject.name = 'PillMinder'
include ':react-native-picker'
project(':react-native-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-picker/android')
include ':realm'
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
include ':react-native-push-notification'
......
......@@ -61,6 +61,7 @@
E171D72366A84D4F895C1793 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3810037A43F84AEF8BE2AEDF /* libRealmReact.a */; };
3E4551D5ECD34C78B5CA9466 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B233663AAC4D56B48CE593 /* libc++.tbd */; };
EC83982BEE5B40FE8C6A1CBF /* libRNCamera.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E75D49961054457590A5CFEF /* libRNCamera.a */; };
8E168B3CFE9A490CB89C0114 /* libRCTBEEPickerManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE5A4E9780D3422CB7E6E167 /* libRCTBEEPickerManager.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -319,6 +320,8 @@
83B233663AAC4D56B48CE593 /* libc++.tbd */ = {isa = PBXFileReference; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; };
8984A4BE9AA646DFA3628D48 /* RNCamera.xcodeproj */ = {isa = PBXFileReference; name = "RNCamera.xcodeproj"; path = "../node_modules/react-native-camera/ios/RNCamera.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
E75D49961054457590A5CFEF /* libRNCamera.a */ = {isa = PBXFileReference; name = "libRNCamera.a"; path = "libRNCamera.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
A8ED09151DE3412BA00A7359 /* RCTBEEPickerManager.xcodeproj */ = {isa = PBXFileReference; name = "RCTBEEPickerManager.xcodeproj"; path = "../node_modules/react-native-picker/ios/RCTBEEPickerManager.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
EE5A4E9780D3422CB7E6E167 /* libRCTBEEPickerManager.a */ = {isa = PBXFileReference; name = "libRCTBEEPickerManager.a"; path = "libRCTBEEPickerManager.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -358,6 +361,7 @@
E171D72366A84D4F895C1793 /* libRealmReact.a in Frameworks */,
3E4551D5ECD34C78B5CA9466 /* libc++.tbd in Frameworks */,
EC83982BEE5B40FE8C6A1CBF /* libRNCamera.a in Frameworks */,
8E168B3CFE9A490CB89C0114 /* libRCTBEEPickerManager.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -532,6 +536,7 @@
8DBECF570FB04728BF3A6D66 /* RNGoogleSignin.xcodeproj */,
2E3477DB564D4B6CB4679C62 /* RealmReact.xcodeproj */,
8984A4BE9AA646DFA3628D48 /* RNCamera.xcodeproj */,
A8ED09151DE3412BA00A7359 /* RCTBEEPickerManager.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
......@@ -1136,6 +1141,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
......@@ -1145,6 +1151,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Debug;
......@@ -1171,6 +1178,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
......@@ -1180,6 +1188,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Release;
......@@ -1207,6 +1216,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Debug;
......@@ -1233,6 +1243,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Release;
......@@ -1268,6 +1279,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
......@@ -1277,6 +1289,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Debug;
......@@ -1312,6 +1325,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
......@@ -1321,6 +1335,7 @@
"$(SRCROOT)/../node_modules/react-native-google-signin/ios/RNGoogleSignin/**",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
"$(SRCROOT)/../node_modules/react-native-picker/ios/RCTBEEPickerManager",
);
};
name = Release;
......@@ -1351,6 +1366,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
};
name = Debug;
......@@ -1381,6 +1397,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
};
name = Release;
......
......@@ -7375,6 +7375,11 @@
}
}
},
"react-native-picker": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/react-native-picker/-/react-native-picker-4.3.5.tgz",
"integrity": "sha1-v3kd3mkIAooRqss/3HxrK9ss0/M="
},
"react-native-push-notification": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/react-native-push-notification/-/react-native-push-notification-3.0.2.tgz",
......
......@@ -29,6 +29,7 @@ export function scheduleLocalNotification(message, date, id, payload) {
date: fireDate,
//for android only
data: JSON.stringify(payload),
repeatType: 'day'
};
//schedule the notification
......@@ -61,7 +62,7 @@ export function cancleNotification(id) {
export function generateID() {
let d = new Date().getTime();
let id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let id = 'xxxy'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(5);
......@@ -69,3 +70,18 @@ export function generateID() {
return id;
}
export const futch = (url, opts = {}, onProgress) => {
console.log(url, opts)
return new Promise((res, rej) => {
var xhr = new XMLHttpRequest();
xhr.open(opts.method || 'get', url);
for (var k in opts.headers || {})
xhr.setRequestHeader(k, opts.headers[k]);
xhr.onload = e => res(e.target);
xhr.onerror = rej;
if (xhr.upload && onProgress)
xhr.upload.onprogress = onProgress; // event.loaded / event.total * 100 ; //event.lengthComputable
xhr.send(opts.body);
});
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import {
} from './../actions/types'
import realm from './../Database/'
import moment from 'moment'
import { ToastAndroid } from 'react-native'
import { appointmentNotification, cancleNotification } from './../Utils'
export const appointmentCreate = ({ id, doctorName, date, place, time }) => {
return (dispatch) => {
......@@ -20,6 +20,9 @@ export const appointmentCreate = ({ id, doctorName, date, place, time }) => {
timeStamp: moment().toDate()
})
})
var time = moment(date).format('HH:mm').split(':')
var msg = "แจ้งเตือนนัดพบแพทย์\n" + "แพทย์: " + doctorName + "\nเวลา: " + time[0] + ":" + time[1];
appointmentNotification(msg, date, id)
let appointments = realm.objects("Appointments")
dispatch({ type: APPOINTMENT_CREATE, payload: appointments })
}
......@@ -44,6 +47,7 @@ export const appointmentDelete = (id) => {
realm.write(() => {
realm.delete(item)
})
cancleNotification(id)
let appointments = realm.objects("Appointments")
dispatch({ type: APPOINTMENT_DELETE, payload: appointments })
}
......
......@@ -6,7 +6,7 @@ import {
} from './../actions/types'
import realm from './../Database/'
import moment from 'moment'
import { ToastAndroid } from 'react-native'
import { scheduleLocalNotification, cancleNotification } from './../Utils'
export const reminderCreate = ({ id, medName, reminderTime, meal, period, dose }) => {
return (dispatch) => {
......@@ -21,6 +21,9 @@ export const reminderCreate = ({ id, medName, reminderTime, meal, period, dose }
timeStamp: moment().toDate()
})
})
var time = moment(date).format('HH:mm').split(':')
var msg = "แจ้งเตือนกินยา\n" + "เวลา: " + time[0] + ":" + time[1] + "\nยา: " + medName + '\n' + meal;
scheduleLocalNotification(msg, reminderTime, id)
let reminders = realm.objects("Reminder")
dispatch({ type: REMINDER_CREATE, payload: reminders })
}
......@@ -45,6 +48,7 @@ export const reminderDelete = (id) => {
realm.write(() => {
realm.delete(item)
})
cancleNotification(id)
let reminders = realm.objects("Reminder")
dispatch({ type: REMINDER_DELETE, payload: reminders })
}
......
import React, { Component } from 'react'
import { TouchableOpacity } from 'react-native'
import {
View,
Text,
Picker,
Item
} from 'native-base'
import { SinglePickerMaterialDialog } from 'react-native-material-dialog'
import { ToastAndroid } from 'react-native'
import realm from './../Database'
class ReminderDialogForm extends Component {
constructor(props) {
super(props);
this.state = {
selectedTime: '',
selectedBeforeAfter: '',
morningTime: '',
afternoonTime: '',
eveningTime: '',
nightTime: '',
beforeMeal: 'ก่อนอาหาร',
afterMeal: 'หลังอาหาร',
singlePickerVisible: false,
dose: '1'
}
}
componentWillMount() {
let timePeriod = realm.objects('TimePeriod')
var morningTime = timePeriod[0].morning
var afternoonTime = timePeriod[0].afternoon
var eveningTime = timePeriod[0].evening
var nightTime = timePeriod[0].night
this.setState({ morningTime, afternoonTime, eveningTime, nightTime })
}
render() {
const dose = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
const { uploadProgress, imageToText } = this.props
const Loading = ({ uploadProgress }) => {
return (
<View>
<Text>{"Upload : " + uploadProgress + "%\n"}</Text>
</View>
)
}
if (uploadProgress !== "100") {
return <Loading uploadProgress={uploadProgress} />;
} else {
if (imageToText && imageToText.closeMatches != -1) {
return (
<View>
<Text>{imageToText.closeMatches}</Text>
<Picker
selectedValue={this.state.selectedTime}
onValueChange={(value) => this.setState({ selectedTime: value })}
>
<Picker.Item label={this.state.morningTime} value={this.state.morningTime} />
<Picker.Item label={this.state.afternoonTime} value={this.state.afternoonTime} />
<Picker.Item label={this.state.eveningTime} value={this.state.eveningTime} />
<Picker.Item label={this.state.nightTime} value={this.state.nightTime} />
</Picker>
<Picker
selectedValue={this.state.selectedBeforeAfter}
onValueChange={(value) => this.setState({ selectedBeforeAfter: value })}
>
<Picker.Item label={this.state.beforeMeal} value={this.state.beforeMeal} />
<Picker.Item label={this.state.afterMeal} value={this.state.afterMeal} />
</Picker>
<SinglePickerMaterialDialog
title={'Dose'}
scrolled
items={dose.map((row, index) => ({ value: index, label: row }))}
visible={this.state.singlePickerVisible}
selectedItem={this.state.singlePickerSelectedItem}
onCancel={() => this.setState({ singlePickerVisible: false })}
onOk={result => {
this.setState({ singlePickerVisible: false });
this.setState({ dose: result.selectedItem["label"].toString() });
}} />
<TouchableOpacity onPress={() => this.setState({ singlePickerVisible: true })}>
<Text>{"Dose: " + this.state.dose}</Text>
</TouchableOpacity>
</View>
)
} else if (imageToText && imageToText.closeMatches == -1) {
return (
<View>
<Text>{"Medicine Name Not Found."}</Text>
</View>
)
} else {
return (
<View>
<Text>{"In Progress.."}</Text>
</View>
)
}
}
}
}
export default ReminderDialogForm;
\ No newline at end of file
......@@ -6,11 +6,14 @@ import {
View,
TouchableOpacity
} from 'react-native';
import { IMAGE_TO_TEXT } from './../ServiceUrl'
import { IMAGE_TO_TEXT } from './../ServiceUrl';
import { Container, Header, Content, Icon, Button } from 'native-base';
import { MaterialDialog } from 'react-native-material-dialog'
import { RNCamera } from 'react-native-camera'
import { scheduleLocalNotification, appointmentNotification } from './../Utils';
import { MaterialDialog } from 'react-native-material-dialog';
import { RNCamera } from 'react-native-camera';
import { scheduleLocalNotification, appointmentNotification, futch } from './../Utils';
import { connect } from 'react-redux'
import { reminderCreate } from './../actions'
import ReminderDialogForm from './../components/ReminderDialogForm';
import moment from 'moment';
import realm from './../Database/';
......@@ -24,7 +27,10 @@ class AppCamera extends Component {
eveningTime: "",
nightTime: "",
addItemVisible: true,
visible: true,
visible: false,
imageToText: "",
uploadProgress: "0",
addReminder: false
}
}
......@@ -47,6 +53,7 @@ class AppCamera extends Component {
}}
style={styles.preview}
type={RNCamera.Constants.Type.back}
fixOrientation={true}
permissionDialogTitle={'Permission to use camera'}
permissionDialogMessage={'We need your permission to use your camera phone'}
/>
......@@ -58,11 +65,24 @@ class AppCamera extends Component {
<Text style={{ fontSize: 14 }}> SNAP </Text>
</TouchableOpacity>
</View>
<MaterialDialog
title="Add Reminder"
visible={this.state.visible}
onOk={() => this.setState({ visible: false, imageToText: '', uploadProgress: '0' })}
onCancel={() => this.setState({ visible: false, imageToText: '', uploadProgress: '0' })}>
<ReminderDialogForm
uploadProgress={this.state.uploadProgress}
imageToText={this.state.imageToText}
/>
</MaterialDialog>
</Container >
);
}
takePicture = async function () {
this.setState({ visible: true })
if (this.camera) {
const options = { quality: 0.5, base64: true };
const data = await this.camera.takePictureAsync(options)
......@@ -73,13 +93,16 @@ class AppCamera extends Component {
name: 'image'
})
fetch(IMAGE_TO_TEXT, {
futch(IMAGE_TO_TEXT, {
method: 'post',
body: image
}, (progressEvent) => {
const progress = (progressEvent.loaded / progressEvent.total) * 100;
this.setState({ uploadProgress: parseInt(progress).toString() })
}).then(res => {
ToastAndroid.show(JSON.stringify(res.body.closeMatches), ToastAndroid.LONG)
this.setState({ imageToText: JSON.parse(res._response) })
}).catch(err => {
ToastAndroid.show(JSON.stringify(err), ToastAndroid.LONG)
this.setState({ imageToText: JSON.stringify(err) })
})
}
......@@ -129,4 +152,4 @@ const styles = StyleSheet.create({
}
});
export default AppCamera;
\ No newline at end of file
export default connect(null, { reminderCreate })(AppCamera);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment