app.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import React, { Component } from "react";
  2. import {
  3. ActivityIndicator,
  4. AsyncStorage,
  5. Keyboard,
  6. ListView,
  7. Platform,
  8. StyleSheet,
  9. Text,
  10. View
  11. } from "react-native";
  12. import Header from "./header";
  13. import Footer from "./footer";
  14. import Row from "./row";
  15. const styles = StyleSheet.create({
  16. container: {
  17. flex: 1,
  18. backgroundColor: "#F5F5F5",
  19. ...Platform.select({
  20. ios: {
  21. paddingTop: 30
  22. }
  23. })
  24. },
  25. content: {
  26. flex: 1
  27. },
  28. list: {
  29. backgroundColor: "#fff"
  30. },
  31. loading: {
  32. backgroundColor: "rgba(0, 0, 0, 0.2)",
  33. bottom: 0,
  34. justifyContent: "center",
  35. left: 0,
  36. position: "absolute",
  37. right: 0,
  38. top: 0
  39. },
  40. separator: {
  41. borderWidth: 2,
  42. borderColor: "#eee"
  43. }
  44. });
  45. const filterItems = (filter, items) => {
  46. return items.filter((item) => {
  47. if ((filter === 'ACTIVE' && item.complete) || (filter === 'COMPLETED' && !item.complete)) {
  48. return false;
  49. }
  50. return true;
  51. });
  52. };
  53. class App extends Component {
  54. constructor(props) {
  55. super(props);
  56. const ds = new ListView.DataSource({
  57. rowHasChanged: (r1, r2) => r1 !== r2
  58. });
  59. this.state = {
  60. allComplete: false,
  61. dataSource: ds.cloneWithRows([]),
  62. filter: "ALL",
  63. items: [],
  64. loading: true,
  65. value: ""
  66. };
  67. this.handleAddItem = this.handleAddItem.bind(this);
  68. this.handleClearComplete = this.handleClearComplete.bind(this);
  69. this.handleFilter = this.handleFilter.bind(this);
  70. this.handleRemoveItem = this.handleRemoveItem.bind(this);
  71. this.handleToggleAllComplete = this.handleToggleAllComplete.bind(this);
  72. this.handleToggleComplete = this.handleToggleComplete.bind(this);
  73. this.setSource = this.setSource.bind(this);
  74. }
  75. componentWillMount() {
  76. AsyncStorage.getItem("items").then((json) => {
  77. try {
  78. const items = JSON.parse(json);
  79. this.setSource(items, items, { loading: false });
  80. }
  81. catch (e) {
  82. this.setState({ loading: false });
  83. }
  84. });
  85. }
  86. handleAddItem() {
  87. if (!this.state.value) {
  88. return;
  89. }
  90. const newItems = [
  91. ...this.state.items,
  92. {
  93. key: Date.now(),
  94. text: this.state.value,
  95. complete: false
  96. }
  97. ];
  98. this.setSource(newItems, newItems, { value: "" });
  99. }
  100. handleClearComplete() {
  101. const newItems = filterItems('ACTIVE', this.state.items);
  102. this.setSource(newItems, filterItems(this.state.filter, newItems));
  103. }
  104. handleFilter(filter) {
  105. this.setSource(this.state.items, filterItems(filter, this.state.items), { filter });
  106. }
  107. handleRemoveItem(key) {
  108. const newItems = this.state.items.filter((item) => item.key !== key);
  109. this.setSource(newItems, filterItems(this.state.filter, newItems));
  110. }
  111. handleToggleAllComplete() {
  112. const complete = !this.state.allComplete;
  113. const newItems = this.state.items.map((item) => ({
  114. ...item,
  115. complete
  116. }));
  117. // console.table(newItems);
  118. this.setSource(newItems, filterItems(this.state.filter, newItems), { allComplete: complete });
  119. }
  120. handleToggleComplete(key, complete) {
  121. const newItems = this.state.items.map((item) => {
  122. if (item.key !== key) {
  123. return item;
  124. }
  125. return {
  126. ...item,
  127. complete
  128. };
  129. });
  130. this.setSource(newItems, filterItems(this.state.filter, newItems));
  131. }
  132. render() {
  133. // console.log("App state", this.state);
  134. return (
  135. <View style={styles.container}>
  136. <Header
  137. onAddItem={this.handleAddItem}
  138. onChange={(value) => this.setState({ value })}
  139. onToggleAllComplete={this.handleToggleAllComplete}
  140. value={this.state.value}
  141. />
  142. <View style={styles.content}>
  143. <ListView
  144. enableEmptySections
  145. dataSource={this.state.dataSource}
  146. onScroll={() => Keyboard.dismiss()}
  147. renderRow={({ key, ...value }) => {
  148. // console.log("renderRow", key, value);
  149. return (
  150. <Row
  151. key={key}
  152. onComplete={(complete) => this.handleToggleComplete(key, complete)}
  153. onRemove={() => this.handleRemoveItem(key)}
  154. { ...value }
  155. />
  156. );
  157. }}
  158. renderSeparator={(sectionId, rowId) => {
  159. // console.log('renderSeparator', sectionId, rowId);
  160. return <View key={rowId} style={styles.separator} />;
  161. }}
  162. style={styles.list}
  163. />
  164. </View>
  165. <Footer
  166. count={filterItems("ACTIVE", this.state.items).length}
  167. filter={this.state.filter}
  168. onClearComplete={this.handleClearComplete}
  169. onFilter={this.handleFilter}
  170. />
  171. {this.state.loading && <View style={styles.loading}>
  172. <ActivityIndicator
  173. animating
  174. size="large"
  175. />
  176. </View>}
  177. </View>
  178. );
  179. }
  180. setSource(items, itemsDataSource, otherState = {}) {
  181. this.setState({
  182. items,
  183. dataSource: this.state.dataSource.cloneWithRows(itemsDataSource),
  184. ...otherState
  185. });
  186. AsyncStorage.setItem("items", JSON.stringify(items));
  187. }
  188. }
  189. export default App;