├── README.md ├── __tests__ └── App.js ├── app.json ├── demo.gif ├── index.js ├── package.json └── src ├── Components ├── DateBarItem.js ├── EditModal.js └── TodoItem.js ├── helper ├── Array.js ├── Date.js └── Language.js └── screens ├── Add.js └── Home.js /README.md: -------------------------------------------------------------------------------- 1 | # react-native-todo 2 | Very lightweight and smooth design todo app with react-native 3 | 4 | 5 | ## How to install ? 6 | ``` bash 7 | # Install necessary packages 8 | yarn install 9 | 10 | # Create android&ios folder 11 | react-native eject 12 | 13 | # Update native files 14 | react-native link 15 | 16 | # Run app on emulator 17 | react-native run-android 18 | react-native run-ios 19 | ``` 20 | 21 | ## Demo 22 |

23 | 24 |

25 | -------------------------------------------------------------------------------- /__tests__/App.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import App from '../App'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Todo", 3 | "displayName": "Todo" 4 | } -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irfansener/react-native-todo/5370bd3e87afc88fbdb206942d597ae4288bcf73/demo.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src/screens/Home'; 3 | 4 | AppRegistry.registerComponent('Todo', () => App); 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Todo", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest" 8 | }, 9 | "dependencies": { 10 | "native-base": "^2.3.9", 11 | "react": "16.2.0", 12 | "react-native": "0.53.0", 13 | "react-native-modal": "^5.0.1", 14 | "react-native-modal-datetime-picker": "^4.13.0" 15 | }, 16 | "devDependencies": { 17 | "babel-jest": "22.2.2", 18 | "babel-preset-react-native": "4.0.0", 19 | "jest": "22.2.2", 20 | "react-test-renderer": "16.2.0" 21 | }, 22 | "jest": { 23 | "preset": "react-native" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Components/DateBarItem.js: -------------------------------------------------------------------------------- 1 | //import liraries 2 | import React, { Component } from 'react'; 3 | import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; 4 | import DateHelper from '../helper/Date'; 5 | 6 | // create a component 7 | class DateBarItem extends Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | now: props.now.getUTCDate(), 12 | date: props.date.item.date, 13 | } 14 | } 15 | componentWillReceiveProps(props) { 16 | this.setState({ now: props.now.getUTCDate() }); 17 | } 18 | isSelect() { 19 | if (this.state.now == this.state.date.getUTCDate()) { 20 | const style = { color: 'black' }; 21 | return style; 22 | } 23 | } 24 | setDate() { 25 | this.props.setDate(this.state.date) 26 | } 27 | render() { 28 | return ( 29 | this.setDate()}> 30 | 34 | {this.state.date.getDate()} 35 | {DateHelper.getDayName(this.state.date, false)} 36 | 37 | 38 | ); 39 | } 40 | } 41 | 42 | // define your styles 43 | const styles = StyleSheet.create({ 44 | perDay: { 45 | width: 42, 46 | display: 'flex', 47 | flexDirection: 'column', 48 | }, 49 | daySmInt: { 50 | color: '#C75F46', 51 | fontSize: 18, 52 | textAlign: 'center' 53 | }, 54 | daySmString: { 55 | color: '#C75F46', 56 | fontSize: 14, 57 | textAlign: 'center' 58 | }, 59 | }); 60 | 61 | //make this component available to the app 62 | export default DateBarItem; 63 | -------------------------------------------------------------------------------- /src/Components/EditModal.js: -------------------------------------------------------------------------------- 1 | //import liraries 2 | import React, { Component } from 'react'; 3 | import { View, Text, StyleSheet, Button, TextInput, TouchableOpacity, AsyncStorage, Alert } from 'react-native'; 4 | import DateTimePicker from 'react-native-modal-datetime-picker'; 5 | import DateHelper from '../helper/Date'; 6 | import ArrayHelper from '../helper/Array'; 7 | import _ from '../helper/Language'; 8 | 9 | // create a component 10 | class EditModal extends Component { 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | id: props.id, 15 | name: '', 16 | location: '', 17 | time: '', 18 | date: '', 19 | datePickerVisible: false, 20 | timePickerVisible: false, 21 | } 22 | } 23 | componentWillMount() { 24 | AsyncStorage.getItem('list').then(data => { 25 | let array = JSON.parse(data); 26 | const index = ArrayHelper.find(array, this.state.id); 27 | const { name, location, time, date } = array[index]; 28 | this.setState({ name, location, time, date }); 29 | }) 30 | } 31 | addNewTodo() { 32 | if (this.state.name.length < 1) { 33 | Alert.alert(_('nameRequired')); 34 | } 35 | else { 36 | const { name, location, time, date } = this.state; 37 | AsyncStorage.getItem('list').then(data => { 38 | let newArray = JSON.parse(data); 39 | const index = ArrayHelper.find(newArray, this.state.id); 40 | newArray[index].name = name; 41 | newArray[index].location = location; 42 | newArray[index].time = time; 43 | newArray[index].date = date; 44 | const upData = JSON.stringify(newArray); 45 | AsyncStorage.setItem('list', upData); 46 | this.props.updateData(); 47 | this.props.closeModal(); 48 | }) 49 | } 50 | } 51 | onClosePicker() { 52 | this.setState({ datePickerVisible: false, timePickerVisible: false }) 53 | } 54 | render() { 55 | return ( 56 | 57 | 58 | {_('editTask')} 59 | this.setState({ name })} 62 | value={this.state.name} 63 | placeholder={_('taskName')} 64 | returnKeyType="next" 65 | selectTextOnFocus={true} 66 | onSubmitEditing={() => this.location.focus()} 67 | /> 68 | this.setState({ location })} 71 | value={this.state.location} 72 | placeholder={_('location')} 73 | returnKeyType="next" 74 | onSubmitEditing={() => this.setState({ datePickerVisible: true })} 75 | ref={(input) => this.location = input} 76 | /> 77 | 78 | this.setState({ datePickerVisible: true })}> 79 | 80 | {this.state.date} 81 | 82 | 83 | this.setState({ timePickerVisible: true })}> 84 | 85 | {this.state.time ? this.state.time : _('hour')} 86 | 87 | 88 | 89 | this.addNewTodo()}> 90 | {_('edit')} 91 | 92 | this.setState({ date: DateHelper.getDate(date) })} 95 | onCancel={() => this.onClosePicker()} 96 | mode="date" 97 | /> 98 | this.setState({ time: DateHelper.getTime(time) })} 101 | onCancel={() => this.onClosePicker()} 102 | mode="time" 103 | /> 104 | 105 | 106 | ); 107 | } 108 | } 109 | 110 | // define your styles 111 | const styles = StyleSheet.create({ 112 | modalContainer: { 113 | flex: 1, 114 | justifyContent: 'center', 115 | alignItems: 'center', 116 | borderRadius: 10, 117 | }, 118 | innerContainer: { 119 | backgroundColor: "white", 120 | height: 300, 121 | width: '90%', 122 | borderRadius: 10, 123 | padding: 20 124 | }, 125 | h1: { 126 | color: 'black', 127 | fontSize: 18, 128 | marginTop: 10, 129 | marginBottom: 10, 130 | marginLeft: 10 131 | }, 132 | input: { 133 | borderBottomColor: 'gray', 134 | color: 'black', 135 | fontWeight: '800', 136 | fontSize: 18 137 | }, 138 | addButton: { 139 | backgroundColor: '#ee7659', 140 | color: 'white', 141 | fontWeight: '600', 142 | textAlign: 'center', 143 | lineHeight: 45, 144 | fontSize: 18, 145 | width: '90%', 146 | marginTop: 20, 147 | marginLeft: '5%', 148 | borderRadius: 25 149 | }, 150 | dateTime: { 151 | flexDirection: 'row', 152 | justifyContent: 'space-around' 153 | }, 154 | dateTimeInput: { 155 | width: 90, 156 | height: 40, 157 | fontWeight: '500', 158 | textAlign: 'center', 159 | textAlignVertical: 'center', 160 | borderBottomColor: 'black', 161 | borderBottomWidth: 1 162 | } 163 | }); 164 | 165 | //make this component available to the app 166 | export default EditModal; 167 | -------------------------------------------------------------------------------- /src/Components/TodoItem.js: -------------------------------------------------------------------------------- 1 | //import liraries 2 | import React, { Component } from 'react'; 3 | import { View, Text, StyleSheet, TouchableOpacity, Dimensions, Alert } from 'react-native'; 4 | import { SwipeRow, Button, Icon } from 'native-base'; 5 | import DateHelper from '../helper/Date'; 6 | import _ from '../helper/Language'; 7 | 8 | const { width, height } = Dimensions.get('window'); 9 | class TodoItem extends Component { 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | stateText: _('loading'), 14 | stateColor: 'black', 15 | borderBottomColor: 'grey', 16 | } 17 | } 18 | componentWillReceiveProps() { 19 | // State 0 bekliyor, 1 tamamlandi, 2 iptal edildi 20 | if (this.props.item.state === 0) { 21 | this.setState({ stateText: ' ', stateColor: '#202824', borderBottomColor: '#EAEAEA' }); 22 | } 23 | if (this.props.item.state === 1) { 24 | this.setState({ stateText: _('done'), stateColor: '#7ED221', borderBottomColor: '#7ED221' }); 25 | } 26 | if (this.props.item.state === 2) { 27 | this.setState({ stateText: _('cancel'), stateColor: '#DE0A0A', borderBottomColor: '#DE0A0A' }); 28 | } 29 | } 30 | componentWillMount() { 31 | // State 0 bekliyor, 1 tamamlandi, 2 iptal edildi 32 | if (this.props.item.state === 0) { 33 | this.setState({ stateText: ' ', stateColor: '#202824', borderBottomColor: '#EAEAEA' }); 34 | } 35 | if (this.props.item.state === 1) { 36 | this.setState({ stateText: _('done'), stateColor: '#7ED221', borderBottomColor: '#7ED221' }); 37 | } 38 | if (this.props.item.state === 2) { 39 | this.setState({ stateText: _('cancel'), stateColor: '#DE0A0A', borderBottomColor: '#DE0A0A' }); 40 | } 41 | } 42 | render() { 43 | return ( 44 | 45 | this.props.changeState(this.props.item.id)} > 50 | 51 | {DateHelper.getMonthName(this.props.item.date)} {this.props.item.time} 52 | 53 | {this.props.item.name} 54 | {this.props.item.location ? {this.props.item.location} : null} 55 | 56 | 57 | 58 | {this.state.stateText} 59 | 60 | 61 | 62 | 63 | 64 | 65 | } 66 | right={ 67 | 70 | } 71 | left={ 72 | 75 | } 76 | /> 77 | 78 | ); 79 | } 80 | } 81 | 82 | // define your styles 83 | const styles = StyleSheet.create({ 84 | perList: { 85 | display: 'flex', 86 | flexDirection: 'column', 87 | }, 88 | listTop: { 89 | flexDirection: 'row', 90 | marginLeft: 15, 91 | }, 92 | date: { 93 | fontWeight: '400', 94 | width: width / 4 95 | }, 96 | time: { 97 | fontWeight: '400', 98 | maxWidth: width / 5 99 | }, 100 | locationAndName: { 101 | flexDirection: 'column' 102 | }, 103 | text: { 104 | fontWeight: '400', 105 | width: width / 2 106 | }, 107 | locationText: { 108 | fontWeight: '400', 109 | fontSize: 12, 110 | width: width / 2, 111 | height: 16 112 | }, 113 | listBottom: { 114 | flexDirection: 'row', 115 | marginLeft: 15, 116 | marginTop: 10 117 | }, 118 | state: { 119 | width: width / 4 120 | }, 121 | lineRow: { 122 | marginTop: -15, 123 | width: width 124 | }, 125 | dot: { 126 | fontSize: 38 127 | }, 128 | line: { 129 | borderBottomColor: 'black', 130 | borderBottomWidth: 1, 131 | marginLeft: 10, 132 | marginTop: calc(), 133 | } 134 | }); 135 | function calc() { 136 | const hep = Dimensions.get('screen').height; 137 | if (hep < 533) { 138 | return -35 - ((500 - hep) / 50) 139 | } else { 140 | return -35 + ((hep - 500) / 50) 141 | } 142 | } 143 | 144 | //make this component available to the app 145 | export default TodoItem; 146 | -------------------------------------------------------------------------------- /src/helper/Array.js: -------------------------------------------------------------------------------- 1 | class ArrayHelper { 2 | find(array, element) { 3 | let index = ""; 4 | array.forEach((data, num) => { 5 | if (data.id === element) 6 | index = num; 7 | }); 8 | if (index !== -1) 9 | return index; 10 | } 11 | search(array, element) { 12 | let index = ""; 13 | array.forEach((data, num) => { 14 | data.forEach((inside) => { 15 | if (inside === element) 16 | index = num; 17 | }) 18 | }); 19 | const returnValue = typeof index === "number" ? true : false; 20 | return returnValue; 21 | } 22 | delete(array, element) { 23 | let index = ""; 24 | array.forEach((data, num) => { 25 | if (data.id === element) 26 | index = num; 27 | }); 28 | if (index !== -1) 29 | return array.splice(index, 1); 30 | } 31 | sortDate(array, element) { 32 | let index = ""; 33 | let newArray= Array(); 34 | array.forEach((data, num) => { 35 | if (data.date === element) 36 | newArray.push(array[num]); 37 | }); 38 | return newArray; 39 | } 40 | 41 | } 42 | 43 | const exporDefault = new ArrayHelper(); 44 | export default exporDefault; 45 | -------------------------------------------------------------------------------- /src/helper/Date.js: -------------------------------------------------------------------------------- 1 | import _ from './Language'; 2 | class DateHelper { 3 | getDate(date) { 4 | let dd = date.getDate(); 5 | let mm = date.getMonth() + 1; //January is 0! 6 | 7 | const yyyy = date.getFullYear(); 8 | const value = dd + '/' + mm + '/' + yyyy; 9 | return value; 10 | } 11 | getTime(date) { 12 | let hh = date.getHours(); 13 | let ii = date.getMinutes(); 14 | if (ii < 10) { 15 | ii = '0' + ii; 16 | } 17 | const value = hh + ':' + ii; 18 | return value; 19 | } 20 | getMonthName(date) { 21 | let data = date.split('/'); 22 | const day = data[0]; 23 | const month = Number(data[1]); 24 | let monthName; 25 | switch (month) { 26 | case 1: 27 | monthName = _('january'); 28 | break; 29 | case 2: 30 | monthName = _('february'); 31 | break; 32 | case 3: 33 | monthName = _('march'); 34 | break; 35 | case 4: 36 | monthName = _('april'); 37 | break; 38 | case 5: 39 | monthName = _('may'); 40 | break; 41 | case 6: 42 | monthName = _('june'); 43 | break; 44 | case 7: 45 | monthName = _('july'); 46 | break; 47 | case 8: 48 | monthName = _('august'); 49 | break; 50 | case 9: 51 | monthName = _('september'); 52 | break; 53 | case 10: 54 | monthName = _('october'); 55 | break; 56 | case 11: 57 | monthName = _('november'); 58 | break; 59 | case 12: 60 | monthName = _('december'); 61 | } 62 | return `${day} ${monthName}`; 63 | } 64 | getDayName(date, fullName = true) { 65 | let day; 66 | if (fullName) { 67 | switch (date.getDay()) { 68 | case 0: 69 | day = _('sunday'); 70 | break; 71 | case 1: 72 | day = _('monday'); 73 | break; 74 | case 2: 75 | day = _('tuesday'); 76 | break; 77 | case 3: 78 | day = _('wednesday'); 79 | break; 80 | case 4: 81 | day = _('thursday'); 82 | break; 83 | case 5: 84 | day = _('friday'); 85 | break; 86 | case 6: 87 | day = _('saturday'); 88 | } 89 | } else { 90 | switch (date.getDay()) { 91 | case 0: 92 | day = _('sun'); 93 | break; 94 | case 1: 95 | day = _('mon'); 96 | break; 97 | case 2: 98 | day = _('tue'); 99 | break; 100 | case 3: 101 | day = _('wed'); 102 | break; 103 | case 4: 104 | day = _('thu'); 105 | break; 106 | case 5: 107 | day = _('fri'); 108 | break; 109 | case 6: 110 | day = _('sat'); 111 | } 112 | } 113 | return day; 114 | } 115 | } 116 | 117 | const date = new DateHelper(); 118 | export default date; -------------------------------------------------------------------------------- /src/helper/Language.js: -------------------------------------------------------------------------------- 1 | import { NativeModules } from "react-native"; 2 | let langRegionLocale = "en_US"; 3 | langRegionLocale = NativeModules.I18nManager.localeIdentifier || ""; 4 | let langCode = langRegionLocale.substring(0, 2); // get first two characters 5 | 6 | function Language(value) { 7 | const lang = { 8 | en: { 9 | tooWork: 'A lot of work to do today.', 10 | letsDone: "Lets do it.", 11 | noWork: "Relax or have fun.", 12 | toDo: 'To Do', 13 | daysNoWork: ' there is no work you need to do ', 14 | addNewTask: 'Add New Task', 15 | editTask: 'Edit task', 16 | nameRequired: 'Task name can not be empty !', 17 | taskName: "Task Name", 18 | location: "Location", 19 | hour: 'Hour', 20 | add: 'Add', 21 | edit: 'Edit', 22 | loading: 'Loading', 23 | done: 'Done', 24 | cancel: 'Cancel', 25 | january: 'January', 26 | february: 'February', 27 | march: 'March', 28 | april: 'April', 29 | may: 'May', 30 | june: 'June', 31 | july: 'July', 32 | august: 'August', 33 | september: 'September', 34 | october: 'October', 35 | november: 'November', 36 | december: 'December', 37 | sunday: 'Sunday', 38 | monday: 'Monday', 39 | tuesday: 'Tuesday', 40 | wednesday: 'Wednesday', 41 | thursday: 'Thursday', 42 | friday: 'Friday', 43 | saturday: 'Saturday', 44 | sun: 'Sun', 45 | mon: 'Mon', 46 | tue: 'Tue', 47 | wed: 'Web', 48 | thu: 'Thu', 49 | fri: 'Fri', 50 | sat: 'Sat' 51 | }, 52 | tr: { 53 | tooWork: 'Bugün yapılacak çok iş var.', 54 | letsDone: "Hadi bitirelim şu işi.", 55 | noWork: "Rahatla,dinlen ya da eğlen.", 56 | toDo: 'Yapılacaklar', 57 | daysNoWork: 'günü yapmanız gereken hiçbir şey yok.', 58 | addNewTask: 'Yeni Görev Ekle', 59 | editTask: 'Görevi Düzenle', 60 | nameRequired: 'Görev adı boş bırakılamaz !', 61 | taskName: "Görev Adı", 62 | location: "Mekan", 63 | hour: 'Saat', 64 | add: 'Ekle', 65 | edit: 'Düzenle', 66 | loading: 'Bekliyor', 67 | done: 'Tamamlandı', 68 | cancel: 'İptal edildi', 69 | january: 'Ocak', 70 | february: 'Şubat', 71 | march: 'Mart', 72 | april: 'Nisan', 73 | may: 'Mayıs', 74 | june: 'Haziran', 75 | july: 'Temmuz', 76 | august: 'Ağustos', 77 | september: 'Eylül', 78 | october: 'Ekim', 79 | november: 'Kasım', 80 | december: 'Aralık', 81 | sunday: 'Pazar', 82 | monday: 'Pazartesi', 83 | tuesday: 'Salı', 84 | wednesday: 'Çarşamba', 85 | thursday: 'Perşembe', 86 | friday: 'Cuma', 87 | saturday: 'Cumartesi', 88 | sun: 'Paz', 89 | mon: 'Pzt', 90 | tue: 'sal', 91 | wed: 'Çar', 92 | thu: 'Sal', 93 | fri: 'Cum', 94 | sat: 'Cmt' 95 | } 96 | } 97 | const isAvailableLang = langCode === 'tr' || langCode === 'en'; 98 | const returnValue = isAvailableLang ? eval(`lang.${langCode}.${value}`) : eval(`lang.en.${value}`); 99 | return returnValue; 100 | } 101 | 102 | export default Language; -------------------------------------------------------------------------------- /src/screens/Add.js: -------------------------------------------------------------------------------- 1 | //import liraries 2 | import React, { Component } from 'react'; 3 | import { View, Text, StyleSheet, Button, TextInput, TouchableOpacity, AsyncStorage, Alert } from 'react-native'; 4 | import DateTimePicker from 'react-native-modal-datetime-picker'; 5 | import DateHelper from '../helper/Date'; 6 | import _ from '../helper/Language'; 7 | 8 | // create a component 9 | class Add extends Component { 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | name: '', 14 | location: '', 15 | time: '', 16 | date: DateHelper.getDate(new Date()), 17 | datePickerVisible: false, 18 | timePickerVisible: false, 19 | } 20 | } 21 | addNewTodo() { 22 | if (this.state.name.length < 1) { 23 | Alert.alert(_('nameRequired')); 24 | } 25 | else { 26 | const timeStamp = Math.floor(Date.now()); 27 | const id = Number(timeStamp); 28 | const state = 0; 29 | const { name, location, time, date } = this.state; 30 | AsyncStorage.getItem('list').then(data => { 31 | let newArray = Array(); 32 | if (data !== null) { 33 | newArray = JSON.parse(data); 34 | } 35 | newArray.push({ id, name, location, time, date, state }); 36 | const upData = JSON.stringify(newArray); 37 | AsyncStorage.setItem('list', upData); 38 | this.props.closeModal(); 39 | }) 40 | } 41 | } 42 | onClosePicker() { 43 | this.setState({ datePickerVisible: false, timePickerVisible: false }) 44 | } 45 | render() { 46 | return ( 47 | 48 | 49 | {_('addNewTask')} 50 | this.setState({ name })} 53 | placeholder={_('taskName')} 54 | returnKeyType="next" 55 | selectTextOnFocus={true} 56 | onSubmitEditing={() => this.location.focus()} 57 | /> 58 | this.setState({ location })} 61 | placeholder={_('location')} 62 | returnKeyType="next" 63 | onSubmitEditing={() => this.setState({ datePickerVisible: true })} 64 | ref={(input) => this.location = input} 65 | /> 66 | 67 | this.setState({ datePickerVisible: true })}> 68 | 69 | {this.state.date} 70 | 71 | 72 | this.setState({ timePickerVisible: true })}> 73 | 74 | {this.state.time ? this.state.time : _('hour')} 75 | 76 | 77 | 78 | this.addNewTodo()}> 79 | {_('add')} 80 | 81 | this.setState({ date: DateHelper.getDate(date) })} 84 | onCancel={() => this.onClosePicker()} 85 | mode="date" 86 | /> 87 | this.setState({ time: DateHelper.getTime(time) })} 90 | onCancel={() => this.onClosePicker()} 91 | mode="time" 92 | /> 93 | 94 | 95 | ); 96 | } 97 | } 98 | 99 | // define your styles 100 | const styles = StyleSheet.create({ 101 | modalContainer: { 102 | flex: 1, 103 | justifyContent: 'center', 104 | alignItems: 'center', 105 | borderRadius: 10, 106 | }, 107 | innerContainer: { 108 | backgroundColor: "white", 109 | height: 300, 110 | width: '90%', 111 | borderRadius: 10, 112 | padding: 20 113 | }, 114 | h1: { 115 | color: 'black', 116 | fontSize: 18, 117 | marginTop: 10, 118 | marginBottom: 10, 119 | marginLeft: 10 120 | }, 121 | input: { 122 | borderBottomColor: 'gray', 123 | color: 'black', 124 | fontWeight: '800', 125 | fontSize: 18 126 | }, 127 | addButton: { 128 | backgroundColor: '#ee7659', 129 | color: 'white', 130 | fontWeight: '600', 131 | textAlign: 'center', 132 | lineHeight: 45, 133 | fontSize: 18, 134 | width: '90%', 135 | marginTop: 20, 136 | marginLeft: '5%', 137 | borderRadius: 25 138 | }, 139 | dateTime: { 140 | flexDirection: 'row', 141 | justifyContent: 'space-around' 142 | }, 143 | dateTimeInput: { 144 | width: 90, 145 | height: 40, 146 | fontWeight: '500', 147 | textAlign: 'center', 148 | textAlignVertical: 'center', 149 | borderBottomColor: 'black', 150 | borderBottomWidth: 1 151 | } 152 | }); 153 | 154 | //make this component available to the app 155 | export default Add; 156 | -------------------------------------------------------------------------------- /src/screens/Home.js: -------------------------------------------------------------------------------- 1 | //import liraries 2 | import React, { Component } from 'react'; 3 | import { View, Text, StyleSheet, TouchableOpacity, StatusBar, AsyncStorage, FlatList, ScrollView, Touc, TouchableNativeFeedback, ActivityIndicator } from 'react-native'; 4 | import Add from './Add'; 5 | import TodoItem from '../Components/TodoItem'; 6 | import Helper from '../helper/Array'; 7 | import DateHelper from '../helper/Date'; 8 | import Modal from 'react-native-modal'; 9 | import EditModal from '../Components/EditModal'; 10 | import DateBarItem from '../Components/DateBarItem'; 11 | import _ from '../helper/Language'; 12 | 13 | // create a component 14 | class Home extends Component { 15 | constructor(props) { 16 | super(props); 17 | this.state = { 18 | addModalVis: false, 19 | editModalVis: false, 20 | editId: null, 21 | data: [], 22 | date: new Date(), 23 | loading: true 24 | } 25 | } 26 | componentDidMount() { 27 | this.updateData(true); 28 | this.returnCalendar(); 29 | } 30 | openModal() { 31 | this.setState({ addModalVis: true }); 32 | } 33 | closeModal() { 34 | this.setState({ addModalVis: false }); 35 | this.updateData(); 36 | } 37 | updateData(first = false) { 38 | AsyncStorage.getItem('list').then(snapshot => { 39 | if (snapshot === null) { 40 | this.setState({loading:false}) 41 | return; 42 | } 43 | const data = JSON.parse(snapshot); 44 | const nowDate = DateHelper.getDate(this.state.date); 45 | const val = Helper.sortDate(data, nowDate); 46 | this.setState({ data: val, loading: false }) 47 | if (first) { 48 | setTimeout(() => { 49 | const x = this.state.date.getUTCDate() * 30; 50 | this.scroll.scrollTo({ x, y: 1, animated: false }); 51 | }, 500) 52 | } 53 | }) 54 | } 55 | deleteTodo(id) { 56 | Helper.delete(this.state.data, id); 57 | const newData = JSON.stringify(this.state.data); 58 | AsyncStorage.setItem('list', newData); 59 | this.updateData(); 60 | } 61 | changeState(id) { 62 | const { data } = this.state; 63 | const index = Helper.find(data, id); 64 | const oldState = Number(data[index].state); 65 | let newState; 66 | switch (oldState) { 67 | case 0: 68 | newState = 1; 69 | break; 70 | case 1: 71 | newState = 2; 72 | break; 73 | case 2: 74 | newState = 0; 75 | break; 76 | } 77 | data[index].state = newState; 78 | const asynPushData = JSON.stringify(data); 79 | AsyncStorage.setItem('list', asynPushData); 80 | this.updateData(); 81 | } 82 | editTodo(id) { 83 | this.setState({ editId: id, editModalVis: true }) 84 | } 85 | returnCalendar() { 86 | let array = Array(); 87 | const now = new Date(); 88 | const year = now.getFullYear(); 89 | const month = now.getMonth(); 90 | const lastDay = new Date(year, month + 1, 0).getUTCDate(); 91 | for (let i = 0; i < lastDay; i++) { 92 | var tomorrow = new Date(year, month, 1); 93 | tomorrow.setDate(tomorrow.getDate() + i); 94 | array.push({ date: tomorrow }); 95 | } 96 | this.setState({ array }) 97 | } 98 | changeDate(date) { 99 | this.setState({ date }) 100 | const index = date.getUTCDate(); 101 | let x = index * 12; 102 | if (index > 7) 103 | x = index * 25; 104 | if (index > 13) 105 | x = index * 30 106 | if (index > 18) 107 | x = index * 35 108 | this.scroll.scrollTo({ x, y: 1, animated: true }); 109 | this.updateData() 110 | } 111 | goHome() { 112 | this.setState({ date: new Date() }) 113 | this.updateData() 114 | } 115 | render() { 116 | return ( 117 | 118 | 122 | 123 | 124 | this.goHome()}> 125 | {this.state.date.getDate()} 126 | 127 | 128 | {DateHelper.getMonthName(DateHelper.getDate(this.state.date)).split(' ')[1]} 129 | {DateHelper.getDayName(this.state.date)} 2017 130 | 131 | this.openModal()}> 132 | + 133 | 134 | 135 | 136 | {this.state.data.length > 1 ? _('tooWork') : this.state.data.length === 1 ? _('letsDone') : _('noWork')} 137 | 138 | this.scroll = ref} > 139 | this.changeDate(date)} />} 143 | keyExtractor={(item, index) => index.toString()} 144 | horizontal={true} 145 | /> 146 | 147 | 148 | {this.state.loading ? : 149 | 150 | {this.state.data.length > 0 ? {_('toDo')} : 151 | {this.state.date.getDate()} {DateHelper.getMonthName(DateHelper.getDate(this.state.date)).split(' ')[1]} {_('daysNoWork')} 152 | } 153 | this.editTodo(id)} deleteTodo={(id) => this.deleteTodo(id)} changeState={(id) => this.changeState(id)} />} 156 | keyExtractor={(item, index) => item.id.toString()} 157 | /> 158 | } 159 | this.setState({ addModalVis: false })} 166 | onBackdropPress={() => this.setState({ addModalVis: false })} 167 | onSwipe={() => this.setState({ addModalVis: false })} 168 | swipeDirection="down" 169 | > 170 | this.closeModal()} visible={this.state.addModalVis} /> 171 | 172 | this.setState({ editModalVis: false })} 179 | onBackdropPress={() => this.setState({ editModalVis: false })} 180 | onSwipe={() => this.setState({ editModalVis: false })} 181 | swipeDirection="down" 182 | > 183 | this.updateData()} closeModal={() => this.setState({ editModalVis: false })} visible={this.state.editModalVis} id={this.state.editId} /> 184 | 185 | 186 | ); 187 | } 188 | } 189 | 190 | // define your styles 191 | const styles = StyleSheet.create({ 192 | container: { 193 | flex: 1, 194 | backgroundColor: '#ee7659', 195 | }, 196 | top: { 197 | display: 'flex', 198 | flexDirection: 'column', 199 | marginTop: 10, 200 | marginLeft: 30, 201 | elevation: 2, 202 | }, 203 | currentDate: { 204 | display: 'flex', 205 | flexDirection: 'row', 206 | justifyContent: 'space-around' 207 | }, 208 | dayNumber: { 209 | fontFamily: 'Effra', 210 | fontSize: 52, 211 | fontWeight: '400', 212 | color: 'white', 213 | flexGrow: 1 214 | }, 215 | month: { 216 | display: 'flex', 217 | flexDirection: 'column', 218 | marginTop: 15, 219 | flexGrow: 8 220 | }, 221 | dayString: { 222 | fontFamily: 'Effra', 223 | fontSize: 16, 224 | fontWeight: '400', 225 | color: '#FFFEFE' 226 | }, 227 | addItem: { 228 | backgroundColor: 'white', 229 | color: '#f27455', 230 | fontSize: 30, 231 | marginTop: 15, 232 | marginRight: 25, 233 | textAlign: 'center', 234 | width: 48, 235 | height: 48, 236 | borderRadius: 29, 237 | textAlignVertical: 'center', 238 | elevation: 2, 239 | }, 240 | lineString: { 241 | color: 'white', 242 | marginTop: 5, 243 | marginBottom: 15, 244 | fontSize: 14 245 | }, 246 | calendar: { 247 | flexDirection: 'row', 248 | marginLeft: -10, 249 | marginBottom: 30 250 | }, 251 | bottom: { 252 | backgroundColor: 'white', 253 | flex: 1 254 | }, 255 | h1: { 256 | fontSize: 24, 257 | marginLeft: 20, 258 | marginTop: 20, 259 | marginBottom: 20, 260 | fontWeight: '600', 261 | color: '#202824' 262 | }, 263 | nothing: { 264 | fontSize: 18, 265 | padding: 20, 266 | textAlign: 'center' 267 | } 268 | }); 269 | 270 | //make this component available to the app 271 | export default Home; 272 | --------------------------------------------------------------------------------