Skip to content

Commit

Permalink
Chapter01 Network requests, concurrency.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikola Mitrovic authored and Nikola Mitrovic committed Jun 23, 2024
1 parent a65dd08 commit abeb2e2
Show file tree
Hide file tree
Showing 38 changed files with 2,344 additions and 349 deletions.
5 changes: 4 additions & 1 deletion Chapter01/network-requests/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
"src/assets",
"src/mockServiceWorker.js"
],
"styles": [
"@angular/material/prebuilt-themes/deeppurple-amber.css",
"src/styles.scss"
],
"scripts": []
Expand Down Expand Up @@ -90,6 +92,7 @@
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/deeppurple-amber.css",
"src/styles.scss"
],
"scripts": []
Expand Down
1,262 changes: 1,257 additions & 5 deletions Chapter01/network-requests/package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Chapter01/network-requests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"private": true,
"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/cdk": "^17.3.10",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/material": "^17.3.10",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
Expand All @@ -33,6 +35,7 @@
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"msw": "^2.3.1",
"typescript": "~5.4.2"
}
}
}
337 changes: 1 addition & 336 deletions Chapter01/network-requests/src/app/app.component.html

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Chapter01/network-requests/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { MatButtonModule } from '@angular/material/button';
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { RecipesListComponent } from './components/recipes-list/recipes-list.component';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
imports: [RouterOutlet, MatButtonModule, RecipesListComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
Expand Down
7 changes: 6 additions & 1 deletion Chapter01/network-requests/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';

import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';

export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)]
providers: [
provideRouter(routes),
provideHttpClient(), provideAnimationsAsync(), provideAnimationsAsync()
]
};
7 changes: 6 additions & 1 deletion Chapter01/network-requests/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { Routes } from '@angular/router';
import { RecipeDetailsComponent } from './components/recipe-details/recipe-details.component';
import { RecipesListComponent } from './components/recipes-list/recipes-list.component';

