diff --git a/.firebase/hosting.ZGlzdFxteWFwcA.cache b/.firebase/hosting.ZGlzdFxteWFwcA.cache new file mode 100644 index 00000000..aacde544 --- /dev/null +++ b/.firebase/hosting.ZGlzdFxteWFwcA.cache @@ -0,0 +1,7 @@ +favicon.ico,1695655048321,2c19690e9587bae12f419b34d2edeecc76808099540a9c9f4ea6194116cfc8f7 +styles.a3438b96a051397b.css,1695698150126,713384c7a28549bc7590bc4e9662d5f36675bbb741bb4ff09fd78b89e58f8ebb +index.html,1695698150478,b8e616aaa42b9b90cea7ae4b73fb7850cdc064b42accefd624c1a9ed3300ebfd +3rdpartylicenses.txt,1695698150126,383c1d41903eff2274ee14e40a66d29277f6fb626a08a03ce7e3c24b18d3f4a9 +runtime.1c98015aec84e5af.js,1695698150126,a9a2242fbb64fd6d942119ead9e92d64b59c0aaf0e05c408d16eb13140cc05d1 +polyfills.fa2d22cf5f8cbea5.js,1695698150124,2a7e7f461361dc4fc55f7748895f006ecab3359aeeb313a17c891dd96a4e472e +main.69c0ec6ce40e47d2.js,1695698150125,3f281fb4cb22a66cfa4e03d369e2e4dc12b92af4b5ed1cac266bdd6c981182cb diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..813e3767 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "platzi-prueba-tecnica" + } +} diff --git a/angular.json b/angular.json index 7e1e741e..746dbb9f 100644 --- a/angular.json +++ b/angular.json @@ -42,7 +42,7 @@ { "type": "anyComponentStyle", "maximumWarning": "2kb", - "maximumError": "4kb" + "maximumError": "10kb" } ], "fileReplacements": [ diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..b478cc6c --- /dev/null +++ b/firebase.json @@ -0,0 +1,16 @@ +{ + "hosting": { + "public": "dist/myapp", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 00db1a2f..10e69056 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,6 +8,11 @@ const routes: Routes = [ path: '', component: HomeComponent, pathMatch: 'full' + }, + { + path: ':filtro', + component: HomeComponent, + pathMatch: 'full' } ]; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0d6eea4d..1a4ac5b9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,15 +4,23 @@ import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './pages/home/home.component'; +import { MainComponent } from './pages/main/main.component'; +import { FooterComponent } from './pages/footer/footer.component'; +import { FormsModule } from '@angular/forms'; +import { AutofocusDirective } from './directives/autofocus.directive'; @NgModule({ declarations: [ AppComponent, - HomeComponent + HomeComponent, + MainComponent, + FooterComponent, + AutofocusDirective ], imports: [ BrowserModule, - AppRoutingModule + AppRoutingModule, + FormsModule ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/directives/autofocus.directive.ts b/src/app/directives/autofocus.directive.ts new file mode 100644 index 00000000..441fecdd --- /dev/null +++ b/src/app/directives/autofocus.directive.ts @@ -0,0 +1,14 @@ +import { AfterViewInit, Directive, ElementRef } from '@angular/core'; + +@Directive({ + selector: '[appAutofocus]' +}) +export class AutofocusDirective implements AfterViewInit{ + + constructor( private host: ElementRef) { } + + ngAfterViewInit(): void { + this.host.nativeElement.focus(); + } + +} diff --git a/src/app/models/tarea.model.ts b/src/app/models/tarea.model.ts new file mode 100644 index 00000000..a4d84779 --- /dev/null +++ b/src/app/models/tarea.model.ts @@ -0,0 +1,5 @@ +export interface Tarea { + id: number; + title: string; + completed: boolean; +} \ No newline at end of file diff --git a/src/app/pages/footer/footer.component.html b/src/app/pages/footer/footer.component.html new file mode 100644 index 00000000..8e483f6b --- /dev/null +++ b/src/app/pages/footer/footer.component.html @@ -0,0 +1,18 @@ + diff --git a/src/app/pages/footer/footer.component.ts b/src/app/pages/footer/footer.component.ts new file mode 100644 index 00000000..cb48cb8f --- /dev/null +++ b/src/app/pages/footer/footer.component.ts @@ -0,0 +1,41 @@ +import { Component, OnDestroy, OnInit, Input } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { TareaService } from 'src/app/services/tarea.service'; + +@Component({ + selector: 'app-footer', + templateUrl: './footer.component.html', + styleUrls: ['../../../styles.css'] +}) +export class FooterComponent implements OnInit, OnDestroy{ + + // contador: number = 0; + subTarea!: Subscription; + + + @Input() contador: number = 0; + @Input() showButton: boolean = false; + @Input() word: string = 'item'; + + constructor( + private tareaService: TareaService + ){ + } + + + ngOnInit(): void { + console.log('ngOnInit') + } + + filterTareas( mode: string ){ + this.tareaService.filterTareas( mode ); + } + + clearTareas(){ + this.tareaService.clearTareas(); + } + + ngOnDestroy(): void { + console.log('onDestroy') + } +} diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html index 66de2be3..d0f9c205 100644 --- a/src/app/pages/home/home.component.html +++ b/src/app/pages/home/home.component.html @@ -6,59 +6,17 @@

My Day

-
- -
+ -
diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index 33d0e6d9..440b781c 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -1,14 +1,47 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Tarea } from 'src/app/models/tarea.model'; +import { TareaService } from 'src/app/services/tarea.service'; +import { Subscription } from 'rxjs'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-home', templateUrl: './home.component.html', }) -export class HomeComponent implements OnInit { +export class HomeComponent implements OnInit, OnDestroy { + + titleTarea: string = ''; + contador: number = 0; + subContador!: Subscription; + filtro: string = 'all'; - constructor() { } + constructor( + private tareaService: TareaService, + private activatedroute:ActivatedRoute + ) { } ngOnInit(): void { + this.tareaService.getTareas(); + this.subContador = this.tareaService.contador$ + .subscribe(cont => { + this.contador = cont; + }); + + this.activatedroute.params + .subscribe(param => { + this.filtro = param['filtro']; + this.tareaService.filterTareas(param['filtro']) + }); + } + + addTarea(){ + let tarea: Tarea = { id: 0, title: this.titleTarea.replace(/ +(?= )/g,''), completed: false }; + this.tareaService.addTarea(tarea); + this.titleTarea = ''; + } + + ngOnDestroy(): void { + this.subContador.unsubscribe(); } } diff --git a/src/app/pages/main/main.component.html b/src/app/pages/main/main.component.html new file mode 100644 index 00000000..c326ec11 --- /dev/null +++ b/src/app/pages/main/main.component.html @@ -0,0 +1,16 @@ +
+ +
+ + \ No newline at end of file diff --git a/src/app/pages/main/main.component.ts b/src/app/pages/main/main.component.ts new file mode 100644 index 00000000..a380ae37 --- /dev/null +++ b/src/app/pages/main/main.component.ts @@ -0,0 +1,106 @@ +import { Component, OnInit, OnDestroy, ViewChild, ElementRef, Input } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { Tarea } from 'src/app/models/tarea.model'; +import { TareaService } from 'src/app/services/tarea.service'; + +@Component({ + selector: 'app-main', + templateUrl: './main.component.html', + styleUrls: ['../../../styles.css'] +}) +export class MainComponent implements OnInit, OnDestroy{ + + @ViewChild('edit') inputEdit!: ElementRef; + @Input() filtro: string = 'all'; + + contador: number = 0; + showButton: boolean = false; + word: string = 'item'; + + + tareas: Tarea[] = []; + tareasTemp: Tarea[] = []; + + tareaEdit: Tarea = {id: 0, title: '', completed: false}; + subTarea!: Subscription; + subFilter!: Subscription; + isEditing: boolean = false; + + constructor( + private tareaService: TareaService + ){ + + } + + ngOnInit(){ + this.subTarea = this.tareaService.tareas$ + .subscribe(tareas =>{ + this.showButton = false; + this.tareas = tareas; + this.tareas.map(t => { + if(t.completed === true){ + this.showButton = true; + } + }); + + this.filtroDatos(this.filtro); + }); + + this.subFilter =this.tareaService.filter$ + .subscribe(filter =>{ + this.filtroDatos(filter); + }); + + this.subTarea =this.tareaService.contador$ + .subscribe(cont =>{ + this.contador = cont; + this.word = this.contador > 1 ? 'items' : 'item'; + }); + } + + filtroDatos(filtro:string){ + console.log('filtro->',filtro) + if( filtro && filtro !== 'all' ){ + let cond: boolean = filtro === 'pending' ? false : true; + this.tareasTemp = this.tareas.filter(tarea => tarea.completed === cond); + // console.log('tareasTemp1->',this.tareasTemp) + }else{ + this.tareasTemp = this.tareas; + // console.log('tareasTemp2->',this.tareasTemp) + } + this.tareaService.setContador( this.tareas.length ); + + } + + editTarea( tarea: Tarea ){ + this.isEditing = true; + this.tareaEdit = {id: tarea.id, title: tarea.title.replace(/ +(?= )/g,''), completed: tarea.completed}; + // console.log('elemt',this.inputEdit.nativeElement); + // this.inputEdit.nativeElement.focus(); + } + + key(event: any){ + if(event.key === 'Enter'){ + this.updateTarea( this.tareaEdit ); + this.tareaEdit = {id: 0, title: '', completed: false}; + this.isEditing = false; + }else if( event.key === 'Escape' ){ + this.isEditing = false; + this.tareaEdit = {id: 0, title: '', completed: false}; + } + } + + deleteTarea( index: number ){ + this.tareaService.deleteTarea( index ); + } + + updateTarea( tarea: Tarea ){ + this.tareaService.updateTarea( tarea ); + } + + ngOnDestroy(){ + this.subTarea.unsubscribe(); + } + +} diff --git a/src/app/services/tarea.service.ts b/src/app/services/tarea.service.ts new file mode 100644 index 00000000..68655df7 --- /dev/null +++ b/src/app/services/tarea.service.ts @@ -0,0 +1,77 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { Tarea } from '../models/tarea.model'; + +@Injectable({ + providedIn: 'root' +}) +export class TareaService { + + listTarea: Tarea[] = []; + + private tareas = new BehaviorSubject([]); + tareas$ = this.tareas.asObservable(); + + private filter = new BehaviorSubject('all'); + filter$ = this.filter.asObservable(); + + private contador = new BehaviorSubject(0); + contador$ = this.contador.asObservable(); + + constructor() { } + + getTareas(){ + let tarea = localStorage.getItem('mydayapp-angular'); + if(tarea){ + let data:Tarea[] = JSON.parse(tarea); + this.listTarea = data; + this.saveTareas(); + } + } + + filterTareas( mode: string ){ + this.filter.next( mode ); + } + + addTarea(tarea: Tarea){ + tarea.id = Math.random()// this.listTarea.length > 0 ? Number(this.listTarea.map(tarea => tarea.id).reduce((max, act) => max + act)) + 1 : 0; + this.listTarea.push(tarea); + this.saveTareas(); + } + + updateTarea( tarea: Tarea ){ + this.listTarea.map( t => { + console.log('antes->',t) + console.log('desp->',tarea) + if( t.id === tarea.id ){ + t.title = tarea.title.trim(); + t.completed = tarea.completed; + } + }); + this.saveTareas(); + } + + deleteTarea( index: number ){ + this.listTarea.splice(index, 1); + this.saveTareas(); + } + + clearTareas(){ + for(let i = this.listTarea.length - 1; i >= 0; i--){ + if(this.listTarea[i].completed === true){ + this.listTarea.splice(i,1); + } + } + this.saveTareas(); + } + + saveTareas(){ + localStorage.setItem('mydayapp-angular', JSON.stringify(this.listTarea)); + this.tareas.next(this.listTarea); + } + + setContador( valor: number ){ + this.contador.next( valor ); + } + +}