commit
f6a913c360
@ -1,5 +1,6 @@
|
|||||||
<h1>Ratatouille</h1>
|
<h1>Ratatouille</h1>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
<app-recipe-list></app-recipe-list>
|
||||||
<app-recipe-form></app-recipe-form>
|
<app-recipe-form></app-recipe-form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,27 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { RecipeFormComponent } from './recipe-form/recipe-form.component';
|
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({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
RouterOutlet,
|
RouterOutlet,
|
||||||
RecipeFormComponent
|
RecipeFormComponent,
|
||||||
|
RecipeListComponent,
|
||||||
],
|
],
|
||||||
|
providers: [RecipeService],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'bromista-nisqa-receta';
|
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
Loading…
Reference in new issue