Skip to content

Commit 915c875

Browse files
authored
Merge pull request #157 from ioet/89-Edit-and-delete-customers
fix: #89 edit and delete customers
2 parents 8c19d64 + 6a8cc0c commit 915c875

17 files changed

+561
-85
lines changed

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
<div class="form-group">
44
<div
55
*ngIf="showAlert && messageToShow !== ''"
6-
[ngClass]="{'bg-secondary': messageToShow == 'Customer created successfully!', 'bg-primary': messageToShow != 'Customer created successfully!'}"
6+
[ngClass]="{'bg-secondary': messageToShow == 'Customer created successfully!' || messageToShow == 'Customer updated successfully!',
7+
'bg-primary': messageToShow !== 'Customer created successfully!' }"
78
class="alert alert-dismissible fade fade-in show text-white"
89
role="alert"
910
>
@@ -12,7 +13,7 @@
1213

1314
<input
1415
class="form-control form-control-sm"
15-
id="name"
16+
id="customerName"
1617
type="text"
1718
formControlName="name"
1819
placeholder="Customer name"
@@ -26,7 +27,7 @@
2627
>
2728
<textarea
2829
class="form-control form-control-sm mt-2"
29-
id="description"
30+
id="customerDescription"
3031
rows="3"
3132
formControlName="description"
3233
placeholder="Customer description"

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing';
44

55
import { CreateCustomerComponent } from './create-customer';
66
import { CustomerState, CreateCustomer } from 'src/app/modules/customer-management/store';
7-
import * as models from 'src/app/modules/shared/models/index';
8-
import { LoadCustomers } from './../../../../store/customer-management.actions';
7+
import { LoadCustomers, ResetCustomerToEdit } from './../../../../store/customer-management.actions';
8+
import { Customer } from 'src/app/modules/shared/models';
99

