From 5a87f131b50cf675e9f038bfd6fe82108da89e49 Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Tue, 12 Feb 2019 15:44:59 -0800 Subject: [PATCH] fleshed out up to step 6 --- index.html | 8 +++ step01/index.html | 4 +- step03/index.html | 91 ++++++++++++++++++++++++++ step03/index.js | 0 step03/style.css | 50 ++++++++++++++ step04/index.html | 8 +++ step04/src/App.tsx | 13 ++++ step04/src/index.tsx | 4 ++ step05/index.html | 9 +++ step05/src/App.tsx | 18 +++++ step05/src/components/TodoFooter.tsx | 13 ++++ step05/src/components/TodoHeader.tsx | 23 +++++++ step05/src/components/TodoList.tsx | 40 +++++++++++ step05/src/components/TodoListItem.tsx | 13 ++++ step05/src/index.tsx | 4 ++ step05/src/style.css | 50 ++++++++++++++ step06/index.html | 9 +++ step06/src/App.tsx | 27 ++++++++ step06/src/components/TodoFooter.tsx | 11 ++++ step06/src/components/TodoHeader.tsx | 21 ++++++ step06/src/components/TodoList.tsx | 28 ++++++++ step06/src/components/TodoListItem.tsx | 15 +++++ step06/src/index.tsx | 4 ++ step06/src/style.css | 50 ++++++++++++++ tsconfig.json | 2 +- webpack.config.js | 5 +- 26 files changed, 516 insertions(+), 4 deletions(-) create mode 100644 step03/index.html create mode 100644 step03/index.js create mode 100644 step03/style.css create mode 100644 step04/index.html create mode 100644 step04/src/App.tsx create mode 100644 step04/src/index.tsx create mode 100644 step05/index.html create mode 100644 step05/src/App.tsx create mode 100644 step05/src/components/TodoFooter.tsx create mode 100644 step05/src/components/TodoHeader.tsx create mode 100644 step05/src/components/TodoList.tsx create mode 100644 step05/src/components/TodoListItem.tsx create mode 100644 step05/src/index.tsx create mode 100644 step05/src/style.css create mode 100644 step06/index.html create mode 100644 step06/src/App.tsx create mode 100644 step06/src/components/TodoFooter.tsx create mode 100644 step06/src/components/TodoHeader.tsx create mode 100644 step06/src/components/TodoList.tsx create mode 100644 step06/src/components/TodoListItem.tsx create mode 100644 step06/src/index.tsx create mode 100644 step06/src/style.css diff --git a/index.html b/index.html index 793036f..960cfca 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,13 @@
Step01 +Step02 +Step03 +Step04 +Step05 +Step06 +Step07 +Step08 +Step09 Playground
diff --git a/step01/index.html b/step01/index.html index 8b6c177..c534e69 100644 --- a/step01/index.html +++ b/step01/index.html @@ -2,7 +2,9 @@

todos

- +
+ +
diff --git a/step03/index.html b/step03/index.html new file mode 100644 index 0000000..321247d --- /dev/null +++ b/step03/index.html @@ -0,0 +1,91 @@ + + + + +

todos