export const routes: Routes = [];
export const routes: Routes = [
{ path: '', component: RecipesListComponent },
{ path: 'recipes/:id', component: RecipeDetailsComponent },
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@if (recipe) {
<mat-card class="card">
<mat-card-content>
<div class="card-content">
<div class="card-info">
<div>
<h5>
{{ recipe.name }}
</h5>
<p>{{ recipe.description }}</p>
</div>
<mat-chip-set class="ingredients">
@for (ingredient of recipe.ingredients; track ingredient) {
<mat-chip color="accent" class="ingredient">{{ ingredient }}</mat-chip>
}
</mat-chip-set>

@if (details) {
<div class="instructions">
<h5>Details</h5>
<p>Prep time: {{ details.prepTime }}</p>
<p>Cuisine: {{ details.cuisine }}</p>
<p>Diet: {{ details.diet }}</p>
<div>
<p>Calories: {{ details.nutrition.calories }}</p>
<p>Carbs: {{ details.nutrition.carbs }}</p>
<p>Fat: {{ details.nutrition.fat }}</p>
<p>Protein: {{ details.nutrition.protein }}</p>
</div>
</div>
}
</div>
<img mat-card-image class="card-image" [src]="details?.url" [alt]="recipe.name">
</div>
</mat-card-content>
</mat-card>
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.card {
cursor: pointer;
}

.card-image {
width: 100%;
height: 100%;
object-fit: contain;
}

.mat-mdc-card-content {
padding: 0;

&:first-child, &:last-child {
padding: 0;
}
}

.card-content {
display: flex;
justify-content: space-between;

img {
width: 50%;
}
}

.card-info {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
}

.ingredient:nth-child(2n + 1) {
background-color: #F9E49B;
}

.ingredient:nth-child(2n + 2) {
background-color: #F0A594;
}

// .ingredient:nth-child(4n + 3) {
// background-color: #7FD8C0;
// }

// .ingredient:nth-child(4n + 4) {
// background-color: #F6D294;
// }

// .ingredient:nth-child(4n) {
// background-color: #BDE6FF;
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { RecipeDetailsComponent } from './recipe-details.component';

describe('RecipeDetailsComponent', () => {
let component: RecipeDetailsComponent;
let fixture: ComponentFixture<RecipeDetailsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RecipeDetailsComponent]
})
.compileComponents();

fixture = TestBed.createComponent(RecipeDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatChipsModule } from '@angular/material/chips';
import { ActivatedRoute } from '@angular/router';
import { RecipesService } from '../../services/recipes.service';
import { Recipe, RecipeDetails } from '../../types/recipes.type';

@Component({
selector: 'app-recipe-details',
standalone: true,
imports: [MatCardModule, MatChipsModule],
templateUrl: './recipe-details.component.html',
styleUrl: './recipe-details.component.scss'
})
export class RecipeDetailsComponent implements OnInit {
private id = '';
public recipe: Recipe | null = null;
public details: RecipeDetails | null = null;

constructor(private route: ActivatedRoute, private recipesService: RecipesService) { }

ngOnInit(): void {
this.id = this.route.snapshot.paramMap.get('id') || '';
this.recipesService.getRecipeDetails$(+this.id).subscribe({
next: ({ recipe, details }) => {
this.recipe = recipe;
this.details = details;
},
error: (error) => {
console.error(error);
}
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<mat-card class="card">
<mat-card-content>
<div class="card-content">
<div class="card-info">
<div>
<h5>
{{ recipe()?.name }}
</h5>
<p>{{ recipe()?.description }}</p>
</div>
<mat-chip-set class="ingredients">
@for (ingredient of recipe()?.ingredients; track ingredient) {
<mat-chip color="accent" class="ingredient">{{ ingredient }}</mat-chip>
}
</mat-chip-set>
</div>
@if (image()) {
<img mat-card-image class="card-image" [src]="image()" [alt]="recipe()?.name">
} @else {
<img mat-card-image class="card-image" src="/assets/images/image-placeholder.png">
}
</div>
</mat-card-content>
</mat-card>

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.card {
cursor: pointer;
}

.card-image {
width: 100%;
height: 100%;
object-fit: contain;
}

.mat-mdc-card-content {
padding: 0;

&:first-child, &:last-child {
padding: 0;
}
}

.card-content {
display: flex;
justify-content: space-between;

img {
width: 50%;
}
}

.card-info {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
}

.ingredient:nth-child(2n + 1) {
background-color: #F9E49B;
}

.ingredient:nth-child(2n + 2) {
background-color: #F0A594;
}

// .ingredient:nth-child(4n + 3) {
// background-color: #7FD8C0;
// }

// .ingredient:nth-child(4n + 4) {
// background-color: #F6D294;
// }

// .ingredient:nth-child(4n) {
// background-color: #BDE6FF;
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { RecipeItemComponent } from './recipe-item.component';

describe('RecipeItemComponent', () => {
let component: RecipeItemComponent;
let fixture: ComponentFixture<RecipeItemComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RecipeItemComponent]
})
.compileComponents();

fixture = TestBed.createComponent(RecipeItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, input } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatChipsModule } from '@angular/material/chips';
import { Recipe } from '../../types/recipes.type';

@Component({
selector: 'app-recipe-item',
standalone: true,
imports: [MatCardModule, MatChipsModule],
templateUrl: './recipe-item.component.html',
styleUrl: './recipe-item.component.scss'
})
export class RecipeItemComponent {
recipe = input<Recipe>();
image = input<string>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@if(recipes) {
<div class="recipes-list">
@for (item of recipes; track item.id) {
<div class="item" (click)="goToDetailsPage(item.id)">
<app-recipe-item [recipe]="item" [image]="findRecipeImage(item.id)"></app-recipe-item>
</div>
}
</div>
}
@if(error) {
<div class="error">
<p>{{ error }}</p>
<p>Recipes list could not be downloaded</p>
</div>
}
Loading

0 comments on commit abeb2e2

Please sign in to comment.