1010
describe('CreateCustomerComponent', () => {
1111
let component: CreateCustomerComponent;
@@ -16,9 +16,10 @@ describe('CreateCustomerComponent', () => {
1616
data: [],
1717
isLoading: false,
1818
message: '',
19+
customerIdToEdit: '',
1920
};
2021

21-
const customerData: models.Customer = {
22+
const customerData: Customer = {
2223
name: 'aa',
2324
description: 'bb',
2425
tenant_id: 'cc',
@@ -35,7 +36,6 @@ describe('CreateCustomerComponent', () => {
3536
fixture = TestBed.createComponent(CreateCustomerComponent);
3637
component = fixture.componentInstance;
3738
fixture.detectChanges();
38-
3939
store = TestBed.inject(MockStore);
4040
store.setState(state);
4141
});
@@ -68,9 +68,12 @@ describe('CreateCustomerComponent', () => {
6868

6969
it('should call resetCustomerForm', () => {
7070
spyOn(component.customerForm, 'reset');
71+
spyOn(store, 'dispatch');
7172

7273
component.resetCustomerForm();
7374

75+
expect(store.dispatch).toHaveBeenCalledTimes(1);
76+
expect(store.dispatch).toHaveBeenCalledWith(new ResetCustomerToEdit());
7477
expect(component.customerForm.reset).toHaveBeenCalled();
7578
});
7679

@@ -81,9 +84,7 @@ describe('CreateCustomerComponent', () => {
8184
spyOn(store, 'dispatch');
8285

8386
component.ngOnInit();
84-
8587
component.onSubmit(customerData);
86-
8788
component.setStatusOnScreen('Customer created successfully!');
8889

8990
expect(component.messageToShow).toEqual('Customer created successfully!');
@@ -97,12 +98,19 @@ describe('CreateCustomerComponent', () => {
9798
spyOn(store, 'dispatch');
9899

99100
component.ngOnInit();
100-
101101
component.onSubmit(customerData);
102-
103102
component.setStatusOnScreen('An error occurred, try again later.');
104103

105104
expect(component.messageToShow).toEqual('An error occurred, try again later.');
106105
expect(component.areTabsActive).toBeFalse();
107106
});
107+
108+
it('set data to update ', () => {
109+
spyOn(store, 'dispatch');
110+
111+
component.ngOnInit();
112+
component.setDataToUpdate(customerData);
113+
114+
expect(component.messageToShow).toEqual(undefined);
115+
});
108116
});

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms';
33
import { Store, select } from '@ngrx/store';
44

55
import { Subscription } from 'rxjs';
6-
import { CustomerState, CreateCustomer, LoadCustomers } from 'src/app/modules/customer-management/store';
7-
import { getStatusMessage } from './../../../../store/customer-management.selectors';
6+
import { getStatusMessage, getCustomerById } from './../../../../store/customer-management.selectors';
7+
import { Customer } from 'src/app/modules/shared/models';
8+
import {
9+
CustomerState,
10+
CreateCustomer,
11+
LoadCustomers,
12+
UpdateCustomer,
13+
ResetCustomerToEdit,
14+
} from 'src/app/modules/customer-management/store';
815

916
@Component({
1017
selector: 'app-create-customer',
@@ -17,7 +24,9 @@ export class CreateCustomerComponent implements OnInit, OnDestroy {
1724
@Output() changeValueAreTabsActives = new EventEmitter<boolean>();
1825
showAlert = false;
1926
messageToShow = '';
27+
customerToEdit: Customer;
2028
saveSubscription: Subscription;
29+
editSubscription: Subscription;
2130

2231
constructor(private formBuilder: FormBuilder, private store: Store<CustomerState>) {
2332
this.customerForm = this.formBuilder.group({
@@ -31,17 +40,34 @@ export class CreateCustomerComponent implements OnInit, OnDestroy {
3140
this.saveSubscription = messages$.subscribe((valueMessage) => {
3241
this.setStatusOnScreen(valueMessage);
3342
});
43+
44+
const customers$ = this.store.pipe(select(getCustomerById));
45+
this.editSubscription = customers$.subscribe((customer) => {
46+
this.customerToEdit = customer;
47+
this.setDataToUpdate(this.customerToEdit);
48+
});
3449
}
3550

3651
ngOnDestroy() {
3752
this.areTabsActive = false;
3853
this.saveSubscription.unsubscribe();
54+
this.editSubscription.unsubscribe();
3955
}
4056

4157
onSubmit(customerData) {
42-
this.store.dispatch(new CreateCustomer(customerData));
43-
this.store.dispatch(new LoadCustomers());
58+
if (this.customerToEdit) {
59+
const customer = {
60+
...customerData,
61+
id: this.customerToEdit.id,
62+
};
63+
this.store.dispatch(new UpdateCustomer(customer));
64+
this.customerForm.reset();
65+
} else {
66+
this.store.dispatch(new CreateCustomer(customerData));
67+
this.store.dispatch(new LoadCustomers());
68+
}
4469
this.showAlert = true;
70+
setTimeout(() => (this.showAlert = false), 3000);
4571
}
4672

4773
setStatusOnScreen(message: string) {
@@ -54,10 +80,20 @@ export class CreateCustomerComponent implements OnInit, OnDestroy {
5480
this.areTabsActive = false;
5581
this.changeValueAreTabsActives.emit(this.areTabsActive);
5682
}
83+
this.messageToShow = message;
84+
}
85+
86+
setDataToUpdate(customerData: Customer) {
87+
if (customerData) {
88+
this.customerForm.setValue({
89+
name: customerData.name,
90+
description: customerData.description,
91+
});
92+
}
5793
}
5894

5995
resetCustomerForm() {
60-
this.showAlert = false;
6196
this.customerForm.reset();
97+
this.store.dispatch(new ResetCustomerToEdit());
6298
}
6399
}

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
<div
2+
*ngIf="showAlert && messageToShow !== ''"
3+
[ngClass]="{
4+
'bg-secondary': messageToShow == 'Customer removed successfully!',
5+
'bg-primary': messageToShow != 'Customer removed successfully!'
6+
}"
7+
class="alert alert-dismissible fade fade-in show text-white"
8+
role="alert"
9+
>
10+
<strong>{{ messageToShow }}</strong>
11+
</div>
112
<table class="table table-sm table-bordered table-striped mb-0">
213
<thead class="thead-orange">
314
<tr class="d-flex">
@@ -12,10 +23,10 @@
1223
>
1324
<td class="col-sm-9">{{ customer.name }}</td>
1425
<td class="col-sm-3 text-center">
15-
<button type="button" class="btn btn-sm btn-secondary">
26+
<button (click)="editCustomer(customer.id)" type="button" class="btn btn-sm btn-secondary">
1627
<i class="fa fa-pencil fa-xs"></i>
1728
</button>
18-
<button type="button" class="btn btn-sm btn-danger ml-2">
29+
<button (click)="deleteCustomer(customer.id)" type="button" class="btn btn-sm btn-danger ml-2">
1930
<i class="fas fa-trash-alt fa-xs"></i>
2031
</button>
2132
</td>

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import { MockStore, provideMockStore } from '@ngrx/store/testing';
21
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { MockStore, provideMockStore } from '@ngrx/store/testing';
33

4-
import { CustomerListComponent } from './customer-list.component';
54
import { NgxPaginationModule } from 'ngx-pagination';
5+
import { CustomerListComponent } from './customer-list.component';
66
import { allCustomers } from './../../../../store/customer-management.selectors';
7-
import { CustomerState } from 'src/app/modules/customer-management/store';
7+
import { CustomerState, SetCustomerToEdit, DeleteCustomer } from 'src/app/modules/customer-management/store';
88

99
describe('CustomerTableListComponent', () => {
1010
let component: CustomerListComponent;
1111
let fixture: ComponentFixture<CustomerListComponent>;
1212
let store: MockStore<CustomerState>;
1313
let mockCustomerSelector;
1414

15-
1615
const state = {
1716
data: [{ tenant_id: 'id', name: 'name', description: 'description' }],
1817
isLoading: false,
1918
message: '',
19+
customerIdToEdit: '',
2020
};
2121

2222
beforeEach(async(() => {
@@ -50,8 +50,25 @@ describe('CustomerTableListComponent', () => {
5050
expect(component.customers).toEqual(state.data);
5151
});
5252

53+
it('onClick edit, dispatch SetCustomerToEdit and enable customer form', () => {
54+
spyOn(store, 'dispatch');
55+
56+
component.editCustomer('1');
57+
58+
expect(store.dispatch).toHaveBeenCalledWith(new SetCustomerToEdit('1'));
59+
expect(component.showCustomerForm).toBeTruthy();
60+
});
61+
62+
it('onClick delete, dispatch DeleteCustomer and enable show alert', () => {
63+
spyOn(store, 'dispatch');
64+
65+
component.deleteCustomer('1');
66+
67+
expect(store.dispatch).toHaveBeenCalledWith(new DeleteCustomer('1'));
68+
expect(component.showAlert).toBeTruthy();
69+
});
70+
5371
afterEach(() => {
5472
fixture.destroy();
5573
});
56-
5774
});
Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,62 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
22
import { Store, select } from '@ngrx/store';
33

4-
import { allCustomers } from './../../../../store/customer-management.selectors';
5-
import { LoadCustomers } from './../../../../store/customer-management.actions';
4+
import { Subscription } from 'rxjs';
5+
import { allCustomers, getStatusMessage } from './../../../../store/customer-management.selectors';
6+
import { LoadCustomers, DeleteCustomer, SetCustomerToEdit } from './../../../../store/customer-management.actions';
67
import { Customer } from './../../../../../shared/models/customer.model';
78
import { ITEMS_PER_PAGE } from 'src/environments/environment';
89

9-
1010
@Component({
1111
selector: 'app-customer-list',
1212
templateUrl: './customer-list.component.html',
1313
styleUrls: ['./customer-list.component.scss'],
1414
})
15-
export class CustomerListComponent implements OnInit {
16-
15+
export class CustomerListComponent implements OnInit, OnDestroy {
1716
initPage1 = 1;
1817
itemsPerPage = ITEMS_PER_PAGE;
18+
@Input() showCustomerForm: boolean;
19+
@Output() changeValueShowCustomerForm = new EventEmitter<boolean>();
1920

2021
customers: Customer[] = [];
22+
messageToShow = '';
23+
showAlert = false;
24+
customerSubscription: Subscription;
25+
customerMessageSubscription: Subscription;
2126

2227
constructor(private store: Store<Customer>) {}
2328

2429
ngOnInit(): void {
2530
this.store.dispatch(new LoadCustomers());
2631
const customers$ = this.store.pipe(select(allCustomers));
27-
customers$.subscribe((response) => {
32+
this.customerSubscription = customers$.subscribe((response) => {
2833
this.customers = response;
2934
});
35+
36+
const messages$ = this.store.pipe(select(getStatusMessage));
37+
this.customerMessageSubscription = messages$.subscribe((valueMessage) => {
38+
this.setStatusOnScreen(valueMessage);
39+
});
40+
}
41+
42+
ngOnDestroy() {
43+
this.customerSubscription.unsubscribe();
44+
this.customerMessageSubscription.unsubscribe();
3045
}
3146

47+
setStatusOnScreen(message: string) {
48+
this.messageToShow = message;
49+
}
50+
51+
editCustomer(customerId: string) {
52+
this.showCustomerForm = true;
53+
this.changeValueShowCustomerForm.emit(this.showCustomerForm);
54+
this.store.dispatch(new SetCustomerToEdit(customerId));
55+
}
56+
57+
deleteCustomer(customerId: string) {
58+
this.showAlert = true;
59+
setTimeout(() => (this.showAlert = false), 3000);
60+
this.store.dispatch(new DeleteCustomer(customerId));
61+
}
3262
}

0 commit comments

Comments
 (0)