app.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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.handleToggleEditing = this.handleToggleEditing.bind(this);
  74. this.handleUpdateText = this.handleUpdateText.bind(this);
  75. this.setSource = this.setSource.bind(this);
  76. }
  77. componentWillMount() {
  78. AsyncStorage.getItem("items").then((json) => {
  79. try {
  80. const items = JSON.parse(json);
  81. this.setSource(items, items, { loading: false });
  82. }
  83. catch (e) {
  84. this.setState({ loading: false });
  85. }
  86. });
  87. }
  88. handleAddItem() {
  89. if (!this.state.value) {
  90. return;
  91. }
  92. const newItems = [
  93. ...this.state.items,
  94. {
  95. key: Date.now(),
  96. text: this.state.value,
  97. complete: false
  98. }
  99. ];
  100. this.setSource(newItems, newItems, { value: "" });
  101. }
  102. handleClearComplete() {
  103. const newItems = filterItems('ACTIVE', this.state.items);
  104. this.setSource(newItems, filterItems(this.state.filter, newItems));
  105. }
  106. handleFilter(filter) {
  107. this.setSource(this.state.items, filterItems(filter, this.state.items), { filter });
  108. }
  109. handleRemoveItem(key) {
  110. const newItems = this.state.items.filter((item) => item.key !== key);
  111. this.setSource(newItems, filterItems(this.state.filter, newItems));
  112. }
  113. handleToggleAllComplete() {
  114. const complete = !this.state.allComplete;
  115. const newItems = this.state.items.map((item) => ({
  116. ...item,
  117. complete
  118. }));
  119. // console.table(newItems);
  120. this.setSource(newItems, filterItems(this.state.filter, newItems), { allComplete: complete });
  121. }
  122. handleToggleComplete(key, complete) {
  123. const newItems = this.state.items.map((item) => {
  124. if (item.key !== key) {
  125. return item;
  126. }
  127. return {
  128. ...item,
  129. complete
  130. };
  131. });
  132. this.setSource(newItems, filterItems(this.state.filter, newItems));
  133. }
  134. handleToggleEditing(key, editing) {
  135. const newItems = this.state.items.map((item) => {
  136. if (item.key !== key) {
  137. return item;
  138. }
  139. return {
  140. ...item,
  141. editing
  142. };
  143. });
  144. this.setSource(newItems, filterItems(this.state.filter, newItems));
  145. }
  146. handleUpdateText(key, text) {
  147. const newItems = this.state.items.map((item) => {
  148. if (item.key !== key) {
  149. return item;
  150. }
  151. return {
  152. ...item,
  153. text
  154. };
  155. });
  156. this.setSource(newItems, filterItems(this.state.filter, newItems));
  157. }
  158. render() {
  159. // console.log("App state", this.state);
  160. return (
  161. <View style={styles.container}>
  162. <Header
  163. onAddItem={this.handleAddItem}
  164. onChange={(value) => this.setState({ value })}
  165. onToggleAllComplete={this.handleToggleAllComplete}
  166. value={this.state.value}
  167. />
  168. <View style={styles.content}>
  169. <ListView
  170. enableEmptySections
  171. dataSource={this.state.dataSource}
  172. onScroll={() => Keyboard.dismiss()}
  173. renderRow={({ key, ...value }) => {
  174. // console.log("renderRow", key, value);
  175. return (
  176. <Row
  177. key={key}
  178. onComplete={(complete) => this.handleToggleComplete(key, complete)}
  179. onRemove={() => this.handleRemoveItem(key)}
  180. onToggleEdit={(editing) => this.handleToggleEditing(key, editing)}
  181. onUpdate={(text) => this.handleUpdateText(key, text)}
  182. { ...value }
  183. />
  184. );
  185. }}
  186. renderSeparator={(sectionId, rowId) => {
  187. // console.log('renderSeparator', sectionId, rowId);
  188. return <View key={rowId} style={styles.separator} />;
  189. }}
  190. style={styles.list}
  191. />
  192. </View>
  193. <Footer
  194. count={filterItems("ACTIVE", this.state.items).length}
  195. filter={this.state.filter}
  196. onClearComplete={this.handleClearComplete}
  197. onFilter={this.handleFilter}
  198. />
  199. {this.state.loading && <View style={styles.loading}>
  200. <ActivityIndicator
  201. animating
  202. size="large"
  203. />
  204. </View>}
  205. </View>
  206. );
  207. }
  208. setSource(items, itemsDataSource, otherState = {}) {
  209. this.setState({
  210. items,
  211. dataSource: this.state.dataSource.cloneWithRows(itemsDataSource),
  212. ...otherState
  213. });
  214. AsyncStorage.setItem("items", JSON.stringify(items));
  215. }
  216. }
  217. export default App;