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({
medName: 'string',
reminderTime: 'date',
meal: 'string',
period: 'int'
period: 'int',
dose: 'string',
timeStamp: 'date',
}
}, {
name: 'TimePeriod',
......@@ -17,9 +19,19 @@ let realm = new Realm({
morning: 'string',
afternoon: 'string',
evening: 'string',
night: 'string'
night: 'string',
}
}]
}, {
name: 'Appointments',
properties: {
id: 'int',
doctorName: 'string',
date: 'date',
place: 'string',
timeStamp: 'date'
}
}
]
})
export default realm;
\ No newline at end of file
......@@ -34,3 +34,23 @@ export function scheduleLocalNotification(message, date, id, 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
PushNotification.localNotificationSchedule(notification);
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ import {
class AppHeader extends Component {
render() {
return (
<Header>
<Header style={this.props.headerStyle}>
<Left>
{this.props.headerLeft}
</Left>
......
......@@ -8,55 +8,88 @@ import SettingsScreen from './../screens/SettingsScreen';
import MedicationsScreen from './../screens/MedicationsScreen';
import SignInScreen from './../screens/SignInScreen';
import MainScreen from './../screens/MainScreen';
import SettingsTimePeriod from './../screens/SettingsTimePeriod'
import ReminderDetail from './../screens/ReminderDetail'
import AppointmentsScreen from './../screens/AppointmentsScreen'
import SettingsTimePeriod from './../screens/SettingsTimePeriod';
import ReminderDetail from './../screens/ReminderDetail';
import AppointmentsScreen from './../screens/AppointmentsScreen';
import MedicationsListScreen from './../screens/MedicationListScreen';
import AppointmentsListScreen from './../screens/AppointmentListScreen';
const RootNavigator = StackNavigator(
{
Home: {
screen: DrawerNavigator({
Home: {
screen: StackNavigator({
const HomeNavigator = StackNavigator({
Home: {
screen: HomeScreen
},
Detail: {
screen: ReminderDetail
}
}, {
}, {
headerMode: 'none'
})
},
Camera: {
screen: StackNavigator({
const CameraNavigator = StackNavigator({
Camera: {
screen: CameraScreen,
},
PreviewPhoto: {
screen: PreviewPhotoScreen,
}
}, {
}, {
headerMode: 'none'
}),
},
Medications: {
screen: MedicationsScreen
},
Appointments: {
screen: AppointmentsScreen
},
Settings: {
screen: StackNavigator({
})
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(
{
Home: {
screen: DrawerNavigator({
Home: {
screen: HomeNavigator,
},
Camera: {
screen: CameraNavigator,
},
Medications: {
screen: MedicationsNavigator
},
Appointments: {
screen: AppointmentsNavigator,
},
Settings: {
screen: SettingsNavigator,
}
})
},
......
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 { DatePickerAndroid, TimePickerAndroid, Alert, Keyboard } from 'react-native';
import { DatePickerAndroid, TimePickerAndroid, Alert, Keyboard, ToastAndroid } from 'react-native';
import {
Container,
Content,
......@@ -15,6 +15,7 @@ import {
import AppHeader from './../components/Header';
import MedForm from './../components/MedForm';
import { Grid, Col } from 'react-native-easy-grid';
import { appointmentNotification } from './../Utils';
import realm from './../Database';
import moment from 'moment';
......@@ -80,12 +81,12 @@ class AppointmentsScreen extends React.Component {
<Grid>
<Col>
<Button full style={btnAddNoti}>
<Button full style={btnAddNoti} onPress={() => this._onResetPressed()}>
<Text style={{ color: "#1686C4" }}>Reset</Text>
</Button>
</Col>
<Col>
<Button full style={btnAddNoti}>
<Button full style={btnAddNoti} onPress={() => this._addAppointment()}>
<Text style={{ color: "#1686C4" }}>Add</Text>
</Button>
</Col>
......@@ -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() {
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() {
......
import React, { Component } from 'react';
import { BackHandler, ToastAndroid } from 'react-native';
import { BackHandler, ToastAndroid, Alert } from 'react-native';
import {
Dimensions,
StyleSheet,
Text,
View
} from 'react-native';
import { Container, Header, Content, Icon, Button } from 'native-base';
import { MaterialDialog } from 'react-native-material-dialog'
import Camera from 'react-native-camera';
import { scheduleLocalNotification, appointmentNotification } from './../Utils';
import moment from 'moment';
import realm from './../Database/';
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() {
return (
<Container style={styles.container}>
......@@ -23,13 +48,14 @@ class AppCamera extends Component {
aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.temp}
playSoundOnCapture={false}
onBarCodeRead={(data, type) => this._onBarCodeRead(data, type)}
defaultTouchToFocus>
<Button onPress={this.takePicture.bind(this)} style={styles.capture}>
<Text>[CAPTURE]</Text>
</Button>
</Camera>
</Container>
</Container >
);
}
......@@ -44,6 +70,117 @@ class AppCamera extends Component {
.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';
import realm from './../Database';
class HomeScreen extends Component {
constructor() {
super();
constructor(props) {
super(props);
this.state = {
firstLaunch: null,
active: false,
......@@ -117,7 +117,7 @@ class HomeScreen extends Component {
}
onAddMedicinePressed() {
this.props.navigation.navigate('Medications')
this.props.navigation.navigate('AddMedication')
}
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';
import { DeviceEventEmitter, ToastAndroid, Alert } from 'react-native';
import { formatDate, scheduleLocalNotification } from './../Utils';
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 {
Container,
......@@ -67,7 +67,9 @@ class MedicationsScreen extends Component {
nightTime: "",
beforeMeal: true,
afterMeal: false,
visible: null,
dose: '1',
singlePickerVisible: false,
singlePickerSelectedItem: undefined
};
}
......@@ -99,16 +101,19 @@ class MedicationsScreen extends Component {
}
render() {
var { goBack } = this.props.navigation
var { timeStyle, btnAddNoti } = styles;
const dose = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
return (
<Container>
<AppHeader
headerText={'Medications'}
headerText={'Add Medication'}
headerLeft={
<Button onPress={this._onMenuPressed.bind(this)}>
<Icon name='menu' />
<Button onPress={() => goBack(null)}>
<Icon name='arrow-back' />
</Button>
}
/>
......@@ -200,15 +205,23 @@ class MedicationsScreen extends Component {
</MedForm>
<MedForm titleText={"Dose"}>
{/* <MaterialDialog
title="Use Google's Location Service?"
visible={true}
onOk={() => this.setState({ visible: false })}
onCancel={() => this.setState({ visible: false })}>
<Text style={styles.dialogText}>
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
</Text>
</MaterialDialog>; */}
<View style={{ padding: 15 }}>
<Button style={{ backgroundColor: 'white' }} onPress={() => this.setState({ singlePickerVisible: true })}>
<Text style={{ color: "#1686C4" }}>{this.state.dose}</Text>
</Button>
<SinglePickerMaterialDialog
title={'Pick one element!'}
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() });
}} />
</View>
</MedForm>
......@@ -305,7 +318,9 @@ class MedicationsScreen extends Component {
medName: this.state.text,
reminderTime: reminderDate,
meal: beforeMeal.trim(),
period: period
period: period,
dose: this.state.dose,
timeStamp: moment().toDate()
})
})
}
......
......@@ -19,13 +19,16 @@ class Menu extends Component {
}
render() {
var { goBack } = this.props.navigation
return (
<Container>
<AppHeader
headerText={"Setting"}
headerLeft={
<Button onPress={this._onMenuPressed.bind(this)}>
<Icon name='menu' />
<Button onPress={() => goBack(null)}>
<Icon name='arrow-back' />
</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