Skip to content

Commit f2f62e4

Browse files
committed
fix: ioet#87 c1-save-customers
1 parent c772336 commit f2f62e4

File tree

52 files changed

+475
-63
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+475
-63
lines changed

src/app/app-routing.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { TimeEntriesComponent } from './modules/time-entries/pages/time-entries.
88
import { ActivitiesManagementComponent } from './modules/activities-management/pages/activities-management.component';
99
import { HomeComponent } from './modules/home/home.component';
1010
import { LoginComponent } from './modules/login/login.component';
11-
import { CustomerComponent } from './modules/customer-managment/pages/customer.component';
11+
import { CustomerComponent } from './modules/customer-management/pages/customer.component';
1212

1313
const routes: Routes = [
1414
{

src/app/app.module.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,21 @@ import { ProjectEffects } from './modules/project-management/store/project.effec
3636
import { TechnologyEffects } from './modules/shared/store/technology.effects';
3737
import { reducers, metaReducers } from './reducers';
3838
import { environment } from '../environments/environment';
39-
import { CustomerComponent } from './modules/customer-managment/pages/customer.component';
39+
import { CustomerComponent } from './modules/customer-management/pages/customer.component';
4040
// tslint:disable-next-line: max-line-length
41-
import { CustomerListComponent } from './modules/customer-managment/components/customer-info/components/customer-list/customer-list.component';
42-
import { SearchComponent } from './modules/customer-managment/components/search/search.component';
41+
import { CustomerListComponent } from './modules/customer-management/components/customer-info/components/customer-list/customer-list.component';
42+
import { SearchComponent } from './modules/customer-management/components/search/search.component';
4343
// tslint:disable-next-line: max-line-length
44-
import { ManagementCustomerProjectsComponent } from './modules/customer-managment/components/management-customer-projects/management-customer-projects.component';
45-
import { CreateCustomerComponent } from './modules/customer-managment/components/customer-info/components/create-customer/create-customer';
44+
import { ManagementCustomerProjectsComponent } from './modules/customer-management/components/management-customer-projects/management-customer-projects.component';
45+
import { CreateCustomerComponent } from './modules/customer-management/components/customer-info/components/create-customer/create-customer';
4646
// tslint:disable-next-line: max-line-length
47-
import { CreateProjectComponent } from './modules/customer-managment/components/projects/components/create-project/create-project.component';
48-
import { ProjectListComponent } from './modules/customer-managment/components/projects/components/project-list/project-list.component';
47+
import { CreateProjectComponent } from './modules/customer-management/components/projects/components/create-project/create-project.component';
48+
import { ProjectListComponent } from './modules/customer-management/components/projects/components/project-list/project-list.component';
4949
// tslint:disable-next-line: max-line-length
50-
import { ProjectTypeListComponent } from './modules/customer-managment/components/projects-type/components/project-type-list/project-type-list.component';
50+
import { ProjectTypeListComponent } from './modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component';
5151
// tslint:disable-next-line: max-line-length
52-
import { CreateProjectTypeComponent } from './modules/customer-managment/components/projects-type/components/create-project-type/create-project-type.component';
52+
import { CreateProjectTypeComponent } from './modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component';
53+
import { CustomerEffects } from './modules/customer-management/store/customer-management.effects';
5354

5455
@NgModule({
5556
declarations: [
@@ -102,7 +103,7 @@ import { CreateProjectTypeComponent } from './modules/customer-managment/compone
102103
maxAge: 15, // Retains last 15 states
103104
})
104105
: [],
105-
EffectsModule.forRoot([ProjectEffects, ActivityEffects, TechnologyEffects]),
106+
EffectsModule.forRoot([ProjectEffects, ActivityEffects, CustomerEffects, TechnologyEffects]),
106107
],
107108
providers: [],
108109
bootstrap: [AppComponent],
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<div class="container">
2+
<form style="width: 600px;" [formGroup]="customerForm" (ngSubmit)="onSubmit(customerForm.value)">
3+
<div class="form-group">
4+
<div
5+
*ngIf="showAlert && messageToShow !== ''"
6+
[ngClass]="{'bg-secondary': messageToShow == 'Customer create successfully!', 'bg-primary': messageToShow != 'Customer create successfully!'}"
7+
class="alert alert-dismissible fade fade-in show text-white"
8+
role="alert"
9+
>
10+
<strong>{{ messageToShow }}</strong>
11+
</div>
12+
13+
<input
14+
class="form-control form-control-sm"
15+
id="name"
16+
type="text"
17+
formControlName="name"
18+
placeholder="Customer name"
19+
[class.is-invalid]="customerForm.invalid && customerForm.touched"
20+
required
21+
/>
22+
<span
23+
class="badge badge-pill badge-light text-danger"
24+
*ngIf="(customerForm.dirty || customerForm.touched) && customerForm.invalid"
25+
>Activity name is required</span
26+
>
27+
<textarea
28+
class="form-control form-control-sm mt-2"
29+
id="description"
30+
rows="3"
31+
formControlName="description"
32+
placeholder="Customer description"
33+
></textarea>
34+
<button type="submit" class="btn btn-sm btn-primary" [disabled]="!customerForm.valid">Save</button>
35+
<button (click)="resetCustomerForm()" id="cancel" type="button" class="btn btn-sm btn-secondary mb-2 ml-2 mt-2">
36+
Cancel
37+
</button>
38+
</div>
39+
</form>
40+
</div>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { CreateCustomerComponent } from './create-customer';
4+
import { MockStore, provideMockStore } from '@ngrx/store/testing';
5+
import { CustomerState, CreateCustomer } from 'src/app/modules/customer-management/store';
6+
import { FormBuilder } from '@angular/forms';
7+
import { Customer } from 'src/app/modules/shared/models/customer.model';
8+
9+
describe('CreateCustomerComponent', () => {
10+
let component: CreateCustomerComponent;
11+
let fixture: ComponentFixture<CreateCustomerComponent>;
12+
let store: MockStore<CustomerState>;
13+
14+
const state = {
15+
data: [],
16+
isLoading: false,
17+
message: '',
18+
};
19+
20+
const customerData: Customer = {
21+
name: 'aa',
22+
description: 'bb',
23+
tenant_id: 'cc',
24+
};
25+
26+
beforeEach(async(() => {
27+
TestBed.configureTestingModule({
28+
declarations: [CreateCustomerComponent],
29+
providers: [FormBuilder, provideMockStore({ initialState: state })],
30+
}).compileComponents();
31+
}));
32+
33+
beforeEach(() => {
34+
fixture = TestBed.createComponent(CreateCustomerComponent);
35+
component = fixture.componentInstance;
36+
fixture.detectChanges();
37+
38+
store = TestBed.inject(MockStore);
39+
store.setState(state);
40+
});
41+
42+
afterEach(() => {
43+
fixture.destroy();
44+
});
45+
46+
it('component should be created', () => {
47+
expect(component).toBeTruthy();
48+
});
49+
50+
it('should call resetCustomerForm', () => {
51+
spyOn(component.customerForm, 'reset');
52+
53+
component.resetCustomerForm();
54+
55+
expect(component.customerForm.reset).toHaveBeenCalled();
56+
});
57+
58+
it('onSubmit and dispatch CreateCustomer action', () => {
59+
spyOn(store, 'dispatch');
60+
61+
component.onSubmit(customerData);
62+
63+
expect(store.dispatch).toHaveBeenCalledTimes(1);
64+
expect(store.dispatch).toHaveBeenCalledWith(new CreateCustomer(customerData));
65+
});
66+
67+
it('should call resetCustomerForm', () => {
68+
spyOn(component.customerForm, 'reset');
69+
70+
component.resetCustomerForm();
71+
72+
expect(component.customerForm.reset).toHaveBeenCalled();
73+
});
74+
75+
it('should be enable tabs and show message Customer create successfully! ', () => {
76+
component.isActiveItemTabs = false;
77+
component.messageToShow = '';
78+
79+
spyOn(store, 'dispatch');
80+
81+
component.ngOnInit();
82+
83+
component.onSubmit(customerData);
84+
85+
component.setStatusOnScreen('Customer create successfully!');
86+
87+
expect(component.messageToShow).toEqual('Customer create successfully!');
88+
expect(component.isActiveItemTabs).toBeTrue();
89+
});
90+
91+
it('should be disabled tabs and show message Something went wrong creating customer! ', () => {
92+
component.isActiveItemTabs = false;
93+
component.messageToShow = '';
94+
95+
spyOn(store, 'dispatch');
96+
97+
component.ngOnInit();
98+
99+
component.onSubmit(customerData);
100+
101+
component.setStatusOnScreen('Something went wrong creating customer!');
102+
103+
expect(component.messageToShow).toEqual('Something went wrong creating customer!');
104+
expect(component.isActiveItemTabs).toBeFalse();
105+
});
106+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Component, Input, Output, EventEmitter, OnDestroy, OnInit } from '@angular/core';
2+
import { Store, select } from '@ngrx/store';
3+
import { CustomerState, CreateCustomer } from 'src/app/modules/customer-management/store';
4+
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
5+
import { Subscription } from 'rxjs';
6+
import { getStatusMessage } from 'src/app/modules/customer-management/store/customer-management.selectors';
7+
8+
@Component({
9+
selector: 'app-create-customer',
10+
templateUrl: './create-customer.html',
11+
styleUrls: ['./create-customer.scss'],
12+
})
13+
export class CreateCustomerComponent implements OnInit, OnDestroy {
14+
customerForm: FormGroup;
15+
@Input() isActiveItemTabs: boolean;
16+
@Output() changeValueIsActiveItemTabs = new EventEmitter<boolean>();
17+
showAlert = false;
18+
messageToShow = '';
19+
saveSubscription: Subscription;
20+
21+
constructor(private formBuilder: FormBuilder, private store: Store<CustomerState>) {
22+
this.customerForm = this.formBuilder.group({
23+
name: ['', Validators.required],
24+
description: [''],
25+
});
26+
}
27+
28+
ngOnInit() {
29+
const messages$ = this.store.pipe(select(getStatusMessage));
30+
this.saveSubscription = messages$.subscribe((valueMessage) => {
31+
this.setStatusOnScreen(valueMessage);
32+
console.log(valueMessage);
33+
});
34+
}
35+
36+
ngOnDestroy() {
37+
this.isActiveItemTabs = false;
38+
this.saveSubscription.unsubscribe();
39+
}
40+
41+
onSubmit(customerData) {
42+
this.store.dispatch(new CreateCustomer(customerData));
43+
this.showAlert = true;
44+
}
45+
46+
setStatusOnScreen(message: string) {
47+
if (message === 'Customer create successfully!') {
48+
this.messageToShow = message;
49+
this.isActiveItemTabs = true;
50+
this.changeValueIsActiveItemTabs.emit(this.isActiveItemTabs);
51+
} else if (message === 'Something went wrong creating customer!') {
52+
this.messageToShow = message;
53+
this.isActiveItemTabs = false;
54+
this.changeValueIsActiveItemTabs.emit(this.isActiveItemTabs);
55+
}
56+
}
57+
58+
resetCustomerForm() {
59+
this.showAlert = false;
60+
this.customerForm.reset();
61+
}
62+
}

0 commit comments

Comments
 (0)