todo-lit.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /**
  2. * @license
  3. * Copyright 2019 Google LLC
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. import {LitElement, html, css} from 'lit';
  7. import {customElement, property} from 'lit/decorators.js';
  8. import TodoModel from './models/todo-model';
  9. import Util from './util/util';
  10. import './components/click-counter';
  11. import './components/todo-input';
  12. import './components/todo-list';
  13. const DISPLAY_STRINGS = {
  14. PLACEHOLDER: 'What needs to be done?',
  15. }
  16. /**
  17. * An example element.
  18. *
  19. * @slot - This element has a slot
  20. * @csspart button - The button
  21. */
  22. @customElement('todo-lit')
  23. export class TodoLit extends LitElement {
  24. static styles = css`
  25. :host {
  26. display: grid;
  27. grid-template-columns: auto [main-content] 600px auto;
  28. padding: 16px;
  29. }
  30. h1, .todo-app {
  31. grid-column: main-content;
  32. }
  33. .todo-app {
  34. border: 1px solid rgba(0,0,0,0.3);
  35. padding: 20px;
  36. }
  37. `;
  38. @property({type: Array})
  39. todos: TodoModel[] = [];
  40. @property({attribute: false})
  41. filter: Function = () => {}
  42. connectedCallback() {
  43. super.connectedCallback();
  44. this.todos = Util.store('todos');
  45. }
  46. render() {
  47. return html`
  48. <h1>todos</h1>
  49. <section class="todo-app">
  50. <div class="controls">
  51. <button type="button" @click="${this._toggleAllCompleted}">Mark all completed</button>
  52. <!-- <button type="button" @click="${this._removeAllTodos}">Remove all</button> -->
  53. <todo-input
  54. .placeholder="${DISPLAY_STRINGS.PLACEHOLDER}"
  55. @submit-todo="${this._addTodo}"></todo-input>
  56. </div>
  57. <todo-list
  58. .todos="${this.todos}"
  59. @remove-todo="${this._removeTodo}"
  60. @toggle-completed="${this._toggleCompleted}"
  61. @update-todo="${this._updateTodo}"
  62. @remove-completed="${this._removeCompletedTodos}"></todo-list>
  63. </section>
  64. `;
  65. }
  66. private _getIndexById(id: string) {
  67. return this.todos.findIndex((todo) => todo.id === id);
  68. }
  69. private _addTodo(event: CustomEvent) {
  70. const newTodo = new TodoModel(event.detail);
  71. this.todos = [
  72. ...this.todos,
  73. newTodo
  74. ];
  75. Util.store('todos', this.todos);
  76. }
  77. private _removeTodo(event: CustomEvent) {
  78. const indexToDelete = this._getIndexById(event.detail.id);
  79. const newArray = [...this.todos];
  80. newArray.splice(indexToDelete, 1);
  81. this.todos = newArray;
  82. Util.store('todos', this.todos);
  83. }
  84. private _toggleCompleted(event: CustomEvent) {
  85. const indexToChange = this._getIndexById(event.detail.id);
  86. const newArray = [...this.todos];
  87. newArray[indexToChange].completed = !newArray[indexToChange].completed;
  88. this.todos = newArray;
  89. Util.store('todos', this.todos);
  90. }
  91. private _updateTodo(event: CustomEvent) {
  92. const indexToChange = this._getIndexById(event.detail.id);
  93. const newArray = [...this.todos];
  94. newArray[indexToChange].description = event.detail.description;
  95. this.todos = newArray;
  96. Util.store('todos', this.todos);
  97. }
  98. private _toggleAllCompleted() {
  99. let completedBool = true
  100. if (this.todos.every((todo) => todo.completed)) {
  101. completedBool = false
  102. }
  103. const newArray = this.todos.map((todo) => {
  104. todo.completed = completedBool;
  105. return todo;
  106. });
  107. this.todos = newArray;
  108. Util.store('todos', this.todos);
  109. }
  110. private _removeAllTodos() {
  111. this.todos = [];
  112. Util.store('todos', this.todos);
  113. }
  114. private _removeCompletedTodos() {
  115. const newArray = this.todos.filter((todo) => !todo.completed);
  116. this.todos = newArray;
  117. Util.store('todos', this.todos);
  118. }
  119. }
  120. declare global {
  121. interface HTMLElementTagNameMap {
  122. 'todo-lit': TodoLit;
  123. }
  124. }