Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M8 start #3

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions _course-resources/cart/cart.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
.container {
display: flex;
flex-direction: column;
}

.header {
align-self: center;
}

.empty-cart {
margin: 0 100px;
align-self: center;
font-size: 20px;
margin-top: 20px;
}

.cart {
margin: 0 100px;
border-top: 2px solid #999;
}

.cart-item {
border-bottom: 2px solid #999;
}

.total {
margin: 25px 175px 0 0;
align-self: right;
font-size: 25px;
text-align: right;
}

/* Product Details */
.product {
display: flex;
justify-content: space-between;
padding: 20px 25px;
}

.product .product-details {
display: flex;
align-items: center;
}


.product img {
width: 125px;
}

.product .product-info {
margin-left: 25px;
}

.product .name {
font-size: 22px;
font-weight: bold;
}

.product .description {
margin-top: 3px;
font-size: 18px;
}

.product .category {
margin-top: 20px;
color: #777;
}

.product .price {
display: flex;
flex-direction: column;
font-size: 25px;
justify-content: space-around;
align-items: center;
min-width: 190px;
color: #555;
border-left: 2px solid #aaa;
margin-left: 50px;
}

.product .price button {
padding: 10px;
width: 100px;
}

.discount {
margin-top: -15px;
color: #d25ca1;
}

.strikethrough {
text-decoration: line-through;
font-size: 18px;
}
31 changes: 31 additions & 0 deletions _course-resources/cart/cart.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div class="container">
<h1 class="header">Your Cart</h1>

<div class="empty-cart" *ngIf="cartItems.length === 0">
You have no items in your cart
</div>
<ul class="cart" *ngIf="cartItems.length > 0">
<li class="cart-item" *ngFor="let product of cartItems">
<div class="product">
<div class="product-details">
<img [src]="getImageUrl(product)" [alt]="product.name" />
<div class="product-info">
<div class="name">{{ product.name }}</div>
<div class="description">{{ product.description }}</div>
<div class="category">Part Type: {{ product.category }}</div>
</div>
</div>
<div class="price">
<div [ngClass]="{ strikethrough: product.discount > 0 }">
{{ product.price | currency : "USD" }}
</div>
<div *ngIf="product.discount > 0" class="discount">
{{ product.price * (1 - product.discount) | currency : "USD" }}
</div>
<button (click)="removeFromCart(product)">Remove</button>
</div>
</div>
</li>
</ul>
<div class="total">Total: {{ cartTotal | currency }}</div>
</div>
24 changes: 24 additions & 0 deletions _course-resources/cart/cart.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CartComponent } from './cart.component';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [CartComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(CartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
39 changes: 39 additions & 0 deletions _course-resources/cart/cart.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Component, OnInit } from '@angular/core';
import { IProduct } from '../catalog/product.model';
import { CartService } from './cart.service';

@Component({
selector: 'bot-cart',
templateUrl: './cart.component.html',
styleUrls: ['./cart.component.css'],
})
export class CartComponent implements OnInit {
private cart: IProduct[] = [];
constructor(private cartService: CartService) { }

ngOnInit() {
this.cartService.getCart().subscribe({
next: (cart) => (this.cart = cart),
});
}

get cartItems() {
return this.cart;
}

get cartTotal() {
return this.cart.reduce((prev, next) => {
let discount = next.discount && next.discount > 0 ? 1 - next.discount : 1;
return prev + next.price * discount;
}, 0);
}

removeFromCart(product: IProduct) {
this.cartService.remove(product);
}

getImageUrl(product: IProduct) {
if (!product) return '';
return '/assets/images/robot-parts/' + product.imageName;
}
}
16 changes: 16 additions & 0 deletions _course-resources/cart/cart.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { CartService } from './cart.service';

describe('CartService', () => {
let service: CartService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CartService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
38 changes: 38 additions & 0 deletions _course-resources/cart/cart.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';

import { IProduct } from '../catalog/product.model';

@Injectable({
providedIn: 'root',
})
export class CartService {
private cart: BehaviorSubject<IProduct[]> = new BehaviorSubject<IProduct[]>([]);

constructor(private http: HttpClient) {
this.http.get<IProduct[]>('/api/cart').subscribe({
next: (cart) => this.cart.next(cart),
});
}

getCart(): Observable<IProduct[]> {
return this.cart.asObservable();
}

add(product: IProduct) {
const newCart = [...this.cart.getValue(), product];
this.cart.next(newCart);
this.http.post('/api/cart', newCart).subscribe(() => {
console.log('added ' + product.name + ' to cart!');
});
}

remove(product: IProduct) {
let newCart = this.cart.getValue().filter((i) => i !== product);
this.cart.next(newCart);
this.http.post('/api/cart', newCart).subscribe(() => {
console.log('removed ' + product.name + ' from cart!');
});
}
}
5 changes: 5 additions & 0 deletions _course-resources/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ a.active {
border-bottom: 2px solid #d25ca1;
}

a.button.active {
padding-bottom: 5px;
border-bottom: 2px solid #d25ca1;
}

a:visited {
color: #444;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.container {
display: flex;
justify-content: space-around;
}

.form {
display: flex;
padding: 30px 50px 50px 50px;
flex-direction: column;
margin-top: 25px;
border: 1px solid #ddd;
border-radius: 15px;
}

.control {
display: flex;
flex-direction: column;
}

.control {
margin-top: 25px;
}

.control div {
font-size: 18px;
}

.control select {
padding: 15px;
font-size: 18px;
}

.control input {
display: inline-block;
}

.header {
font-size: 30px;
align-self: center;
color: #555;
}

.sub-text {
font-size: 18px;
align-self: center;
margin-bottom: 15px;
color: #444;
}

.form .buttons {
margin-top: 10px;
display: inline-flex;
justify-content: flex-end;
font-size: 16px;
}

input.error {
border: 1px solid #d25ca1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<div class="container">
<form class="form">
<div class="header">Form Control Examples</div>

<div class="control">
<input name="textInput" type="text" [(ngModel)]="textInput" />
<div>Value: {{textInput}} Type: {{getType(textInput)}}</div>
</div>

<div class="control">
<input name="numberInput" type="number" [(ngModel)]="numericInput" />
<div>Value: {{numericInput}} Type: {{getType(numericInput)}}</div>
</div>

<div class="control">
<select name="select" type="select" [(ngModel)]="stringInput">
<option *ngFor="let option of selectOptions" [value]="option.value">{{option.text}}</option>
</select>
<div>Value: {{stringInput}} Type: {{getType(stringInput)}}</div>
</div>

<div class="control">
<select name="numericSelect" type="numericSelect" [(ngModel)]="numericSelect">
<option [ngValue]="1">One</option>
<option [ngValue]="2">Two</option>
</select>
<div>Value: {{numericSelect}} Type: {{getType(numericSelect)}}</div>
</div>

<div class="control">
<div>
<input name="radioInput" type="radio" [value]="1" [(ngModel)]="radioInput" /> Radio One
</div>
<div>
<input name="radioInput" type="radio" [value]="2" [(ngModel)]="radioInput" /> Radio Two
</div>
<div>Value: {{radioInput}} Type: {{getType(radioInput)}}</div>
</div>

<div class="control">
<div><input type="checkbox" name="checkboxInput" [(ngModel)]="checkboxInput" /> Checkbox Input</div>
<div>Value: {{checkboxInput}} Type: {{getType(checkboxInput)}}</div>
</div>
</form>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TemplateFormControlsComponent } from './template-form-controls.component';

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

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

beforeEach(() => {
fixture = TestBed.createComponent(TemplateFormControlsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading