merge recipe list & form

add-recipe-form
remrem 12 months ago
commit f6a913c360

@ -1,5 +1,6 @@
<h1>Ratatouille</h1>
<div class="wrapper">
<app-recipe-list></app-recipe-list>
<app-recipe-form></app-recipe-form>
</div>
</div>

@ -1,16 +1,27 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { RecipeFormComponent } from './recipe-form/recipe-form.component';
import { RecipeService } from './services/recipe.service';
import { Recipe } from './model/recipe.model';
import { RecipeListComponent } from './components/recipe-list/recipe-list.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [
RouterOutlet,
RecipeFormComponent
RecipeFormComponent,
RecipeListComponent,
],
providers: [RecipeService],
templateUrl: './app.component.html',
})
export class AppComponent {
title = 'bromista-nisqa-receta';
constructor(protected recipeService: RecipeService){}
addRecipe($event: Recipe): void {
this.recipeService.addRecipe($event);
}
}

@ -0,0 +1,4 @@
<p>recipe-list works!</p>
<div>
<app-recipe-mini *ngFor="let recipe of recipes" [recipe]="recipe"></app-recipe-mini>
</div>

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RecipeListComponent } from './recipe-list.component';
describe('RecipeListComponent', () => {
let component: RecipeListComponent;
let fixture: ComponentFixture<RecipeListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RecipeListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(RecipeListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,24 @@
import { Component } from '@angular/core';
import { Recipe } from '../../model/recipe.model';
import { RecipeService } from '../../services/recipe.service';
import { NgFor } from '@angular/common';
import { RecipeMiniComponent } from '../recipe-mini/recipe-mini.component';
@Component({
selector: 'app-recipe-list',
standalone: true,
imports: [NgFor, RecipeMiniComponent],
templateUrl: './recipe-list.component.html',
styleUrl: './recipe-list.component.css'
})
export class RecipeListComponent {
recipes : Recipe[] = [];
constructor(protected recipeService: RecipeService){}
ngOnInit(){
this.recipes = this.recipeService.getRecipes();
}
}

@ -0,0 +1,126 @@
.recipe-card {
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
width: 300px;
margin: 10px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.recipe-image img {
width: 100%;
height: 200px;
object-fit: cover;
}
.recipe-details {
padding: 16px;
}
.recipe-details h2 {
margin: 0;
font-size: 1.5em;
}
.recipe-details p {
margin-top: 8px;
font-size: 1em;
color: #666;
}
button {
position: relative;
background: #444;
color: #fff;
text-decoration: none;
text-transform: uppercase;
border: none;
letter-spacing: 0.1rem;
font-size: 1rem;
padding: 1rem 3rem;
transition: 0.2s;
}
button:hover {
background: var(--clr);
color: var(--clr);
/* box-shadow: 0 0 35px var(--clr); */
animation: box 3s infinite;
}
button::before {
content: "";
position: absolute;
inset: 2px;
background: #272822;
}
button span {
position: relative;
z-index: 1;
}
button i {
position: absolute;
inset: 0;
display: block;
}
button i::before {
content: "";
position: absolute;
width: 10px;
height: 2px;
left: 80%;
top: -2px;
border: 2px solid var(--clr);
background: #272822;
transition: 0.2s;
}
button:hover i::before {
width: 15px;
left: 20%;
animation: move 3s infinite;
}
button i::after {
content: "";
position: absolute;
width: 10px;
height: 2px;
left: 20%;
bottom: -2px;
border: 2px solid var(--clr);
background: #272822;
transition: 0.2s;
}
button:hover i::after {
width: 15px;
left: 80%;
animation: move 3s infinite;
}
@keyframes move {
0% {
transform: translateX(0);
}
50% {
transform: translateX(5px);
}
100% {
transform: translateX(0);
}
}
@keyframes box {
0% {
box-shadow: #27272c;
}
50% {
box-shadow: 0 0 25px var(--clr);
}
100% {
box-shadow: #27272c;
}
}

@ -0,0 +1,10 @@
<div class="recipe-card">
<div class="recipe-image">
<img [src]="recipe.image" onerror="this.onerror=null;this.src='https://placehold.co/100x100';" alt="{{recipe.name}}">
</div>
<div class="recipe-details">
<h2>{{recipe.name}}</h2>
<p>{{recipe.description}}</p>
<button (click)="navigateToRecipe()" style="--clr:#39FF14"><span>Voir la recette</span><i></i></button>
</div>
</div>

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RecipeMiniComponent } from './recipe-mini.component';
describe('RecipeMiniComponent', () => {
let component: RecipeMiniComponent;
let fixture: ComponentFixture<RecipeMiniComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RecipeMiniComponent]
})
.compileComponents();
fixture = TestBed.createComponent(RecipeMiniComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,19 @@
import { Component } from '@angular/core';
import { Recipe } from '../../model/recipe.model';
import { Input } from '@angular/core';
@Component({
selector: 'app-recipe-mini',
standalone: true,
imports: [],
templateUrl: './recipe-mini.component.html',
styleUrl: './recipe-mini.component.css'
})
export class RecipeMiniComponent {
@Input() recipe!: Recipe;
navigateToRecipe(){
console.log("TODO");
}
}

File diff suppressed because one or more lines are too long

@ -21,7 +21,7 @@ export class RecipeFormComponent {
recipeForm: FormGroup;
base64Image: string | ArrayBuffer | null = null;
ingredientsOptions = ['Champignon', 'Tomata', 'Mozarella'];
defaultOption : string = this.ingredientsOptions[2];
defaultOption: string = this.ingredientsOptions[2];
constructor(private fb: FormBuilder, private recipeService: RecipeService) {
this.recipeForm = this.fb.group({
@ -74,11 +74,10 @@ export class RecipeFormComponent {
};
console.log('Recipe added:', newRecipe);
this.recipeService.addRecipe(newRecipe);
this.recipeForm.reset();
} else {
console.log('Form is invalid');
}
this.recipeForm.reset();
}
}

@ -6,20 +6,22 @@ import { Recipe } from '../model/recipe.model';
})
export class RecipeService {
private localStorageKey = 'recipes';
private recipes: Recipe[] = [];
constructor() { }
// Get recipes from local storage
getRecipes(): Recipe[] {
const recipesJson = localStorage.getItem(this.localStorageKey);
return recipesJson ? JSON.parse(recipesJson) : [];
const recipesJson = localStorage.getItem(this.localStorageKey) || "[]";
this.recipes = JSON.parse(recipesJson) || [];
return this.recipes;
}
// Add a new recipe
addRecipe(recipe: Recipe): void {
const recipes = this.getRecipes();
recipes.push(recipe);
localStorage.setItem(this.localStorageKey, JSON.stringify(recipes));
this.getRecipes();
this.recipes.push(recipe);
localStorage.setItem(this.localStorageKey, JSON.stringify(this.recipes));
}
// Clear all recipes (for example, if needed)

Loading…
Cancel
Save