forked from Fernanda-Kipper/eventostec-frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: extract app home to a component
- Loading branch information
1 parent
97e6acd
commit 326af29
Showing
7 changed files
with
351 additions
and
306 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,175 +1 @@ | ||
<app-header></app-header> | ||
|
||
<main id="content" class="bg-white py-24 sm:py-32"> | ||
<div class="mx-auto max-w-7xl px-6 lg:px-8"> | ||
<div id="list-header" class="mx-auto max-w-2xl text-center mb-6"> | ||
<h2 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl"> | ||
Lista de Eventos | ||
</h2> | ||
<p class="mt-2 text-lg leading-8 text-gray-600"> | ||
Aqui você irá encontrar a lista de próximos eventos de tecnologia que | ||
irão rolar no Brasil compartilhados pela comunidade! | ||
</p> | ||
</div> | ||
<div id="event-filter" class="relative"> | ||
<div class="absolute inset-0 flex items-center" aria-hidden="true"> | ||
<div class="w-full border-t border-gray-300"></div> | ||
</div> | ||
<div class="relative flex justify-center"> | ||
<div class="flex items-center justify-center"> | ||
<span class="relative inline-flex"> | ||
<button | ||
(click)="toggleModal()" | ||
type="button" | ||
class="rounded-xl inline-flex items-center px-6 py-1 font-semibold leading-6 text-sm shadow bg-white hover:bg-gray-50 dark:bg-slate-800 dark:hover:bg-slate-600 dark:text-white transition ease-in-out duration-150 cursor-pointer ring-1 ring-slate-900/10 dark:ring-slate-200/20" | ||
> | ||
<svg | ||
class="-ml-1 -mr-0.5 h-5 w-5 text-gray-400" | ||
viewBox="0 0 20 20" | ||
fill="currentColor" | ||
aria-hidden="true" | ||
> | ||
<path | ||
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z" | ||
/> | ||
</svg> | ||
Filtro | ||
</button> | ||
<span | ||
class="flex {{ | ||
isFilterActive() | ||
}} absolute h-3 w-3 top-0 right-0 -mt-1 -mr-1" | ||
> | ||
<span | ||
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-indigo-600 opacity-75" | ||
></span> | ||
<span | ||
class="relative inline-flex rounded-full h-3 w-3 bg-indigo-600" | ||
></span> | ||
</span> | ||
</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div | ||
id="event-list" | ||
class="mt-16 flex justify-center w-full sm:mt-20 lg:mx-0" | ||
> | ||
<ul class="-my-8 grid grid-cols-3 gap-7 w-full divide-y divide-gray-100"> | ||
@for (event of eventList; track event) { | ||
<app-event | ||
[url]="event.url" | ||
[banner]="event.banner" | ||
[title]="event.title" | ||
[description]="event.description" | ||
[date]="event.date" | ||
[place]="event.place" | ||
>{{ event }}</app-event | ||
> | ||
} | ||
</ul> | ||
</div> | ||
</div> | ||
</main> | ||
<app-modal [isModalOpen]="isModalOpen" (closeModal)="toggleModal()"> | ||
<div> | ||
<div class="mt-3 text-center sm:mt-5"> | ||
<h3 | ||
class="text-base font-semibold leading-6 text-gray-900" | ||
id="modal-title" | ||
> | ||
Selecione os filtros | ||
</h3> | ||
</div> | ||
</div> | ||
<form [formGroup]="filterForm"> | ||
<div class="mb-5"> | ||
<label | ||
for="stateDropdown" | ||
class="mb-3 block text-base font-medium text-[#07074D]" | ||
> | ||
Estado | ||
</label> | ||
<select | ||
id="stateDropdown" | ||
formControlName="locale" | ||
class="w-full rounded-md border py-3 px-6 outline-none" | ||
(change)="stateSelect2()" | ||
> | ||
@for (option of states; track option.label) { | ||
<option [value]="option.id">{{ option.label }}</option> | ||
} | ||
</select> | ||
</div> | ||
<div class="mb-5"> | ||
<label | ||
for="cityDropdown" | ||
class="mb-3 block text-base font-medium text-[#07074D]" | ||
> | ||
Cidade | ||
</label> | ||
<select | ||
id="cityDropdown" | ||
formControlName="city" | ||
class="w-full rounded-md border py-3 px-6 outline-none" | ||
> | ||
@for (option of cities; track option.label) { | ||
<option [value]="option.value">{{ option.label }}</option> | ||
} | ||
</select> | ||
</div> | ||
<div class="-mx-3 flex flex-wrap"> | ||
<div class="w-full px-3 sm:w-1/2"> | ||
<div class="mb-5"> | ||
<label | ||
for="date" | ||
class="mb-3 block text-base font-medium text-[#07074D]" | ||
> | ||
De | ||
</label> | ||
<input | ||
formControlName="from" | ||
type="date" | ||
name="date" | ||
id="date" | ||
class="w-full rounded-md border border-[#e0e0e0] bg-white py-3 px-6 text-base font-medium text-[#6B7280] outline-none focus:border-[#6A64F1] focus:shadow-md" | ||
/> | ||
</div> | ||
</div> | ||
<div class="w-full px-3 sm:w-1/2"> | ||
<div class="mb-5"> | ||
<label | ||
for="date" | ||
class="mb-3 block text-base font-medium text-[#07074D]" | ||
> | ||
Até | ||
</label> | ||
<input | ||
formControlName="to" | ||
type="date" | ||
name="date" | ||
id="date" | ||
class="w-full rounded-md border border-[#e0e0e0] bg-white py-3 px-6 text-base font-medium text-[#6B7280] outline-none focus:border-[#6A64F1] focus:shadow-md" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="mt-5 flex flex-col gap-2 sm:mt-6"> | ||
<button | ||
(click)="submit()" | ||
[disabled]="!filterForm.valid" | ||
type="button" | ||
class="inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:bg-red-400 disabled:hover:bg-red-300 disabled:cursor-not-allowed" | ||
> | ||
Aplicar | ||
</button> | ||
<button | ||
(click)="clearFilter()" | ||
type="button" | ||
class="inline-flex w-full justify-center rounded-md bg-indigo-400 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" | ||
> | ||
Limpar filtro | ||
</button> | ||
</div> | ||
</form> | ||
</app-modal> | ||
<router-outlet></router-outlet> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,11 @@ | ||
import { | ||
Component, | ||
ElementRef, | ||
OnInit, | ||
signal, | ||
ViewChild, | ||
} from '@angular/core'; | ||
import { Component } from '@angular/core'; | ||
import { RouterOutlet } from '@angular/router'; | ||
import { | ||
FormControl, | ||
FormGroup, | ||
ReactiveFormsModule, | ||
Validators, | ||
} from '@angular/forms'; | ||
import { CommonModule } from '@angular/common'; | ||
|
||
import { NgSelectModule } from '@ng-select/ng-select'; | ||
|
||
import { EventComponent } from './components/event/event.component'; | ||
import { ModalComponent } from './components/modal/modal.component'; | ||
import { HeaderComponent } from './header/header.component'; | ||
import { FilterService } from './services/filter.service'; | ||
import { UF } from './types/UF.type'; | ||
import { City } from './types/City.type'; | ||
import { EventItem } from './types/Event.type'; | ||
|
||
interface FilterForm { | ||
locale: FormControl<string | null>; | ||
city: FormControl<string | null>; | ||
from: FormControl<Date | null>; | ||
to: FormControl<Date | null>; | ||
} | ||
|
||
@Component({ | ||
selector: 'app-root', | ||
standalone: true, | ||
imports: [ | ||
RouterOutlet, | ||
CommonModule, | ||
NgSelectModule, | ||
ReactiveFormsModule, | ||
ModalComponent, | ||
EventComponent, | ||
HeaderComponent, | ||
], | ||
imports: [RouterOutlet], | ||
templateUrl: './app.component.html', | ||
styleUrls: ['./app.component.scss'], | ||
}) | ||
export class AppComponent implements OnInit { | ||
@ViewChild('stateSelect') stateSelect!: ElementRef<HTMLSelectElement>; | ||
|
||
filterForm!: FormGroup<FilterForm>; | ||
isModalOpen = signal(false); | ||
|
||
states: { id: number; label: string; value: string }[] = []; | ||
cities: { id: number; label: string; value: string }[] = []; | ||
|
||
eventList: EventItem[] = []; | ||
|
||
filterIsActive = false; | ||
|
||
constructor(private filterService: FilterService) {} | ||
|
||
ngOnInit() { | ||
this.filterForm = new FormGroup<FilterForm>({ | ||
locale: new FormControl<string | null>(null, [Validators.required]), | ||
city: new FormControl<string | null>(null, [Validators.required]), | ||
from: new FormControl<Date | null>(null, [Validators.required]), | ||
to: new FormControl<Date | null>(null, [Validators.required]), | ||
}); | ||
|
||
this.loadLocalesFilter(); | ||
|
||
this.eventList = [ | ||
{ | ||
title: 'Frontin Sampa', | ||
place: 'São Paulo', | ||
date: '19/10/2024', | ||
description: 'Maior evento de Frontend do Brasil!', | ||
banner: 'https://images.sympla.com.br/630305a3009a1-lg.png', | ||
url: 'https://frontinsampa.com.br/', | ||
}, | ||
]; | ||
} | ||
|
||
loadLocalesFilter() { | ||
this.filterService.loadLocales().subscribe({ | ||
next: (body: UF[]) => { | ||
this.states = body.map((value) => ({ | ||
id: value.id, | ||
label: value.nome, | ||
value: value.sigla, | ||
})); | ||
}, | ||
}); | ||
} | ||
|
||
loadCities(selectedState: number) { | ||
this.filterService.loadCitiesByState(selectedState).subscribe({ | ||
next: (cities: City[]) => { | ||
this.cities = cities.map((city) => ({ | ||
id: city.id, | ||
label: city.nome, | ||
value: city.nome, | ||
})); | ||
}, | ||
error: (error) => { | ||
console.error('Error loading cities:', error); | ||
// Handle the error (e.g., show an error message to the user) | ||
}, | ||
}); | ||
} | ||
|
||
stateSelect2() { | ||
const selectedStateValue = this.filterForm.get('locale')!.value; | ||
if (selectedStateValue) { | ||
this.loadCities(Number(selectedStateValue)); | ||
} | ||
} | ||
|
||
toggleModal() { | ||
this.isModalOpen.update((value) => !value); | ||
} | ||
|
||
submit() { | ||
this.isModalOpen.set(false); | ||
this.filterIsActive = true; | ||
} | ||
|
||
isFilterActive() { | ||
return this.filterIsActive ? 'visible' : 'invisible'; | ||
} | ||
|
||
clearFilter() { | ||
this.filterIsActive = false; | ||
this.filterForm.reset(); | ||
} | ||
} | ||
export class AppComponent {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
import { Routes } from '@angular/router'; | ||
import { HomeComponent } from './pages/home/home.component'; | ||
import { RegisterEventComponent } from './pages/register-event/register-event.component'; | ||
|
||
export const routes: Routes = []; | ||
export const routes: Routes = [ | ||
{ | ||
path: '', | ||
component: HomeComponent, | ||
}, | ||
{ | ||
path: 'registra-evento', | ||
component: RegisterEventComponent, | ||
}, | ||
]; |
Oops, something went wrong.