Merged in feature/HIMA-53-create-shopping-cart-screen (pull request #30)

[HIMA-53] Cart component
This commit is contained in:
milos.jovanov
2019-02-09 12:03:15 +00:00
committed by Eraldo Hasanaj
19 changed files with 839 additions and 70 deletions

View File

@@ -11,6 +11,7 @@ import { SearchResultsComponent } from './components/search-results/search-resul
import { ProductDetailsComponent } from './components/product-details/product-details.component';
import { BarcodeSearchComponent } from './modules/barcode-search/barcode-search.component';
import { NewsletterSignupComponent } from './modules/newsletter-signup/newsletter-signup.component';
import { CartReviewComponent } from './modules/cart/components/cart-review/cart-review.component';
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
@@ -23,7 +24,8 @@ const routes: Routes = [
{ path: 'product-details/:id', component: ProductDetailsComponent },
{ path: 'article-scan', component: BarcodeSearchComponent },
{ path: 'newsletter', component: NewsletterSignupComponent },
{ path: 'debug', loadChildren: './modules/debug/debug.module#DebugModule' }
{ path: 'debug', loadChildren: './modules/debug/debug.module#DebugModule' },
{ path: 'cart', component: CartReviewComponent },
];
@NgModule({

View File

@@ -36,7 +36,7 @@ import { BreadcrumbsState } from './core/store/state/breadcrumbs.state';
import { FilterState } from './core/store/state/filter.state';
import { CheckoutComponent } from './components/checkout/checkout.component';
import { ModalComponent } from './shared/components/modal/modal.component';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
const states = [FeedState, ProcessState, BreadcrumbsState, FilterState];
@@ -70,7 +70,7 @@ export function _feedServiceEndpointProviderFactory(conf: ConfigService) {
ProductCardComponent,
ProductDetailsComponent,
CheckoutComponent,
ModalComponent
ModalComponent,
],
imports: [
BrowserModule,
@@ -83,7 +83,8 @@ export function _feedServiceEndpointProviderFactory(conf: ConfigService) {
NgxsLoggerPluginModule,
CatServiceModule,
FeedServiceModule,
FormsModule
FormsModule,
ReactiveFormsModule
],
providers: [
{

View File

@@ -26,7 +26,7 @@ export class BreadcrumbsComponent implements OnInit {
getBreadcrumbsFromCurentProcess(processes: Process[]) {
const currentProcess = processes.find(p => p.selected === true);
if (currentProcess) {
this.currentRoute = `/${currentProcess.currentRoute}`;
this.currentRoute = `${currentProcess.currentRoute}`;
this.breadcrumbs = currentProcess.breadcrumbs;
this.bredcrumbDots = currentProcess.breadcrumbs.length > 3;
}

View File

@@ -7,7 +7,7 @@
<span class="process-name">{{ process.name }}</span>
</div>
<ng-container *ngIf="process.cart">
<div>
<div (click)="openCart()">
<img class="process-cart-icon" src="../../../assets/images/Shopping_Cart.svg">
</div>
<div class="pt-3">

View File

@@ -2,8 +2,10 @@ import { Component, OnInit, Input } from '@angular/core';
import { Process } from 'src/app/core/models/process.model';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { DeleteProcess, SelectProcess, PreventProductLoad } from 'src/app/core/store/actions/process.actions';
import { DeleteProcess, SelectProcess, PreventProductLoad, ChangeCurrentRoute } from '../../core/store/actions/process.actions';
import { Cart } from '../../core/models/cart.model';
import { AddBreadcrumb } from '../../core/store/actions/process.actions';
import { Breadcrumb } from '../../core/models/breadcrumb.model';
@Component({
selector: 'app-process-tab',
@@ -39,4 +41,15 @@ export class ProcessTabComponent implements OnInit {
}
}
openCart() {
const newBread: Breadcrumb = {
name: 'Warenkorb',
path: 'cart'
}
this.store.dispatch(new AddBreadcrumb(newBread));
this.store.dispatch(new ChangeCurrentRoute('cart'));
this.router.navigate(['cart']);
}
}

View File

@@ -17,5 +17,5 @@ export interface Process {
itemsDTO: ItemDTO[];
selectedItem: ItemDTO;
preventLoading: boolean;
editUser: User;
activeUser: User;
}

View File

@@ -10,12 +10,13 @@ export const SELECT_PROCESS = '[PROCESS] Select';
export const CHANGE_CURRENT_ROUTE = '[PROCESS] Change current route';
export const ADD_SEARCH = '[PROCESS] Add search';
export const SEARCH_USER = '[PROCESS] Search for user';
export const SET_USER_NAME = '[PROCESS] Set the users name in tab';
export const SET_ACTIVE_USER = '[PROCESS] Set active user in tab';
export const SET_CART = '[PROCESS] Set cart data for user';
export const PREVENT_PRODUCT_LOAD = '[POCESS] Prevent product load';
export const ALLOW_PRODUCT_LOAD = '[POCESS] Allow product load';
export const ADD_USER = '[PROCESS] Add new user to store';
export const SET_EDIT_USER = '[PROCESS] User which data will be updated';
export const ADD_BREADCRUMB = '[PROCESS] Add breadcrumb';
export class AddProcess {
static readonly type = ADD_PROCESS;
@@ -53,10 +54,10 @@ export class SearchUser {
constructor(public payload: string) {}
}
export class SethUserName {
static readonly type = SET_USER_NAME;
export class SetActiveUser {
static readonly type = SET_ACTIVE_USER;
constructor(public payload: string) {}
constructor(public payload: User) {}
}
export class SetCartData {
@@ -83,3 +84,9 @@ export class SetUserDetails {
constructor(public payload: User) {}
}
export class AddBreadcrumb {
static readonly type = ADD_BREADCRUMB;
constructor(public payload: Breadcrumb) {}
}

View File

@@ -104,8 +104,13 @@ export class ProcessState {
}
@Selector()
static getEditUser(state: ProcessStateModel) {
return state.processes.find(t => t.selected === true).editUser;
static getActiveUser(state: ProcessStateModel) {
return state.processes.find(t => t.selected === true).activeUser;
}
@Selector()
static getCart(state: ProcessStateModel) {
return state.processes.find(t => t.selected === true).cart;
}
@Action(actions.AddProcess)
@@ -289,13 +294,13 @@ export class ProcessState {
});
}
@Action(actions.SethUserName)
setUserName(ctx: StateContext<ProcessStateModel>, { payload }: actions.SethUserName) {
@Action(actions.SetActiveUser)
setActiveUser(ctx: StateContext<ProcessStateModel>, { payload }: actions.SetActiveUser) {
const state = ctx.getState();
const newProcessState = state.processes.map(
(process: Process) => {
if (process.selected === true) {
return { ...process, name: payload };
return { ...process, name: payload.name, activeUser: payload };
} else {
return process;
}
@@ -497,7 +502,7 @@ export class ProcessState {
if (process.selected === true) {
return {
...process,
editUser: payload,
activeUser: payload,
breadcrumbs: [
...process.breadcrumbs,
{
@@ -512,4 +517,20 @@ export class ProcessState {
)
});
}
@Action(actions.AddBreadcrumb)
addBreadcrumb(ctx: StateContext<ProcessStateModel>, { payload }: actions.AddBreadcrumb) {
const state = ctx.getState();
ctx.patchState({
...state,
processes: state.processes.map(
process => {
if (process.selected === true) {
return {...process, breadcrumbs: [...process.breadcrumbs, payload]};
}
return {...process};
}
)
});
}
}

View File

@@ -0,0 +1,18 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SharedModule } from 'src/app/shared/shared.module';
import { CartReviewComponent } from './components/cart-review/cart-review.component';
@NgModule({
declarations: [
CartReviewComponent
],
exports: [
CartReviewComponent
],
imports: [CommonModule, FormsModule, ReactiveFormsModule, SharedModule]
})
export class CartModule {}

View File

@@ -0,0 +1,78 @@
<div class="cart-container">
<div class="cart-content">
<div class="cart-list">
<div class="cart-title">
<span>Warenkorb</span>
</div>
<div class="cart-description">
<span>Überprüfen Sie die Details.</span>
</div>
<form [formGroup]="invoiceForm">
<div class="line"></div>
<div class="form-group">
<label class="placeholder form-control-placeholder" for="invoice_addrees">Rechnungsadresse</label>
<input type="text" id="invoice_addrees" class="input form-control" formControlName="invoice_addrees" required #invoicelInput>
<a class="inline-btn" >Ändern</a>
</div>
<div class="line"></div>
<div class="form-group">
<label class="placeholder form-control-placeholder" for="notification_type">Benachrichtigung</label>
<input type="text" id="notification_type" class="input form-control" formControlName="notification_type" required #notificationInput>
<a class="inline-btn" (click)="redirecrtToUserDetails()">Ändern</a>
</div>
</form>
<div class="line"></div>
<div class="delivery-title">
<img class="img" src="../../../../../assets/images/truck_Icon.svg" alt="truck">
<h2>Versand</h2>
</div>
<form [formGroup]="deliveryForm">
<div class="line"></div>
<div class="form-group">
<label class="placeholder form-control-placeholder" for="delivery_addrees">Lieferadresse</label>
<input type="text" id="delivery_addrees" class="input form-control" formControlName="delivery_addrees" required #deliveryInput>
<a class="inline-btn">Ändern</a>
</div>
</form>
<div class="cart-row" *ngFor="let book of books; let i = index">
<div class="line"></div>
<div class="row-content">
<img src="{{ book.imgUrl }}" alt="book">
<span class="book-title">{{ book.book.pr.name }}</span>
<div class="order-details">
<span><img class="order-book-icon" src="../../../../../assets/images/Book_Icon.svg" alt="book-icon"> {{ book.book.pr.manufacturer }} I {{ book.book.pr.contributors }}</span>
<span class="order-details-delivery-info">DHL I Lieferung 18.01.</span>
</div>
<span class="price">{{ book.price }} {{ book.currency }}</span>
<div class="dropdown_container">
<div (click)="openDropdown(i)" class="dropdown-selected-text" id="drop_txt_{{i}}">
<span class="">{{ book.quantity }}</span>
<div class="open-icon" id="drop_img_{{i}}"></div>
</div>
<div class="dropdown-options" id="drop_{{i}}">
<ul>
<li *ngFor="let item of possibleItems" (click)="setNumberOfItems(item, i, book)">{{ item }}</li>
</ul>
</div>
</div>
<a class="btn" (click)="recalculate()">Ändern</a>
</div>
</div>
</div>
<div class="cart-footer">
<div class="overview">
<span class="items">{{ displayItemsNumber }} Artikel I {{ currentPoints }} Lesepunkte</span>
<div class="overview-price-container">
<span class="overview-price">Zwischensumme {{ booksTotalSumString }} {{ currency }}</span>
<span class="overview-tax">ohne Versandkosten</span>
</div>
<a class="btn">Weiter</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,385 @@
@import "../../../../../assets/scss/variables";
.cart-container {
background-color: #ffffff;
border-radius: 5px;
box-shadow: 0px 0px 10px 0px #dce2e9;
height: 745px;
display: grid;
grid-template-rows: min-content min-content 1fr min-content;
}
.cart-title {
padding-top: 40px;
font-weight: bold;
font-size: 26px;
text-align: center;
}
.cart-description {
font-size: 22px;
padding-top: 15px;
text-align: center;
padding-bottom: 30px;
}
.line {
height: 3px;
width: 100%;
background-image: url('../../../../../assets/images/Line.svg');
background-repeat: repeat-x;
background-size: contain;
}
.cart-content {
.cart-list {
width: 100%;
height: 637px;
overflow-y: scroll;
.row-content {
margin-bottom: 20px;
margin-top: 5px;
}
}
.cart-footer {
background-color: #ffffff;
border-radius: 5px;
box-shadow: 0px -2px 24px 0px #dce2e9;
height: 108px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.form-group {
position: relative;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.form {
display: flex;
flex-direction: column;
width: 100%;
justify-content: center;
align-items: center;
}
.input {
width: 75%;
padding: 15px 0;
caret-color: $hima-button-color;
border: none;
font-size: 16px;
color: #000000;
text-align: left;
line-height: 21px;
padding-left: 3%;
padding-right: 7%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
input:focus {
outline: none;
border:none;
}
input:disabled {
background-color: transparent;
}
label {
font-size: 16px;
font-weight: bold;
color: #000000;
text-align: left;
line-height: 21px;
padding-left: 15px;
white-space: nowrap;
}
.inline-btn {
padding-right: 5px;
width: 100px;
font-size: 18px;
font-weight: bold;
color: $hima-button-color;
text-align: left;
line-height: 21px;
text-align: right;
display: block;
padding-right: 20px;
}
.delivery-title{
padding: 25px 15px 10px 15px;
text-align: left;
display: flex;
align-items: center;
h2 {
font-size: 20px;
font-weight: bold;
color: #000000;
text-align: center;
line-height: 21px;
}
img {
height: 17px;
width: 27px;
display: block;
padding-right: 15px;
}
}
}
.row-content {
margin-top: 5px 0px;
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
text-align: left;
img {
height: 39px;
width: 24px;
}
.book-title {
font-size: 16px;
font-weight: 600;
text-overflow: ellipsis;
overflow: hidden;
width: 112px;
white-space: nowrap;
}
.order-details {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
height: 50px;
width: 215px;
position: relative;
top: 13px;
.order-book-icon {
height: 18px;
width: 13px;
position: relative;
top: 2px;
padding-right: 10px;
}
span {
font-size: 16px;
text-align: left;
line-height: 25px;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&-delivery-info {
font-weight: bold;
}
}
.price {
font-weight: 600;
font-size: 16px;
line-height: 25px;
}
.dropdown_container {
display: flex;
justify-content: space-between;
align-items: center;
width: 35px;
&:hover {
cursor: pointer;
}
img {
height: 9px;
width: 17px;
padding-left: 5px;
}
.dropdown-selected-text {
padding: 5px;
display: flex;
justify-content: center;
align-items: center;
&-active {
background-color: #E9EDF9;
}
.open-icon {
background-image: url('../../../../../assets/images/Arrow_Down_2.svg');
height: 9px;
width: 17px;
background-position: center;
background-repeat: no-repeat;
padding: 5px 4px;
}
.close-icon {
background-image: url('../../../../../assets/images/Arrow_Up.svg');
height: 9px;
width: 17px;
background-position: center;
background-repeat: no-repeat;
padding: 5px 4px;
}
}
.dropdown-options {
display: none;
flex-direction: column;
position: fixed;
top: 220px;
z-index: 10;
display: none;
cursor: pointer;
text-align: left;
right: 115px;
ul {
list-style: none;
padding: 15px 10px;
margin: 0;
background-color: #ffffff;
border-radius: 5px;
box-shadow: 0px -2px 24px 0px #dce2e9;
padding: 15px 0;
width: 60px;
li {
padding: 7px 10px;
font-weight: 300;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
&:hover {
background-color: #E9EDF9;
}
}
}
}
}
.btn {
font-size: 18px;
font-weight: bold;
color: #f70400;
cursor: pointer;
}
}
.overview {
display: flex;
justify-content: space-between;
justify-items: center;
width: 95%;
.items {
font-size: 16px;
color: rgba(167, 185, 203, 1);
text-align: left;
}
.overview-price-container {
display: flex;
justify-content: flex-start;
justify-items: center;
flex-direction: column;
.overview-price {
font-size: 18px;
font-weight: bold;
text-align: left;
}
.overview-tax {
font-size: 14px;
text-align: right;
}
}
.btn {
font-family: 'Open Sans';
font-size: 18px;
font-weight: bold;
background-color: $hima-button-color;
cursor: pointer;
text-align: center;
border-radius: 25px;
color: #ffffff;
width: 111px;
border: none;
padding: 14px 5px 14px 5px;
}
}
// OLD IPADS
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (-webkit-min-device-pixel-ratio: 1) {
}
// OLD IPADS LANDSCAPE
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) and (-webkit-min-device-pixel-ratio: 1) {
.row-content {
margin-left: 15px;
justify-content: space-between;
.btn {
margin-right: 36px;
}
}
}
// RETINA IPADS LANDSCAPE
@media only screen and (min-device-width: 768px) and (max-device-width: 1366px) and (orientation: landscape) and (-webkit-min-device-pixel-ratio: 2) {
.row-content {
margin-left: 15px;
justify-content: space-between;
.btn {
margin-right: 36px;
}
}
}
// RETINA IPADS
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (-webkit-min-device-pixel-ratio: 2) {
.row-content {
margin-left: 15px;
justify-content: space-between;
.btn {
margin-right: 36px;
}
}
}

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CartReviewComponent } from './cart-review.component';
describe('CartComponent', () => {
let component: CartReviewComponent;
let fixture: ComponentFixture<CartReviewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CartReviewComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CartReviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,223 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
import { Store, Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import { ProcessState } from '../../../../core/store/state/process.state';
import { User } from '../../../../core/models/user.model';
import { ChangeCurrentRoute, AddBreadcrumb } from '../../../../core/store/actions/process.actions';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import { ItemDTO, CatImageService } from 'cat-service';
import { Cart } from '../../../../core/models/cart.model';
const points = 60;
export interface BookData {
book: ItemDTO;
quantity: number;
price: string;
currency: string;
imgUrl: string;
}
@Component({
selector: 'app-cart',
templateUrl: './cart-review.component.html',
styleUrls: ['./cart-review.component.scss']
})
export class CartReviewComponent implements OnInit {
@Select(ProcessState.getActiveUser) user$: Observable<User>;
@Select(ProcessState.getCart) cart$: Observable<Cart[]>;
user: User;
invoiceForm: FormGroup;
deliveryForm: FormGroup;
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
possibleItems = [1, 2, 3, 4];
books: BookData[] = [];
currentNumberOfItems = 1;
displayItemsNumber = 0;
currentPrice = '';
currentPoints = 0;
currency = 'EUR';
booksTotalSumString = '';
booksTotalSum = 0;
constructor(
private store: Store,
private fb: FormBuilder,
private router: Router,
private catImageService: CatImageService
) { }
ngOnInit() {
this.invoiceForm = this.buildInvoiceForm(this.fb);
this.deliveryForm = this.buildDeliveryForm(this.fb);
this.user$.subscribe((user: User) => {
if (user) {
this.processUserData(user);
} else {
this.setInputData('invoice_addrees', 'Karl Schneier I Kazmairstraße 34, 80339 München', this.invoiceForm);
this.setInputData('notification_type', 'Email', this.invoiceForm);
this.setInputData('delivery_addrees', 'Karl Schneier I Kazmairstraße 34, 80339 München', this.deliveryForm);
}
});
this.cart$.subscribe((cart: Cart[]) => {
if (cart) {
this.processCartData(cart);
}
});
}
private processCartData(cart: Cart[]) {
let totalSum = 0;
let totalQuantity = 0;
cart.forEach(async(bookInCart: Cart) => {
totalSum += bookInCart.book.av[0].price.value.value * bookInCart.quantity;
totalQuantity += bookInCart.quantity;
const currency = bookInCart.book.av[0].price.value.currency;
const formatedPrice = (+Math.round(bookInCart.book.av[0].price.value.value * 100) / 100).toFixed(2).toLocaleString().replace('.', ',');
await this.catImageService.getImageUrl(bookInCart.book.pr.ean).subscribe((url: string) => {
this.books.push(
{
book: bookInCart.book,
quantity: bookInCart.quantity,
currency: currency,
price: formatedPrice,
imgUrl: url
}
);
});
})
this.displayItemsNumber = totalQuantity;
this.currentPoints = totalQuantity * points;
this.booksTotalSum = totalSum;
this.booksTotalSumString = (+Math.round(totalSum * 100) / 100).toFixed(2).toLocaleString().replace('.', ',');
}
private processUserData(user: User) {
this.user = user;
const invoiceAddress = `${user.invoice_address.street} ${user.invoice_address.zip} ${user.invoice_address.city}`;
const deliveryAddress = `${user.delivery_addres.street} ${user.delivery_addres.zip} ${user.delivery_addres.city}`;
this.setInputData('invoice_addrees', invoiceAddress ? invoiceAddress : deliveryAddress, this.invoiceForm);
this.setInputData('notification_type', 'Email', this.invoiceForm);
this.setInputData('delivery_addrees', deliveryAddress, this.deliveryForm);
}
redirecrtToUserDetails() {
if (this.user) {
const newBread: Breadcrumb = {
name: 'Kundendetails',
path: 'customer-edit/' + this.user.id
}
this.store.dispatch(new AddBreadcrumb(newBread));
const currentRoute = 'customer-edit/' + this.user.id;
this.store.dispatch(new ChangeCurrentRoute(currentRoute));
this.router.navigate([currentRoute]);
}
}
setNumberOfItems (numberOfItems: number, id: number, book: BookData) {
const updatedBooks = this.books.map((bookToUpdate: BookData) => {
if (bookToUpdate.book.id === book.book.id) {
bookToUpdate.quantity = numberOfItems;
return bookToUpdate;
}
return bookToUpdate;
});
this.books = updatedBooks;
this.openDropdown(id);
}
recalculate() {
let totalSum = 0;
let totalQuantity = 0;
this.books.forEach((book: BookData) => {
totalSum += book.book.av[0].price.value.value * book.quantity;
totalQuantity += book.quantity;
});
this.displayItemsNumber = totalQuantity;
this.booksTotalSum = totalSum;
this.booksTotalSumString = (+Math.round(totalSum * 100) / 100).toFixed(2).toLocaleString().replace('.', ',');
this.currentPoints = totalQuantity * points;
}
openDropdown(id: number) {
// Close all other dropdowns
for (let i = 0; i < this.items.length - 1; i++) {
if (i !== id) {
const ele = document.getElementById('drop_' + i);
let text = document.getElementById('drop_txt_' + i);
let icon = document.getElementById('drop_img_' + i);
if(text && text.classList.contains('dropdown-selected-text-active')) {
text.classList.remove('dropdown-selected-text-active');
icon.classList.remove('open-icon');
icon.classList.add('close-icon');
}
if (ele && ele.style.display && ele.style.display === 'flex') {
icon.classList.remove('close-icon');
icon.classList.add('open-icon');
ele.style.display = 'none';
}
}
}
const ele = document.getElementById('drop_' + id);
const text = document.getElementById('drop_txt_' + id);
const icon = document.getElementById('drop_img_' + id);
if(text.classList.contains('dropdown-selected-text-active')) {
text.classList.remove('dropdown-selected-text-active');
} else {
text.classList.add('dropdown-selected-text-active');
}
if (!ele.style.display || ele.style.display === 'none') {
// open
var rect = icon.getBoundingClientRect();
ele.style.top = (rect.top + 33) + 'px';
ele.style.left = (rect.left - 30) + 'px';
ele.style.display = 'flex';
icon.classList.remove('open-icon');
icon.classList.add('close-icon');
} else {
icon.classList.remove('close-icon');
icon.classList.add('open-icon');
ele.style.display = 'none';
}
}
private setInputData (field: string, val: string, form: FormGroup) {
form.get(field).patchValue(val);
form.get(field).disable();
}
get f() { return this.invoiceForm.controls; }
get deliveryF() { return this.deliveryForm.controls; }
private buildInvoiceForm(fb: FormBuilder) {
return fb.group({
invoice_addrees: ['', Validators.required],
notification_type: ['', Validators.required],
});
}
private buildDeliveryForm(fb: FormBuilder) {
return fb.group({
delivery_addrees: ['', Validators.required],
});
}
}

View File

@@ -0,0 +1 @@
export * from './components/cart-review/cart-review.component';

View File

@@ -19,6 +19,7 @@ import { DashboardModule } from './dashboard/dashboard.module';
import { NewsletterSignupModule } from './newsletter-signup/newsletter-signup.module';
import { ContentPageComponent } from '../pages/content/content.component';
import { CustomerSearchModule } from './customer-search/customer-search.module';
import { CartModule } from './cart/cart-modul';
@NgModule({
declarations: [
@@ -40,7 +41,8 @@ import { CustomerSearchModule } from './customer-search/customer-search.module';
InfiniteScrollModule,
BarcodeSearchModule,
DashboardModule,
CustomerSearchModule
CustomerSearchModule,
CartModule
],
exports: [
HeaderComponent,

View File

@@ -140,13 +140,6 @@
align-items: center;
}
.line {
height: 3px;
width: 100%;
background-image: url('../../../../../assets/images/Line.svg');
background-repeat: repeat-x;
}
.input {
width: 75%;
padding: 15px 0;

View File

@@ -1,19 +1,13 @@
import { Component, OnInit } from '@angular/core';
import { ProcessState } from '../../../../core/store/state/process.state';
import { Observable } from 'rxjs';
import { Observable, forkJoin } from 'rxjs';
import { User } from '../../../../core/models/user.model';
import { Select, Store } from '@ngxs/store';
import {
FormGroup,
FormBuilder,
Validators,
FormControl
} from '@angular/forms';
import {
SethUserName,
ChangeCurrentRoute
} from '../../../../core/store/actions/process.actions';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { SetActiveUser, ChangeCurrentRoute } from '../../../../core/store/actions/process.actions';
import { Router } from '@angular/router';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import { switchMap } from 'rxjs/operators';
@Component({
selector: 'app-edit-customer-card',
@@ -21,9 +15,12 @@ import { Router } from '@angular/router';
styleUrls: ['./edit-customer-card.component.scss']
})
export class EditCustomerCardComponent implements OnInit {
@Select(ProcessState.getEditUser) user$: Observable<User>;
@Select(ProcessState.getActiveUser) user$: Observable<User>;
@Select(ProcessState.getBreadcrumbs) breadcrumbs$: Observable<Breadcrumb[]>;
user: User;
userForm: FormGroup;
breadcrumbs: Breadcrumb[] = [];
constructor(
private store: Store,
@@ -51,6 +48,12 @@ export class EditCustomerCardComponent implements OnInit {
this.setInputData('delivery_address', address);
}
});
this.breadcrumbs$.subscribe((breadcrumbs: Breadcrumb[]) => {
if (breadcrumbs) {
this.breadcrumbs = breadcrumbs;
}
});
}
enableInput(field: string, input: any) {
@@ -62,24 +65,35 @@ export class EditCustomerCardComponent implements OnInit {
} else {
// TODO: Save new data
if (control.valid) {
control.disable();
if (!control.value) {
control.setErrors({ required: true });
} else {
control.disable();
}
}
}
}
back() {
///customer-search-result
const currentRoute = 'customer-search-result';
this.store.dispatch(new ChangeCurrentRoute(currentRoute, true));
this.router.navigate([currentRoute]);
if (this.breadcrumbs.length >= 3 &&
this.breadcrumbs[this.breadcrumbs.length -2].name === 'Warenkorb'
) {
const currentRoute = 'cart';
this.store.dispatch(new ChangeCurrentRoute(currentRoute, true));
this.router.navigate([currentRoute]);
} else {
const currentRoute = 'customer-search-result';
this.store.dispatch(new ChangeCurrentRoute(currentRoute, true));
this.router.navigate([currentRoute]);
}
}
approve() {
this.store.dispatch(new SethUserName(this.userForm.get('name').value));
this.store.dispatch(new SetActiveUser(this.user));
}
clear(field: string) {
this.userForm.get(field).patchValue('');
this.userForm.get(field).patchValue(null);
this.userForm.get(field).setErrors(null);
}
@@ -93,27 +107,13 @@ export class EditCustomerCardComponent implements OnInit {
}
private buildForm(fb: FormBuilder) {
return fb.group(
{
name: ['', Validators.required],
email: ['', Validators.required],
phone_number: ['', Validators.required],
pay: ['', Validators.required],
invoice_addrees: ['', Validators.required],
delivery_address: ['', Validators.required]
},
{ validators: this.validateAllFormFields }
);
}
validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
return fb.group({
name: ['', Validators.required],
email: ['', Validators.required],
phone_number: ['', Validators.required],
pay: ['', Validators.required],
invoice_addrees: ['', Validators.required],
delivery_address: ['', Validators.required],
});
}
}

View File

@@ -18,7 +18,7 @@
</div>
<div class="user-actions">
<a (click)="details(user)">Details</a>
<a (click)="approve(user.name)" class="active">Vorgang zuweisen</a>
<a (click)="approve(user)" class="active">Vorgang zuweisen</a>
</div>
</div>
</div>

View File

@@ -3,7 +3,7 @@ import { Select, Store } from '@ngxs/store';
import { ProcessState } from '../../../../core/store/state/process.state';
import { Observable } from 'rxjs';
import { User } from '../../../../core/models/user.model';
import { SethUserName, ChangeCurrentRoute, SetUserDetails } from '../../../../core/store/actions/process.actions';
import { SetActiveUser, ChangeCurrentRoute, SetUserDetails } from '../../../../core/store/actions/process.actions';
import { Router } from '@angular/router';
@Component({
@@ -35,8 +35,8 @@ export class SearchCustomerResultComponent implements OnInit {
this.router.navigate([currentRoute]);
}
approve(name: string): void {
this.store.dispatch(new SethUserName(name));
approve(user: User): void {
this.store.dispatch(new SetActiveUser(user));
}
}