Skip to content

Commit 125e429

Browse files
Dan WahlinDan Wahlin
Dan Wahlin
authored and
Dan Wahlin
committed
General tweaks
1 parent 46d824e commit 125e429

File tree

9 files changed

+632
-4
lines changed

9 files changed

+632
-4
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const customersRepo = require('../../../lib/customersRepository'),
2+
statesRepo = require('../../../lib/statesRepository'),
3+
util = require('util');
4+
5+
class CustomersController {
6+
// /api/customers
7+
constructor(router) {
8+
router.get('/', this.getCustomers.bind(this));
9+
router.get('/:id', this.getCustomer.bind(this));
10+
router.post('/', this.insertCustomer.bind(this));
11+
router.put('/:id', this.updateCustomer.bind(this));
12+
}
13+
14+
getCustomers(req, res) {
15+
console.log('*** getCustomers');
16+
customersRepo.getCustomers((err, data) => {
17+
if (err) {
18+
console.log('*** getCustomers error: ' + util.inspect(err));
19+
res.json(null);
20+
} else {
21+
console.log('*** getCustomers ok');
22+
res.json(data.customers);
23+
}
24+
});
25+
}
26+
27+
getCustomer(req, res) {
28+
console.log('*** getCustomer');
29+
const id = req.params.id;
30+
customersRepo.getCustomer(id, (err, customer) => {
31+
if (err) {
32+
console.log('*** getCustomer error: ' + util.inspect(err));
33+
res.json(null);
34+
} else {
35+
console.log('*** getCustomer ok');
36+
res.json(customer);
37+
}
38+
});
39+
40+
}
41+
42+
insertCustomer(req, res) {
43+
console.log('*** insertCustomer');
44+
statesRepo.getState(req.body.stateId, (err, state) => {
45+
if (err) {
46+
console.log('*** statesRepo.getState error: ' + util.inspect(err));
47+
res.json({ status: false, error: 'State not found', customer: null });
48+
} else {
49+
customersRepo.insertCustomer(req.body, state, (err, customer) => {
50+
if (err) {
51+
console.log('*** customersRepo.insertCustomer error: ' + util.inspect(err));
52+
res.json({status: false, error: 'Insert failed', customer: null});
53+
} else {
54+
console.log('*** insertCustomer ok');
55+
res.json({ status: true, error: null, customer: customer });
56+
}
57+
});
58+
}
59+
});
60+
}
61+
62+
updateCustomer(req, res) {
63+
console.log('*** updateCustomer');
64+
console.log('*** req.body');
65+
console.log(req.body);
66+
67+
statesRepo.getState(req.body.stateId, (err, state) => {
68+
if (err) {
69+
console.log('*** statesRepo.getState error: ' + util.inspect(err));
70+
res.json({ status: false, error: 'State not found', customer: null });
71+
} else {
72+
customersRepo.updateCustomer(req.params.id, req.body, state, (err, customer) => {
73+
if (err) {
74+
console.log('*** customersRepo.updateCustomer error: ' + util.inspect(err));
75+
res.json({status: false, error: 'Update failed', customer: null});
76+
} else {
77+
console.log('*** updateCustomer ok');
78+
res.json({ status: true, error: null, customer: customer });
79+
}
80+
});
81+
}
82+
});
83+
}
84+
85+
86+
87+
88+
}
89+
90+
module.exports = CustomersController;
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { Injectable } from '@angular/core';
2+
import { Http, Headers, Response, RequestOptions } from '@angular/http';
3+
4+
import { Observable } from 'rxjs/Observable';
5+
import 'rxjs/add/observable/throw';
6+
import 'rxjs/add/operator/map';
7+
import 'rxjs/add/operator/catch';
8+
9+
import { ICustomer, IOrder, IState } from '../shared/interfaces';
10+
11+
@Injectable()
12+
export class DataService {
13+
14+
baseUrl: string = '/api/customers';
15+
16+
constructor(private http: Http) {
17+
18+
}
19+
20+
getCustomers() : Observable<ICustomer[]> {
21+
return this.http.get(this.baseUrl)
22+
.map((res: Response) => {
23+
let customers = res.json();
24+
this.calculateCustomersOrderTotal(customers);
25+
return customers;
26+
})
27+
.catch(this.handleError);
28+
}
29+
30+
getCustomer(id: string) : Observable<ICustomer> {
31+
return this.http.get(this.baseUrl + '/' + id)
32+
.map((res: Response) => res.json())
33+
.catch(this.handleError);
34+
}
35+
36+
getStates() : Observable<IState[]> {
37+
return this.http.get('/api/states')
38+
.map((res: Response) => res.json())
39+
.catch(this.handleError);
40+
}
41+
42+
insertCustomer(customer: ICustomer) : Observable<ICustomer> {
43+
return this.http.post(this.baseUrl, customer)
44+
.map((res: Response) => {
45+
const data = res.json();
46+
console.log('insertCustomer status: ' + data.status);
47+
return data.customer;
48+
})
49+
.catch(this.handleError);
50+
}
51+
52+
updateCustomer(customer: ICustomer) : Observable<ICustomer> {
53+
return this.http.put(this.baseUrl + '/' + customer._id, customer)
54+
.map((res: Response) => {
55+
const data = res.json();
56+
console.log('updateCustomer status: ' + data.status);
57+
return data.customer;
58+
})
59+
.catch(this.handleError);
60+
}
61+
62+
calculateCustomersOrderTotal(customers: ICustomer[]) {
63+
for (let customer of customers) {
64+
if (customer && customer.orders) {
65+
let total = 0;
66+
for (let order of customer.orders) {
67+
total += (order.price * order.quantity);
68+
}
69+
customer.orderTotal = total;
70+
}
71+
}
72+
}
73+
74+
private handleError(error: any) {
75+
console.error('server error:', error);
76+
if (error instanceof Response) {
77+
let errMessage = '';
78+
try {
79+
errMessage = error.json().error;
80+
} catch(err) {
81+
errMessage = error.statusText;
82+
}
83+
return Observable.throw(errMessage);
84+
// Use the following instead if using lite-server
85+
//return Observable.throw(err.text() || 'backend server error');
86+
}
87+
return Observable.throw(error || 'Node.js server error');
88+
}
89+
90+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { Router, ActivatedRoute } from '@angular/router';
3+
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
4+
5+
import { DataService } from '../core/data.service';
6+
import { ICustomer, IState } from '../shared/interfaces';
7+
import { ValidationService } from '../shared/validation.service';
8+
9+
@Component({
10+
moduleId: module.id,
11+
selector: 'customer-edit-reactive',
12+
templateUrl: 'customer-edit-reactive.component.html'
13+
})
14+
export class CustomerEditReactiveComponent implements OnInit {
15+
16+
customerForm: FormGroup;
17+
customer: ICustomer = {
18+
_id: '',
19+
firstName: '',
20+
lastName: '',
21+
gender: '',
22+
address: '',
23+
email: '',
24+
city: '',
25+
stateId: 0,
26+
zip: 0
27+
};
28+
states: IState[];
29+
errorMessage: string;
30+
deleteMessageEnabled: boolean;
31+
operationText: string = 'Insert';
32+
33+
constructor(private router: Router,
34+
private route: ActivatedRoute,
35+
private dataService: DataService,
36+
private formBuilder: FormBuilder) { }
37+
38+
ngOnInit() {
39+
let id = this.route.snapshot.params['id'];
40+
if (id !== '0') {
41+
this.operationText = 'Update';
42+
this.getCustomer(id);
43+
}
44+
45+
this.getStates();
46+
this.buildForm();
47+
}
48+
49+
getCustomer(id: string) {
50+
this.dataService.getCustomer(id)
51+
.subscribe((customer: ICustomer) => {
52+
//Quick and dirty clone used in case user cancels out of form
53+
const cust = JSON.stringify(customer);
54+
this.customer = JSON.parse(cust);
55+
this.buildForm();
56+
},
57+
(err) => console.log(err));
58+
}
59+
60+
buildForm() {
61+
this.customerForm = this.formBuilder.group({
62+
firstName: [this.customer.firstName, Validators.required],
63+
lastName: [this.customer.lastName, Validators.required],
64+
gender: [this.customer.gender, Validators.required],
65+
email: [this.customer.email, [Validators.required, ValidationService.emailValidator]],
66+
address: [this.customer.address, Validators.required],
67+
city: [this.customer.city, Validators.required],
68+
stateId: [this.customer.stateId, Validators.required]
69+
});
70+
}
71+
72+
getStates() {
73+
this.dataService.getStates().subscribe((states: IState[]) => this.states = states);
74+
}
75+
76+
submit({ value, valid }: { value: ICustomer, valid: boolean }) {
77+
78+
value._id = this.customer._id;
79+
value.zip = this.customer.zip || 0;
80+
81+
if (value._id) {
82+
83+
this.dataService.updateCustomer(value)
84+
.subscribe((customer: ICustomer) => {
85+
if (customer) {
86+
this.router.navigate(['/customers']);
87+
}
88+
else {
89+
this.errorMessage = 'Unable to save customer';
90+
}
91+
},
92+
(err) => console.log(err));
93+
94+
} else {
95+
96+
this.dataService.insertCustomer(value)
97+
.subscribe((customer: ICustomer) => {
98+
if (customer) {
99+
this.router.navigate(['/customers']);
100+
}
101+
else {
102+
this.errorMessage = 'Unable to add customer';
103+
}
104+
},
105+
(err) => console.log(err));
106+
107+
}
108+
}
109+
110+
cancel(event: Event) {
111+
event.preventDefault();
112+
this.router.navigate(['/customers']);
113+
}
114+
115+
delete(event: Event) {
116+
117+
}
118+
119+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<div>
2+
<header>
3+
<h3>
4+
<span class="glyphicon glyphicon-user"></span>
5+
{{ customer.firstName }} {{ customer.lastName }}
6+
</h3>
7+
</header>
8+
<br />
9+
<form (ngSubmit)="submit()" #customerForm="ngForm" class="editForm" novalidate>
10+
<div class="form-group">
11+
<label>First Name</label>
12+
<input type="text" class="form-control" name="firstName" [(ngModel)]="customer.firstName" #firstName="ngModel" required>
13+
<div class="alert alert-danger" [hidden]="firstName.untouched || firstName.valid">First Name is required</div>
14+
</div>
15+
<div class="form-group">
16+
<label>Last Name</label>
17+
<input type="text" class="form-control" name="lastName" [(ngModel)]="customer.lastName" #lastName="ngModel" required>
18+
<div class="alert alert-danger" [hidden]="lastName.untouched || lastName.valid">Last Name is required</div>
19+
</div>
20+
<div class="form-group">
21+
<label>Gender</label>
22+
<br />
23+
<div class="radio">
24+
<label>
25+
<input type="radio" name="gender" [(ngModel)]="customer.gender" #gender="ngModel" value="Male" required />
26+
Male
27+
</label>
28+
</div>
29+
<div class="radio">
30+
<label>
31+
<input type="radio" name="gender" [(ngModel)]="customer.gender" #gender="ngModel" value="Female" required />
32+
Female
33+
</label>
34+
</div>
35+
</div>
36+
<div class="form-group">
37+
<label>Email</label>
38+
<input type="email" class="form-control" name="email" [(ngModel)]="customer.email" #email="ngModel" required pattern="^[^\s@]+@[^\s@]+\.[^\s@]{2,}$" />
39+
<div class="alert alert-danger" [hidden]="email.untouched || email.valid">Email is required and must be valid</div>
40+
</div>
41+
<div class="form-group">
42+
<label>Address</label>
43+
<input type="text" class="form-control" name="address" [(ngModel)]="customer.address" #address="ngModel" required>
44+
<div class="alert alert-danger" [hidden]="address.untouched || address.valid">Address is required</div>
45+
</div>
46+
<div class="form-group">
47+
<label>City</label>
48+
<input type="text" class="form-control" name="city" [(ngModel)]="customer.city" #city="ngModel" required>
49+
<div class="alert alert-danger" [hidden]="city.untouched || city.valid">City is required</div>
50+
</div>
51+
<div class="form-group">
52+
<label>State</label>
53+
<select class="form-control"
54+
[(ngModel)]="customer.stateId"
55+
name="state"
56+
required>
57+
<option *ngFor="let state of states" [ngValue]="state.id">{{state.name}}</option>
58+
</select>
59+
</div>
60+
<br />
61+
62+
<div *ngIf="customer">
63+
<!-- Delete code goes here -->
64+
65+
66+
67+
<div class="pull-right" *ngIf="!deleteMessageEnabled">
68+
<button class="btn btn-default" (click)="cancel($event)">Cancel</button>&nbsp;&nbsp;
69+
<button type="submit" class="btn btn-success" [disabled]="!customerForm.valid">{{ operationText }}</button>
70+
</div>
71+
</div>
72+
<br />
73+
<br />
74+
<div class="alert alert-danger" *ngIf="errorMessage != null">{{ errorMessage }}</div>
75+
76+
</form>
77+
</div>

0 commit comments

Comments
 (0)