diff --git a/src/app/@core/data/smart-table.service.ts b/src/app/@core/data/smart-table.service.ts index 56f1087..1e48fef 100644 --- a/src/app/@core/data/smart-table.service.ts +++ b/src/app/@core/data/smart-table.service.ts @@ -4,425 +4,10 @@ import { Injectable } from '@angular/core'; export class SmartTableService { data = [{ - id: 1, - firstName: 'Mark', - lastName: 'Otto', - username: '@mdo', - email: 'mdo@gmail.com', - age: '28', - }, { - id: 2, - firstName: 'Jacob', - lastName: 'Thornton', - username: '@fat', - email: 'fat@yandex.ru', - age: '45', - }, { - id: 3, - firstName: 'Larry', - lastName: 'Bird', - username: '@twitter', - email: 'twitter@outlook.com', - age: '18', - }, { - id: 4, - firstName: 'John', - lastName: 'Snow', - username: '@snow', - email: 'snow@gmail.com', - age: '20', - }, { - id: 5, - firstName: 'Jack', - lastName: 'Sparrow', - username: '@jack', - email: 'jack@yandex.ru', - age: '30', - }, { - id: 6, - firstName: 'Ann', - lastName: 'Smith', - username: '@ann', - email: 'ann@gmail.com', - age: '21', - }, { - id: 7, - firstName: 'Barbara', - lastName: 'Black', - username: '@barbara', - email: 'barbara@yandex.ru', - age: '43', - }, { - id: 8, - firstName: 'Sevan', - lastName: 'Bagrat', - username: '@sevan', - email: 'sevan@outlook.com', - age: '13', - }, { - id: 9, - firstName: 'Ruben', - lastName: 'Vardan', - username: '@ruben', - email: 'ruben@gmail.com', - age: '22', - }, { - id: 10, - firstName: 'Karen', - lastName: 'Sevan', - username: '@karen', - email: 'karen@yandex.ru', - age: '33', - }, { - id: 11, - firstName: 'Mark', - lastName: 'Otto', - username: '@mark', - email: 'mark@gmail.com', - age: '38', - }, { - id: 12, - firstName: 'Jacob', - lastName: 'Thornton', - username: '@jacob', - email: 'jacob@yandex.ru', - age: '48', - }, { - id: 13, - firstName: 'Haik', - lastName: 'Hakob', - username: '@haik', - email: 'haik@outlook.com', - age: '48', - }, { - id: 14, - firstName: 'Garegin', - lastName: 'Jirair', - username: '@garegin', - email: 'garegin@gmail.com', - age: '40', - }, { - id: 15, - firstName: 'Krikor', - lastName: 'Bedros', - username: '@krikor', - email: 'krikor@yandex.ru', - age: '32', - }, { - 'id': 16, - 'firstName': 'Francisca', - 'lastName': 'Brady', - 'username': '@Gibson', - 'email': 'franciscagibson@comtours.com', - 'age': 11, - }, { - 'id': 17, - 'firstName': 'Tillman', - 'lastName': 'Figueroa', - 'username': '@Snow', - 'email': 'tillmansnow@comtours.com', - 'age': 34, - }, { - 'id': 18, - 'firstName': 'Jimenez', - 'lastName': 'Morris', - 'username': '@Bryant', - 'email': 'jimenezbryant@comtours.com', - 'age': 45, - }, { - 'id': 19, - 'firstName': 'Sandoval', - 'lastName': 'Jacobson', - 'username': '@Mcbride', - 'email': 'sandovalmcbride@comtours.com', - 'age': 32, - }, { - 'id': 20, - 'firstName': 'Griffin', - 'lastName': 'Torres', - 'username': '@Charles', - 'email': 'griffincharles@comtours.com', - 'age': 19, - }, { - 'id': 21, - 'firstName': 'Cora', - 'lastName': 'Parker', - 'username': '@Caldwell', - 'email': 'coracaldwell@comtours.com', - 'age': 27, - }, { - 'id': 22, - 'firstName': 'Cindy', - 'lastName': 'Bond', - 'username': '@Velez', - 'email': 'cindyvelez@comtours.com', - 'age': 24, - }, { - 'id': 23, - 'firstName': 'Frieda', - 'lastName': 'Tyson', - 'username': '@Craig', - 'email': 'friedacraig@comtours.com', - 'age': 45, - }, { - 'id': 24, - 'firstName': 'Cote', - 'lastName': 'Holcomb', - 'username': '@Rowe', - 'email': 'coterowe@comtours.com', - 'age': 20, - }, { - 'id': 25, - 'firstName': 'Trujillo', - 'lastName': 'Mejia', - 'username': '@Valenzuela', - 'email': 'trujillovalenzuela@comtours.com', - 'age': 16, - }, { - 'id': 26, - 'firstName': 'Pruitt', - 'lastName': 'Shepard', - 'username': '@Sloan', - 'email': 'pruittsloan@comtours.com', - 'age': 44, - }, { - 'id': 27, - 'firstName': 'Sutton', - 'lastName': 'Ortega', - 'username': '@Black', - 'email': 'suttonblack@comtours.com', - 'age': 42, - }, { - 'id': 28, - 'firstName': 'Marion', - 'lastName': 'Heath', - 'username': '@Espinoza', - 'email': 'marionespinoza@comtours.com', - 'age': 47, - }, { - 'id': 29, - 'firstName': 'Newman', - 'lastName': 'Hicks', - 'username': '@Keith', - 'email': 'newmankeith@comtours.com', - 'age': 15, - }, { - 'id': 30, - 'firstName': 'Boyle', - 'lastName': 'Larson', - 'username': '@Summers', - 'email': 'boylesummers@comtours.com', - 'age': 32, - }, { - 'id': 31, - 'firstName': 'Haynes', - 'lastName': 'Vinson', - 'username': '@Mckenzie', - 'email': 'haynesmckenzie@comtours.com', - 'age': 15, - }, { - 'id': 32, - 'firstName': 'Miller', - 'lastName': 'Acosta', - 'username': '@Young', - 'email': 'milleryoung@comtours.com', - 'age': 55, - }, { - 'id': 33, - 'firstName': 'Johnston', - 'lastName': 'Brown', - 'username': '@Knight', - 'email': 'johnstonknight@comtours.com', - 'age': 29, - }, { - 'id': 34, - 'firstName': 'Lena', - 'lastName': 'Pitts', - 'username': '@Forbes', - 'email': 'lenaforbes@comtours.com', - 'age': 25, - }, { - 'id': 35, - 'firstName': 'Terrie', - 'lastName': 'Kennedy', - 'username': '@Branch', - 'email': 'terriebranch@comtours.com', - 'age': 37, - }, { - 'id': 36, - 'firstName': 'Louise', - 'lastName': 'Aguirre', - 'username': '@Kirby', - 'email': 'louisekirby@comtours.com', - 'age': 44, - }, { - 'id': 37, - 'firstName': 'David', - 'lastName': 'Patton', - 'username': '@Sanders', - 'email': 'davidsanders@comtours.com', - 'age': 26, - }, { - 'id': 38, - 'firstName': 'Holden', - 'lastName': 'Barlow', - 'username': '@Mckinney', - 'email': 'holdenmckinney@comtours.com', - 'age': 11, - }, { - 'id': 39, - 'firstName': 'Baker', - 'lastName': 'Rivera', - 'username': '@Montoya', - 'email': 'bakermontoya@comtours.com', - 'age': 47, - }, { - 'id': 40, - 'firstName': 'Belinda', - 'lastName': 'Lloyd', - 'username': '@Calderon', - 'email': 'belindacalderon@comtours.com', - 'age': 21, - }, { - 'id': 41, - 'firstName': 'Pearson', - 'lastName': 'Patrick', - 'username': '@Clements', - 'email': 'pearsonclements@comtours.com', - 'age': 42, - }, { - 'id': 42, - 'firstName': 'Alyce', - 'lastName': 'Mckee', - 'username': '@Daugherty', - 'email': 'alycedaugherty@comtours.com', - 'age': 55, - }, { - 'id': 43, - 'firstName': 'Valencia', - 'lastName': 'Spence', - 'username': '@Olsen', - 'email': 'valenciaolsen@comtours.com', - 'age': 20, - }, { - 'id': 44, - 'firstName': 'Leach', - 'lastName': 'Holcomb', - 'username': '@Humphrey', - 'email': 'leachhumphrey@comtours.com', - 'age': 28, - }, { - 'id': 45, - 'firstName': 'Moss', - 'lastName': 'Baxter', - 'username': '@Fitzpatrick', - 'email': 'mossfitzpatrick@comtours.com', - 'age': 51, - }, { - 'id': 46, - 'firstName': 'Jeanne', - 'lastName': 'Cooke', - 'username': '@Ward', - 'email': 'jeanneward@comtours.com', - 'age': 59, - }, { - 'id': 47, - 'firstName': 'Wilma', - 'lastName': 'Briggs', - 'username': '@Kidd', - 'email': 'wilmakidd@comtours.com', - 'age': 53, - }, { - 'id': 48, - 'firstName': 'Beatrice', - 'lastName': 'Perry', - 'username': '@Gilbert', - 'email': 'beatricegilbert@comtours.com', - 'age': 39, - }, { - 'id': 49, - 'firstName': 'Whitaker', - 'lastName': 'Hyde', - 'username': '@Mcdonald', - 'email': 'whitakermcdonald@comtours.com', - 'age': 35, - }, { - 'id': 50, - 'firstName': 'Rebekah', - 'lastName': 'Duran', - 'username': '@Gross', - 'email': 'rebekahgross@comtours.com', - 'age': 40, - }, { - 'id': 51, - 'firstName': 'Earline', - 'lastName': 'Mayer', - 'username': '@Woodward', - 'email': 'earlinewoodward@comtours.com', - 'age': 52, - }, { - 'id': 52, - 'firstName': 'Moran', - 'lastName': 'Baxter', - 'username': '@Johns', - 'email': 'moranjohns@comtours.com', - 'age': 20, - }, { - 'id': 53, - 'firstName': 'Nanette', - 'lastName': 'Hubbard', - 'username': '@Cooke', - 'email': 'nanettecooke@comtours.com', - 'age': 55, - }, { - 'id': 54, - 'firstName': 'Dalton', - 'lastName': 'Walker', - 'username': '@Hendricks', - 'email': 'daltonhendricks@comtours.com', - 'age': 25, - }, { - 'id': 55, - 'firstName': 'Bennett', - 'lastName': 'Blake', - 'username': '@Pena', - 'email': 'bennettpena@comtours.com', - 'age': 13, - }, { - 'id': 56, - 'firstName': 'Kellie', - 'lastName': 'Horton', - 'username': '@Weiss', - 'email': 'kellieweiss@comtours.com', - 'age': 48, - }, { - 'id': 57, - 'firstName': 'Hobbs', - 'lastName': 'Talley', - 'username': '@Sanford', - 'email': 'hobbssanford@comtours.com', - 'age': 28, - }, { - 'id': 58, - 'firstName': 'Mcguire', - 'lastName': 'Donaldson', - 'username': '@Roman', - 'email': 'mcguireroman@comtours.com', - 'age': 38, - }, { - 'id': 59, - 'firstName': 'Rodriquez', - 'lastName': 'Saunders', - 'username': '@Harper', - 'email': 'rodriquezharper@comtours.com', - 'age': 20, - }, { - 'id': 60, - 'firstName': 'Lou', - 'lastName': 'Conner', - 'username': '@Sanchez', - 'email': 'lousanchez@comtours.com', - 'age': 16, + cedula: "25872062", + nombre: "Manuel", + apellido: "Rodriguez", + telefono: "04141633960" }]; getData() { diff --git a/src/app/pages/catalog/catalog-routing.module.ts b/src/app/pages/catalog/catalog-routing.module.ts index 92896bf..12dc6dc 100644 --- a/src/app/pages/catalog/catalog-routing.module.ts +++ b/src/app/pages/catalog/catalog-routing.module.ts @@ -3,13 +3,17 @@ import { Routes, RouterModule } from '@angular/router'; import { ProductsComponent } from './products/products.component'; import { CatalogComponent } from './catalog.component'; +import { ClientsComponent } from './clients/clients.component'; const routes: Routes = [{ path: '', - component: ProductsComponent, + component: CatalogComponent, children: [{ path: 'products', - component: CatalogComponent, + component: ProductsComponent, + }, { + path: 'clients', + component: ClientsComponent, }], }]; @@ -22,4 +26,5 @@ export class CatalogRoutingModule { } export const routedComponents = [ ProductsComponent, CatalogComponent, + ClientsComponent ]; diff --git a/src/app/pages/catalog/clients/clients.component.html b/src/app/pages/catalog/clients/clients.component.html new file mode 100644 index 0000000..ba59aa0 --- /dev/null +++ b/src/app/pages/catalog/clients/clients.component.html @@ -0,0 +1,122 @@ + + + Clientes CRUD + + + + + + + + + + + + + +
+ + +
+
+ + + + + + + diff --git a/src/app/pages/catalog/clients/clients.component.scss b/src/app/pages/catalog/clients/clients.component.scss new file mode 100644 index 0000000..33a91ed --- /dev/null +++ b/src/app/pages/catalog/clients/clients.component.scss @@ -0,0 +1,29 @@ +@import '../../../@theme/styles/themes'; +@import '~bootstrap/scss/mixins/breakpoints'; +@import '~@nebular/theme/styles/global/bootstrap/breakpoints'; + +@include nb-install-component() { + + nb-card-footer { + padding-bottom: 0.25rem; + + button { + @include nb-ltr(margin, 0 1rem 1rem 0); + @include nb-rtl(margin, 0 0 1rem 1rem); + } + } + + /* stylelint-disable */ + toaster-container /deep/ { + #toast-container .toast-close-button { + right: 0; + } + } + /* stylelint-enable */ + + @include media-breakpoint-down(xs) { + .dropdown-toggle { + font-size: 0.75rem; + } + } +} \ No newline at end of file diff --git a/src/app/pages/catalog/clients/clients.component.ts b/src/app/pages/catalog/clients/clients.component.ts new file mode 100644 index 0000000..7d56aea --- /dev/null +++ b/src/app/pages/catalog/clients/clients.component.ts @@ -0,0 +1,220 @@ +import { Component, OnInit } from '@angular/core'; +import { LocalDataSource } from 'ng2-smart-table'; +import { Clientmodel } from './clients.model'; +import { SmartTableService } from '../../../@core/data/smart-table.service'; +import { ClientService } from './clients.service'; +import { NgbModal, NgbModalOptions } from '@ng-bootstrap/ng-bootstrap'; +import { error } from '@angular/compiler/src/util'; +import { ToasterService, ToasterConfig, Toast, BodyOutputType } from 'angular2-toaster'; +import 'style-loader!angular2-toaster/toaster.css'; + +/** + * Component for crud of clients + * + * @export + * @class ClientsComponent + */ +@Component({ + selector: 'mac-clients', + templateUrl: './clients.component.html', + styles: ['./clients.component.scss'], + providers: [ClientService] +}) + +export class ClientsComponent { + + // smart-table settings + settings = { + mode: 'external', + actions: { + columnTitle: 'Acciones', + position: 'right' + }, + add: { + addButtonContent: '' + }, + edit: { + editButtonContent: '' + }, + delete: { + deleteButtonContent: '' + }, + columns: { + id_document: { + title: 'Cédula', + type: 'string', + editable: false + }, + first_name: { + title: 'Nombre', + type: 'string', + }, + last_name: { + title: 'Apellido', + type: 'string', + }, + phone_number: { + title: 'Teléfono', + type: 'string', + }, + }, + }; + + source: LocalDataSource = new LocalDataSource(); + clientemodel: Clientmodel = new Clientmodel(); + activeModal: any; + config:ToasterConfig = new ToasterConfig({ + positionClass: 'toast-top-full-width', + timeout: 30000, + tapToDismiss: true, + showCloseButton: true + }); + edit: boolean = false; + + + /** + *Creates an instance of ClientsComponent. + * @param {SmartTableService} service + * @param {ClientService} clientService + * @param {NgbModal} modalService + * @param {ToasterService} toasterService + * @memberof ClientsComponent + */ + constructor(private service: SmartTableService, + private clientService: ClientService, + private modalService: NgbModal, + private toasterService: ToasterService) { + this.getClients() + } + + /** + * Get clients and show their info on smart-table + * + * @memberof ClientsComponent + */ + getClients(): void{ + this.clientService.getClients().subscribe(clients => + this.source.load(clients)) + } + + /** + * Confirm method for delete client + * + * @param {Clientmodel} client to be deleted + * @memberof ClientsComponent + */ + onDeleteConfirm(client: Clientmodel): void { + this.clientService.deleteClient(client).subscribe(client =>{ + if (client == null){ + this.activeModal.dismiss() + this.getClients() + }else{ + this.showErrorMessage(client.error) + } + }) + } + + /** + * Method that makes the update for a client info + * + * @memberof ClientsComponent + */ + editClient():void { + this.clientService.updateClient(this.clientemodel).subscribe(client =>{ + if (!client.error){ + this.activeModal.dismiss() + this.getClients() + }else{ + this.showErrorMessage(client.error) + } + } + ) + } + + /** + * Activate create client modal + * + * @param {*} content Template to be render + * @memberof ClientsComponent + */ + createClientModal(content): void{ + this.activeModal = this.modalService.open(content, { size: 'lg'}) + } + + /** + * Activate edit client modal + * + * @param {*} content Template to be render + * @param {*} event with client info + * @memberof ClientsComponent + */ + editClientModal(content, event): void{ + this.edit = true + Object.assign(this.clientemodel, event.data) + const modal_options : NgbModalOptions = { + size: 'lg', + beforeDismiss: () => { + this.clientemodel = new Clientmodel(); + this.edit = false + return true + } + } + this.activeModal = this.modalService.open(content, modal_options) + } + + /** + * Delete client modal + * + * @param {*} content to be render + * @param {*} event with client info + * @memberof ClientsComponent + */ + deleteClientModal(content, event): void{ + this.clientemodel = event.data + const modal_options : NgbModalOptions = { + size: 'lg', + beforeDismiss: () => { + this.clientemodel = new Clientmodel(); + return true + } + } + this.activeModal = this.modalService.open(content, modal_options) + } + + /** + * Add client to DB + * + * @memberof ClientsComponent + */ + createClient(): void{ + this.clientService.addClient(this.clientemodel).subscribe(client =>{ + if(client){ + if(!client.error){ + this.activeModal.dismiss() + this.getClients() + }else{ + this.showErrorMessage(client.error) + } + } + } + ) + } + + /** + * Method to show notifications + * when some error occurs + * + * @param {*} object with error info + * @memberof ClientsComponent + */ + showErrorMessage(object): void{ + let error_message = "" + for ( var key in object){ + if (object.hasOwnProperty(key)){ + error_message += object[key] + "\n" + } + } + this.toasterService.pop('warning', 'Tu solicitud presentó los siguientes errores:\n', + error_message) + } +} diff --git a/src/app/pages/catalog/clients/clients.model.ts b/src/app/pages/catalog/clients/clients.model.ts new file mode 100644 index 0000000..589d21c --- /dev/null +++ b/src/app/pages/catalog/clients/clients.model.ts @@ -0,0 +1,10 @@ +/** + * @export + * @class Clientmodel + */ +export class Clientmodel { + id_document: string; + first_name: string; + last_name: string; + phone_number: string +} \ No newline at end of file diff --git a/src/app/pages/catalog/clients/clients.service.ts b/src/app/pages/catalog/clients/clients.service.ts new file mode 100644 index 0000000..3b75d83 --- /dev/null +++ b/src/app/pages/catalog/clients/clients.service.ts @@ -0,0 +1,112 @@ + +import { of, Observable } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { Clientmodel } from './clients.model'; +import { catchError, tap } from 'rxjs/operators' +import { HttpHeaders, HttpClient } from '@angular/common/http' + +const httpOptions = { + headers: new HttpHeaders({'Content-Type': 'application/json'}) +} + + +/** + * Service with methods to add, edit or + * delete clients. + * + * @export + * @class ClientService + */ +@Injectable() +export class ClientService { + + API_URL:string = "https://mactaquilla.herokuapp.com/taquilla-api" + + /** + *Creates an instance of ClientService. + * @param {HttpClient} http + * @memberof ClientService + */ + constructor( + private http: HttpClient + ){} + + /** + * Method to get all clients + * + * @returns {Observable} Return list of clients + * if everything is ok or error if not + * @memberof ClientService + */ + getClients():Observable{ + let apiURL = `${this.API_URL}/client/` + return this.http.get(apiURL).pipe( + tap(clients => console.log("Fetched clients")), + catchError(this.handleError('getClients')) + ) + } + + /** + * Method to add client + * + * @param {Clientmodel} client to be added + * @returns {Observable} Return client if everything is ok + * or error if not + * @memberof ClientService + */ + addClient(client: Clientmodel):Observable{ + let apiURL = `${this.API_URL}/client/` + return this.http.post(apiURL, client, httpOptions).pipe( + tap((client: Clientmodel) => console.log("Client added")), + catchError(this.handleError('addClient')) + ) + } + + /** + * Method to edit client + * + * @param {Clientmodel} client to be edited + * @returns {Observable} return client if everythings is ok + * or error if not + * @memberof ClientService + */ + updateClient(client: Clientmodel):Observable{ + let apiURL = `${this.API_URL}/client/${client.id_document}/` + return this.http.put(apiURL, client, httpOptions).pipe( + tap(_ => console.log(`update client ${client.id_document}`)), + catchError(this.handleError('updateClient')) + ) + } + + /** + * Method to delete client + * + * @param {Clientmodel} client to be deleted + * @returns {Observable} return null if everythings is ok + * or error if not + * @memberof ClientService + */ + deleteClient(client: Clientmodel):Observable{ + let apiURL = `${this.API_URL}/client/${client.id_document}/` + return this.http.delete(apiURL, httpOptions).pipe( + tap(_ => console.log(`delete client ${client.id_document}`)), + catchError(this.handleError('deleteClient')) + ) + } + + + /** + * Method to handle errors + * + * @private + * @template T + * @param {string} [operation='operation'] operation that generates the error + * @returns Observable with error info + * @memberof ClientService + */ + private handleError(operation = 'operation'){ + return (error_object: any):Observable =>{ + return of(error_object) + } + } +} diff --git a/src/app/pages/pages-menu.ts b/src/app/pages/pages-menu.ts index e94ca64..e3a2f15 100644 --- a/src/app/pages/pages-menu.ts +++ b/src/app/pages/pages-menu.ts @@ -20,6 +20,10 @@ export const MENU_ITEMS: NbMenuItem[] = [ title: 'Articulos', link: '/pages/catalog/products', }, + { + title: 'Clientes', + link: '/pages/catalog/clients' + } ], }, { @@ -62,7 +66,7 @@ export const MENU_ITEMS: NbMenuItem[] = [ { title: 'Tabs', link: '/pages/ui-features/tabs', - }, + } ], }, { diff --git a/src/app/pages/pages.module.ts b/src/app/pages/pages.module.ts index adcae4a..ebac09e 100644 --- a/src/app/pages/pages.module.ts +++ b/src/app/pages/pages.module.ts @@ -5,6 +5,8 @@ import { DashboardModule } from './dashboard/dashboard.module'; import { PagesRoutingModule } from './pages-routing.module'; import { ThemeModule } from '../@theme/theme.module'; import { MiscellaneousModule } from './miscellaneous/miscellaneous.module'; +import { Ng2SmartTableModule } from 'ng2-smart-table'; +import { ToasterModule } from 'angular2-toaster'; const PAGES_COMPONENTS = [ PagesComponent, @@ -16,6 +18,8 @@ const PAGES_COMPONENTS = [ ThemeModule, DashboardModule, MiscellaneousModule, + Ng2SmartTableModule, + ToasterModule.forRoot() ], declarations: [ ...PAGES_COMPONENTS,