Skip to content

Commit

Permalink
feat: add trending weather
Browse files Browse the repository at this point in the history
  • Loading branch information
luifr10 committed Oct 28, 2024
1 parent 5e6549c commit aca0f7d
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 7 deletions.
12 changes: 7 additions & 5 deletions src/app/components/weather/weather.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<h1 class="display-2" data-testid="app-title">Current Weather</h1>
<div class="display-5 weather-tending">
<span>Trending: </span>
<span class="text-primary">Not implemented yet !!! </span>
</div>
@if (globalWeather$ | async) {
<div class="display-5 weather-tending">
<span>Trending: </span>
@if (trending()) {
<a [href]="trending()?.url" class="link-offset-1 link-underline link-underline-opacity-10">{{trending()?.label}}</a>
}
</div>
<div class="weather-view">
<p class="mb-2">First select a town or use the filter before</p>
<p class="my-2">First select a town or use the filter before</p>
<form class="mb-2" [formGroup]="townFilterForm" (ngSubmit)="onSubmitForm()">
<div class="row">
<div class="col-auto">
Expand Down
10 changes: 8 additions & 2 deletions src/app/components/weather/weather.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {WeatherDetailsComponent} from '@components/weather-details/weather-detai
import {AsyncPipe} from '@angular/common';
import {toSignal} from '@angular/core/rxjs-interop';
import {Observable} from 'rxjs';
import {TrendingService} from '@services/trending.service';
import {Trending} from '@models/trending';

const SEARCH_FIELD_FORM_ID = 'townTextSearch';

Expand All @@ -26,10 +28,12 @@ export class WeatherComponent implements OnInit {
public selectedTownWeather : WritableSignal<TownWeather | null> = signal(null);
public globalWeather!: Signal<TownWeather[] | undefined>;
public townFilter: WritableSignal<string | null> = signal(null);
public availableTownWeather!: Signal<TownWeather[] | undefined>;
public availableTownWeather!: Signal<TownWeather[]>;
public trending!: Signal<Trending | null>;
public globalWeather$?: Observable<TownWeather[]>;
public townFilterForm!: FormGroup;
private weatherService = inject(WeatherService);
private trendingService = inject(TrendingService);
private formBuilder = inject(FormBuilder);

constructor() {
Expand All @@ -55,7 +59,9 @@ export class WeatherComponent implements OnInit {
return globalWeather;
}
});

this.trending = computed(() => {
return this.trendingService.retrieveTrending(this.availableTownWeather())
});
}

public selectedTown($selectedTownWeather: TownWeather) {
Expand Down
4 changes: 4 additions & 0 deletions src/app/models/trending.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type Trending = {
label: string,
url: string
}
117 changes: 117 additions & 0 deletions src/app/services/trending.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { TestBed } from '@angular/core/testing';

import { TrendingService } from './trending.service';
import {TownWeather} from '@models/town-weather';

const TOWNS_WEATHER = [
{
"id": 1,
"name": "Douala",
"forecast": {
"condition": "cloudy",
"wind": {
"speed": {
"value": 18.5,
"unit": "km/h"
},
"direction": "North-West"
},
"temperature": {
"min": {
"value": 10.8,
"unit": "°c"
},
"max": {
"value": 29,
"unit": "°c"
}
}
}
},
{
"id": 2,
"name": "Bafoussam",
"forecast": {
"condition": "cloudy",
"wind": {
"speed": {
"value": 18.5,
"unit": "km/h"
},
"direction": "North-West"
},
"temperature": {
"min": {
"value": 10.8,
"unit": "°c"
},
"max": {
"value": 29,
"unit": "°c"
}
}
}
},
{
"id": 3,
"name": "Yaoundé",
"forecast": {
"condition": "cloudy",
"wind": {
"speed": {
"value": 18.5,
"unit": "km/h"
},
"direction": "North-West"
},
"temperature": {
"min": {
"value": 10.8,
"unit": "°c"
},
"max": {
"value": 29,
"unit": "°c"
}
}
}
}
];

describe('TrendingService', () => {
let service: TrendingService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(TrendingService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});

it('should generate random index', () => {
expect(service).toBeTruthy();
const townWeathers = TOWNS_WEATHER as TownWeather[];
expect(service["generateRandomIndex"](townWeathers)).toBeGreaterThanOrEqual(0);
expect(service["generateRandomIndex"](townWeathers)).toBeLessThan(townWeathers.length);
});

it('retrieveTrending should return null empty array', () => {
expect(service).toBeTruthy();
const townWeathers: TownWeather[] = [];
expect(service.retrieveTrending(townWeathers)).toBeNull();
});

it('retrieveTrending should return trending', () => {
expect(service).toBeTruthy();
const townWeathers = TOWNS_WEATHER as TownWeather[];
service["generateRandomIndex"] = jest.fn().mockImplementation(() => 1);
const trending = service.retrieveTrending(townWeathers);
expect(service["generateRandomIndex"]).toHaveBeenCalledTimes(1);
expect(trending).toEqual({
label: "Visiter Bafoussam",
url: "https://www.google.com/search?q=Bafoussam"
});
});
});
26 changes: 26 additions & 0 deletions src/app/services/trending.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Injectable} from '@angular/core';
import {TownWeather} from '@models/town-weather';
import {Trending} from '@models/trending';

@Injectable({
providedIn: 'root'
})
export class TrendingService {

constructor() { }

public retrieveTrending(townWeathers: TownWeather[]): Trending | null {
if (townWeathers.length === 0) {
return null;
}
const randomIndex = this.generateRandomIndex(townWeathers);
return {
label: `Visiter ${townWeathers[randomIndex].name}`,
url: `https://www.google.com/search?q=${townWeathers[randomIndex].name}`
};
}

private generateRandomIndex(townWeathers: TownWeather[]): number {
return Math.floor(Math.random() * townWeathers.length);
}
}

0 comments on commit aca0f7d

Please sign in to comment.