Hacking away at signals and resources.
This commit is contained in:
parent
ab1c39560f
commit
86ef321065
@ -1,5 +1,4 @@
|
||||
<main>
|
||||
<app-recipe></app-recipe>
|
||||
</main>
|
||||
|
||||
<h1>Meals Made Easy</h1>
|
||||
<router-outlet />
|
||||
</main>
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { RecipeView } from './recipe-view/recipe-view.component';
|
||||
|
||||
export const routes: Routes = [];
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: 'recipes/:username/:slug',
|
||||
component: RecipeView
|
||||
}
|
||||
];
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { Component, signal } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import { Recipe } from './recipe/recipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [RouterOutlet, Recipe],
|
||||
imports: [RouterOutlet],
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
|
||||
@ -6,7 +6,20 @@ export interface RecipeInfoViews {
|
||||
content: Recipe[];
|
||||
}
|
||||
|
||||
export interface RecipeView {
|
||||
isOwner: boolean | null;
|
||||
isStarred: boolean | null;
|
||||
recipe: Recipe;
|
||||
}
|
||||
|
||||
export interface Recipe {
|
||||
id: number;
|
||||
title: string;
|
||||
mainImage: ImageView;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface ImageView {
|
||||
alt: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<h1>{{ recipe.title }}</h1>
|
||||
<img [ngSrc]="recipe.mainImage.url" [alt]="recipe.mainImage.alt" [width]="600" [height]="400">
|
||||
<div [innerHTML]="recipe.text"></div>
|
||||
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RecipeViewCard } from './recipe-view-card.component';
|
||||
|
||||
describe('Card', () => {
|
||||
let component: RecipeViewCard;
|
||||
let fixture: ComponentFixture<RecipeViewCard>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [RecipeViewCard]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(RecipeViewCard);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Recipe } from '../../model/Recipe.model';
|
||||
import { NgOptimizedImage } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-view-card',
|
||||
imports: [
|
||||
NgOptimizedImage
|
||||
],
|
||||
templateUrl: './recipe-view-card.component.html',
|
||||
styleUrl: './recipe-view-card.component.css',
|
||||
})
|
||||
export class RecipeViewCard {
|
||||
|
||||
@Input({ required: true })
|
||||
public recipe!: Recipe;
|
||||
|
||||
}
|
||||
0
src/app/recipe-view/recipe-view.component.css
Normal file
0
src/app/recipe-view/recipe-view.component.css
Normal file
5
src/app/recipe-view/recipe-view.component.html
Normal file
5
src/app/recipe-view/recipe-view.component.html
Normal file
@ -0,0 +1,5 @@
|
||||
@if (recipe.isLoading()) {
|
||||
<p>Loading...</p>
|
||||
} @else if (recipe.hasValue()) {
|
||||
<app-recipe-view-card [recipe]="recipe.value()"></app-recipe-view-card>
|
||||
}
|
||||
@ -1,17 +1,17 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Recipe } from './recipe';
|
||||
import { RecipeView } from './recipe-view.component';
|
||||
|
||||
describe('Recipe', () => {
|
||||
let component: Recipe;
|
||||
let fixture: ComponentFixture<Recipe>;
|
||||
let component: RecipeView;
|
||||
let fixture: ComponentFixture<RecipeView>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Recipe],
|
||||
imports: [RecipeView],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Recipe);
|
||||
fixture = TestBed.createComponent(RecipeView);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
25
src/app/recipe-view/recipe-view.component.ts
Normal file
25
src/app/recipe-view/recipe-view.component.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Component, inject, resource } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { RecipeService } from '../recipe.service';
|
||||
import { RecipeViewCard } from './recipe-view-card/recipe-view-card.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-view',
|
||||
imports: [
|
||||
RecipeViewCard
|
||||
],
|
||||
templateUrl: './recipe-view.component.html',
|
||||
styleUrl: './recipe-view.component.css',
|
||||
})
|
||||
export class RecipeView {
|
||||
private recipeService = inject(RecipeService);
|
||||
private route = inject(ActivatedRoute);
|
||||
private username = this.route.snapshot.paramMap.get('username') as string;
|
||||
private slug = this.route.snapshot.paramMap.get('slug') as string;
|
||||
|
||||
protected recipe = resource({
|
||||
loader: () => {
|
||||
return this.recipeService.getRecipe(this.username, this.slug);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { Recipe, RecipeInfoViews } from './model/Recipe.model';
|
||||
import { Recipe, RecipeInfoViews, RecipeView } from './model/Recipe.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@ -14,4 +14,10 @@ export class RecipeService {
|
||||
.get<RecipeInfoViews>('http://localhost:8080/recipes')
|
||||
.pipe(map((res) => res.content));
|
||||
}
|
||||
|
||||
public async getRecipe(username: string, slug: string): Promise<Recipe> {
|
||||
const res = await fetch(`http://localhost:8080/recipes/${username}/${slug}`)
|
||||
const recipeView = await res.json() as RecipeView;
|
||||
return recipeView.recipe;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
<p>recipe works!</p>
|
||||
<p>{{ title() }}</p>
|
||||
@for (recipeTitle of recipeTitles(); track recipeTitle) {
|
||||
<p>{{ recipeTitle }}</p>
|
||||
}
|
||||
<button (click)="onClick()">Click me!</button>
|
||||
@ -1,21 +0,0 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { RecipeService } from '../recipe.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe',
|
||||
imports: [],
|
||||
templateUrl: './recipe.html',
|
||||
styleUrl: './recipe.css',
|
||||
})
|
||||
export class Recipe {
|
||||
protected readonly title = signal('Hello, Jesse!');
|
||||
protected readonly recipeTitles = signal<string[]>([]);
|
||||
|
||||
private readonly recipeService = inject(RecipeService);
|
||||
|
||||
protected onClick() {
|
||||
this.recipeService.getRecipes().subscribe((recipes) => {
|
||||
this.recipeTitles.set(recipes.map((recipe) => recipe.title));
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user