diff --git a/src/app/app.component.html b/src/app/app.component.html index 2934ad1..6659729 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1,2 @@ - + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f33c411..6541f44 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,12 +1,14 @@ import { Component } from '@angular/core'; import { HomeComponent } from './pages/home/home.component'; +import { RouterOutlet } from '@angular/router'; +import { NavbarComponent } from './components/navbar/navbar.component'; @Component({ selector: 'app-root', standalone: true, - imports: [HomeComponent], + imports: [RouterOutlet, NavbarComponent], templateUrl: './app.component.html', - styleUrl: './app.component.css' + styleUrl: './app.component.css', }) export class AppComponent { title = 'TASK-NG-Routing'; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index dc39edb..e5ba4be 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,3 +1,14 @@ import { Routes } from '@angular/router'; +import { TripsListComponent } from './pages/trips-list/trips-list.component'; +import { TripComponent } from './pages/trip/trip.component'; +import { HomeComponent } from './pages/home/home.component'; -export const routes: Routes = []; +export const routes: Routes = [ + { path: 'trips', component: TripsListComponent }, + { path: 'trips/:slug', component: TripComponent }, + { path: '', component: HomeComponent }, + { + path: '**', + redirectTo: '', + }, +]; diff --git a/src/app/components/navbar/navbar.component.html b/src/app/components/navbar/navbar.component.html index 86bcc47..ec9d940 100644 --- a/src/app/components/navbar/navbar.component.html +++ b/src/app/components/navbar/navbar.component.html @@ -6,10 +6,10 @@ diff --git a/src/app/components/search-filter/search-filter.component.html b/src/app/components/search-filter/search-filter.component.html index 5df8e03..0eac80a 100644 --- a/src/app/components/search-filter/search-filter.component.html +++ b/src/app/components/search-filter/search-filter.component.html @@ -3,8 +3,10 @@ type="search" class="search-input" placeholder="Search" + [value]="initialSearch" (input)="onSearch($event)" /> +
@for (level of difficultyLevels; track $index) {
diff --git a/src/app/components/trip-details/trip-details.component.ts b/src/app/components/trip-details/trip-details.component.ts index ad029f7..f410628 100644 --- a/src/app/components/trip-details/trip-details.component.ts +++ b/src/app/components/trip-details/trip-details.component.ts @@ -1,13 +1,14 @@ import { Component, Input } from '@angular/core'; import { Trip } from '../../../data/trips'; import { DividerComponent } from '../divider/divider.component'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'app-trip-details', standalone: true, - imports: [DividerComponent], + imports: [DividerComponent, CommonModule], templateUrl: './trip-details.component.html', - styleUrl: './trip-details.component.css' + styleUrl: './trip-details.component.css', }) export class TripDetailsComponent { @Input() trip!: Trip; diff --git a/src/app/components/trips-grid/trips-grid.component.html b/src/app/components/trips-grid/trips-grid.component.html index 2829032..daed6f6 100644 --- a/src/app/components/trips-grid/trips-grid.component.html +++ b/src/app/components/trips-grid/trips-grid.component.html @@ -1,5 +1,7 @@
@for (trip of trips; track trip.id) { - + + + }
diff --git a/src/app/components/trips-grid/trips-grid.component.ts b/src/app/components/trips-grid/trips-grid.component.ts index c0d5289..10d1b0a 100644 --- a/src/app/components/trips-grid/trips-grid.component.ts +++ b/src/app/components/trips-grid/trips-grid.component.ts @@ -1,13 +1,14 @@ import { Component, Input } from '@angular/core'; -import { Trip } from '../../../data/trips'; +import { Trip, trips } from '../../../data/trips'; import { TripCardComponent } from '../trip-card/trip-card.component'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-trips-grid', standalone: true, - imports: [TripCardComponent], + imports: [TripCardComponent, RouterLink], templateUrl: './trips-grid.component.html', - styleUrl: './trips-grid.component.css' + styleUrl: './trips-grid.component.css', }) export class TripsGridComponent { @Input() trips: Trip[] = []; diff --git a/src/app/pages/home/home.component.css b/src/app/pages/home/home.component.css index 8630602..8b13789 100644 --- a/src/app/pages/home/home.component.css +++ b/src/app/pages/home/home.component.css @@ -1,25 +1 @@ -.explore-section { - padding-top: 6rem; - padding-bottom: 6rem; - background-color: #ffffff; -} -.explore-container { - max-width: 1200px; - margin: 0 auto; - padding: 0 1rem; -} - -.explore-title { - text-align: center; - text-transform: uppercase; - font-size: 1.875rem; - font-weight: 700; - color: #2c3e50; -} - -@media (min-width: 768px) { - .explore-title { - font-size: 2.25rem; - } -} diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html index 08171ab..9f2c545 100644 --- a/src/app/pages/home/home.component.html +++ b/src/app/pages/home/home.component.html @@ -1,25 +1,4 @@ - - - -
-
-

Explore Trips

-
- - - -
-
- -@if (selectedTrip) { - -} diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index 00f224f..7239658 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -10,46 +10,10 @@ import { NavbarComponent } from '../../components/navbar/navbar.component'; @Component({ selector: 'app-home', standalone: true, - imports: [ - BannerComponent, - SearchFilterComponent, - DividerComponent, - TripsGridComponent, - TripDetailsComponent, - NavbarComponent, - ], + imports: [BannerComponent], templateUrl: './home.component.html', styleUrl: './home.component.css', }) export class HomeComponent { - trips: Trip[] = trips; - filteredTrips: Trip[] = [...trips]; selectedTrip: Trip = trips[0]; - searchQuery: string = ''; - activeDifficultyFilter: DifficultyLevel = 'All'; - - handleSearch(searchTerm: string) { - this.searchQuery = searchTerm.toLowerCase(); - this.applyFilters(); - } - - handleFilter(difficulty: DifficultyLevel) { - this.activeDifficultyFilter = difficulty; - this.applyFilters(); - } - - private applyFilters() { - this.filteredTrips = this.trips.filter((trip) => { - const matchesSearch = - !this.searchQuery || - trip.name.toLowerCase().includes(this.searchQuery.toLowerCase()) || - trip.city.toLowerCase().includes(this.searchQuery.toLowerCase()) - - const matchesDifficulty = - this.activeDifficultyFilter === 'All' || - trip.difficulty === this.activeDifficultyFilter; - - return matchesSearch && matchesDifficulty; - }); - } } diff --git a/src/app/pages/trip/trip.component.css b/src/app/pages/trip/trip.component.css new file mode 100644 index 0000000..8630602 --- /dev/null +++ b/src/app/pages/trip/trip.component.css @@ -0,0 +1,25 @@ +.explore-section { + padding-top: 6rem; + padding-bottom: 6rem; + background-color: #ffffff; +} + +.explore-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.explore-title { + text-align: center; + text-transform: uppercase; + font-size: 1.875rem; + font-weight: 700; + color: #2c3e50; +} + +@media (min-width: 768px) { + .explore-title { + font-size: 2.25rem; + } +} diff --git a/src/app/pages/trip/trip.component.html b/src/app/pages/trip/trip.component.html new file mode 100644 index 0000000..f0c9eae --- /dev/null +++ b/src/app/pages/trip/trip.component.html @@ -0,0 +1,3 @@ +@if (trip) { + +} diff --git a/src/app/pages/trip/trip.component.spec.ts b/src/app/pages/trip/trip.component.spec.ts new file mode 100644 index 0000000..4c19a5b --- /dev/null +++ b/src/app/pages/trip/trip.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TripComponent } from './trip.component'; + +describe('TripComponent', () => { + let component: TripComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TripComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TripComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/trip/trip.component.ts b/src/app/pages/trip/trip.component.ts new file mode 100644 index 0000000..73c0e35 --- /dev/null +++ b/src/app/pages/trip/trip.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { Trip, trips } from '../../../data/trips'; +import { ActivatedRoute, Router } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { TripDetailsComponent } from '../../components/trip-details/trip-details.component'; + +@Component({ + selector: 'app-trip', + standalone: true, + imports: [CommonModule, TripDetailsComponent], + templateUrl: './trip.component.html', + styleUrl: './trip.component.css', +}) +export class TripComponent { + trip!: Trip | undefined; + + constructor(private route: ActivatedRoute, private router: Router) { + this.route.params.subscribe((params) => { + const slug = params['slug']; + this.trip = trips.find((t) => t.slug === slug); + + if (!this.trip) { + this.router.navigate(['/trips']); + } + }); + } +} diff --git a/src/app/pages/trips-list/trips-list.component.css b/src/app/pages/trips-list/trips-list.component.css new file mode 100644 index 0000000..8630602 --- /dev/null +++ b/src/app/pages/trips-list/trips-list.component.css @@ -0,0 +1,25 @@ +.explore-section { + padding-top: 6rem; + padding-bottom: 6rem; + background-color: #ffffff; +} + +.explore-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.explore-title { + text-align: center; + text-transform: uppercase; + font-size: 1.875rem; + font-weight: 700; + color: #2c3e50; +} + +@media (min-width: 768px) { + .explore-title { + font-size: 2.25rem; + } +} diff --git a/src/app/pages/trips-list/trips-list.component.html b/src/app/pages/trips-list/trips-list.component.html new file mode 100644 index 0000000..0d1619b --- /dev/null +++ b/src/app/pages/trips-list/trips-list.component.html @@ -0,0 +1,13 @@ +
+
+

Explore Trips

+
+ + + +
+
diff --git a/src/app/pages/trips-list/trips-list.component.spec.ts b/src/app/pages/trips-list/trips-list.component.spec.ts new file mode 100644 index 0000000..354f397 --- /dev/null +++ b/src/app/pages/trips-list/trips-list.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TripsListComponent } from './trips-list.component'; + +describe('TripsListComponent', () => { + let component: TripsListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TripsListComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TripsListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/trips-list/trips-list.component.ts b/src/app/pages/trips-list/trips-list.component.ts new file mode 100644 index 0000000..793ebb8 --- /dev/null +++ b/src/app/pages/trips-list/trips-list.component.ts @@ -0,0 +1,91 @@ +import { Component } from '@angular/core'; +import { DifficultyLevel, Trip, trips } from '../../../data/trips'; +import { CommonModule } from '@angular/common'; +import { TripsGridComponent } from '../../components/trips-grid/trips-grid.component'; +import { DividerComponent } from '../../components/divider/divider.component'; +import { SearchFilterComponent } from '../../components/search-filter/search-filter.component'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'app-trips-list', + standalone: true, + imports: [ + CommonModule, + TripsGridComponent, + DividerComponent, + SearchFilterComponent, + ], + templateUrl: './trips-list.component.html', + styleUrl: './trips-list.component.css', +}) +export class TripsListComponent { + searchQuery: string = ''; + trips: Trip[] = trips; + filteredTrips: Trip[] = [...trips]; + activeDifficultyFilter: DifficultyLevel = 'All'; + + constructor(private route: ActivatedRoute, private router: Router) {} + + ngOnInit(): void { + this.route.queryParams.subscribe((params) => { + const difficulty = params['difficulty'] as DifficultyLevel; + const search = params['search']?.toLowerCase(); + + if (difficulty && ['Easy', 'Moderate', 'Hard'].includes(difficulty)) { + this.activeDifficultyFilter = difficulty; + } + + if (search) { + this.searchQuery = search; + } + + this.applyFilters(); + }); + } + + handleSearch(searchTerm: string) { + this.searchQuery = searchTerm.toLowerCase(); + + this.router.navigate([], { + queryParams: { + search: this.searchQuery || null, + difficulty: + this.activeDifficultyFilter !== 'All' + ? this.activeDifficultyFilter + : null, + }, + queryParamsHandling: 'merge', + }); + + this.applyFilters(); + } + + handleFilter(difficulty: DifficultyLevel) { + this.activeDifficultyFilter = difficulty; + + this.router.navigate([], { + queryParams: { + difficulty: difficulty !== 'All' ? difficulty : null, + search: this.searchQuery || null, + }, + queryParamsHandling: 'merge', + }); + + this.applyFilters(); + } + + private applyFilters() { + this.filteredTrips = this.trips.filter((trip) => { + const matchesSearch = + !this.searchQuery || + trip.name.toLowerCase().includes(this.searchQuery.toLowerCase()) || + trip.city.toLowerCase().includes(this.searchQuery.toLowerCase()); + + const matchesDifficulty = + this.activeDifficultyFilter === 'All' || + trip.difficulty === this.activeDifficultyFilter; + + return matchesSearch && matchesDifficulty; + }); + } +} diff --git a/src/styles.css b/src/styles.css index 7a33287..c81086e 100644 --- a/src/styles.css +++ b/src/styles.css @@ -2,3 +2,6 @@ body { margin: 0; } +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..2f5ac05 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,7 @@ +module.exports = { + content: ["./src/**/*.{html,ts}"], + theme: { + extend: {}, + }, + plugins: [], +};