Commit c634a92a authored by Phuengton Chummuel's avatar Phuengton Chummuel

add medicine & appointment reminder via qrcode

parent 1ff53183
This diff is collapsed.
...@@ -9,7 +9,9 @@ let realm = new Realm({ ...@@ -9,7 +9,9 @@ let realm = new Realm({
medName: 'string', medName: 'string',
reminderTime: 'date', reminderTime: 'date',
meal: 'string', meal: 'string',
period: 'int' period: 'int',
dose: 'string',
timeStamp: 'date',
} }
}, { }, {
name: 'TimePeriod', name: 'TimePeriod',
...@@ -17,9 +19,19 @@ let realm = new Realm({ ...@@ -17,9 +19,19 @@ let realm = new Realm({
morning: 'string', morning: 'string',
afternoon: 'string', afternoon: 'string',
evening: 'string', evening: 'string',
night: 'string' night: 'string',
} }
}] }, {
name: 'Appointments',
properties: {
id: 'int',
doctorName: 'string',
date: 'date',
place: 'string',
timeStamp: 'date'
}
}
]
}) })
export default realm; export default realm;
\ No newline at end of file
...@@ -31,6 +31,26 @@ export function scheduleLocalNotification(message, date, id, payload) { ...@@ -31,6 +31,26 @@ export function scheduleLocalNotification(message, date, id, payload) {
data: JSON.stringify(payload), data: JSON.stringify(payload),
}; };
//schedule the notification
PushNotification.localNotificationSchedule(notification);
}
export function appointmentNotification(message, date, id, payload) {
//message: type String
//date: type String format 'YYYY-MM-DD HH:mm' (NOTIFICATION_DATE_TIME_FORMAT)
//construct the notification parameters
// const fireDate = moment(date, NOTIFICATION_DATE_TIME_FORMAT).toDate();
const fireDate = date
const notification = {
id: id, //for android cancel notification (must be stringified number)
message,
number: 0, //necessary for iOS cancellation (not sure why)
date: fireDate,
//for android only
data: JSON.stringify(payload),
};
//schedule the notification //schedule the notification
PushNotification.localNotificationSchedule(notification); PushNotification.localNotificationSchedule(notification);
} }
\ No newline at end of file
...@@ -13,7 +13,7 @@ import { ...@@ -13,7 +13,7 @@ import {
class AppHeader extends Component { class AppHeader extends Component {
render() { render() {
return ( return (
<Header> <Header style={this.props.headerStyle}>
<Left> <Left>
{this.props.headerLeft} {this.props.headerLeft}
</Left> </Left>
......
...@@ -8,55 +8,88 @@ import SettingsScreen from './../screens/SettingsScreen'; ...@@ -8,55 +8,88 @@ import SettingsScreen from './../screens/SettingsScreen';
import MedicationsScreen from './../screens/MedicationsScreen'; import MedicationsScreen from './../screens/MedicationsScreen';
import SignInScreen from './../screens/SignInScreen'; import SignInScreen from './../screens/SignInScreen';
import MainScreen from './../screens/MainScreen'; import MainScreen from './../screens/MainScreen';
import SettingsTimePeriod from './../screens/SettingsTimePeriod' import SettingsTimePeriod from './../screens/SettingsTimePeriod';
import ReminderDetail from './../screens/ReminderDetail' import ReminderDetail from './../screens/ReminderDetail';
import AppointmentsScreen from './../screens/AppointmentsScreen' import AppointmentsScreen from './../screens/AppointmentsScreen';
import MedicationsListScreen from './../screens/MedicationListScreen';
import AppointmentsListScreen from './../screens/AppointmentListScreen';
const HomeNavigator = StackNavigator({
Home: {
screen: HomeScreen
},
Detail: {
screen: ReminderDetail
}
}, {
headerMode: 'none'
})
const CameraNavigator = StackNavigator({
Camera: {
screen: CameraScreen,
},
PreviewPhoto: {
screen: PreviewPhotoScreen,
}
}, {
headerMode: 'none'
})
const SettingsNavigator = StackNavigator({
Settings: {
screen: SettingsScreen
},
SettingsTime: {
screen: SettingsTimePeriod
}
}, {
headerMode: 'none'
})
const MedicationsNavigator = StackNavigator({
MedicationsList: {
screen: MedicationsListScreen
},
AddMedication: {
screen: MedicationsScreen
}
}, {
headerMode: 'none'
})
const AppointmentsNavigator = StackNavigator({
AppointmentsList: {
screen: AppointmentsListScreen,
},
AddAppointment: {
screen: AppointmentsScreen,
}
}, {
headerMode: 'none'
})
const RootNavigator = StackNavigator( const RootNavigator = StackNavigator(
{ {
Home: { Home: {
screen: DrawerNavigator({ screen: DrawerNavigator({
Home: { Home: {
screen: StackNavigator({ screen: HomeNavigator,
Home: {
screen: HomeScreen
},
Detail: {
screen: ReminderDetail
}
}, {
headerMode: 'none'
})
}, },
Camera: { Camera: {
screen: StackNavigator({ screen: CameraNavigator,
Camera: {
screen: CameraScreen,
},
PreviewPhoto: {
screen: PreviewPhotoScreen,
}
}, {
headerMode: 'none'
}),
}, },
Medications: { Medications: {
screen: MedicationsScreen screen: MedicationsNavigator
}, },
Appointments: { Appointments: {
screen: AppointmentsScreen screen: AppointmentsNavigator,
}, },
Settings: { Settings: {
screen: StackNavigator({ screen: SettingsNavigator,
Settings: {
screen: SettingsScreen
},
SettingsTime: {
screen: SettingsTimePeriod
}
}, {
headerMode: 'none'
})
} }
}) })
}, },
......
import React, { Component } from 'react';
import {
Container,
Content,
View,
Text,
Button,
Icon,
List,
ListItem,
Right,
Left,
} from 'native-base';
import AppHeader from './../components/Header';
import realm from './../Database/';
import moment from 'moment';
class AppointmentListScreen extends Component {
constructor(props) {
super(props)
this.state = {
appointmentList: [],
}
}
componentWillMount() {
this._queryDbAppointment()
}
render() {
const { appointmentListStyle } = styles
const { goBack } = this.props.navigation
return (
<Container>
<AppHeader
headerText={"Appointments"}
headerLeft={
<Button onPress={() => goBack(null)}>
<Icon name='arrow-back' />
</Button>
}
headerRight={
<Button onPress={() => this._addAppointment()}>
<Icon name='add' />
</Button>
}
/>
<Content>
<Text>Appointment List</Text>
<List dataArray={this.state.appointmentList}
renderRow={(item) =>
<ListItem style={appointmentListStyle}>
<View style={{ flex: 1 }}>
<Text>{"Doctor: " + item.doctorName}</Text>
<Text>{"Date: " + moment(item.date).format("DD MM YYYY")}</Text>
<Text>{"Time: " + moment(item.date).format("HH:mm")}</Text>
<Text>{"Place: " + item.place}</Text>
</View>
<View>
<Icon name='more' />
</View>
</ListItem>
}>
</List>
</Content>
</Container>
)
}
_addAppointment() {
this.props.navigation.navigate("AddAppointment")
}
_queryDbAppointment() {
const tmpAppointment = realm.objects("Appointments")
this.setState({ appointmentList: tmpAppointment })
}
}
const styles = {
appointmentListStyle: {
marginLeft: 0,
marginRight: 0,
marginTop: 0,
marginBottom: 0,
padding: 15,
}
}
export default AppointmentListScreen;
\ No newline at end of file
import React from 'react'; import React from 'react';
import { DatePickerAndroid, TimePickerAndroid, Alert, Keyboard } from 'react-native'; import { DatePickerAndroid, TimePickerAndroid, Alert, Keyboard, ToastAndroid } from 'react-native';
import { import {
Container, Container,
Content, Content,
...@@ -15,6 +15,7 @@ import { ...@@ -15,6 +15,7 @@ import {
import AppHeader from './../components/Header'; import AppHeader from './../components/Header';
import MedForm from './../components/MedForm'; import MedForm from './../components/MedForm';
import { Grid, Col } from 'react-native-easy-grid'; import { Grid, Col } from 'react-native-easy-grid';
import { appointmentNotification } from './../Utils';
import realm from './../Database'; import realm from './../Database';
import moment from 'moment'; import moment from 'moment';
...@@ -80,12 +81,12 @@ class AppointmentsScreen extends React.Component { ...@@ -80,12 +81,12 @@ class AppointmentsScreen extends React.Component {
<Grid> <Grid>
<Col> <Col>
<Button full style={btnAddNoti}> <Button full style={btnAddNoti} onPress={() => this._onResetPressed()}>
<Text style={{ color: "#1686C4" }}>Reset</Text> <Text style={{ color: "#1686C4" }}>Reset</Text>
</Button> </Button>
</Col> </Col>
<Col> <Col>
<Button full style={btnAddNoti}> <Button full style={btnAddNoti} onPress={() => this._addAppointment()}>
<Text style={{ color: "#1686C4" }}>Add</Text> <Text style={{ color: "#1686C4" }}>Add</Text>
</Button> </Button>
</Col> </Col>
...@@ -96,8 +97,59 @@ class AppointmentsScreen extends React.Component { ...@@ -96,8 +97,59 @@ class AppointmentsScreen extends React.Component {
) )
} }
_onResetPressed() {
realm.write(() => {
let allReminder = realm.objects('Appointments')
realm.delete(allReminder)
})
ToastAndroid.show("reset", ToastAndroid.SHORT)
}
_addAppointment() { _addAppointment() {
if (this.state.doctor && this.state.date && this.state.time) {
Alert.alert(
'Confrim?',
'Are you sure to add this appointment?',
[
{ text: 'CANCLE', onPress: () => ToastAndroid.show("Cancled", ToastAndroid.SHORT) },
{
text: 'OK', onPress: () => {
var id = Math.random() * 10000
var time = this.state.time.split(':')
var appointmentDate = moment(this.state.date).hour(time[0]).minute(time[1]).second(0).toDate()
var msg = "แจ้งเตือนการนัดพบแพทย์\n" + "แพทย์: " + this.state.doctor + "เวลา: " + this.state.time
appointmentNotification(msg, appointmentDate, id)
realm.write(() => {
realm.create('Appointments', {
id: id,
doctorName: this.state.doctor,
date: appointmentDate,
place: this.state.place,
timeStamp: moment().toDate()
})
})
this.props.navigation.goBack(null)
}
},
],
{ cancelable: false }
)
} else {
Alert.alert(
'Please enter Doctor name / Select appointment date and time',
'',
[
{ text: 'OK', onPress: () => ToastAndroid.show("Please enter medine name / Select reminder time", ToastAndroid.SHORT) },
],
{ cancelable: false }
)
}
} }
_datePicker() { _datePicker() {
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import { BackHandler, ToastAndroid } from 'react-native'; import { BackHandler, ToastAndroid, Alert } from 'react-native';
import { import {
Dimensions, Dimensions,
StyleSheet, StyleSheet,
Text, Text,
View View
} from 'react-native'; } from 'react-native';
import { Container, Header, Content, Icon, Button } from 'native-base'; import { Container, Header, Content, Icon, Button } from 'native-base';
import { MaterialDialog } from 'react-native-material-dialog'
import Camera from 'react-native-camera'; import Camera from 'react-native-camera';
import { scheduleLocalNotification, appointmentNotification } from './../Utils';
import moment from 'moment';
import realm from './../Database/';
class AppCamera extends Component { class AppCamera extends Component {
constructor(props) {
super(props)
this.state = {
morningTime: "",
afternoonTime: "",
eveningTime: "",
nightTime: "",
addItemVisible: true,
visible: true,
}
}
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() { render() {
return ( return (
<Container style={styles.container}> <Container style={styles.container}>
...@@ -23,13 +48,14 @@ class AppCamera extends Component { ...@@ -23,13 +48,14 @@ class AppCamera extends Component {
aspect={Camera.constants.Aspect.fill} aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.temp} captureTarget={Camera.constants.CaptureTarget.temp}
playSoundOnCapture={false} playSoundOnCapture={false}
onBarCodeRead={(data, type) => this._onBarCodeRead(data, type)}
defaultTouchToFocus> defaultTouchToFocus>
<Button onPress={this.takePicture.bind(this)} style={styles.capture}> <Button onPress={this.takePicture.bind(this)} style={styles.capture}>
<Text>[CAPTURE]</Text> <Text>[CAPTURE]</Text>
</Button> </Button>
</Camera> </Camera>
</Container> </Container >
); );
} }
...@@ -44,6 +70,117 @@ class AppCamera extends Component { ...@@ -44,6 +70,117 @@ class AppCamera extends Component {
.catch(err => console.error(err)); .catch(err => console.error(err));
} }
_onBarCodeRead(data, type) {
if (data.type == 'QR_CODE') {
var tmpData = JSON.parse(decodeURI(data.data))
switch (tmpData.type) {
case "medicine":
if (this.state.addItemVisible) {
this._addMedicine(tmpData)
this.setState({ addItemVisible: false })
}
break;
case "appointment":
if (this.state.addItemVisible) {
this._addAppointment(tmpData)
this.setState({ addItemVisible: false })
}
break;
}
}
}
_addMedicine(data) {
var time = null
switch (data.period) {
case 1:
time = this.state.morningTime.split(":")
break;
case 2:
time = this.state.afternoonTime.split(":")
break;
case 3:
time = this.state.eveningTime.split(":")
break;
case 4:
time = this.state.nightTime.split(":")
break;
}
Alert.alert(
'Confrim?',
JSON.stringify(data),
[
{ text: 'CANCLE', onPress: () => this.setState({ addItemVisible: true }) },
{
text: 'OK', onPress: () => {
var id = Math.random() * 10000
var reminderDate = moment().hour(time[0]).minute(time[1]).second(0).toDate()
var beforeMeal = data.beforeMeal ? "\tก่อนอาหาร" : "\tหลังอาหาร";
var msg = "แจ้งเตือนกินยา\n" + "เวลา: " + time[0] + ":" + time[1] + "\nยา: " + data.medName + beforeMeal;
scheduleLocalNotification(msg, reminderDate, id)
realm.write(() => {
realm.create('Reminder', {
id: id,
medName: data.medName,
reminderTime: reminderDate,
meal: beforeMeal.trim(),
period: data.period,
dose: data.dose.toString(),
timeStamp: moment().toDate()
})
})
this.props.navigation.goBack(null)
}
},
],
{ cancelable: false }
)
}
_addAppointment(data) {
const time = data.date.split(':')
Alert.alert(
'Confrim?',
"Doctor: " + data.doctorName + "\nDate: " + moment(data.date).format("DD MMM YYYY") + "\nTime: " + moment(data.date).format("HH:mm") + "\nPlace: " + data.place,
[
{ text: 'CANCLE', onPress: () => this.setState({ addItemVisible: true }) },
{
text: 'OK', onPress: () => {
var id = Math.random() * 10000
var appointmentDate = moment(data.date).hour(time[0]).minute(time[1]).second(0).toDate()
var msg = "แจ้งเตือนการนัดพบแพทย์\n" + "แพทย์: " + data.doctorName + "เวลา: " + moment(data.date).format("HH:mm")
appointmentNotification(msg, appointmentDate, id)
realm.write(() => {
realm.create('Appointments', {
id: id,
doctorName: data.doctorName,
date: appointmentDate,
place: data.place,
timeStamp: moment().toDate()
})
})
this.props.navigation.goBack(null)
}
},
],
{ cancelable: false }
)
}
} }
......
...@@ -23,8 +23,8 @@ import { formatDate } from './../Utils'; ...@@ -23,8 +23,8 @@ import { formatDate } from './../Utils';
import realm from './../Database'; import realm from './../Database';
class HomeScreen extends Component { class HomeScreen extends Component {
constructor() { constructor(props) {
super(); super(props);
this.state = { this.state = {
firstLaunch: null, firstLaunch: null,
active: false, active: false,
...@@ -117,7 +117,7 @@ class HomeScreen extends Component { ...@@ -117,7 +117,7 @@ class HomeScreen extends Component {
} }
onAddMedicinePressed() { onAddMedicinePressed() {
this.props.navigation.navigate('Medications') this.props.navigation.navigate('AddMedication')
} }
onMenuPressed() { onMenuPressed() {
......
import React, { Component } from 'react';
import {
Container,
Content,
View,
Button,
Icon,
Text,
List,
ListItem
} from 'native-base';
import AppHeader from './../components/Header';
import realm from './../Database/'
class MedicationListScreen extends Component {
constructor(props) {
super(props)
this.state = {
reminderList: []
}
}
componentWillMount() {
this._queryMedicineList()
}
render() {
const { reminderListStyle } = styles
const { goBack } = this.props.navigation
return (
<Container>
<AppHeader
headerText={"Medications"}
headerLeft={
<Button onPress={() => goBack(null)}>
<Icon name='arrow-back' />
</Button>
}
headerRight={
<Button onPress={() => this._addReminder()}>
<Icon name='add' />
</Button>
}
/>
<Content>
<Text>Reminder List</Text>
<List dataArray={this.state.reminderList}
renderRow={(item) =>
<ListItem style={reminderListStyle}>
<Text>{item.medName}</Text>
</ListItem>
}>
</List>
</Content>
</Container>
)
}
_queryMedicineList() {
var tmpReminder = realm.objects("Reminder")
this.setState({ reminderList: tmpReminder })
}
_addReminder() {
this.props.navigation.navigate("AddMedication")
}
}
const styles = {
reminderListStyle: {
marginLeft: 0,
marginRight: 0,
marginTop: 0,
marginBottom: 0,
padding: 15
}
}
export default MedicationListScreen;
\ No newline at end of file
...@@ -2,7 +2,7 @@ import React, { Component } from 'react'; ...@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { DeviceEventEmitter, ToastAndroid, Alert } from 'react-native'; import { DeviceEventEmitter, ToastAndroid, Alert } from 'react-native';
import { formatDate, scheduleLocalNotification } from './../Utils'; import { formatDate, scheduleLocalNotification } from './../Utils';
import { Grid, Col } from 'react-native-easy-grid'; import { Grid, Col } from 'react-native-easy-grid';
import { MaterialDialog } from 'react-native-material-dialog'; import { SinglePickerMaterialDialog } from 'react-native-material-dialog';
import PushNotification from 'react-native-push-notification'; import PushNotification from 'react-native-push-notification';
import { import {
Container, Container,
...@@ -67,7 +67,9 @@ class MedicationsScreen extends Component { ...@@ -67,7 +67,9 @@ class MedicationsScreen extends Component {
nightTime: "", nightTime: "",
beforeMeal: true, beforeMeal: true,
afterMeal: false, afterMeal: false,
visible: null, dose: '1',
singlePickerVisible: false,
singlePickerSelectedItem: undefined
}; };
} }
...@@ -99,16 +101,19 @@ class MedicationsScreen extends Component { ...@@ -99,16 +101,19 @@ class MedicationsScreen extends Component {
} }
render() { render() {
var { goBack } = this.props.navigation
var { timeStyle, btnAddNoti } = styles; var { timeStyle, btnAddNoti } = styles;
const dose = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
return ( return (
<Container> <Container>
<AppHeader <AppHeader
headerText={'Medications'} headerText={'Add Medication'}
headerLeft={ headerLeft={
<Button onPress={this._onMenuPressed.bind(this)}> <Button onPress={() => goBack(null)}>
<Icon name='menu' /> <Icon name='arrow-back' />
</Button> </Button>
} }
/> />
...@@ -200,15 +205,23 @@ class MedicationsScreen extends Component { ...@@ -200,15 +205,23 @@ class MedicationsScreen extends Component {
</MedForm> </MedForm>
<MedForm titleText={"Dose"}> <MedForm titleText={"Dose"}>
{/* <MaterialDialog <View style={{ padding: 15 }}>
title="Use Google's Location Service?" <Button style={{ backgroundColor: 'white' }} onPress={() => this.setState({ singlePickerVisible: true })}>
visible={true} <Text style={{ color: "#1686C4" }}>{this.state.dose}</Text>
onOk={() => this.setState({ visible: false })} </Button>
onCancel={() => this.setState({ visible: false })}>
<Text style={styles.dialogText}> <SinglePickerMaterialDialog
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running. title={'Pick one element!'}
</Text> scrolled
</MaterialDialog>; */} 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() });
}} />
</View>
</MedForm> </MedForm>
...@@ -305,7 +318,9 @@ class MedicationsScreen extends Component { ...@@ -305,7 +318,9 @@ class MedicationsScreen extends Component {
medName: this.state.text, medName: this.state.text,
reminderTime: reminderDate, reminderTime: reminderDate,
meal: beforeMeal.trim(), meal: beforeMeal.trim(),
period: period period: period,
dose: this.state.dose,
timeStamp: moment().toDate()
}) })
}) })
} }
......
...@@ -19,13 +19,16 @@ class Menu extends Component { ...@@ -19,13 +19,16 @@ class Menu extends Component {
} }
render() { render() {
var { goBack } = this.props.navigation
return ( return (
<Container> <Container>
<AppHeader <AppHeader
headerText={"Setting"} headerText={"Setting"}
headerLeft={ headerLeft={
<Button onPress={this._onMenuPressed.bind(this)}> <Button onPress={() => goBack(null)}>
<Icon name='menu' /> <Icon name='arrow-back' />
</Button> </Button>
} }
/> />
......
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