diff --git a/angular.json b/angular.json
index 3a667d1..b8ad48d 100644
--- a/angular.json
+++ b/angular.json
@@ -28,6 +28,7 @@
"src/assets"
],
"styles": [
+ "node_modules/font-awesome/scss/font-awesome.scss",
"node_modules/bulma/bulma.sass",
"src/styles.scss"
],
diff --git a/package-lock.json b/package-lock.json
index 7f69f67..8b691ff 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@angular/platform-browser-dynamic": "^14.1.0",
"@angular/router": "^14.1.0",
"bulma": "^0.9.4",
+ "font-awesome": "^4.7.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
@@ -5822,6 +5823,14 @@
}
}
},
+ "node_modules/font-awesome": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+ "integrity": "sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg==",
+ "engines": {
+ "node": ">=0.10.3"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -15989,6 +15998,11 @@
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"dev": true
},
+ "font-awesome": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+ "integrity": "sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg=="
+ },
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
diff --git a/package.json b/package.json
index 75f3f78..99dfa24 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@angular/platform-browser-dynamic": "^14.1.0",
"@angular/router": "^14.1.0",
"bulma": "^0.9.4",
+ "font-awesome": "^4.7.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 27166ee..2ec8989 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,10 +1,40 @@
-
-
-
Todo List
-
-
+
+
{{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/src/app/app.component.scss b/src/app/app.component.scss
index e69de29..5a0c145 100644
--- a/src/app/app.component.scss
+++ b/src/app/app.component.scss
@@ -0,0 +1,13 @@
+input[type=checkbox] + label {
+ transition: all 500ms;
+}
+
+input[type=checkbox]:checked + label {
+ text-decoration: line-through;
+ color: gray;
+}
+
+.empty-list {
+ color: gray;
+ font-style: italic;
+}
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 12d5133..bdc8370 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,56 @@
-import { Component } from '@angular/core';
+import {Component, OnInit} from '@angular/core';
+import TodoItem from "../models/todo-item.model";
+import LocalService from "../services/local.service";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
-export class AppComponent {
- title = 'todo-list';
+export class AppComponent implements OnInit {
+ public title = 'Todo List App';
+ public list: TodoItem[] = [];
+
+ private LOCAL_STORAGE_KEY = "todoList";
+ inputValue: any;
+
+ ngOnInit(): void {
+ const savedData: null | TodoItem[] = LocalService.getData(this.LOCAL_STORAGE_KEY)
+ if (savedData) this.list = savedData;
+ }
+
+ /**
+ * Create a new item if input is not empty and the item doesn't exist already
+ */
+ addItem(): void {
+ const listOfTodoText = this.list.map(item => item.text);
+
+ if (this.inputValue && !listOfTodoText.includes(this.inputValue)) {
+ this.list.push(new TodoItem(this.inputValue))
+ this.inputValue = "";
+ this.saveList();
+ }
+ }
+
+ /**
+ * Remove a specific item of the list
+ * @param toRemove TodoItem to remove
+ */
+ removeItem(toRemove: TodoItem): void {
+ this.list = this.list.filter(item => item !== toRemove);
+ this.saveList();
+ }
+
+ /**
+ * Remove all checked items of the list
+ */
+ removeCheckedItems(): void {
+ this.list = this.list.filter(item => !item.checked)
+ this.saveList();
+ }
+
+ private saveList(): void {
+ LocalService.saveData(this.LOCAL_STORAGE_KEY, this.list);
+ }
+
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 3053728..f87c0b3 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -2,17 +2,11 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
-import { TodoListComponent } from './todo-list/todo-list.component';
-import { TodoItemComponent } from './todo-item/todo-item.component';
-import { TodoInputComponent } from './todo-input/todo-input.component';
import {FormsModule} from "@angular/forms";
@NgModule({
declarations: [
- AppComponent,
- TodoListComponent,
- TodoItemComponent,
- TodoInputComponent
+ AppComponent
],
imports: [
BrowserModule,
diff --git a/src/app/todo-input/todo-input.component.html b/src/app/todo-input/todo-input.component.html
deleted file mode 100644
index 6ba32f8..0000000
--- a/src/app/todo-input/todo-input.component.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/src/app/todo-input/todo-input.component.scss b/src/app/todo-input/todo-input.component.scss
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/todo-input/todo-input.component.spec.ts b/src/app/todo-input/todo-input.component.spec.ts
deleted file mode 100644
index a006708..0000000
--- a/src/app/todo-input/todo-input.component.spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { TodoInputComponent } from './todo-input.component';
-
-describe('TodoInputComponent', () => {
- let component: TodoInputComponent;
- let fixture: ComponentFixture
;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ TodoInputComponent ]
- })
- .compileComponents();
-
- fixture = TestBed.createComponent(TodoInputComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
diff --git a/src/app/todo-input/todo-input.component.ts b/src/app/todo-input/todo-input.component.ts
deleted file mode 100644
index a5586c0..0000000
--- a/src/app/todo-input/todo-input.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import {TodoItemService} from "../../services/todo-item.service";
-
-@Component({
- selector: 'app-todo-input',
- templateUrl: './todo-input.component.html',
- styleUrls: ['./todo-input.component.scss']
-})
-export class TodoInputComponent implements OnInit {
- textInput: string = "";
-
- constructor(private todoItemService: TodoItemService) { }
- ngOnInit(): void {}
-
- createTodoItem(): void {
- if (this.textInput) {
- this.todoItemService.newItem(this.textInput);
- this.textInput = "";
- }
- }
-}
diff --git a/src/app/todo-item/todo-item.component.html b/src/app/todo-item/todo-item.component.html
deleted file mode 100644
index 4472c4b..0000000
--- a/src/app/todo-item/todo-item.component.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
diff --git a/src/app/todo-item/todo-item.component.scss b/src/app/todo-item/todo-item.component.scss
deleted file mode 100644
index 62c5008..0000000
--- a/src/app/todo-item/todo-item.component.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-li {
- list-style: none;
-
- input:checked + label {
- color: gray;
- &::after { width: 100%; }
- }
-
- label::after {
- content: '';
- width: 0; // Before animation
- height: 2px;
- background-color: gray;
-
- position: absolute;
- top: 50%; left: 0;
-
- transition: width 300ms ease-in-out;
- }
-}
diff --git a/src/app/todo-item/todo-item.component.spec.ts b/src/app/todo-item/todo-item.component.spec.ts
deleted file mode 100644
index f7580ef..0000000
--- a/src/app/todo-item/todo-item.component.spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { TodoItemComponent } from './todo-item.component';
-
-describe('TodoItemComponent', () => {
- let component: TodoItemComponent;
- let fixture: ComponentFixture;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ TodoItemComponent ]
- })
- .compileComponents();
-
- fixture = TestBed.createComponent(TodoItemComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
diff --git a/src/app/todo-item/todo-item.component.ts b/src/app/todo-item/todo-item.component.ts
deleted file mode 100644
index c8bdf12..0000000
--- a/src/app/todo-item/todo-item.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import {Component, Input, OnInit} from '@angular/core';
-import {TodoItem} from "../../models/todo-item.model";
-import {TodoItemService} from "../../services/todo-item.service";
-
-@Component({
- selector: 'app-todo-item',
- templateUrl: './todo-item.component.html',
- styleUrls: ['./todo-item.component.scss']
-})
-export class TodoItemComponent implements OnInit {
- @Input() todoItem!: TodoItem
-
- constructor(private todoItemService: TodoItemService) {}
- ngOnInit(): void {}
-
- check() {
- this.todoItem.checked = !this.todoItem.checked;
- this.todoItemService.checkById(this.todoItem.id, this.todoItem.checked)
- }
-
-}
diff --git a/src/app/todo-list/todo-list.component.html b/src/app/todo-list/todo-list.component.html
deleted file mode 100644
index 1535950..0000000
--- a/src/app/todo-list/todo-list.component.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/app/todo-list/todo-list.component.scss b/src/app/todo-list/todo-list.component.scss
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/todo-list/todo-list.component.spec.ts b/src/app/todo-list/todo-list.component.spec.ts
deleted file mode 100644
index cbb54a9..0000000
--- a/src/app/todo-list/todo-list.component.spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { TodoListComponent } from './todo-list.component';
-
-describe('TodoListComponent', () => {
- let component: TodoListComponent;
- let fixture: ComponentFixture;
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- declarations: [ TodoListComponent ]
- })
- .compileComponents();
-
- fixture = TestBed.createComponent(TodoListComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
diff --git a/src/app/todo-list/todo-list.component.ts b/src/app/todo-list/todo-list.component.ts
deleted file mode 100644
index eff02e0..0000000
--- a/src/app/todo-list/todo-list.component.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import {Component, OnInit} from '@angular/core';
-import {TodoItem} from "../../models/todo-item.model";
-import {TodoItemService} from "../../services/todo-item.service";
-
-@Component({
- selector: 'app-todo-list',
- templateUrl: './todo-list.component.html',
- styleUrls: ['./todo-list.component.scss']
-})
-export class TodoListComponent implements OnInit {
- todoItems!: TodoItem[];
-
- constructor(private todoItemService: TodoItemService) {}
- ngOnInit(): void {
- this.todoItemService.loadItems();
- this.todoItems = this.todoItemService.todoItems;
- }
-}
diff --git a/src/models/todo-item.model.ts b/src/models/todo-item.model.ts
index c52b187..cfd7fc8 100644
--- a/src/models/todo-item.model.ts
+++ b/src/models/todo-item.model.ts
@@ -1,6 +1,6 @@
-export class TodoItem {
+export default class TodoItem {
+
constructor(
- public id: number,
public text: string,
public checked: boolean = false
) {}
diff --git a/src/services/local.service.ts b/src/services/local.service.ts
new file mode 100644
index 0000000..6ea0762
--- /dev/null
+++ b/src/services/local.service.ts
@@ -0,0 +1,19 @@
+import { Injectable } from '@angular/core';
+import TodoItem from "../models/todo-item.model";
+
+@Injectable({
+ providedIn: 'root'
+})
+export default class LocalService {
+
+ static saveData(key: string, data: TodoItem[]) {
+ localStorage.setItem(key, JSON.stringify(data));
+ }
+
+ static getData(key: string): TodoItem[] | null {
+ const data = localStorage.getItem(key);
+ if (!data) return null
+
+ return JSON.parse(data) as TodoItem[];
+ }
+}
diff --git a/src/services/todo-item.service.ts b/src/services/todo-item.service.ts
deleted file mode 100644
index 1489c67..0000000
--- a/src/services/todo-item.service.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import {Injectable} from "@angular/core";
-import {TodoItem} from "../models/todo-item.model";
-
-@Injectable({
- providedIn: 'root'
-})
-export class TodoItemService {
- todoItems: TodoItem[] = [];
-
- get nextId(): number {
- return this.todoItems.length + 1
- }
-
- getById(id: number): TodoItem {
- const todoItem = this.todoItems.find(item => item.id === id);
- if (!todoItem) throw new Error('Todo item not found!');
- return todoItem;
- }
-
- newItem(text: string): void {
- const newTodoItem: TodoItem = new TodoItem(this.nextId, text);
- this.todoItems.push(newTodoItem);
-
- this.saveItems()
- }
-
- checkById(id: number, checked: boolean) {
- this.todoItems[id - 1].checked = checked;
- this.saveItems()
- }
-
- loadItems() {
- const saveDataRaw: any = localStorage.getItem("todoList");
-
- if (saveDataRaw as string) this.todoItems = JSON.parse(saveDataRaw);
- }
-
- saveItems() {
- localStorage.setItem("todoList", JSON.stringify(this.todoItems))
- }
-}
diff --git a/src/styles.scss b/src/styles.scss
index 90d4ee0..3b5bd06 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -1 +1,9 @@
/* You can add global styles to this file, and also import other style files */
+body {
+ width: 100vw;
+ min-height: 100vh;
+ background-color: whitesmoke;
+
+ display: grid;
+ place-items: center;
+}