+ + +
+ + + +
+ +
+ 4 items left + +
+ + + + diff --git a/step03/index.js b/step03/index.js new file mode 100644 index 0000000..e69de29 diff --git a/step03/style.css b/step03/style.css new file mode 100644 index 0000000..c897b4c --- /dev/null +++ b/step03/style.css @@ -0,0 +1,50 @@ +body { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + width: 400px; + margin: 20px auto; +} +h1 { + text-align: center; +} + +.textfield { + width: 80%; +} + +.add { + margin-left: 5%; +} + +.button { + border: none; + padding: 5px 10px; +} + +.filter { + margin: 10px 0 0; +} + +.filter button { + background: transparent; + border: none; +} +.filter .active { + border-bottom: 2px solid blue; +} + +.todos { + list-style: none; + padding: 0; +} + +footer { + display: flex; +} + +footer span { + flex-grow: 1; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/step04/index.html b/step04/index.html new file mode 100644 index 0000000..a5fad94 --- /dev/null +++ b/step04/index.html @@ -0,0 +1,8 @@ + + + +
+ + + + diff --git a/step04/src/App.tsx b/step04/src/App.tsx new file mode 100644 index 0000000..23cb3da --- /dev/null +++ b/step04/src/App.tsx @@ -0,0 +1,13 @@ +import React from 'react'; + + +export class App extends React.Component { + render() { + + return ( +
+ +
+ ); + } +} diff --git a/step04/src/index.tsx b/step04/src/index.tsx new file mode 100644 index 0000000..1d9694f --- /dev/null +++ b/step04/src/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { App } from "./App"; +ReactDOM.render(, document.getElementById("app")); diff --git a/step05/index.html b/step05/index.html new file mode 100644 index 0000000..de2c99d --- /dev/null +++ b/step05/index.html @@ -0,0 +1,9 @@ + + + + +
+ + + + diff --git a/step05/src/App.tsx b/step05/src/App.tsx new file mode 100644 index 0000000..5726b54 --- /dev/null +++ b/step05/src/App.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { TodoFooter } from './components/TodoFooter'; +import { TodoHeader } from './components/TodoHeader'; +import { TodoList } from './components/TodoList'; + + +export class TodoApp extends React.Component { + render() { + + return ( +
+ + + +
+ ); + } +} diff --git a/step05/src/components/TodoFooter.tsx b/step05/src/components/TodoFooter.tsx new file mode 100644 index 0000000..ff294ec --- /dev/null +++ b/step05/src/components/TodoFooter.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +export const TodoFooter = (props: any) => { + + return ( +
+ + 4 items left + + +
+ ); +}; diff --git a/step05/src/components/TodoHeader.tsx b/step05/src/components/TodoHeader.tsx new file mode 100644 index 0000000..2b2da8b --- /dev/null +++ b/step05/src/components/TodoHeader.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +export class TodoHeader extends React.Component { + + render() { + return ( +
+

todos

+ + +
+ + + +
+
+ ); + } +} diff --git a/step05/src/components/TodoList.tsx b/step05/src/components/TodoList.tsx new file mode 100644 index 0000000..93dbc04 --- /dev/null +++ b/step05/src/components/TodoList.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { TodoListItem } from './TodoListItem'; + +export class TodoList extends React.Component { + render() { + const { filter, todos } = this.props; + let filteredTodos: typeof todos = {}; + + switch (filter) { + case 'completed': + Object.keys(todos).forEach(id => { + if (todos[id].completed) { + filteredTodos[id] = todos[id]; + } + }); + break; + + case 'active': + Object.keys(todos).forEach(id => { + if (!todos[id].completed) { + filteredTodos[id] = todos[id]; + } + }); + break; + + default: + filteredTodos = todos; + break; + } + + return ( +
    + + + + +
+ ); + } +} diff --git a/step05/src/components/TodoListItem.tsx b/step05/src/components/TodoListItem.tsx new file mode 100644 index 0000000..1bff0f7 --- /dev/null +++ b/step05/src/components/TodoListItem.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +export class TodoListItem extends React.Component { + render() { + return ( +
  • + +
  • + ); + } +} diff --git a/step05/src/index.tsx b/step05/src/index.tsx new file mode 100644 index 0000000..3289ec8 --- /dev/null +++ b/step05/src/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { TodoApp } from "./App"; +ReactDOM.render(, document.getElementById("app")); diff --git a/step05/src/style.css b/step05/src/style.css new file mode 100644 index 0000000..c897b4c --- /dev/null +++ b/step05/src/style.css @@ -0,0 +1,50 @@ +body { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + width: 400px; + margin: 20px auto; +} +h1 { + text-align: center; +} + +.textfield { + width: 80%; +} + +.add { + margin-left: 5%; +} + +.button { + border: none; + padding: 5px 10px; +} + +.filter { + margin: 10px 0 0; +} + +.filter button { + background: transparent; + border: none; +} +.filter .active { + border-bottom: 2px solid blue; +} + +.todos { + list-style: none; + padding: 0; +} + +footer { + display: flex; +} + +footer span { + flex-grow: 1; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/step06/index.html b/step06/index.html new file mode 100644 index 0000000..de2c99d --- /dev/null +++ b/step06/index.html @@ -0,0 +1,9 @@ + + + + +
    + + + + diff --git a/step06/src/App.tsx b/step06/src/App.tsx new file mode 100644 index 0000000..d6265ff --- /dev/null +++ b/step06/src/App.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { TodoFooter } from './components/TodoFooter'; +import { TodoHeader } from './components/TodoHeader'; +import { TodoList } from './components/TodoList'; + + +export class TodoApp extends React.Component { + render() { + + const todos = [ + {key: 1, text: 'Todo 1', completed: true}, + {key: 2, text: 'Todo 2'}, + {key: 3, text: 'Todo 3'}, + {key: 4, text: 'Todo 4'}, + ]; + + const filter = 'all'; + + return ( +
    + + + +
    + ); + } +} diff --git a/step06/src/components/TodoFooter.tsx b/step06/src/components/TodoFooter.tsx new file mode 100644 index 0000000..53417df --- /dev/null +++ b/step06/src/components/TodoFooter.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +export const TodoFooter = (props: any) => { + const items = props.todos.filter(todo => !todo.completed) + return ( +
    + {items.length} items left + +
    + ); +}; diff --git a/step06/src/components/TodoHeader.tsx b/step06/src/components/TodoHeader.tsx new file mode 100644 index 0000000..11787c5 --- /dev/null +++ b/step06/src/components/TodoHeader.tsx @@ -0,0 +1,21 @@ +import React from "react"; + +export class TodoHeader extends React.Component { + render() { + const { filter } = this.props; + return ( +
    +

    todos

    + + +
    + + + +
    +
    + ); + } +} diff --git a/step06/src/components/TodoList.tsx b/step06/src/components/TodoList.tsx new file mode 100644 index 0000000..8fb047a --- /dev/null +++ b/step06/src/components/TodoList.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { TodoListItem } from './TodoListItem'; + +export class TodoList extends React.Component { + render() { + const { filter, todos } = this.props; + let filteredTodos: typeof todos = {}; + + filteredTodos = todos.filter(todo => { + const matchesActive = filter == 'active' && !todo.completed; + const matchesCompleted = filter == 'completed' && todo.completed; + + return filter == 'all' || matchesActive || matchesCompleted; + }) + + const TodoListItems = filteredTodos.map(todo => { + return ( + + ); + }) + + return ( +
      + {TodoListItems} +
    + ); + } +} diff --git a/step06/src/components/TodoListItem.tsx b/step06/src/components/TodoListItem.tsx new file mode 100644 index 0000000..29db423 --- /dev/null +++ b/step06/src/components/TodoListItem.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +export class TodoListItem extends React.Component { + + render() { + const {text, completed} = this.props; + return ( +
  • + +
  • + ); + } +} diff --git a/step06/src/index.tsx b/step06/src/index.tsx new file mode 100644 index 0000000..3289ec8 --- /dev/null +++ b/step06/src/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { TodoApp } from "./App"; +ReactDOM.render(, document.getElementById("app")); diff --git a/step06/src/style.css b/step06/src/style.css new file mode 100644 index 0000000..c897b4c --- /dev/null +++ b/step06/src/style.css @@ -0,0 +1,50 @@ +body { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + width: 400px; + margin: 20px auto; +} +h1 { + text-align: center; +} + +.textfield { + width: 80%; +} + +.add { + margin-left: 5%; +} + +.button { + border: none; + padding: 5px 10px; +} + +.filter { + margin: 10px 0 0; +} + +.filter button { + background: transparent; + border: none; +} +.filter .active { + border-bottom: 2px solid blue; +} + +.todos { + list-style: none; + padding: 0; +} + +footer { + display: flex; +} + +footer span { + flex-grow: 1; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 91a0625..a0963f8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "outDir": "./dist/", - "noImplicitAny": true, + "noImplicitAny": false, "module": "esnext", "moduleResolution": "node", "esModuleInterop": true, diff --git a/webpack.config.js b/webpack.config.js index 48e8663..a27dc12 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,8 +2,9 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const entries = { - step01: './step01/index', - step02: './step02/index', + step04: './step04/src/index', + step05: './step05/src/index', + step06: './step06/src/index', playground: './playground/src/index' };