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>
|
@ -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
Loading…
Reference in new issue