├── .angular-cli.json ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── 0.199027b778401bd939dd.chunk.js ├── 1.aa7a59fc8f79e7c15bbf.chunk.js ├── assets │ └── bg.jpg ├── bg.e88a2d4544db10e6bdcf.jpg ├── index.html ├── inline.4f04594155dcd0da1dd8.bundle.js ├── main.7b3b5ac7102628da6d15.bundle.js ├── ngsw-manifest.json ├── polyfills.272a0a92e0b8d1d5eab2.bundle.js ├── styles.6a63a43850233e912137.bundle.css ├── sw-register.c12a0e1d4fd37a7ce413.bundle.js ├── vendor.e726a2429f090af1601d.bundle.js └── worker-basic.min.js ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── src ├── apfem-theme.scss ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routing.ts │ ├── cart │ │ ├── cart-item.component.spec.ts │ │ ├── cart-item.component.ts │ │ ├── cart-routing.module.ts │ │ ├── cart.component.html │ │ ├── cart.component.spec.ts │ │ ├── cart.component.ts │ │ ├── cart.module.ts │ │ ├── cart.service.spec.ts │ │ ├── cart.service.ts │ │ ├── cart.ts │ │ └── index.ts │ ├── homepage.component.css │ ├── homepage.component.html │ ├── homepage.component.ts │ ├── items │ │ ├── index.ts │ │ ├── item-by-category.component.css │ │ ├── item-by-category.component.html │ │ ├── item-by-category.component.spec.ts │ │ ├── item-by-category.component.ts │ │ ├── item-details.component.css │ │ ├── item-details.component.html │ │ ├── item-details.component.spec.ts │ │ ├── item-details.component.ts │ │ ├── item-list.component.css │ │ ├── item-list.component.html │ │ ├── item-list.component.spec.ts │ │ ├── item-list.component.ts │ │ ├── item-routing.module.ts │ │ ├── item.component.css │ │ ├── item.component.html │ │ ├── item.component.spec.ts │ │ ├── item.component.ts │ │ ├── item.service.spec.ts │ │ ├── item.service.ts │ │ ├── item.ts │ │ └── items.module.ts │ ├── layouts │ │ ├── default-layout.component.css │ │ ├── default-layout.component.html │ │ ├── default-layout.component.ts │ │ ├── index.ts │ │ ├── simple-layout.component.css │ │ ├── simple-layout.component.html │ │ └── simple-layout.component.ts │ └── shared │ │ ├── carousel.component.ts │ │ ├── carousel.module.ts │ │ ├── cart-counter.component.ts │ │ ├── footer.component.css │ │ ├── footer.component.html │ │ ├── footer.component.ts │ │ ├── index.ts │ │ ├── main-nav.component.css │ │ ├── main-nav.component.html │ │ ├── main-nav.component.ts │ │ ├── side-nav.component.css │ │ ├── side-nav.component.html │ │ ├── side-nav.component.ts │ │ └── slide.component.ts ├── assets │ ├── .gitkeep │ └── bg.jpg ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── fav.png ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json └── tslint.json /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "angular-pwa-firebase-ecommerce" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "dist", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "test": "test.ts", 18 | "tsconfig": "tsconfig.app.json", 19 | "testTsconfig": "tsconfig.spec.json", 20 | "prefix": "apfem", 21 | "serviceWorker": true, 22 | "styles": [ 23 | "styles.css", 24 | "apfem-theme.scss" 25 | ], 26 | "scripts": [], 27 | "environmentSource": "environments/environment.ts", 28 | "environments": { 29 | "dev": "environments/environment.ts", 30 | "prod": "environments/environment.prod.ts" 31 | } 32 | } 33 | ], 34 | "e2e": { 35 | "protractor": { 36 | "config": "./protractor.conf.js" 37 | } 38 | }, 39 | "lint": [ 40 | { 41 | "project": "src/tsconfig.app.json" 42 | }, 43 | { 44 | "project": "src/tsconfig.spec.json" 45 | }, 46 | { 47 | "project": "e2e/tsconfig.e2e.json" 48 | } 49 | ], 50 | "test": { 51 | "karma": { 52 | "config": "./karma.conf.js" 53 | } 54 | }, 55 | "defaults": { 56 | "styleExt": "css", 57 | "component": { 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /tmp 5 | /out-tsc 6 | /dist 7 | firebase.json 8 | .firebaserc 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # IDEs and editors 14 | /.idea 15 | .project 16 | .classpath 17 | .c9/ 18 | *.launch 19 | .settings/ 20 | *.sublime-workspace 21 | 22 | # IDE - VSCode 23 | .vscode/* 24 | !.vscode/settings.json 25 | !.vscode/tasks.json 26 | !.vscode/launch.json 27 | !.vscode/extensions.json 28 | .vscode-upload.json 29 | launch.json 30 | 31 | # misc 32 | /.sass-cache 33 | /connect.lock 34 | /coverage 35 | /libpeerconnection.log 36 | npm-debug.log 37 | testem.log 38 | /typings 39 | 40 | # e2e 41 | /e2e/*.js 42 | /e2e/*.map 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Koko Godswill Davis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This is an E-commerce PWA(Progressive Web Application) built with Angular 4, Angular Material and Google Firebase 2 | 3 | Live demo can be found here: (https://apfem-c20fc.firebaseapp.com/) 4 | 5 | # Requirements 6 | - [Angular 4+](https://angular.io) 7 | - [Angular CLI v1.1.0](https://github.com/angular/angular-cli) 8 | - [Angular Material 2](https://github.com/angular/material2) 9 | - [TypeScript 2.4](https://www.typescriptlang.org/) 10 | - [Node v6.6.0](https://nodejs.org/en/blog/release/v6.6.0/) 11 | 12 | # Getting Started 13 | 14 | 1. Clone the [github repository](https://github.com/daviskoko/angular-pwa-firebase-ecommerce.git) to your project directory. 15 | 2. cd to /your-project-directory/angular-pwa-firebase-ecommerce 16 | 3. Run `npm install` to install all the application dependencies 17 | 4. Run `ng serve` to start a development server, open your browser and navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 18 | 19 | To run the development server on a custom development server port(eg: `http://localhost:4201`), run `ng serve --port 4201` 20 | 21 | To customize the application theme to your taste, simply open `apfem-theme.scss` located in the `src` directory and make your changes. For more details on how to them your application, visit [Theming Angular Material](https://material.angular.io/guide/theming) 22 | 23 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 24 | -------------------------------------------------------------------------------- /docs/0.199027b778401bd939dd.chunk.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0],{Cs2T:function(l,n,u){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=u("3j3K"),e=u("aZMA"),_=u("Nwqk"),i=u("qcWQ"),a=u("TO/P"),o=u("ZWsw"),r=u("2Je8"),d=u("fYnu"),c=u("NVOs"),s=u("Fzro"),m=u("Qbdm"),f=u("5oXY"),g=u("uRPH"),p=u("8vZK"),b=u("QzJe"),v=u("xf8J"),h=u("azVJ");u.d(n,"ItemsModuleNgFactory",function(){return y});var y=t.b(e.a,[],function(l){return t.c([t.d(512,t.e,t.f,[[8,[_.a,i.a,a.a,o.a,o.b,o.c,o.d,o.e]],[3,t.e],t.g]),t.d(4608,r.a,r.b,[t.h]),t.d(4608,d.b,d.b,[]),t.d(5120,d.c,d.d,[[3,d.c],t.q,d.b]),t.d(5120,d.e,d.f,[[3,d.e],d.c]),t.d(4608,d.g,d.g,[d.c,d.e]),t.d(5120,d.h,d.i,[[3,d.h]]),t.d(4608,d.j,d.j,[d.e]),t.d(4608,d.k,d.k,[d.g,d.h,t.e,d.j,t.x,t.v,t.q]),t.d(5120,d.l,d.m,[[3,d.l],t.q,d.b]),t.d(4608,c.a,c.a,[]),t.d(5120,d.n,d.o,[[3,d.n]]),t.d(4608,d.p,d.p,[]),t.d(4608,d.q,d.q,[d.b]),t.d(4608,d.r,d.r,[d.q,d.b,t.q]),t.d(5120,d.s,d.t,[[3,d.s],[2,d.u],d.b]),t.d(4608,d.v,d.v,[d.k,t.v,[2,r.c],[3,d.v]]),t.d(4608,d.w,d.w,[]),t.d(5120,d.x,d.y,[[3,d.x],[2,s.i],m.b]),t.d(4608,m.e,d.a,[]),t.d(4608,d.z,d.z,[d.k,d.s,[3,d.z]]),t.d(4608,c.d,c.d,[]),t.d(512,r.d,r.d,[]),t.d(512,f.w,f.w,[[2,f.m],[2,f.c]]),t.d(512,g.a,g.a,[]),t.d(512,d.A,d.A,[]),t.d(256,d.B,!0,[]),t.d(512,d.C,d.C,[[2,m.d],[2,d.B]]),t.d(512,d.D,d.D,[]),t.d(512,d.E,d.E,[]),t.d(512,d.F,d.F,[]),t.d(512,d.G,d.G,[]),t.d(512,d.H,d.H,[]),t.d(512,d.I,d.I,[]),t.d(512,d.J,d.J,[]),t.d(512,d.K,d.K,[]),t.d(512,d.L,d.L,[]),t.d(512,d.M,d.M,[]),t.d(512,c.b,c.b,[]),t.d(512,c.c,c.c,[]),t.d(512,d.N,d.N,[]),t.d(512,d.O,d.O,[]),t.d(512,d.P,d.P,[]),t.d(512,d.Q,d.Q,[]),t.d(512,d.R,d.R,[]),t.d(512,d.S,d.S,[]),t.d(512,d.T,d.T,[]),t.d(512,d.U,d.U,[]),t.d(512,d.V,d.V,[]),t.d(512,d.W,d.W,[]),t.d(512,d.X,d.X,[]),t.d(512,d.Y,d.Y,[]),t.d(512,d.Z,d.Z,[]),t.d(512,d._0,d._0,[]),t.d(512,d._1,d._1,[]),t.d(512,d._2,d._2,[]),t.d(512,d._3,d._3,[]),t.d(512,d._4,d._4,[]),t.d(512,d._5,d._5,[]),t.d(512,d._6,d._6,[]),t.d(512,d._7,d._7,[]),t.d(512,d._8,d._8,[]),t.d(512,d._9,d._9,[]),t.d(512,d._10,d._10,[]),t.d(512,d._11,d._11,[]),t.d(512,d._12,d._12,[]),t.d(512,d._13,d._13,[]),t.d(512,d._14,d._14,[]),t.d(512,c.e,c.e,[]),t.d(512,p.a,p.a,[]),t.d(512,e.a,e.a,[]),t.d(1024,f.r,function(){return[[{path:"",component:b.a},{path:":slug",component:v.a},{path:":slug/items",component:h.a}]]},[])])})},EfWy:function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=[""]},FaiM:function(l,n,u){"use strict";function t(l){return a._20(0,[(l()(),a._21(0,null,null,46,"md-card",[["class","center-xs item-card mat-card"]],null,null,null,o.p,o.q)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(49152,null,0,r._39,[],null,null),(l()(),a._23(0,["\n "])),(l()(),a._21(0,null,0,2,"div",[["class","item-img"]],null,null,null,null,null)),a._22(278528,null,0,d.p,[a.n,a.Q,a.P],{ngStyle:[0,"ngStyle"]},null),a._41(["background","background-repeat","background-size","width","min-height","background-position","color"]),(l()(),a._23(0,["\n "])),(l()(),a._21(0,null,0,27,"md-card-content",[["class","mat-card-content"]],null,null,null,null,null)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(16384,null,0,r._98,[],null,null),(l()(),a._23(null,["\n "])),(l()(),a._21(0,null,null,22,"div",[],null,null,null,null,null)),(l()(),a._23(null,["\n "])),(l()(),a._21(0,null,null,19,"md-card-header",[["class","center-xs mat-card-header"]],null,null,null,o.r,o.s)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(49152,null,0,r._40,[],null,null),(l()(),a._23(2,["\n "])),(l()(),a._21(0,null,1,14,"md-card-title",[["class","mat-card-title "]],null,null,null,null,null)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(16384,null,0,r._99,[],null,null),(l()(),a._23(null,["\n "])),(l()(),a._21(0,null,null,1,"h3",[],null,null,null,null,null)),(l()(),a._23(null,["",""])),(l()(),a._23(null,["\n "])),(l()(),a._21(0,null,null,2,"span",[],null,null,null,null,null)),(l()(),a._23(null,["","   "])),a._43(3),(l()(),a._23(null,["\n "])),(l()(),a._21(0,null,null,2,"small",[["class","old-price"]],null,null,null,null,null)),(l()(),a._23(null,["",""])),a._43(3),(l()(),a._23(null,["\n "])),(l()(),a._23(2,["\n "])),(l()(),a._23(null,["\n "])),(l()(),a._23(null,["\n "])),(l()(),a._23(0,["\n "])),(l()(),a._21(0,null,0,8,"button",[["class","end-xs mat-raised-button"],["color","primary"],["md-raised-button",""]],[[8,"disabled",0]],null,null,o.n,o.o)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(180224,null,0,r._35,[a._25,a.Q,r.b,r.l],{color:[0,"color"]},null),a._22(16384,null,0,r._20,[],null,null),(l()(),a._23(0,["Add To Cart "])),(l()(),a._21(0,null,0,3,"md-icon",[["class","mat-icon"],["role","img"]],null,null,null,o.h,o.i)),a._22(16384,null,0,r._15,[[2,r._16],a.Q],null,null),a._22(638976,null,0,r._19,[a._25,a.Q,r.x,[8,null]],null,null),(l()(),a._23(0,["add_shopping_cart"])),(l()(),a._23(0,["\n "]))],function(l,n){l(n,5,0,l(n,6,0,"white url("+n.component.item.photos[0].path+")","no-repeat","cover","auto","250px","center center","#FFF"));l(n,39,0,"primary"),l(n,44,0)},function(l,n){var u=n.component;l(n,23,0,u.item.name),l(n,26,0,a._44(n,26,0,l(n,27,0,a._24(n.parent,0),u.item.price,"USD",!0))),l(n,30,0,a._44(n,30,0,l(n,31,0,a._24(n.parent,0),u.item.old_price,u.USD,!0))),l(n,37,0,a._24(n,39).disabled||null)})}function e(l){return a._20(0,[a._42(0,d.s,[a.h]),(l()(),a._21(0,null,null,6,"a",[],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==a._24(l,2).onClick(u.button,u.ctrlKey,u.metaKey,u.shiftKey)&&t}return t},null,null)),a._22(671744,null,0,c.x,[c.c,c.a,d.e],{routerLink:[0,"routerLink"]},null),a._45(2),(l()(),a._23(null,["\n "])),(l()(),a._26(16777216,null,null,1,null,t)),a._22(16384,null,0,d.k,[a._13,a._14],{ngIf:[0,"ngIf"]},null),(l()(),a._23(null,["\n"])),(l()(),a._23(null,["\n"])),(l()(),a._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),a._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),a._23(null,["\n"]))],function(l,n){var u=n.component;l(n,2,0,l(n,3,0,"/items",u.selectedItem)),l(n,6,0,u.item)},function(l,n){l(n,1,0,a._24(n,2).target,a._24(n,2).href)})}function _(l){return a._20(0,[(l()(),a._21(0,null,null,1,"apfem-item",[],null,null,null,e,f)),a._22(114688,null,0,s.a,[],null,null)],function(l,n){l(n,1,0)},null)}var i=u("vHjS"),a=u("3j3K"),o=u("ZWsw"),r=u("fYnu"),d=u("2Je8"),c=u("5oXY"),s=u("Jz7b");u.d(n,"b",function(){return f}),n.a=e;var m=[i.a],f=a._19({encapsulation:0,styles:m,data:{}});a._27("apfem-item",s.a,_,{item:"item",selectedItem:"selectedItem"},{},[])},Nwqk:function(l,n,u){"use strict";function t(l){return o._20(0,[(l()(),o._21(0,null,null,2,"apfem-item",[["class","col-xs-12 col-sm-6 col-md-4 col-lg-3"]],null,null,null,r.a,r.b)),o._22(114688,null,0,d.a,[],{item:[0,"item"],selectedItem:[1,"selectedItem"]},null),(l()(),o._23(null,["\n "]))],function(l,n){l(n,1,0,n.context.$implicit,n.context.index)},null)}function e(l){return o._20(0,[(l()(),o._21(0,null,null,4,"div",[["class","row"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._26(16777216,null,null,1,null,t)),o._22(802816,null,0,c.j,[o._13,o._14,o.l],{ngForOf:[0,"ngForOf"]},null),(l()(),o._23(null,["\n "]))],function(l,n){l(n,3,0,n.component.items)},null)}function _(l){return o._20(0,[(l()(),o._21(0,null,null,14,"div",[["class","content"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,11,"div",[["class","col-xs-12 col-sm-12 col-md-12 col-lg-12"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,1,"div",[],null,null,null,null,null)),(l()(),o._23(null,["List of items"])),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._26(16777216,null,null,1,null,e)),o._22(16384,null,0,c.k,[o._13,o._14],{ngIf:[0,"ngIf"]},null),(l()(),o._23(null,["\n "])),(l()(),o._23(null,["\n"]))],function(l,n){l(n,12,0,n.component.items)},null)}function i(l){return o._20(0,[(l()(),o._21(0,null,null,1,"apfem-item-list",[],null,null,null,_,g)),o._22(114688,null,0,s.a,[m.a],null,null)],function(l,n){l(n,1,0)},null)}var a=u("vZf8"),o=u("3j3K"),r=u("FaiM"),d=u("Jz7b"),c=u("2Je8"),s=u("QzJe"),m=u("r1Ir");u.d(n,"a",function(){return p});var f=[a.a],g=o._19({encapsulation:0,styles:f,data:{}}),p=o._27("apfem-item-list",s.a,i,{},{},[])},"TO/P":function(l,n,u){"use strict";function t(l){return i._20(0,[(l()(),i._21(0,null,null,1,"p",[],null,null,null,null,null)),(l()(),i._23(null,["\n item-by-category works!\n"])),(l()(),i._23(null,["\n"]))],null,null)}function e(l){return i._20(0,[(l()(),i._21(0,null,null,1,"apfem-item-by-category",[],null,null,null,t,r)),i._22(114688,null,0,a.a,[],null,null)],function(l,n){l(n,1,0)},null)}var _=u("EfWy"),i=u("3j3K"),a=u("azVJ");u.d(n,"a",function(){return d});var o=[_.a],r=i._19({encapsulation:0,styles:o,data:{}}),d=i._27("apfem-item-by-category",a.a,e,{},{},[])},aZMA:function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=function(){function l(){}return l}()},gqZg:function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=[".img[_ngcontent-%COMP%]{padding:8px;border-radius:4px}"]},qcWQ:function(l,n,u){"use strict";function t(l){return r._20(0,[(l()(),r._21(0,null,null,13,"apfem-slide",[["class","img"]],[[2,"active",null],[2,"item",null],[2,"carousel-item",null]],null,null,d.a,d.b)),r._22(245760,null,0,c.a,[s.a],{active:[0,"active"]},null),(l()(),r._23(0,["\n "])),(l()(),r._21(0,null,0,9,"md-card",[["class","mat-card"]],null,null,null,m.p,m.q)),r._22(16384,null,0,f._15,[[2,f._16],r.Q],null,null),r._22(49152,null,0,f._39,[],null,null),(l()(),r._23(0,["\n "])),(l()(),r._21(0,null,0,4,"div",[["class","mat-card-image"],["md-card-image",""]],null,null,null,null,null)),r._22(278528,null,0,g.p,[r.n,r.Q,r.P],{ngStyle:[0,"ngStyle"]},null),r._41(["background","background-repeat","background-size","width","height","background-position","color"]),r._22(16384,null,0,f._97,[],null,null),(l()(),r._23(null,["\n "])),(l()(),r._23(0,["\n "])),(l()(),r._23(0,["\n "]))],function(l,n){l(n,1,0,n.context.$implicit.active),l(n,8,0,l(n,9,0,"white url("+n.context.$implicit.path+")","no-repeat","cover","auto","60vh","center center","#FFF"))},function(l,n){l(n,0,0,r._24(n,1).active,r._24(n,1).addClass,r._24(n,1).addClass)})}function e(l){return r._20(0,[(l()(),r._21(0,null,null,3,"md-option",[["class","mat-option"],["role","option"]],[[1,"tabindex",0],[2,"mat-selected",null],[2,"mat-option-multiple",null],[2,"mat-active",null],[8,"id",0],[1,"aria-selected",0],[1,"aria-disabled",0],[2,"mat-option-disabled",null]],[[null,"click"],[null,"keydown"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==r._24(l,1)._selectViaInteraction()&&t}if("keydown"===n){t=!1!==r._24(l,1)._handleKeydown(u)&&t}return t},m.j,m.k)),r._22(49152,[[1,4]],0,f._32,[r.Q,[2,f._33],[2,f._16]],{value:[0,"value"]},null),r._22(16384,null,0,f._15,[[2,f._16],r.Q],null,null),(l()(),r._23(0,["\n ","\n "]))],function(l,n){l(n,1,0,n.context.$implicit.value)},function(l,n){l(n,0,0,r._24(n,1)._getTabIndex(),r._24(n,1).selected,r._24(n,1).multiple,r._24(n,1).active,r._24(n,1).id,r._24(n,1).selected.toString(),r._24(n,1).disabled.toString(),r._24(n,1).disabled),l(n,3,0,n.context.$implicit.display)})}function _(l){return r._20(0,[(l()(),r._21(0,null,null,76,"div",[["class","row"]],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,8,"div",[["class","col-xs-12 col-sm-7 col-md-7"]],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,5,"apfem-carousel",[],null,null,null,p.a,p.b)),r._22(180224,null,0,s.a,[],{noWrap:[0,"noWrap"],interval:[1,"interval"]},null),(l()(),r._23(0,["\n "])),(l()(),r._26(16777216,null,0,1,null,t)),r._22(802816,null,0,g.j,[r._13,r._14,r.l],{ngForOf:[0,"ngForOf"]},null),(l()(),r._23(0,["\n "])),(l()(),r._23(null,["\n "])),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,63,"div",[["class","col-xs-12 col-sm-5 col-md-5"]],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,1,"h3",[],null,null,null,null,null)),(l()(),r._23(null,["",""])),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,2,"h4",[],null,null,null,null,null)),(l()(),r._23(null,["",""])),r._43(3),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,3,"p",[],null,null,null,null,null)),(l()(),r._21(0,null,null,2,"small",[["class","old-price"]],null,null,null,null,null)),(l()(),r._23(null,["",""])),r._43(3),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,5,"p",[],null,null,null,null,null)),(l()(),r._21(0,null,null,4,"small",[],null,null,null,null,null)),(l()(),r._23(null,["Availability"])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._21(0,null,null,1,"b",[],null,null,null,null,null)),(l()(),r._23(null,["",""])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,40,"form",[["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngSubmit"],[null,"submit"],[null,"reset"]],function(l,n,u){var t=!0,e=l.component;if("submit"===n){t=!1!==r._24(l,36).onSubmit(u)&&t}if("reset"===n){t=!1!==r._24(l,36).onReset()&&t}if("ngSubmit"===n){t=!1!==e.onAddToCart()&&t}return t},null,null)),r._22(16384,null,0,b.n,[],null,null),r._22(540672,null,0,b.i,[[8,null],[8,null]],{form:[0,"form"]},{ngSubmit:"ngSubmit"}),r._36(2048,null,b.o,null,[b.i]),r._22(16384,null,0,b.p,[b.o],null,null),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,5,"input",[["formControlName","item"],["type","hidden"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0,e=l.component;if("input"===n){t=!1!==r._24(l,41)._handleInput(u.target.value)&&t}if("blur"===n){t=!1!==r._24(l,41).onTouched()&&t}if("compositionstart"===n){t=!1!==r._24(l,41)._compositionStart()&&t}if("compositionend"===n){t=!1!==r._24(l,41)._compositionEnd(u.target.value)&&t}if("ngModelChange"===n){t=!1!==(e.item=u)&&t}return t},null,null)),r._22(16384,null,0,b.q,[r.P,r.Q,[2,b.r]],null,null),r._36(1024,null,b.f,function(l){return[l]},[b.q]),r._22(671744,null,0,b.s,[[3,b.o],[8,null],[8,null],[2,b.f]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),r._36(2048,null,b.g,null,[b.s]),r._22(16384,null,0,b.t,[b.g],null,null),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,11,"md-select",[["class","mat-select"],["formControlName","quantity"],["placeholder","Quantity"],["role","listbox"]],[[1,"tabindex",0],[1,"aria-label",0],[1,"aria-labelledby",0],[1,"aria-required",0],[1,"aria-disabled",0],[1,"aria-invalid",0],[1,"aria-owns",0],[2,"mat-select-disabled",null],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"keydown"],[null,"blur"]],function(l,n,u){var t=!0;if("keydown"===n){t=!1!==r._24(l,51)._handleClosedKeydown(u)&&t}if("blur"===n){t=!1!==r._24(l,51)._onBlur()&&t}return t},m.l,m.m)),r._22(16384,null,0,f._15,[[2,f._16],r.Q],null,null),r._22(671744,null,0,b.s,[[3,b.o],[8,null],[8,null],[8,null]],{name:[0,"name"]},null),r._36(2048,null,b.g,null,[b.s]),r._22(1294336,null,2,f._79,[f.e,r._18,r._25,r.Q,[2,f._54],[2,b.g],[8,null],[2,f._66]],{placeholder:[0,"placeholder"]},null),r._35(603979776,1,{options:1}),r._35(603979776,2,{optionGroups:1}),r._22(16384,null,0,b.t,[b.g],null,null),(l()(),r._23(0,["\n "])),(l()(),r._26(16777216,null,0,1,null,e)),r._22(802816,null,0,g.j,[r._13,r._14,r.l],{ngForOf:[0,"ngForOf"]},null),(l()(),r._23(0,["\n "])),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,10,"button",[["class","mat-button mat-raised-button"],["color","accent"],["md-button",""],["md-raised-button",""]],[[8,"disabled",0]],null,null,m.n,m.o)),r._22(16384,null,0,f._15,[[2,f._16],r.Q],null,null),r._22(180224,null,0,f._35,[r._25,r.Q,f.b,f.l],{disabled:[0,"disabled"],color:[1,"color"]},null),r._22(16384,null,0,f._18,[],null,null),r._22(16384,null,0,f._20,[],null,null),(l()(),r._23(0,["\n "])),(l()(),r._21(0,null,0,3,"md-icon",[["class","mat-icon"],["role","img"]],null,null,null,m.h,m.i)),r._22(16384,null,0,f._15,[[2,f._16],r.Q],null,null),r._22(638976,null,0,f._19,[r._25,r.Q,f.x,[8,null]],null,null),(l()(),r._23(0,["add_shopping_cart"])),(l()(),r._23(0,[" ADD TO CART\n "])),(l()(),r._23(null,["\n "])),(l()(),r._23(null,["\n "])),(l()(),r._23(null,["\n"]))],function(l,n){var u=n.component;l(n,5,0,u.loop,u.delay),l(n,8,0,u.item.photos),l(n,36,0,u.cartForm);l(n,43,0,"item",u.item);l(n,49,0,"quantity");l(n,51,0,"Quantity"),l(n,57,0,u.numbers);l(n,65,0,!u.cartForm.valid,"accent"),l(n,71,0)},function(l,n){var u=n.component;l(n,15,0,u.item.name),l(n,18,0,r._44(n,18,0,l(n,19,0,r._24(n.parent,0),u.item.price,u.USD,!0))),l(n,23,0,r._44(n,23,0,l(n,24,0,r._24(n.parent,0),u.item.old_price,u.USD,!0))),l(n,31,0,u.item.availability),l(n,34,0,r._24(n,38).ngClassUntouched,r._24(n,38).ngClassTouched,r._24(n,38).ngClassPristine,r._24(n,38).ngClassDirty,r._24(n,38).ngClassValid,r._24(n,38).ngClassInvalid,r._24(n,38).ngClassPending),l(n,40,0,r._24(n,45).ngClassUntouched,r._24(n,45).ngClassTouched,r._24(n,45).ngClassPristine,r._24(n,45).ngClassDirty,r._24(n,45).ngClassValid,r._24(n,45).ngClassInvalid,r._24(n,45).ngClassPending),l(n,47,1,[r._24(n,51).tabIndex,r._24(n,51)._ariaLabel,r._24(n,51).ariaLabelledby,r._24(n,51).required.toString(),r._24(n,51).disabled.toString(),(null==r._24(n,51)._control?null:r._24(n,51)._control.invalid)||"false",r._24(n,51)._optionIds,r._24(n,51).disabled,r._24(n,54).ngClassUntouched,r._24(n,54).ngClassTouched,r._24(n,54).ngClassPristine,r._24(n,54).ngClassDirty,r._24(n,54).ngClassValid,r._24(n,54).ngClassInvalid,r._24(n,54).ngClassPending]),l(n,63,0,r._24(n,65).disabled||null)})}function i(l){return r._20(0,[r._42(0,g.s,[r.h]),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._23(null,["\n"])),(l()(),r._21(0,null,null,3,"div",[],null,null,null,null,null)),(l()(),r._21(0,null,null,2,"a",[["routerLink","/items"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==r._24(l,5).onClick(u.button,u.ctrlKey,u.metaKey,u.shiftKey)&&t}return t},null,null)),r._22(671744,null,0,v.x,[v.c,v.a,g.e],{routerLink:[0,"routerLink"]},null),(l()(),r._23(null,["Back to items"])),(l()(),r._23(null,["\n"])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._23(null,["\n"])),(l()(),r._26(16777216,null,null,1,null,_)),r._22(16384,null,0,g.k,[r._13,r._14],{ngIf:[0,"ngIf"]},null),(l()(),r._23(null,["\n"])),(l()(),r._21(0,null,null,11,"div",[["class","row"]],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,8,"div",[["class","col-xs-12"]],null,null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),r._21(0,null,null,2,"small",[],null,null,null,null,null)),(l()(),r._21(0,null,null,1,"b",[],null,null,null,null,null)),(l()(),r._23(null,["Description:"])),(l()(),r._23(null,["\n "])),(l()(),r._21(0,null,null,0,"p",[],[[8,"innerHTML",1]],null,null,null,null)),(l()(),r._23(null,["\n "])),(l()(),r._23(null,["\n"])),(l()(),r._23(null,["\n"])),(l()(),r._21(0,null,null,0,"br",[],null,null,null,null,null))],function(l,n){var u=n.component;l(n,5,0,"/items"),l(n,11,0,u.item)},function(l,n){var u=n.component;l(n,4,0,r._24(n,5).target,r._24(n,5).href),l(n,22,0,r._37(1,"",u.item.description,""))})}function a(l){return r._20(0,[(l()(),r._21(0,null,null,1,"apfem-item-details",[],null,null,null,i,x)),r._22(114688,null,0,h.a,[v.a,y.a,f.z,k.a],null,null)],function(l,n){l(n,1,0)},null)}var o=u("gqZg"),r=u("3j3K"),d=u("7pch"),c=u("BkHY"),s=u("4fdy"),m=u("ZWsw"),f=u("fYnu"),g=u("2Je8"),p=u("4BHv"),b=u("NVOs"),v=u("5oXY"),h=u("xf8J"),y=u("r1Ir"),k=u("L+Ae");u.d(n,"a",function(){return Q});var C=[o.a],x=r._19({encapsulation:0,styles:C,data:{}}),Q=r._27("apfem-item-details",h.a,a,{},{},[])},uRPH:function(l,n,u){"use strict";var t=u("4ppr");u.d(n,"a",function(){return e});var e=(t.b,t.c,t.d,function(){function l(){}return l}())},vHjS:function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=[""]},vZf8:function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=[""]}}); -------------------------------------------------------------------------------- /docs/1.aa7a59fc8f79e7c15bbf.chunk.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],{"1ZB8":function(l,n,u){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=u("3j3K"),e=u("e4e+"),a=u("4Kkw"),i=u("ZWsw"),_=u("2Je8"),r=u("fYnu"),o=u("NVOs"),d=u("Fzro"),c=u("Qbdm"),s=u("5oXY"),m=u("sUip"),f=u("6Bwb");u.d(n,"CartModuleNgFactory",function(){return g});var g=t.b(e.a,[],function(l){return t.c([t.d(512,t.e,t.f,[[8,[a.a,i.a,i.b,i.c,i.d,i.e]],[3,t.e],t.g]),t.d(4608,_.a,_.b,[t.h]),t.d(4608,r.b,r.b,[]),t.d(5120,r.c,r.d,[[3,r.c],t.q,r.b]),t.d(5120,r.e,r.f,[[3,r.e],r.c]),t.d(4608,r.g,r.g,[r.c,r.e]),t.d(5120,r.h,r.i,[[3,r.h]]),t.d(4608,r.j,r.j,[r.e]),t.d(4608,r.k,r.k,[r.g,r.h,t.e,r.j,t.x,t.v,t.q]),t.d(5120,r.l,r.m,[[3,r.l],t.q,r.b]),t.d(4608,o.a,o.a,[]),t.d(5120,r.n,r.o,[[3,r.n]]),t.d(4608,r.p,r.p,[]),t.d(4608,r.q,r.q,[r.b]),t.d(4608,r.r,r.r,[r.q,r.b,t.q]),t.d(5120,r.s,r.t,[[3,r.s],[2,r.u],r.b]),t.d(4608,r.v,r.v,[r.k,t.v,[2,_.c],[3,r.v]]),t.d(4608,r.w,r.w,[]),t.d(5120,r.x,r.y,[[3,r.x],[2,d.i],c.b]),t.d(4608,c.e,r.a,[]),t.d(4608,r.z,r.z,[r.k,r.s,[3,r.z]]),t.d(4608,o.d,o.d,[]),t.d(512,_.d,_.d,[]),t.d(512,s.w,s.w,[[2,s.m],[2,s.c]]),t.d(512,m.a,m.a,[]),t.d(512,r.A,r.A,[]),t.d(256,r.B,!0,[]),t.d(512,r.C,r.C,[[2,c.d],[2,r.B]]),t.d(512,r.D,r.D,[]),t.d(512,r.E,r.E,[]),t.d(512,r.F,r.F,[]),t.d(512,r.G,r.G,[]),t.d(512,r.H,r.H,[]),t.d(512,r.I,r.I,[]),t.d(512,r.J,r.J,[]),t.d(512,r.K,r.K,[]),t.d(512,r.L,r.L,[]),t.d(512,r.M,r.M,[]),t.d(512,o.b,o.b,[]),t.d(512,o.c,o.c,[]),t.d(512,r.N,r.N,[]),t.d(512,r.O,r.O,[]),t.d(512,r.P,r.P,[]),t.d(512,r.Q,r.Q,[]),t.d(512,r.R,r.R,[]),t.d(512,r.S,r.S,[]),t.d(512,r.T,r.T,[]),t.d(512,r.U,r.U,[]),t.d(512,r.V,r.V,[]),t.d(512,r.W,r.W,[]),t.d(512,r.X,r.X,[]),t.d(512,r.Y,r.Y,[]),t.d(512,r.Z,r.Z,[]),t.d(512,r._0,r._0,[]),t.d(512,r._1,r._1,[]),t.d(512,r._2,r._2,[]),t.d(512,r._3,r._3,[]),t.d(512,r._4,r._4,[]),t.d(512,r._5,r._5,[]),t.d(512,r._6,r._6,[]),t.d(512,r._7,r._7,[]),t.d(512,r._8,r._8,[]),t.d(512,r._9,r._9,[]),t.d(512,r._10,r._10,[]),t.d(512,r._11,r._11,[]),t.d(512,r._12,r._12,[]),t.d(512,r._13,r._13,[]),t.d(512,r._14,r._14,[]),t.d(512,o.e,o.e,[]),t.d(512,e.a,e.a,[]),t.d(1024,s.r,function(){return[[{path:"",component:f.a}]]},[])])})},"3fiE":function(l,n,u){"use strict";var t=u("NVOs");u.d(n,"a",function(){return e});var e=function(){function l(){this.numbers=[{value:1,display:"One"},{value:2,display:"Two"},{value:3,display:"Three"},{value:4,display:"Four"},{value:5,display:"Five"}],this.updateCartForm=new t.l({item:new t.m("",t.k.required),quantity:new t.m("",t.k.required)})}return l.prototype.onUpdateCart=function(){console.log(this.updateCartForm.value)},l.prototype.ngOnInit=function(){},l.ctorParameters=function(){return[]},l}()},"4Kkw":function(l,n,u){"use strict";function t(l){return o._20(0,[(l()(),o._21(0,null,null,2,"apfem-cart-item",[["class","cart-wrapper"]],null,null,null,d.a,d.b)),o._22(114688,null,0,c.a,[],{cartItem:[0,"cartItem"]},null),(l()(),o._23(null,["\n "]))],function(l,n){l(n,1,0,n.context.$implicit)},null)}function e(l){return o._20(0,[(l()(),o._21(0,null,null,31,"div",[["class","row center-xs"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,12,"div",[["class","col-xs-12 col-sm-6"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,9,"a",[["class","mat-button"],["color","accent"],["md-button",""],["routerLink","/items"]],[[1,"target",0],[8,"href",4],[1,"disabled",0],[1,"aria-disabled",0],[8,"tabIndex",0]],[[null,"click"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==o._24(l,5).onClick(u.button,u.ctrlKey,u.metaKey,u.shiftKey)&&t}if("click"===n){t=!1!==o._24(l,7)._haltDisabledEvents(u)&&t}return t},s.f,s.g)),o._22(671744,null,0,m.x,[m.c,m.a,f.e],{routerLink:[0,"routerLink"]},null),o._22(16384,null,0,g._15,[[2,g._16],o.Q],null,null),o._22(180224,null,0,g._17,[g.b,g.l,o.Q,o._25],{color:[0,"color"]},null),o._22(16384,null,0,g._18,[],null,null),(l()(),o._21(0,null,0,3,"md-icon",[["class","mat-icon"],["role","img"]],null,null,null,s.h,s.i)),o._22(16384,null,0,g._15,[[2,g._16],o.Q],null,null),o._22(638976,null,0,g._19,[o._25,o.Q,g.x,[8,null]],null,null),(l()(),o._23(0,["keyboard_arrow_left"])),(l()(),o._23(0,[" CONTINUE SHOPPING"])),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),o._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),o._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,11,"div",[["class","col-xs-12 col-sm-6"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,8,"a",[["class","mat-raised-button"],["color","primary"],["href","javascript:;"],["md-raised-button",""]],[[1,"disabled",0],[1,"aria-disabled",0],[8,"tabIndex",0]],[[null,"click"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==o._24(l,23)._haltDisabledEvents(u)&&t}return t},s.f,s.g)),o._22(16384,null,0,g._15,[[2,g._16],o.Q],null,null),o._22(180224,null,0,g._17,[g.b,g.l,o.Q,o._25],{color:[0,"color"]},null),o._22(16384,null,0,g._20,[],null,null),(l()(),o._23(0,["CHECK OUT"])),(l()(),o._21(0,null,0,3,"md-icon",[["class","mat-icon"],["role","img"]],null,null,null,s.h,s.i)),o._22(16384,null,0,g._15,[[2,g._16],o.Q],null,null),o._22(638976,null,0,g._19,[o._25,o.Q,g.x,[8,null]],null,null),(l()(),o._23(0,["keyboard_arrow_right"])),(l()(),o._23(null,["\n "])),(l()(),o._23(null,["\n "]))],function(l,n){l(n,5,0,"/items");l(n,7,0,"accent"),l(n,11,0);l(n,23,0,"primary"),l(n,28,0)},function(l,n){l(n,4,0,o._24(n,5).target,o._24(n,5).href,o._24(n,7).disabled||null,o._24(n,7)._isAriaDisabled,o._24(n,7).tabIndex),l(n,21,0,o._24(n,23).disabled||null,o._24(n,23)._isAriaDisabled,o._24(n,23).tabIndex)})}function a(l){return o._20(0,[(l()(),o._21(0,null,null,8,"div",[["class","row center-xs"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,5,"a",[["class","mat-raised-button"],["color","primary"],["md-raised-button",""],["routerLink","/items"]],[[1,"target",0],[8,"href",4],[1,"disabled",0],[1,"aria-disabled",0],[8,"tabIndex",0]],[[null,"click"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==o._24(l,3).onClick(u.button,u.ctrlKey,u.metaKey,u.shiftKey)&&t}if("click"===n){t=!1!==o._24(l,5)._haltDisabledEvents(u)&&t}return t},s.f,s.g)),o._22(671744,null,0,m.x,[m.c,m.a,f.e],{routerLink:[0,"routerLink"]},null),o._22(16384,null,0,g._15,[[2,g._16],o.Q],null,null),o._22(180224,null,0,g._17,[g.b,g.l,o.Q,o._25],{color:[0,"color"]},null),o._22(16384,null,0,g._20,[],null,null),(l()(),o._23(0,["SHOPPING LIST"])),(l()(),o._23(null,["\n "]))],function(l,n){l(n,3,0,"/items");l(n,5,0,"primary")},function(l,n){l(n,2,0,o._24(n,3).target,o._24(n,3).href,o._24(n,5).disabled||null,o._24(n,5)._isAriaDisabled,o._24(n,5).tabIndex)})}function i(l){return o._20(0,[(l()(),o._21(0,null,null,22,"div",[["class","cart"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,19,"div",[["class","row center-xs"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,16,"div",[["class","col-xs-11 col-sm-8 col-md-6"]],null,null,null,null,null)),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,1,"h3",[],null,null,null,null,null)),(l()(),o._23(null,["My Cart"])),(l()(),o._23(null,["\n "])),(l()(),o._21(0,null,null,1,"small",[],null,null,null,null,null)),(l()(),o._23(null,["You have "," items in your basket"])),(l()(),o._23(null,["\n "])),(l()(),o._26(16777216,null,null,1,null,t)),o._22(802816,null,0,f.j,[o._13,o._14,o.l],{ngForOf:[0,"ngForOf"]},null),(l()(),o._23(null,["\n "])),(l()(),o._26(16777216,null,null,1,null,e)),o._22(16384,null,0,f.k,[o._13,o._14],{ngIf:[0,"ngIf"]},null),(l()(),o._23(null,["\n "])),(l()(),o._26(16777216,null,null,1,null,a)),o._22(16384,null,0,f.k,[o._13,o._14],{ngIf:[0,"ngIf"]},null),(l()(),o._23(null,["\n "])),(l()(),o._23(null,["\n "])),(l()(),o._23(null,["\n"]))],function(l,n){var u=n.component;l(n,13,0,u.cart),l(n,16,0,u.cart.length>=1),l(n,19,0,u.cart.length<1)},function(l,n){l(n,10,0,n.component.cart.length)})}function _(l){return o._20(0,[(l()(),o._26(16777216,null,null,1,null,i)),o._22(16384,null,0,f.k,[o._13,o._14],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,1,0,n.component.cart)},null)}function r(l){return o._20(0,[(l()(),o._21(0,null,null,1,"apfem-cart",[],null,null,null,_,h)),o._22(114688,null,0,b.a,[p.a],null,null)],function(l,n){l(n,1,0)},null)}var o=u("3j3K"),d=u("XsFK"),c=u("3fiE"),s=u("ZWsw"),m=u("5oXY"),f=u("2Je8"),g=u("fYnu"),b=u("6Bwb"),p=u("L+Ae");u.d(n,"a",function(){return y});var v=[".cart[_ngcontent-%COMP%]{min-height:500px;}"],h=o._19({encapsulation:0,styles:v,data:{}}),y=o._27("apfem-cart",b.a,r,{},{},[])},XsFK:function(l,n,u){"use strict";function t(l){return _._20(0,[(l()(),_._21(0,null,null,6,"div",[["class","col-xs-5"]],null,null,null,null,null)),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,3,"div",[["class","item-img"]],null,null,null,null,null)),_._22(278528,null,0,r.p,[_.n,_.Q,_.P],{ngStyle:[0,"ngStyle"]},null),_._41(["background","background-repeat","background-size","width","min-height","background-position","color"]),(l()(),_._23(null,["\n "])),(l()(),_._23(null,["\n "]))],function(l,n){l(n,3,0,l(n,4,0,"white url("+n.component.cartItem.val.item.photos[0].path+")","no-repeat","cover","auto","200px","center center","#FFF"))},null)}function e(l){return _._20(0,[(l()(),_._21(0,null,null,3,"md-option",[["class","mat-option"],["role","option"]],[[1,"tabindex",0],[2,"mat-selected",null],[2,"mat-option-multiple",null],[2,"mat-active",null],[8,"id",0],[1,"aria-selected",0],[1,"aria-disabled",0],[2,"mat-option-disabled",null]],[[null,"click"],[null,"keydown"]],function(l,n,u){var t=!0;if("click"===n){t=!1!==_._24(l,1)._selectViaInteraction()&&t}if("keydown"===n){t=!1!==_._24(l,1)._handleKeydown(u)&&t}return t},o.j,o.k)),_._22(49152,[[1,4]],0,d._32,[_.Q,[2,d._33],[2,d._16]],{value:[0,"value"]},null),_._22(16384,null,0,d._15,[[2,d._16],_.Q],null,null),(l()(),_._23(0,["\n ","\n "]))],function(l,n){l(n,1,0,n.context.$implicit.value)},function(l,n){l(n,0,0,_._24(n,1)._getTabIndex(),_._24(n,1).selected,_._24(n,1).multiple,_._24(n,1).active,_._24(n,1).id,_._24(n,1).selected.toString(),_._24(n,1).disabled.toString(),_._24(n,1).disabled),l(n,3,0,n.context.$implicit.display)})}function a(l){return _._20(0,[_._42(0,r.s,[_.h]),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,62,"div",[["class","row cart-wrapper"]],null,null,null,null,null)),(l()(),_._23(null,["\n "])),(l()(),_._26(16777216,null,null,1,null,t)),_._22(16384,null,0,r.k,[_._13,_._14],{ngIf:[0,"ngIf"]},null),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,56,"div",[["class","col-xs-7 start-xs"]],null,null,null,null,null)),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,1,"h4",[],null,null,null,null,null)),(l()(),_._23(null,["",""])),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,7,"p",[],null,null,null,null,null)),(l()(),_._21(0,null,null,2,"small",[],null,null,null,null,null)),(l()(),_._23(null,["",""])),_._43(3),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,2,"small",[["class","old-price"]],null,null,null,null,null)),(l()(),_._23(null,["",""])),_._43(3),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,41,"form",[["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngSubmit"],[null,"submit"],[null,"reset"]],function(l,n,u){var t=!0,e=l.component;if("submit"===n){t=!1!==_._24(l,23).onSubmit(u)&&t}if("reset"===n){t=!1!==_._24(l,23).onReset()&&t}if("ngSubmit"===n){t=!1!==e.onUpdateCart()&&t}return t},null,null)),_._22(16384,null,0,s.n,[],null,null),_._22(540672,null,0,s.i,[[8,null],[8,null]],{form:[0,"form"]},{ngSubmit:"ngSubmit"}),_._36(2048,null,s.o,null,[s.i]),_._22(16384,null,0,s.p,[s.o],null,null),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,5,"input",[["formControlName","item"],["type","hidden"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0,e=l.component;if("input"===n){t=!1!==_._24(l,28)._handleInput(u.target.value)&&t}if("blur"===n){t=!1!==_._24(l,28).onTouched()&&t}if("compositionstart"===n){t=!1!==_._24(l,28)._compositionStart()&&t}if("compositionend"===n){t=!1!==_._24(l,28)._compositionEnd(u.target.value)&&t}if("ngModelChange"===n){t=!1!==(e.cartItem.val.item=u)&&t}return t},null,null)),_._22(16384,null,0,s.q,[_.P,_.Q,[2,s.r]],null,null),_._36(1024,null,s.f,function(l){return[l]},[s.q]),_._22(671744,null,0,s.s,[[3,s.o],[8,null],[8,null],[2,s.f]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),_._36(2048,null,s.g,null,[s.s]),_._22(16384,null,0,s.t,[s.g],null,null),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,11,"md-select",[["class","mat-select"],["formControlName","quantity"],["placeholder","Quantity"],["role","listbox"]],[[1,"tabindex",0],[1,"aria-label",0],[1,"aria-labelledby",0],[1,"aria-required",0],[1,"aria-disabled",0],[1,"aria-invalid",0],[1,"aria-owns",0],[2,"mat-select-disabled",null],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"keydown"],[null,"blur"]],function(l,n,u){var t=!0,e=l.component;if("keydown"===n){t=!1!==_._24(l,38)._handleClosedKeydown(u)&&t}if("blur"===n){t=!1!==_._24(l,38)._onBlur()&&t}if("ngModelChange"===n){t=!1!==(e.cartItem.val.quantity=u)&&t}return t},o.l,o.m)),_._22(16384,null,0,d._15,[[2,d._16],_.Q],null,null),_._22(671744,null,0,s.s,[[3,s.o],[8,null],[8,null],[8,null]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),_._36(2048,null,s.g,null,[s.s]),_._22(1294336,null,2,d._79,[d.e,_._18,_._25,_.Q,[2,d._54],[2,s.g],[8,null],[2,d._66]],{placeholder:[0,"placeholder"]},null),_._35(603979776,1,{options:1}),_._35(603979776,2,{optionGroups:1}),_._22(16384,null,0,s.t,[s.g],null,null),(l()(),_._23(0,["\n "])),(l()(),_._26(16777216,null,0,1,null,e)),_._22(802816,null,0,r.j,[_._13,_._14,_.l],{ngForOf:[0,"ngForOf"]},null),(l()(),_._23(0,["\n "])),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,12,"p",[],null,null,null,null,null)),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,2,"small",[],null,null,null,null,null)),(l()(),_._23(null,["Sub-Total: ",""])),_._43(3),(l()(),_._23(null,["\n    \n "])),(l()(),_._21(0,null,null,5,"button",[["class","mat-button mat-raised-button"],["color","accent"],["md-button",""],["md-raised-button",""]],[[8,"disabled",0]],null,null,o.n,o.o)),_._22(16384,null,0,d._15,[[2,d._16],_.Q],null,null),_._22(180224,null,0,d._35,[_._25,_.Q,d.b,d.l],{disabled:[0,"disabled"],color:[1,"color"]},null),_._22(16384,null,0,d._18,[],null,null),_._22(16384,null,0,d._20,[],null,null),(l()(),_._23(0,["\n UPDATE CART\n "])),(l()(),_._23(null,["\n "])),(l()(),_._23(null,["\n "])),(l()(),_._23(null,["\n "])),(l()(),_._23(null,["\n "])),(l()(),_._23(null,["\n "])),(l()(),_._21(0,null,null,0,"br",[],null,null,null,null,null)),(l()(),_._23(null,["\n "]))],function(l,n){var u=n.component;l(n,5,0,u.cartItem),l(n,23,0,u.updateCartForm);l(n,30,0,"item",u.cartItem.val.item);l(n,36,0,"quantity",u.cartItem.val.quantity);l(n,38,0,"Quantity"),l(n,44,0,u.numbers);l(n,57,0,u.updateCartForm.pristine,"accent")},function(l,n){var u=n.component;l(n,10,0,u.cartItem.val.item.name),l(n,14,0,_._44(n,14,0,l(n,15,0,_._24(n,0),u.cartItem.val.item.price,"USD",!0))),l(n,18,0,_._44(n,18,0,l(n,19,0,_._24(n,0),u.cartItem.val.item.old_price,"USD",!0))),l(n,21,0,_._24(n,25).ngClassUntouched,_._24(n,25).ngClassTouched,_._24(n,25).ngClassPristine,_._24(n,25).ngClassDirty,_._24(n,25).ngClassValid,_._24(n,25).ngClassInvalid,_._24(n,25).ngClassPending),l(n,27,0,_._24(n,32).ngClassUntouched,_._24(n,32).ngClassTouched,_._24(n,32).ngClassPristine,_._24(n,32).ngClassDirty,_._24(n,32).ngClassValid,_._24(n,32).ngClassInvalid,_._24(n,32).ngClassPending),l(n,34,1,[_._24(n,38).tabIndex,_._24(n,38)._ariaLabel,_._24(n,38).ariaLabelledby,_._24(n,38).required.toString(),_._24(n,38).disabled.toString(),(null==_._24(n,38)._control?null:_._24(n,38)._control.invalid)||"false",_._24(n,38)._optionIds,_._24(n,38).disabled,_._24(n,41).ngClassUntouched,_._24(n,41).ngClassTouched,_._24(n,41).ngClassPristine,_._24(n,41).ngClassDirty,_._24(n,41).ngClassValid,_._24(n,41).ngClassInvalid,_._24(n,41).ngClassPending]),l(n,52,0,_._44(n,52,0,l(n,53,0,_._24(n,0),u.cartItem.val.quantity*u.cartItem.val.item.price,"USD",!0))),l(n,55,0,_._24(n,57).disabled||null)})}function i(l){return _._20(0,[(l()(),_._21(0,null,null,1,"apfem-cart-item",[],null,null,null,a,f)),_._22(114688,null,0,c.a,[],null,null)],function(l,n){l(n,1,0)},null)}var _=u("3j3K"),r=u("2Je8"),o=u("ZWsw"),d=u("fYnu"),c=u("3fiE"),s=u("NVOs");u.d(n,"b",function(){return f}),n.a=a;var m=[".cart-wrapper[_ngcontent-%COMP%]{border:1px solid #eee; background-color:#fff; border-radius:4px;}"],f=_._19({encapsulation:0,styles:m,data:{}});_._27("apfem-cart-item",c.a,i,{cartItem:"cartItem"},{},[])},"e4e+":function(l,n,u){"use strict";u.d(n,"a",function(){return t});var t=function(){function l(){}return l}()},sUip:function(l,n,u){"use strict";var t=u("RQxm");u.d(n,"a",function(){return e});var e=(t.b,function(){function l(){}return l}())}}); -------------------------------------------------------------------------------- /docs/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/docs/assets/bg.jpg -------------------------------------------------------------------------------- /docs/bg.e88a2d4544db10e6bdcf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/docs/bg.e88a2d4544db10e6bdcf.jpg -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APFEM SHOP 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/inline.4f04594155dcd0da1dd8.bundle.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var n=window.webpackJsonp;window.webpackJsonp=function(t,a,c){for(var u,i,f,d=0,l=[];dthis.getCurrentIndex()?u.NEXT:u.PREV),n&&n!==this.currentSlide&&this.goNext(n,l)},n.prototype.goNext=function(n,l){this.destroyed||(n.direction=l,n.active=!0,this.currentSlide&&(this.currentSlide.direction=l,this.currentSlide.active=!1),this.currentSlide=n,this.restartTimer())},n.prototype.getSlideByIndex=function(n){for(var l=this.slides.length,t=0;t0&&(this.currentInterval=setInterval(function(){var l=+n.interval;n.isPlaying&&!isNaN(n.interval)&&l>0&&n.slides.length?n.next():n.pause()},l))},n.prototype.resetTimer=function(){this.currentInterval&&(clearInterval(this.currentInterval),this.currentInterval=null)},n.prototype.play=function(){this.isPlaying||(this.isPlaying=!0,this.restartTimer())},n.prototype.pause=function(){this.noPause||(this.isPlaying=!1,this.resetTimer())},n.prototype.addSlide=function(n){n.index=this.slides.length,this.slides.push(n),1===this.slides.length||n.active?(this.select(this.slides[this.slides.length-1]),1===this.slides.length&&this.play()):n.active=!1},n.prototype.removeSlide=function(n){if(this.slides.splice(n.index,1),0===this.slides.length)return void(this.currentSlide=null);for(var l=0;l.item{display:none;position:relative;transition:left .6s ease-in-out}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.8)}.carousel-control.right{left:auto;right:0}.carousel-control:focus,.carousel-control:hover{outline:none;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203A"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000\9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}.carousel-icon{font-size:5vmin;cursor:pointer;width:auto!important;height:auto!important}.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(0,0,0,.14),0 9px 44px 8px rgba(0,0,0,.12)}.mat-elevation-z24{box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12)}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,Helvetica Neue,sans-serif;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,Helvetica Neue,sans-serif;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,Helvetica Neue,sans-serif;margin:0 0 16px}.mat-h5,.mat-typography h5{font-size:11.62px}.mat-h5,.mat-h6,.mat-typography h5,.mat-typography h6{font-weight:400;font-family:Roboto,Helvetica Neue,sans-serif;line-height:20px;margin:0 0 12px}.mat-h6,.mat-typography h6{font-size:9.38px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,Helvetica Neue,sans-serif}.mat-body,.mat-body-1,.mat-typography{font:400 14px/20px Roboto,Helvetica Neue,sans-serif}.mat-body-1 p,.mat-body p,.mat-typography p{margin:0 0 12px}.mat-caption,.mat-small{font:400 12px/20px Roboto,Helvetica Neue,sans-serif}.mat-display-4,.mat-typography .mat-display-4{font:300 112px/112px Roboto,Helvetica Neue,sans-serif;margin:0 0 56px;letter-spacing:-.05em}.mat-display-3,.mat-typography .mat-display-3{font:400 56px/56px Roboto,Helvetica Neue,sans-serif;margin:0 0 64px;letter-spacing:-.02em}.mat-display-2,.mat-typography .mat-display-2{font:400 45px/48px Roboto,Helvetica Neue,sans-serif;margin:0 0 64px;letter-spacing:-.005em}.mat-display-1,.mat-typography .mat-display-1{font:400 34px/40px Roboto,Helvetica Neue,sans-serif;margin:0 0 64px}.mat-button,.mat-icon-button,.mat-raised-button{font-family:Roboto,Helvetica Neue,sans-serif;font-size:14px;font-weight:500}.mat-button-toggle,.mat-card{font-family:Roboto,Helvetica Neue,sans-serif}.mat-card-title{font-size:24px;font-weight:400}.mat-card-content,.mat-card-header .mat-card-title,.mat-card-subtitle{font-size:14px}.mat-checkbox{font-family:Roboto,Helvetica Neue,sans-serif}.mat-checkbox-layout .mat-checkbox-label{line-height:24px}.mat-chip:not(.mat-basic-chip){font-size:13px;line-height:16px}.mat-calendar{font-family:Roboto,Helvetica Neue,sans-serif}.mat-calendar-body{font-size:13px}.mat-calendar-body-label,.mat-calendar-period-button{font-size:14px;font-weight:500}.mat-calendar-table-header th{font-size:11px;font-weight:400}.mat-dialog-title{font:500 20px/32px Roboto,Helvetica Neue,sans-serif}.mat-grid-tile-footer,.mat-grid-tile-header{font-size:14px}.mat-grid-tile-footer .mat-line,.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2),.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:12px}.mat-input-container{font:400 inherit/1.125 Roboto,Helvetica Neue,sans-serif}.mat-input-wrapper{padding-bottom:1.296875em}.mat-input-prefix .mat-datepicker-toggle,.mat-input-prefix .mat-icon,.mat-input-suffix .mat-datepicker-toggle,.mat-input-suffix .mat-icon{font-size:150%}.mat-input-prefix .mat-icon-button,.mat-input-suffix .mat-icon-button{height:1.5em;width:1.5em}.mat-input-prefix .mat-icon-button .mat-icon,.mat-input-suffix .mat-icon-button .mat-icon{line-height:1.5}.mat-input-infix{padding:.4375em 0;border-top:.84375em solid transparent}.mat-input-element:-webkit-autofill+.mat-input-placeholder-wrapper .mat-float{-webkit-transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);-ms-transform:translateY(-1.28125em) scale(.75);width:133.33333333%}.mat-input-placeholder-wrapper{top:-.84375em;padding-top:.84375em}.mat-input-placeholder{top:1.28125em}.mat-focused .mat-input-placeholder.mat-float,.mat-input-placeholder.mat-float:not(.mat-empty){-webkit-transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);-ms-transform:translateY(-1.28125em) scale(.75);width:133.33333333%}.mat-input-underline{bottom:1.296875em}.mat-input-subscript-wrapper{font-size:75%;margin-top:.60416667em;top:calc(100% - 1.72916667em)}.mat-menu-item{font-size:16px}.mat-menu-item,.mat-radio-button,.mat-select{font-family:Roboto,Helvetica Neue,sans-serif}.mat-select-trigger{font-size:16px}.mat-slide-toggle-content{font:400 14px/20px Roboto,Helvetica Neue,sans-serif}.mat-slider-thumb-label-text{font-size:12px;font-weight:500}.mat-tab-group,.mat-tab-label,.mat-tab-link{font-family:Roboto,Helvetica Neue,sans-serif}.mat-tab-label,.mat-tab-link{font-size:14px;font-weight:500}.mat-toolbar,.mat-toolbar h1,.mat-toolbar h2,.mat-toolbar h3,.mat-toolbar h4,.mat-toolbar h5,.mat-toolbar h6{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;margin:0}.mat-tooltip{font-size:10px;padding-top:6px;padding-bottom:6px}.mat-list-item,.mat-tooltip{font-family:Roboto,Helvetica Neue,sans-serif}.mat-list .mat-list-item,.mat-nav-list .mat-list-item{font-size:16px}.mat-list .mat-list-item .mat-line,.mat-nav-list .mat-list-item .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list .mat-list-item .mat-line:nth-child(n+2),.mat-nav-list .mat-list-item .mat-line:nth-child(n+2){font-size:14px}.mat-list .mat-subheader,.mat-nav-list .mat-subheader{font:500 14px/24px Roboto,Helvetica Neue,sans-serif}.mat-list[dense] .mat-list-item,.mat-nav-list[dense] .mat-list-item{font-size:12px}.mat-list[dense] .mat-list-item .mat-line,.mat-nav-list[dense] .mat-list-item .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list[dense] .mat-list-item .mat-line:nth-child(n+2),.mat-nav-list[dense] .mat-list-item .mat-line:nth-child(n+2){font-size:12px}.mat-list[dense] .mat-subheader,.mat-nav-list[dense] .mat-subheader{font:500 12px Roboto,Helvetica Neue,sans-serif}.mat-option{font-size:16px}.mat-option,.mat-simple-snackbar{font-family:Roboto,Helvetica Neue,sans-serif}.mat-simple-snackbar{font-size:14px}.mat-simple-snackbar-action{line-height:1;font-family:inherit;font-size:inherit;font-weight:500}.mat-ripple{overflow:hidden}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,-webkit-transform 0ms cubic-bezier(0,0,.2,1);transition:opacity,transform 0ms cubic-bezier(0,0,.2,1);transition:opacity,transform 0ms cubic-bezier(0,0,.2,1),-webkit-transform 0ms cubic-bezier(0,0,.2,1);-webkit-transform:scale(0);transform:scale(0)}.mat-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;position:relative;cursor:pointer;outline:none}.mat-option[disabled]{cursor:default}[dir=rtl] .mat-option{text-align:right}.mat-option .mat-icon{margin-right:16px}[dir=rtl] .mat-option .mat-icon{margin-left:16px;margin-right:0}.mat-option[aria-disabled=true]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:32px}[dir=rtl] .mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:16px;padding-right:32px}.mat-option-ripple{position:absolute;top:0;left:0;bottom:0;right:0;pointer-events:none}@media screen and (-ms-high-contrast:active){.mat-option-ripple{opacity:.5}}.mat-option-pseudo-checkbox{margin-right:8px}[dir=rtl] .mat-option-pseudo-checkbox{margin-left:8px;margin-right:0}.mat-optgroup-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default;font-weight:700;font-size:14px}.mat-optgroup-label[disabled]{cursor:default}[dir=rtl] .mat-optgroup-label{text-align:right}.mat-optgroup-label .mat-icon{margin-right:16px}[dir=rtl] .mat-optgroup-label .mat-icon{margin-left:16px;margin-right:0}.cdk-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;text-transform:none;width:1px}.cdk-global-overlay-wrapper,.cdk-overlay-container{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-global-overlay-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{box-sizing:border-box}.cdk-overlay-backdrop,.cdk-overlay-pane{position:absolute;pointer-events:auto;z-index:1000}.cdk-overlay-backdrop{top:0;bottom:0;left:0;right:0;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.48}.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.6)}.cdk-overlay-transparent-backdrop{background:none}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.mat-ripple-element{background-color:rgba(0,0,0,.1)}.mat-option{color:rgba(0,0,0,.87)}.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:rgba(0,0,0,.04)}.mat-option.mat-selected.mat-primary,.mat-primary .mat-option.mat-selected{color:#e91e63}.mat-accent .mat-option.mat-selected,.mat-option.mat-selected.mat-accent{color:#ad1457}.mat-option.mat-selected.mat-warn,.mat-warn .mat-option.mat-selected{color:#f44336}.mat-option.mat-active,.mat-option.mat-selected:not(.mat-option-multiple){background:rgba(0,0,0,.04)}.mat-option.mat-active{color:rgba(0,0,0,.87)}.mat-option.mat-option-disabled{color:rgba(0,0,0,.38)}.mat-optgroup-label{color:rgba(0,0,0,.54)}.mat-optgroup-disabled .mat-optgroup-label{color:rgba(0,0,0,.38)}.mat-pseudo-checkbox{color:rgba(0,0,0,.54)}.mat-pseudo-checkbox:after{color:#fafafa}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked.mat-primary,.mat-pseudo-checkbox-indeterminate.mat-primary{background:#e91e63}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked.mat-accent,.mat-pseudo-checkbox-indeterminate.mat-accent{background:#ad1457}.mat-pseudo-checkbox-checked.mat-warn,.mat-pseudo-checkbox-indeterminate.mat-warn,.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#b0b0b0}.mat-app-background{background-color:#fafafa}.mat-theme-loaded-marker{display:none}.mat-autocomplete-panel,.mat-autocomplete-panel .mat-option.mat-selected:not(.mat-active):not(:hover){background:#fff;color:rgba(0,0,0,.87)}.mat-button,.mat-icon-button{background:transparent}.mat-button.mat-primary .mat-button-focus-overlay,.mat-icon-button.mat-primary .mat-button-focus-overlay{background-color:rgba(233,30,99,.12)}.mat-button.mat-accent .mat-button-focus-overlay,.mat-icon-button.mat-accent .mat-button-focus-overlay{background-color:rgba(173,20,87,.12)}.mat-button.mat-warn .mat-button-focus-overlay,.mat-icon-button.mat-warn .mat-button-focus-overlay{background-color:rgba(244,67,54,.12)}.mat-button[disabled] .mat-button-focus-overlay,.mat-icon-button[disabled] .mat-button-focus-overlay{background-color:transparent}.mat-button.mat-primary,.mat-icon-button.mat-primary{color:#e91e63}.mat-button.mat-accent,.mat-icon-button.mat-accent{color:#ad1457}.mat-button.mat-warn,.mat-icon-button.mat-warn{color:#f44336}.mat-button.mat-accent[disabled],.mat-button.mat-primary[disabled],.mat-button.mat-warn[disabled],.mat-button[disabled][disabled],.mat-icon-button.mat-accent[disabled],.mat-icon-button.mat-primary[disabled],.mat-icon-button.mat-warn[disabled],.mat-icon-button[disabled][disabled]{color:rgba(0,0,0,.38)}.mat-fab,.mat-mini-fab,.mat-raised-button{color:rgba(0,0,0,.87);background-color:#fff}.mat-fab.mat-primary,.mat-mini-fab.mat-primary,.mat-raised-button.mat-primary{color:#fff}.mat-fab.mat-accent,.mat-mini-fab.mat-accent,.mat-raised-button.mat-accent{color:hsla(0,0%,100%,.87)}.mat-fab.mat-warn,.mat-mini-fab.mat-warn,.mat-raised-button.mat-warn{color:#fff}.mat-fab.mat-accent[disabled],.mat-fab.mat-primary[disabled],.mat-fab.mat-warn[disabled],.mat-fab[disabled][disabled],.mat-mini-fab.mat-accent[disabled],.mat-mini-fab.mat-primary[disabled],.mat-mini-fab.mat-warn[disabled],.mat-mini-fab[disabled][disabled],.mat-raised-button.mat-accent[disabled],.mat-raised-button.mat-primary[disabled],.mat-raised-button.mat-warn[disabled],.mat-raised-button[disabled][disabled]{color:rgba(0,0,0,.38)}.mat-fab.mat-primary,.mat-mini-fab.mat-primary,.mat-raised-button.mat-primary{background-color:#e91e63}.mat-fab.mat-accent,.mat-mini-fab.mat-accent,.mat-raised-button.mat-accent{background-color:#ad1457}.mat-fab.mat-warn,.mat-mini-fab.mat-warn,.mat-raised-button.mat-warn{background-color:#f44336}.mat-fab.mat-accent[disabled],.mat-fab.mat-primary[disabled],.mat-fab.mat-warn[disabled],.mat-fab[disabled][disabled],.mat-mini-fab.mat-accent[disabled],.mat-mini-fab.mat-primary[disabled],.mat-mini-fab.mat-warn[disabled],.mat-mini-fab[disabled][disabled],.mat-raised-button.mat-accent[disabled],.mat-raised-button.mat-primary[disabled],.mat-raised-button.mat-warn[disabled],.mat-raised-button[disabled][disabled]{background-color:rgba(0,0,0,.12)}.mat-fab.mat-accent .mat-ripple-element,.mat-fab.mat-primary .mat-ripple-element,.mat-fab.mat-warn .mat-ripple-element,.mat-mini-fab.mat-accent .mat-ripple-element,.mat-mini-fab.mat-primary .mat-ripple-element,.mat-mini-fab.mat-warn .mat-ripple-element,.mat-raised-button.mat-accent .mat-ripple-element,.mat-raised-button.mat-primary .mat-ripple-element,.mat-raised-button.mat-warn .mat-ripple-element{background-color:hsla(0,0%,100%,.2)}.mat-button.mat-primary .mat-ripple-element{background-color:rgba(233,30,99,.1)}.mat-button.mat-accent .mat-ripple-element{background-color:rgba(173,20,87,.1)}.mat-button.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.1)}.mat-icon-button.mat-primary .mat-ripple-element{background-color:rgba(233,30,99,.2)}.mat-icon-button.mat-accent .mat-ripple-element{background-color:rgba(173,20,87,.2)}.mat-icon-button.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.2)}.mat-button-toggle{color:rgba(0,0,0,.38)}.mat-button-toggle.cdk-focused .mat-button-toggle-focus-overlay{background-color:rgba(0,0,0,.06)}.mat-button-toggle-checked{background-color:#e0e0e0;color:#000}.mat-button-toggle-disabled{background-color:#eee;color:rgba(0,0,0,.38)}.mat-button-toggle-disabled.mat-button-toggle-checked{background-color:#bdbdbd}.mat-card{background:#fff;color:rgba(0,0,0,.87)}.mat-card-subtitle{color:rgba(0,0,0,.54)}.mat-checkbox-frame{border-color:rgba(0,0,0,.54)}.mat-checkbox-checkmark{fill:#fafafa}.mat-checkbox-checkmark-path{stroke:#fafafa!important}.mat-checkbox-mixedmark{background-color:#fafafa}.mat-checkbox-checked.mat-primary .mat-checkbox-background,.mat-checkbox-indeterminate.mat-primary .mat-checkbox-background{background-color:#e91e63}.mat-checkbox-checked.mat-accent .mat-checkbox-background,.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background{background-color:#ad1457}.mat-checkbox-checked.mat-warn .mat-checkbox-background,.mat-checkbox-indeterminate.mat-warn .mat-checkbox-background{background-color:#f44336}.mat-checkbox-disabled.mat-checkbox-checked .mat-checkbox-background,.mat-checkbox-disabled.mat-checkbox-indeterminate .mat-checkbox-background{background-color:#b0b0b0}.mat-checkbox-disabled:not(.mat-checkbox-checked) .mat-checkbox-frame{border-color:#b0b0b0}.mat-checkbox-disabled .mat-checkbox-label{color:#b0b0b0}.mat-checkbox:not(.mat-checkbox-disabled).mat-primary .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(233,30,99,.26)}.mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(173,20,87,.26)}.mat-checkbox:not(.mat-checkbox-disabled).mat-warn .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(244,67,54,.26)}.mat-chip:not(.mat-basic-chip){background-color:#e0e0e0;color:rgba(0,0,0,.87)}.mat-chip.mat-chip-selected:not(.mat-basic-chip){background-color:gray;color:hsla(0,0%,100%,.87)}.mat-chip.mat-chip-selected:not(.mat-basic-chip).mat-primary{background-color:#e91e63;color:#fff}.mat-chip.mat-chip-selected:not(.mat-basic-chip).mat-accent{background-color:#ad1457;color:hsla(0,0%,100%,.87)}.mat-chip.mat-chip-selected:not(.mat-basic-chip).mat-warn{background-color:#f44336;color:#fff}.mat-datepicker-content{background-color:#fff}.mat-calendar-arrow{border-top-color:rgba(0,0,0,.54)}.mat-calendar-next-button,.mat-calendar-previous-button{color:rgba(0,0,0,.54)}.mat-calendar-table-header{color:rgba(0,0,0,.38)}.mat-calendar-table-header-divider:after{background:rgba(0,0,0,.12)}.mat-calendar-body-label{color:rgba(0,0,0,.54)}.mat-calendar-body-cell-content{color:rgba(0,0,0,.87);border-color:transparent}.mat-calendar-body-disabled>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected){color:rgba(0,0,0,.38)}.cdk-keyboard-focused .mat-calendar-body-active>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected),:not(.mat-calendar-body-disabled):hover>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected){background-color:rgba(0,0,0,.04)}.mat-calendar-body-selected{background-color:#e91e63;color:#fff}.mat-calendar-body-disabled>.mat-calendar-body-selected{background-color:rgba(233,30,99,.4)}.mat-calendar-body-today:not(.mat-calendar-body-selected){border-color:rgba(0,0,0,.38)}.mat-calendar-body-today.mat-calendar-body-selected{box-shadow:inset 0 0 0 1px #fff}.mat-calendar-body-disabled>.mat-calendar-body-today:not(.mat-calendar-body-selected){border-color:rgba(0,0,0,.18)}.mat-dialog-container{background:#fff;color:rgba(0,0,0,.87)}.mat-expansion-panel{background:#fff;color:#000}.mat-action-row{border-top-color:rgba(0,0,0,.12)}.mat-expansion-panel-header:focus,.mat-expansion-panel-header:hover{background:rgba(0,0,0,.04)}.mat-expansion-panel-header-title{color:rgba(0,0,0,.87)}.mat-expansion-indicator:after,.mat-expansion-panel-header-description{color:rgba(0,0,0,.54)}.mat-icon.mat-primary{color:#e91e63}.mat-icon.mat-accent{color:#ad1457}.mat-icon.mat-warn{color:#f44336}.mat-input-placeholder{color:rgba(0,0,0,.38)}.mat-focused .mat-input-placeholder{color:#e91e63}.mat-focused .mat-input-placeholder.mat-accent{color:#ad1457}.mat-focused .mat-input-placeholder.mat-warn{color:#f44336}.mat-input-element:disabled{color:rgba(0,0,0,.38)}.mat-focused .mat-input-placeholder.mat-float .mat-placeholder-required,input.mat-input-element:-webkit-autofill+.mat-input-placeholder .mat-placeholder-required{color:#ad1457}.mat-input-underline{background-color:rgba(0,0,0,.12)}.mat-input-ripple{background-color:#e91e63}.mat-input-ripple.mat-accent{background-color:#ad1457}.mat-input-ripple.mat-warn{background-color:#f44336}.mat-input-invalid .mat-input-placeholder,.mat-input-invalid .mat-input-placeholder.mat-accent,.mat-input-invalid .mat-input-placeholder.mat-float .mat-placeholder-required{color:#f44336}.mat-input-invalid .mat-input-ripple{background-color:#f44336}.mat-input-error{color:#f44336}.mat-list .mat-list-item,.mat-nav-list .mat-list-item{color:rgba(0,0,0,.87)}.mat-list .mat-subheader,.mat-nav-list .mat-subheader{color:rgba(0,0,0,.54)}.mat-divider{border-top-color:rgba(0,0,0,.12)}.mat-nav-list .mat-list-item{outline:none}.mat-nav-list .mat-list-item.mat-list-item-focus,.mat-nav-list .mat-list-item:hover{background:rgba(0,0,0,.04)}.mat-menu-content{background:#fff}.mat-menu-item{background:transparent;color:rgba(0,0,0,.87)}.mat-menu-item[disabled]{color:rgba(0,0,0,.38)}.mat-menu-item .mat-icon{color:rgba(0,0,0,.54);vertical-align:middle}.mat-menu-item:focus:not([disabled]),.mat-menu-item:hover:not([disabled]){background:rgba(0,0,0,.04)}.mat-progress-bar-background{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20version%3D%271.1%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20x%3D%270px%27%20y%3D%270px%27%20enable-background%3D%27new%200%200%205%202%27%20xml%3Aspace%3D%27preserve%27%20viewBox%3D%270%200%205%202%27%20preserveAspectRatio%3D%27none%20slice%27%3E%3Ccircle%20cx%3D%271%27%20cy%3D%271%27%20r%3D%271%27%20fill%3D%27%23f8bbd0%27%2F%3E%3C%2Fsvg%3E")}.mat-progress-bar-buffer{background-color:#f8bbd0}.mat-progress-bar-fill:after{background-color:#e91e63}.mat-progress-bar.mat-accent .mat-progress-bar-background{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20version%3D%271.1%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20x%3D%270px%27%20y%3D%270px%27%20enable-background%3D%27new%200%200%205%202%27%20xml%3Aspace%3D%27preserve%27%20viewBox%3D%270%200%205%202%27%20preserveAspectRatio%3D%27none%20slice%27%3E%3Ccircle%20cx%3D%271%27%20cy%3D%271%27%20r%3D%271%27%20fill%3D%27%23f8bbd0%27%2F%3E%3C%2Fsvg%3E")}.mat-progress-bar.mat-accent .mat-progress-bar-buffer{background-color:#f8bbd0}.mat-progress-bar.mat-accent .mat-progress-bar-fill:after{background-color:#ad1457}.mat-progress-bar.mat-warn .mat-progress-bar-background{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20version%3D%271.1%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20x%3D%270px%27%20y%3D%270px%27%20enable-background%3D%27new%200%200%205%202%27%20xml%3Aspace%3D%27preserve%27%20viewBox%3D%270%200%205%202%27%20preserveAspectRatio%3D%27none%20slice%27%3E%3Ccircle%20cx%3D%271%27%20cy%3D%271%27%20r%3D%271%27%20fill%3D%27%23ffcdd2%27%2F%3E%3C%2Fsvg%3E")}.mat-progress-bar.mat-warn .mat-progress-bar-buffer{background-color:#ffcdd2}.mat-progress-bar.mat-warn .mat-progress-bar-fill:after{background-color:#f44336}.mat-progress-spinner path,.mat-spinner path{stroke:#e91e63}.mat-progress-spinner.mat-accent path,.mat-spinner.mat-accent path{stroke:#ad1457}.mat-progress-spinner.mat-warn path,.mat-spinner.mat-warn path{stroke:#f44336}.mat-radio-outer-circle{border-color:rgba(0,0,0,.54)}.mat-radio-disabled .mat-radio-outer-circle{border-color:rgba(0,0,0,.38)}.mat-radio-disabled .mat-radio-inner-circle,.mat-radio-disabled .mat-radio-ripple .mat-ripple-element{background-color:rgba(0,0,0,.38)}.mat-radio-disabled .mat-radio-label-content{color:rgba(0,0,0,.38)}.mat-radio-button.mat-primary.mat-radio-checked .mat-radio-outer-circle{border-color:#e91e63}.mat-radio-button.mat-primary .mat-radio-inner-circle{background-color:#e91e63}.mat-radio-button.mat-primary .mat-radio-ripple .mat-ripple-element{background-color:rgba(233,30,99,.26)}.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle{border-color:#ad1457}.mat-radio-button.mat-accent .mat-radio-inner-circle{background-color:#ad1457}.mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element{background-color:rgba(173,20,87,.26)}.mat-radio-button.mat-warn.mat-radio-checked .mat-radio-outer-circle{border-color:#f44336}.mat-radio-button.mat-warn .mat-radio-inner-circle{background-color:#f44336}.mat-radio-button.mat-warn .mat-radio-ripple .mat-ripple-element{background-color:rgba(244,67,54,.26)}.mat-select-arrow,.mat-select-trigger{color:rgba(0,0,0,.38)}.mat-select-underline{background-color:rgba(0,0,0,.12)}.mat-select-arrow,.mat-select-disabled .mat-select-value,.mat-select-trigger{color:rgba(0,0,0,.38)}.mat-select-content,.mat-select-panel-done-animating{background:#fff}.mat-select-value{color:rgba(0,0,0,.87)}.mat-select:focus:not(.mat-select-disabled).mat-primary .mat-select-arrow,.mat-select:focus:not(.mat-select-disabled).mat-primary .mat-select-trigger{color:#e91e63}.mat-select:focus:not(.mat-select-disabled).mat-primary .mat-select-underline{background-color:#e91e63}.mat-select:focus:not(.mat-select-disabled).mat-accent .mat-select-arrow,.mat-select:focus:not(.mat-select-disabled).mat-accent .mat-select-trigger{color:#ad1457}.mat-select:focus:not(.mat-select-disabled).mat-accent .mat-select-underline{background-color:#ad1457}.mat-select:focus:not(.mat-select-disabled).mat-warn .mat-select-arrow,.mat-select:focus:not(.mat-select-disabled).mat-warn .mat-select-trigger,.mat-select:not(:focus).ng-invalid.ng-touched:not(.mat-select-disabled) .mat-select-arrow,.mat-select:not(:focus).ng-invalid.ng-touched:not(.mat-select-disabled) .mat-select-trigger{color:#f44336}.mat-select:focus:not(.mat-select-disabled).mat-warn .mat-select-underline,.mat-select:not(:focus).ng-invalid.ng-touched:not(.mat-select-disabled) .mat-select-underline{background-color:#f44336}.mat-sidenav-container{background-color:#fafafa;color:rgba(0,0,0,.87)}.mat-sidenav{color:rgba(0,0,0,.87)}.mat-sidenav,.mat-sidenav.mat-sidenav-push{background-color:#fff}.mat-sidenav-backdrop.mat-sidenav-shown{background-color:rgba(0,0,0,.6)}.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#e91e63}.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(233,30,99,.5)}.mat-slide-toggle:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle .mat-ripple-element{background-color:rgba(233,30,99,.12)}.mat-slide-toggle.mat-primary.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#e91e63}.mat-slide-toggle.mat-primary.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(233,30,99,.5)}.mat-slide-toggle.mat-primary:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle.mat-primary .mat-ripple-element{background-color:rgba(233,30,99,.12)}.mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#f44336}.mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(244,67,54,.5)}.mat-slide-toggle.mat-warn:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.12)}.mat-disabled .mat-slide-toggle-thumb{background-color:#bdbdbd}.mat-disabled .mat-slide-toggle-bar{background-color:rgba(0,0,0,.1)}.mat-slide-toggle-thumb{background-color:#fafafa}.mat-slide-toggle-bar{background-color:rgba(0,0,0,.38)}.mat-slider-track-background{background-color:rgba(0,0,0,.26)}.mat-primary .mat-slider-thumb,.mat-primary .mat-slider-thumb-label,.mat-primary .mat-slider-track-fill{background-color:#e91e63}.mat-primary .mat-slider-thumb-label-text{color:#fff}.mat-accent .mat-slider-thumb,.mat-accent .mat-slider-thumb-label,.mat-accent .mat-slider-track-fill{background-color:#ad1457}.mat-accent .mat-slider-thumb-label-text{color:hsla(0,0%,100%,.87)}.mat-warn .mat-slider-thumb,.mat-warn .mat-slider-thumb-label,.mat-warn .mat-slider-track-fill{background-color:#f44336}.mat-warn .mat-slider-thumb-label-text{color:#fff}.mat-slider-focus-ring{background-color:rgba(173,20,87,.2)}.cdk-focused .mat-slider-track-background,.mat-slider:hover .mat-slider-track-background{background-color:rgba(0,0,0,.38)}.mat-slider-disabled .mat-slider-thumb,.mat-slider-disabled .mat-slider-track-background,.mat-slider-disabled .mat-slider-track-fill,.mat-slider-disabled:hover .mat-slider-track-background{background-color:rgba(0,0,0,.26)}.mat-slider-min-value .mat-slider-focus-ring{background-color:rgba(0,0,0,.12)}.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb,.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb-label{background-color:#000}.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb,.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb-label{background-color:rgba(0,0,0,.26)}.mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb{border-color:rgba(0,0,0,.26);background-color:transparent}.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused .mat-slider-thumb,.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover .mat-slider-thumb{border-color:rgba(0,0,0,.38)}.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused.mat-slider-disabled .mat-slider-thumb,.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover.mat-slider-disabled .mat-slider-thumb{border-color:rgba(0,0,0,.26)}.mat-slider-has-ticks .mat-slider-wrapper:after{border-color:rgba(0,0,0,.7)}.mat-slider-horizontal .mat-slider-ticks{background-image:repeating-linear-gradient(90deg,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent);background-image:-moz-repeating-linear-gradient(.0001deg,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent)}.mat-slider-vertical .mat-slider-ticks{background-image:repeating-linear-gradient(180deg,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent)}.mat-tab-header,.mat-tab-nav-bar{border-bottom:1px solid rgba(0,0,0,.12)}.mat-tab-group-inverted-header .mat-tab-header,.mat-tab-group-inverted-header .mat-tab-nav-bar{border-top:1px solid rgba(0,0,0,.12);border-bottom:none}.mat-tab-label:focus{background-color:rgba(248,187,208,.3)}.mat-ink-bar{background-color:#e91e63}.mat-tab-label,.mat-tab-link{color:rgba(0,0,0,.87)}.mat-tab-label.mat-tab-disabled,.mat-tab-link.mat-tab-disabled{color:rgba(0,0,0,.38)}.mat-toolbar{background:#f5f5f5;color:rgba(0,0,0,.87)}.mat-toolbar.mat-primary{background:#e91e63;color:#fff}.mat-toolbar.mat-accent{background:#ad1457;color:hsla(0,0%,100%,.87)}.mat-toolbar.mat-warn{background:#f44336;color:#fff}.mat-tooltip{background:rgba(97,97,97,.9)} -------------------------------------------------------------------------------- /docs/sw-register.c12a0e1d4fd37a7ce413.bundle.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([5],{0:function(r,e,o){r.exports=o("3WLI")},"3WLI":function(r,e){"serviceWorker"in navigator&&navigator.serviceWorker.register("worker-basic.min.js").catch(function(r){console.error("Error registering service worker:",r)})}},[0]); -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { EAppPage } from './app.po'; 2 | 3 | describe('e-app App', () => { 4 | let page: EAppPage; 5 | 6 | beforeEach(() => { 7 | page = new EAppPage(); 8 | }); 9 | 10 | it('should display welcome message', done => { 11 | page.navigateTo(); 12 | page.getParagraphText() 13 | .then(msg => expect(msg).toEqual('Welcome to app!!')) 14 | .then(done, done.fail); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class EAppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-pwa-firebase-ecommerce", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "build": "ng build", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "^4.0.0", 16 | "@angular/common": "^4.0.0", 17 | "@angular/compiler": "^4.0.0", 18 | "@angular/core": "^4.0.0", 19 | "@angular/forms": "^4.0.0", 20 | "@angular/http": "^4.0.0", 21 | "@angular/material": "^2.0.0-beta.7", 22 | "@angular/platform-browser": "^4.0.0", 23 | "@angular/platform-browser-dynamic": "^4.0.0", 24 | "@angular/router": "^4.0.0", 25 | "core-js": "^2.4.1", 26 | "hammerjs": "^2.0.8", 27 | "rxjs": "^5.1.0", 28 | "zone.js": "^0.8.4" 29 | }, 30 | "devDependencies": { 31 | "@angular/cli": "1.1.0", 32 | "@angular/compiler-cli": "^4.2.5", 33 | "@angular/language-service": "^4.0.0", 34 | "@angular/service-worker": "^1.0.0-beta.16", 35 | "@types/jasmine": "2.5.45", 36 | "@types/node": "~6.0.60", 37 | "codelyzer": "~3.0.1", 38 | "jasmine-core": "~2.6.2", 39 | "jasmine-spec-reporter": "~4.1.0", 40 | "karma": "~1.7.0", 41 | "karma-chrome-launcher": "~2.1.1", 42 | "karma-cli": "~1.0.1", 43 | "karma-coverage-istanbul-reporter": "^1.2.1", 44 | "karma-jasmine": "~1.1.0", 45 | "karma-jasmine-html-reporter": "^0.2.2", 46 | "protractor": "~5.1.2", 47 | "ts-node": "~3.0.4", 48 | "tslint": "~5.3.2", 49 | "typescript": "~2.3.4" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/apfem-theme.scss: -------------------------------------------------------------------------------- 1 | @import '~@angular/material/theming'; 2 | // Plus imports for other components in your app. 3 | 4 | // Include the common styles for Angular Material. We include this here so that you only 5 | // have to load a single css file for Angular Material in your app. 6 | // Be sure that you only ever include this mixin once! 7 | @include mat-core(); 8 | 9 | // Define the palettes for your theme using the Material Design palettes available in palette.scss 10 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker 11 | // hue. 12 | $apfem-app-primary: mat-palette($mat-pink); 13 | $apfem-app-accent: mat-palette($mat-pink, 800); 14 | 15 | // The warn palette is optional (defaults to red). 16 | $apfem-app-warn: mat-palette($mat-red); 17 | 18 | // Create the theme object (a Sass map containing all of the palettes). 19 | $apfem-app-theme: mat-light-theme($apfem-app-primary, $apfem-app-accent, $apfem-app-warn); 20 | 21 | // Include theme styles for core and each component used in your app. 22 | // Alternatively, you can import and @include the theme mixins for each component 23 | // that you are using. 24 | @include angular-material-theme($apfem-app-theme); -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async(() => { 7 | TestBed.configureTestingModule({ 8 | declarations: [ 9 | AppComponent 10 | ], 11 | }).compileComponents(); 12 | })); 13 | 14 | it('should create the app', async(() => { 15 | const fixture = TestBed.createComponent(AppComponent); 16 | const app = fixture.debugElement.componentInstance; 17 | expect(app).toBeTruthy(); 18 | })); 19 | 20 | it(`should have as title 'app'`, async(() => { 21 | const fixture = TestBed.createComponent(AppComponent); 22 | const app = fixture.debugElement.componentInstance; 23 | expect(app.title).toEqual('app'); 24 | })); 25 | 26 | it('should render title in a h1 tag', async(() => { 27 | const fixture = TestBed.createComponent(AppComponent); 28 | fixture.detectChanges(); 29 | const compiled = fixture.debugElement.nativeElement; 30 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!'); 31 | })); 32 | }); 33 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | import { HttpModule } from '@angular/http'; 4 | import { MaterialModule } from '@angular/material'; 5 | import { BrowserModule } from '@angular/platform-browser'; 6 | import { CommonModule, LocationStrategy, PathLocationStrategy } from "@angular/common"; 7 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 8 | import 'hammerjs'; 9 | 10 | import { AppRouting } from './app.routing'; 11 | import { AppComponent } from './app.component'; 12 | import { DefaultLayoutComponent, SimpleLayoutComponent } from './layouts'; 13 | import { HomepageComponent } from './homepage.component'; 14 | import { CarouselModule } from './shared/carousel.module'; 15 | import { 16 | SideNavComponent, 17 | MainNavComponent, 18 | FooterComponent, 19 | CartCounterComponent 20 | } from './shared'; 21 | import { ItemService } from "app/items/item.service"; 22 | import { CartService } from "app/cart/cart.service"; 23 | 24 | @NgModule({ 25 | declarations: [ 26 | AppComponent, 27 | DefaultLayoutComponent, 28 | SimpleLayoutComponent, 29 | SideNavComponent, 30 | MainNavComponent, 31 | FooterComponent, 32 | CartCounterComponent, 33 | HomepageComponent 34 | ], 35 | imports: [ 36 | BrowserModule, 37 | FormsModule, 38 | HttpModule, 39 | AppRouting, 40 | MaterialModule, 41 | BrowserAnimationsModule, 42 | CarouselModule 43 | ], 44 | providers: [ 45 | ItemService, 46 | CartService, 47 | { 48 | provide: LocationStrategy, 49 | useClass: PathLocationStrategy 50 | } 51 | ], 52 | bootstrap: [AppComponent] 53 | }) 54 | export class AppModule { } 55 | -------------------------------------------------------------------------------- /src/app/app.routing.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | // Layouts 5 | import { DefaultLayoutComponent } from './layouts/default-layout.component'; 6 | import { SimpleLayoutComponent } from './layouts/simple-layout.component'; 7 | import { HomepageComponent } from 'app/homepage.component'; 8 | 9 | export const routes: Routes = [ 10 | { 11 | path: '', 12 | component: HomepageComponent 13 | }, 14 | { 15 | path: 'items', 16 | component: DefaultLayoutComponent, 17 | children: [ 18 | { 19 | path: '', 20 | loadChildren: 'app/items/items.module#ItemsModule' 21 | } 22 | ] 23 | }, 24 | { 25 | path: 'my-cart', 26 | component: DefaultLayoutComponent, 27 | children: [ 28 | { 29 | path: '', 30 | loadChildren: 'app/cart/cart.module#CartModule' 31 | } 32 | ] 33 | } 34 | ]; 35 | 36 | @NgModule({ 37 | imports: [ RouterModule.forRoot(routes) ], 38 | exports: [ RouterModule ] 39 | }) 40 | export class AppRouting {} 41 | -------------------------------------------------------------------------------- /src/app/cart/cart-item.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CartItemComponent } from './cart-item.component'; 4 | 5 | describe('CartItemComponent', () => { 6 | let component: CartItemComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CartItemComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CartItemComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/cart/cart-item.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { FormGroup, FormControl, Validators } from '@angular/forms'; 3 | 4 | import { Item } from 'app/items'; 5 | 6 | @Component({ 7 | selector: 'apfem-cart-item', 8 | template: ` 9 |
10 |
11 |
14 |
15 |
16 |
17 |

{{cartItem.val.item.name}}

18 |

{{cartItem.val.item.price | currency:'USD':true}} 19 | {{cartItem.val.item.old_price | currency:'USD':true}}

20 |
21 | 22 | 23 | 24 | {{ qty.display }} 25 | 26 | 27 |
28 |

29 | Sub-Total: {{cartItem.val.quantity * cartItem.val.item.price | currency:'USD':true}} 30 |     31 | 34 |

35 |
36 |
37 |
38 |
39 | `, 40 | styles: ['.cart-wrapper{border:1px solid #eee; background-color:#fff; border-radius:4px;}'] 41 | }) 42 | export class CartItemComponent implements OnInit { 43 | 44 | @Input() cartItem; 45 | updateCartForm: FormGroup; 46 | numbers = [ 47 | {value: 1, display: 'One'}, 48 | {value: 2, display: 'Two'}, 49 | {value: 3, display: 'Three'}, 50 | {value: 4, display: 'Four'}, 51 | {value: 5, display: 'Five'} 52 | ]; 53 | 54 | constructor() { 55 | this.updateCartForm = new FormGroup({ 56 | 'item': new FormControl('', Validators.required), 57 | 'quantity': new FormControl('', Validators.required) 58 | }); 59 | } 60 | 61 | onUpdateCart() { 62 | console.log(this.updateCartForm.value); 63 | } 64 | 65 | ngOnInit() { 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/app/cart/cart-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { 5 | CartComponent 6 | } from './index'; 7 | 8 | const routes: Routes = [ 9 | { 10 | path: '', 11 | component: CartComponent 12 | } 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forChild(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class CartRoutingModule {} 20 | -------------------------------------------------------------------------------- /src/app/cart/cart.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

My Cart

5 | You have {{cart.length}} items in your basket 6 | 10 | 11 | 19 |
20 | SHOPPING LIST 21 |
22 |
23 |
24 |
-------------------------------------------------------------------------------- /src/app/cart/cart.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CartComponent } from './cart.component'; 4 | 5 | describe('CartComponent', () => { 6 | let component: CartComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CartComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CartComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/cart/cart.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { CartService, Cart } from "./index"; 4 | 5 | @Component({ 6 | selector: 'apfem-cart', 7 | templateUrl: './cart.component.html', 8 | styles: ['.cart{min-height:500px;}'] 9 | }) 10 | export class CartComponent implements OnInit { 11 | 12 | cart: Cart[] = []; 13 | 14 | constructor( 15 | private cartService: CartService 16 | ) { } 17 | 18 | ngOnInit() { 19 | this.cart = this.cartService.getCart(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/cart/cart.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MaterialModule } from '@angular/material'; 4 | import { ReactiveFormsModule } from '@angular/forms'; 5 | 6 | import { CartRoutingModule } from "app/cart/cart-routing.module"; 7 | import { CartComponent } from './cart.component'; 8 | import { CartItemComponent } from './cart-item.component'; 9 | 10 | @NgModule({ 11 | imports: [ 12 | CommonModule, 13 | CartRoutingModule, 14 | MaterialModule, 15 | ReactiveFormsModule 16 | ], 17 | declarations: [CartComponent, CartItemComponent] 18 | }) 19 | export class CartModule { } 20 | -------------------------------------------------------------------------------- /src/app/cart/cart.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { CartService } from './cart.service'; 4 | 5 | describe('CartService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [CartService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([CartService], (service: CartService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /src/app/cart/cart.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | import { Cart } from "./index"; 4 | 5 | @Injectable() 6 | export class CartService { 7 | 8 | private cart: Cart[] = []; 9 | 10 | constructor() { } 11 | 12 | private findLocalStorageItems(query) { 13 | let i, results = []; 14 | for (i in localStorage) { 15 | if (localStorage.hasOwnProperty(i)) { 16 | if (i.match(query) || (!query && typeof i === 'string')) { 17 | let value = JSON.parse(localStorage.getItem(i)); 18 | results.push({key:i,val:value}); 19 | } 20 | } 21 | } 22 | return results; 23 | } 24 | 25 | // Get user cart 26 | getCart(){ 27 | return this.cart = this.getCartFromLocalStorage(); 28 | } 29 | 30 | // Extract values that has the 'cart-' key from the localStorage 31 | getCartFromLocalStorage(){ 32 | return this.findLocalStorageItems('cart-'); 33 | } 34 | 35 | // Add item to cart(localStorage) 36 | addItemToCart(formValues: Cart) { 37 | this.cart.push(formValues); 38 | } 39 | 40 | // Remove item from cart and localStorage 41 | removeItemFromCart(cart: Cart) { 42 | localStorage.removeItem('cart-' + cart.item.slug); 43 | } 44 | 45 | // Remove all items in the cart 46 | clear() { 47 | return this.findLocalStorageItems('item-').splice(1) 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/app/cart/cart.ts: -------------------------------------------------------------------------------- 1 | import { Item } from '../items'; 2 | 3 | export class Cart { 4 | item: Item; 5 | size: number; 6 | color: number; 7 | quantity: number; 8 | } -------------------------------------------------------------------------------- /src/app/cart/index.ts: -------------------------------------------------------------------------------- 1 | export { CartService } from './cart.service'; 2 | export { Cart } from './cart'; 3 | export { CartComponent } from './cart.component'; -------------------------------------------------------------------------------- /src/app/homepage.component.css: -------------------------------------------------------------------------------- 1 | @media only screen and (min-width: 768px) { 2 | .menu { 3 | display: none; 4 | } 5 | } 6 | 7 | @media only screen and (max-width: 768px) { 8 | .back-arrow { 9 | display: none; 10 | } 11 | } -------------------------------------------------------------------------------- /src/app/homepage.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 |
 
10 | 11 | APFEM SHOP 12 | 13 | 14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 | 30 | 31 | 64 | 65 | 66 | 67 | 68 |
-------------------------------------------------------------------------------- /src/app/homepage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Response } from '@angular/http'; 3 | 4 | import { ItemService, Item } from './items'; 5 | 6 | @Component({ 7 | selector: 'apfem-homepage', 8 | templateUrl: './homepage.component.html', 9 | styleUrls: ['./homepage.component.css'] 10 | }) 11 | export class HomepageComponent implements OnInit { 12 | 13 | delay = 5000; 14 | loop = false; 15 | loading = false; 16 | items: Item[] = []; 17 | slides: Array = [ 18 | {link: '#', color: 'grey'}, 19 | {link: '#', color: 'purple'}, 20 | {link: '#', color: 'yellow'}, 21 | {link: '#', color: 'orange'} 22 | ]; 23 | 24 | constructor( 25 | private itemService: ItemService 26 | ) { } 27 | 28 | // Simulate a post 29 | postItems() { 30 | this.itemService.storeItem().subscribe( 31 | (data: Response) => console.log(data.statusText) 32 | ) 33 | } 34 | 35 | getItems() { 36 | this.loading = true; 37 | this.itemService.getItems().subscribe( 38 | data => { 39 | this.items = data, 40 | this.loading = false 41 | } 42 | ); 43 | } 44 | 45 | ngOnInit() { 46 | this.getItems(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/items/index.ts: -------------------------------------------------------------------------------- 1 | export { ItemService } from './item.service'; 2 | export { Item, Image, Category } from './item'; 3 | export { ItemDetailsComponent } from './item-details.component'; 4 | export { ItemListComponent } from './item-list.component'; 5 | export { ItemComponent } from './item.component'; 6 | export { ItemByCategoryComponent } from './item-by-category.component'; -------------------------------------------------------------------------------- /src/app/items/item-by-category.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/items/item-by-category.component.css -------------------------------------------------------------------------------- /src/app/items/item-by-category.component.html: -------------------------------------------------------------------------------- 1 |

2 | item-by-category works! 3 |

4 | -------------------------------------------------------------------------------- /src/app/items/item-by-category.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ItemByCategoryComponent } from './item-by-category.component'; 4 | 5 | describe('ItemByCategoryComponent', () => { 6 | let component: ItemByCategoryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ItemByCategoryComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ItemByCategoryComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/items/item-by-category.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'apfem-item-by-category', 5 | templateUrl: './item-by-category.component.html', 6 | styleUrls: ['./item-by-category.component.css'] 7 | }) 8 | export class ItemByCategoryComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/items/item-details.component.css: -------------------------------------------------------------------------------- 1 | .img { 2 | padding: 8px; 3 | /*border: 1px solid #eee;*/ 4 | border-radius: 4px; 5 | } -------------------------------------------------------------------------------- /src/app/items/item-details.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 | 7 | 8 | 9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |

{{item.name}}

19 |

{{item.price | currency:USD:true}}

20 |

{{item.old_price | currency:USD:true}}

21 |

Availability
{{item.availability}}


22 |
23 | 24 | 25 | 26 | {{ qty.display }} 27 | 28 | 29 |

30 | 33 |
34 |
35 |
36 |
37 |
38 |
Description: 39 |

40 |
41 |
42 |
-------------------------------------------------------------------------------- /src/app/items/item-details.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ItemDetailsComponent } from './item-details.component'; 4 | 5 | describe('ItemDetailsComponent', () => { 6 | let component: ItemDetailsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ItemDetailsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ItemDetailsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/items/item-details.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit } from '@angular/core'; 2 | import { Router, ActivatedRoute } from '@angular/router'; 3 | import { MdSnackBar } from '@angular/material'; 4 | import { FormGroup, FormControl, Validators } from '@angular/forms'; 5 | 6 | import { ItemService, Item } from './index'; 7 | import { CartService } from '../cart/cart.service'; 8 | 9 | @Component({ 10 | selector: 'apfem-item-details', 11 | templateUrl: './item-details.component.html', 12 | styleUrls: ['./item-details.component.css'] 13 | }) 14 | export class ItemDetailsComponent implements OnInit { 15 | 16 | loading = false; 17 | delay = 5000; 18 | loop = false; 19 | item: Item; 20 | cartForm: FormGroup; 21 | itemIndex: any; 22 | numbers = [ 23 | {value: 1, display: 'One'}, 24 | {value: 2, display: 'Two'}, 25 | {value: 3, display: 'Three'}, 26 | {value: 4, display: 'Four'}, 27 | {value: 5, display: 'Five'} 28 | ]; 29 | 30 | constructor( 31 | private route: ActivatedRoute, 32 | private itemService: ItemService, 33 | private snackBar: MdSnackBar, 34 | private cartService: CartService 35 | ) { 36 | this.cartForm = new FormGroup({ 37 | 'item': new FormControl('', Validators.required), 38 | 'quantity': new FormControl('', Validators.required) 39 | }); 40 | } 41 | 42 | /** 43 | * Get an item from the items array using the slug parameter 44 | */ 45 | getItem() { 46 | this.route.params.subscribe( 47 | (params: any) => { 48 | this.itemIndex = params['slug']; 49 | this.item = this.itemService.getItem(this.itemIndex); 50 | } 51 | ); 52 | } 53 | 54 | /** 55 | * Add item to cart(users browser - localStorage) 56 | */ 57 | onAddToCart() { 58 | this.loading = true; 59 | if (localStorage.getItem('cart-' + this.item.slug)) { 60 | this.snackBar.open('Already in your cart!', 'Ok', { 61 | duration: 5000, 62 | }), 63 | this.loading = false; 64 | } else { 65 | this.cartService.addItemToCart(this.cartForm.value); 66 | localStorage.setItem('cart-' + this.item.slug, JSON.stringify(this.cartForm.value)); 67 | this.snackBar.open('Successfully added to cart!', 'Dismiss', { 68 | duration: 5000, 69 | }); 70 | } 71 | } 72 | 73 | ngOnInit() { 74 | this.getItem(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/app/items/item-list.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/items/item-list.component.css -------------------------------------------------------------------------------- /src/app/items/item-list.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
List of items
5 |
6 |
7 | 12 | 13 |
14 |
15 |
-------------------------------------------------------------------------------- /src/app/items/item-list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ItemListComponent } from './item-list.component'; 4 | 5 | describe('ItemListComponent', () => { 6 | let component: ItemListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ItemListComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ItemListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/items/item-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { ItemService, Item } from './index'; 4 | 5 | @Component({ 6 | selector: 'apfem-item-list', 7 | templateUrl: './item-list.component.html', 8 | styleUrls: ['./item-list.component.css'] 9 | }) 10 | export class ItemListComponent implements OnInit { 11 | 12 | loading = false; 13 | items: Item[] = []; 14 | 15 | constructor( 16 | private itemService: ItemService 17 | ) { } 18 | 19 | /** 20 | * Get the items from the service 21 | */ 22 | getItems() { 23 | this.loading = true; 24 | this.itemService.getItems().subscribe( 25 | data => { 26 | this.items = data, 27 | this.loading = false 28 | } 29 | ); 30 | } 31 | 32 | ngOnInit() { 33 | this.getItems(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/items/item-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { 5 | ItemDetailsComponent, 6 | ItemByCategoryComponent, 7 | ItemListComponent 8 | } from './index'; 9 | 10 | const routes: Routes = [ 11 | { 12 | path: '', 13 | component: ItemListComponent 14 | }, 15 | { 16 | path: ':slug', 17 | component: ItemDetailsComponent 18 | }, 19 | { 20 | path: ':slug/items', 21 | component: ItemByCategoryComponent 22 | } 23 | ]; 24 | 25 | @NgModule({ 26 | imports: [RouterModule.forChild(routes)], 27 | exports: [RouterModule] 28 | }) 29 | export class ItemRoutingModule {} 30 | -------------------------------------------------------------------------------- /src/app/items/item.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/items/item.component.css -------------------------------------------------------------------------------- /src/app/items/item.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
6 | 7 |
8 | 9 | 10 |

{{ item.name }}

11 | {{ item.price | currency:'USD':true }}    12 | {{item.old_price | currency:USD:true}} 13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 |

21 | -------------------------------------------------------------------------------- /src/app/items/item.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ItemComponent } from './item.component'; 4 | 5 | describe('ItemComponent', () => { 6 | let component: ItemComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ItemComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ItemComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/items/item.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | import { Item } from './index'; 4 | 5 | @Component({ 6 | selector: 'apfem-item', 7 | templateUrl: './item.component.html', 8 | styleUrls: ['./item.component.css'] 9 | }) 10 | export class ItemComponent implements OnInit { 11 | 12 | @Input() item: Item; 13 | @Input() selectedItem: number; 14 | 15 | constructor() { } 16 | 17 | ngOnInit() { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/app/items/item.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { ItemService } from './item.service'; 4 | 5 | describe('ItemService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [ItemService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([ItemService], (service: ItemService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /src/app/items/item.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http, Response } from '@angular/http'; 3 | import { Observable } from 'rxjs/Rx'; 4 | 5 | import { Item, Image, Category } from './index'; 6 | 7 | @Injectable() 8 | export class ItemService { 9 | 10 | private header = new Headers({'Content-Type': 'application/json'}); 11 | private firbaseApi = 'https://apfem-78c34.firebaseio.com/'; 12 | 13 | // Item sample data 14 | private items: Item[] = [ 15 | new Item('angular-t-shirt', 'Angular T-Shirt', new Category('t-shirt', 'T-Shirts'), 120, 135, 'In Stock', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 16 | [ 17 | new Image('http://devstickers.com/assets/img/pro/tee/8ki7_mhoodiez.png'), 18 | new Image('http://devstickers.com/assets/img/pro/tee/lrj4_mens.png') 19 | ]), 20 | new Item('gulp-sass-cup', 'Gulp & Sass Cup', new Category('cup', 'Cups'), 90, 105, 'Pre-Order', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 21 | [ 22 | new Image('http://www.joel-chrabie.com/res/js/gulpsass.png'), 23 | new Image('http://vesparny.github.io/angular-kickstart/assets/images/gulp-logo.png') 24 | ]), 25 | new Item('google-cup', 'Google Cup', new Category('cup', 'Cups'), 96, 117, 'In Stock', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 26 | [ 27 | new Image('https://images-na.ssl-images-amazon.com/images/I/71aEJmSmIYL._SX355_.jpg'), 28 | new Image('http://www.mypeyronies.com/image-files/hourglass-penis-indentations.jpg') 29 | ]), 30 | new Item('female-t-shirts', 'Female T-Shirts(Pink)', new Category('t-shirt', 'T-Shirts'), 90, 108, 'Pre-Order', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 31 | [ 32 | new Image('https://www.mulboo.com.au/wp-content/uploads/2013/04/Ladies-Pink-T-shirt.png'), 33 | new Image('https://shop.googlemerchandisestore.com/store/20160512512/assets/items/images/GGOEGAAX0339.jpg') 34 | ]), 35 | new Item('female-google-t-shirts-black', 'White Female T-Shirts', new Category('t-shirt', 'T-Shirts'), 90, 108, 'Pre-Order', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 36 | [ 37 | new Image('http://www.titanui.com/wp-content/uploads/2013/05/18/Wemen-T-Shirt-Vector-Mockup.jpg'), 38 | new Image('https://gcontent.robertsonmarketing.com/store/20160512512/assets/themes/theme1_en/images/home/jun17/hero3_youtube.png') 39 | ]), 40 | new Item('google-t-shirts-white', 'Google T-Shirts(White)', new Category('t-shirt', 'T-Shirts'), 30, 68, 'Pre-Order', 'Lorem ipsum dolor sit amet, no agam populo apeirian pri, ea eirmod scaevola voluptatibus per. No est maluisset sadipscing, duo soluta dignissim dissentiet ei, malis possim posidonium ad has. Dico error utamur an est, ex tantas expetendis sit. Convenire disputando repudiandae nam no, laudem malorum quaeque sit id.', 41 | [ 42 | new Image('https://ae01.alicdn.com/kf/HTB1Ep4kIFXXXXXIaXXXq6xXFXXXn/2017-Newest-Mans-T-Shirt-Simple-Summer-font-b-Logo-b-font-font-b-Google-b.jpg'), 43 | new Image('https://76.my/Malaysia/google-logo-t-shirt-onlinepasar-1506-05-OnlinePasar@21.jpg') 44 | ]) 45 | ]; 46 | 47 | constructor( private http: Http ) { } 48 | 49 | /** 50 | * Get items from the firebase API 51 | */ 52 | getItems() { 53 | return this.http.get(this.firbaseApi + 'items.json') 54 | .map((response: Response) => response.json() as Item[]); 55 | } 56 | 57 | /** 58 | * Get an item from the items array by id 59 | * @param id 60 | */ 61 | getItem(id: number) { 62 | return this.items[id]; 63 | } 64 | 65 | /** 66 | * Used to send/store items to the backend 67 | */ 68 | storeItem() { 69 | const body = JSON.stringify(this.items); 70 | return this.http.put(this.firbaseApi + 'items.json', body, {headers: this.header}); 71 | } 72 | 73 | // Handle all errors if any 74 | private handleError (error: Response | any) { 75 | // use a remote logging infrastructure 76 | let errMsg: string; 77 | if (error instanceof Response) { 78 | const body = error.json() || ''; 79 | const err = body.error || JSON.stringify(body); 80 | errMsg = `${error.status} - ${error.statusText || ''} ${err}`; 81 | } else { 82 | errMsg = error.message ? error.message : error.toString(); 83 | } 84 | console.error(errMsg); 85 | return Observable.throw(errMsg); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/app/items/item.ts: -------------------------------------------------------------------------------- 1 | export class Item { 2 | constructor( 3 | public slug: string, 4 | public name: string, 5 | public category: Category, 6 | public price: number, 7 | public old_price: number, 8 | public availability: string, 9 | public description: string, 10 | public photos: Image[] 11 | ) {} 12 | } 13 | 14 | export class Image { 15 | constructor(public path: string) {} 16 | } 17 | 18 | export class Category { 19 | constructor(public slug: string, public title: string) {} 20 | } 21 | -------------------------------------------------------------------------------- /src/app/items/items.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MaterialModule } from '@angular/material'; 4 | import { ReactiveFormsModule } from '@angular/forms'; 5 | 6 | import { 7 | ItemDetailsComponent, 8 | ItemComponent, 9 | ItemListComponent, 10 | ItemByCategoryComponent 11 | } from './index'; 12 | import { ItemRoutingModule } from 'app/items/item-routing.module'; 13 | import { CarouselModule } from 'app/shared/carousel.module'; 14 | 15 | @NgModule({ 16 | imports: [ 17 | CommonModule, 18 | ItemRoutingModule, 19 | MaterialModule, 20 | ReactiveFormsModule, 21 | CarouselModule 22 | ], 23 | declarations: [ 24 | ItemDetailsComponent, 25 | ItemComponent, 26 | ItemListComponent, 27 | ItemByCategoryComponent 28 | ] 29 | }) 30 | export class ItemsModule { } 31 | -------------------------------------------------------------------------------- /src/app/layouts/default-layout.component.css: -------------------------------------------------------------------------------- 1 | 2 | @media only screen and (min-width: 768px) { 3 | .menu { 4 | display: none; 5 | } 6 | } 7 | 8 | @media only screen and (max-width: 768px) { 9 | .back-arrow { 10 | display: none; 11 | } 12 | } -------------------------------------------------------------------------------- /src/app/layouts/default-layout.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 10 | 13 |
14 | 15 | APFEM SHOP 16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 |
-------------------------------------------------------------------------------- /src/app/layouts/default-layout.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Location } from '@angular/common'; 3 | 4 | @Component({ 5 | selector: 'apfem-default-layout', 6 | templateUrl: './default-layout.component.html', 7 | styleUrls: ['./default-layout.component.css'] 8 | }) 9 | export class DefaultLayoutComponent implements OnInit { 10 | 11 | constructor( 12 | private location: Location 13 | ) { } 14 | 15 | goBack(): void { 16 | this.location.back(); 17 | } 18 | 19 | ngOnInit() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/layouts/index.ts: -------------------------------------------------------------------------------- 1 | export { DefaultLayoutComponent } from './default-layout.component'; 2 | export { SimpleLayoutComponent } from './simple-layout.component'; -------------------------------------------------------------------------------- /src/app/layouts/simple-layout.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/layouts/simple-layout.component.css -------------------------------------------------------------------------------- /src/app/layouts/simple-layout.component.html: -------------------------------------------------------------------------------- 1 |

2 | simple-layout works! 3 |

4 | -------------------------------------------------------------------------------- /src/app/layouts/simple-layout.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'apfem-simple-layout', 5 | templateUrl: './simple-layout.component.html', 6 | styleUrls: ['./simple-layout.component.css'] 7 | }) 8 | export class SimpleLayoutComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/carousel.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnDestroy, Input} from '@angular/core'; 2 | import { SlideComponent } from './slide.component'; 3 | 4 | export enum Direction {UNKNOWN, NEXT, PREV} 5 | 6 | @Component({ 7 | selector: 'apfem-carousel', 8 | template: ` 9 | 21 | ` 22 | }) 23 | export class CarouselComponent implements OnDestroy { 24 | @Input() public noWrap: boolean; 25 | @Input() public noPause: boolean; 26 | @Input() public noTransition: boolean; 27 | 28 | @Input() public get interval(): number { 29 | return this._interval; 30 | } 31 | 32 | slides: Array = []; 33 | currentInterval: any; 34 | isPlaying: boolean; 35 | destroyed = false; 36 | currentSlide: SlideComponent; 37 | _interval: number; 38 | 39 | public set interval(value: number) { 40 | this._interval = value; 41 | this.restartTimer(); 42 | } 43 | 44 | ngOnDestroy() { 45 | this.destroyed = true; 46 | } 47 | 48 | select(nextSlide: SlideComponent, direction: Direction = Direction.UNKNOWN) { 49 | const nextIndex = nextSlide.index; 50 | if (direction === Direction.UNKNOWN) { 51 | direction = nextIndex > this.getCurrentIndex() ? Direction.NEXT : Direction.PREV; 52 | } 53 | 54 | // Prevent this user-triggered transition from occurring if there is already one in progress 55 | if (nextSlide && nextSlide !== this.currentSlide) { 56 | this.goNext(nextSlide, direction); 57 | } 58 | } 59 | 60 | private goNext(slide: SlideComponent, direction: Direction) { 61 | if (this.destroyed) { 62 | return; 63 | } 64 | 65 | slide.direction = direction; 66 | slide.active = true; 67 | 68 | if (this.currentSlide) { 69 | this.currentSlide.direction = direction; 70 | this.currentSlide.active = false; 71 | } 72 | 73 | this.currentSlide = slide; 74 | 75 | // every time you change slides, reset the timer 76 | this.restartTimer(); 77 | } 78 | 79 | private getSlideByIndex(index: number) { 80 | const len = this.slides.length; 81 | for (let i = 0; i < len; ++i) { 82 | if (this.slides[i].index === index) { 83 | return this.slides[i]; 84 | } 85 | } 86 | } 87 | 88 | getCurrentIndex() { 89 | return !this.currentSlide ? 0 : this.currentSlide.index; 90 | } 91 | 92 | next() { 93 | const newIndex = (this.getCurrentIndex() + 1) % this.slides.length; 94 | 95 | if (newIndex === 0 && this.noWrap) { 96 | this.pause(); 97 | return; 98 | } 99 | 100 | return this.select(this.getSlideByIndex(newIndex), Direction.NEXT); 101 | } 102 | 103 | prev() { 104 | const newIndex = this.getCurrentIndex() - 1 < 0 ? this.slides.length - 1 : this.getCurrentIndex() - 1; 105 | 106 | if (this.noWrap && newIndex === this.slides.length - 1) { 107 | this.pause(); 108 | return; 109 | } 110 | 111 | return this.select(this.getSlideByIndex(newIndex), Direction.PREV); 112 | } 113 | 114 | restartTimer() { 115 | this.resetTimer(); 116 | const interval = +this.interval; 117 | if (!isNaN(interval) && interval > 0) { 118 | this.currentInterval = setInterval(() => { 119 | const nInterval = +this.interval; 120 | if (this.isPlaying && !isNaN(this.interval) && nInterval > 0 && this.slides.length) { 121 | this.next(); 122 | } else { 123 | this.pause(); 124 | } 125 | }, interval); 126 | } 127 | } 128 | 129 | resetTimer() { 130 | if (this.currentInterval) { 131 | clearInterval(this.currentInterval); 132 | this.currentInterval = null; 133 | } 134 | } 135 | 136 | public play() { 137 | if (!this.isPlaying) { 138 | this.isPlaying = true; 139 | this.restartTimer(); 140 | } 141 | } 142 | 143 | public pause() { 144 | if (!this.noPause) { 145 | this.isPlaying = false; 146 | this.resetTimer(); 147 | } 148 | } 149 | 150 | public addSlide(slide: SlideComponent) { 151 | slide.index = this.slides.length; 152 | this.slides.push(slide); 153 | if (this.slides.length === 1 || slide.active) { 154 | this.select(this.slides[this.slides.length - 1]); 155 | if (this.slides.length === 1) { 156 | this.play(); 157 | } 158 | } else { 159 | slide.active = false; 160 | } 161 | } 162 | 163 | public removeSlide(slide: SlideComponent) { 164 | this.slides.splice(slide.index, 1); 165 | 166 | if (this.slides.length === 0) { 167 | this.currentSlide = null; 168 | return; 169 | } 170 | 171 | for (let i = 0; i < this.slides.length; i++) { 172 | this.slides[i].index = i; 173 | } 174 | } 175 | } 176 | 177 | -------------------------------------------------------------------------------- /src/app/shared/carousel.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MaterialModule } from '@angular/material'; 4 | 5 | import { CarouselComponent, SlideComponent } from './index'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | MaterialModule 11 | ], 12 | exports: [ 13 | CarouselComponent, 14 | SlideComponent 15 | ], 16 | declarations: [ 17 | CarouselComponent, 18 | SlideComponent 19 | ] 20 | }) 21 | export class CarouselModule { } 22 | -------------------------------------------------------------------------------- /src/app/shared/cart-counter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { CartService, Cart } from "../cart"; 4 | 5 | @Component({ 6 | selector: 'apfem-cart-counter', 7 | template: ` 8 | 9 | shopping_cart 10 | {{cart.length}} 11 | 12 | `, 13 | styles: [ 14 | '.badge {background-color: #fff; border-radius: 50%; padding: 5px 8px; color: #333;}' 15 | ] 16 | }) 17 | export class CartCounterComponent implements OnInit { 18 | 19 | cart: Cart[] = []; 20 | 21 | constructor( 22 | private cartService: CartService 23 | ) { } 24 | 25 | ngOnInit() { 26 | this.cart = this.cartService.getCart(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/footer.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/shared/footer.component.css -------------------------------------------------------------------------------- /src/app/shared/footer.component.html: -------------------------------------------------------------------------------- 1 | 11 |
12 | -------------------------------------------------------------------------------- /src/app/shared/footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'apfem-footer', 5 | templateUrl: './footer.component.html', 6 | styleUrls: ['./footer.component.css'] 7 | }) 8 | export class FooterComponent implements OnInit { 9 | 10 | year: number = Date.now(); 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/index.ts: -------------------------------------------------------------------------------- 1 | export { CarouselComponent } from './carousel.component'; 2 | export { SlideComponent } from './slide.component'; 3 | export { SideNavComponent } from './side-nav.component'; 4 | export { MainNavComponent } from './main-nav.component'; 5 | export { FooterComponent } from './footer.component'; 6 | export { CartCounterComponent } from './cart-counter.component'; -------------------------------------------------------------------------------- /src/app/shared/main-nav.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/shared/main-nav.component.css -------------------------------------------------------------------------------- /src/app/shared/main-nav.component.html: -------------------------------------------------------------------------------- 1 |

2 | main-nav works! 3 |

4 | -------------------------------------------------------------------------------- /src/app/shared/main-nav.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'apfem-main-nav', 5 | templateUrl: './main-nav.component.html', 6 | styleUrls: ['./main-nav.component.css'] 7 | }) 8 | export class MainNavComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/side-nav.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/app/shared/side-nav.component.css -------------------------------------------------------------------------------- /src/app/shared/side-nav.component.html: -------------------------------------------------------------------------------- 1 |

2 | side-nav works! 3 |

4 | -------------------------------------------------------------------------------- /src/app/shared/side-nav.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'apfem-side-nav', 5 | templateUrl: './side-nav.component.html', 6 | styleUrls: ['./side-nav.component.css'] 7 | }) 8 | export class SideNavComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/slide.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, OnDestroy, Input, HostBinding } from '@angular/core'; 2 | 3 | import { CarouselComponent, Direction} from './carousel.component'; 4 | 5 | @Component({ 6 | selector: 'apfem-slide', 7 | template: ` 8 |
9 | 10 |
11 | ` 12 | }) 13 | export class SlideComponent implements OnInit, OnDestroy { 14 | @Input() public index:number; 15 | @Input() public direction:Direction; 16 | 17 | @HostBinding('class.active') 18 | @Input() public active:boolean; 19 | 20 | @HostBinding('class.item') 21 | @HostBinding('class.carousel-item') 22 | private addClass:boolean = true; 23 | 24 | constructor(private carousel:CarouselComponent) { 25 | } 26 | 27 | public ngOnInit() { 28 | this.carousel.addSlide(this); 29 | } 30 | 31 | public ngOnDestroy() { 32 | this.carousel.removeSlide(this); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/assets/bg.jpg -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daviskoko/angular-firebase-ecommerce/8c72f065d7f2fe166fbbaf2638872f43ad2a246a/src/fav.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APFEM SHOP 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following to support `@angular/animation`. */ 41 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | import 'core-js/es6/reflect'; 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/ 50 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 51 | 52 | 53 | 54 | /*************************************************************************************************** 55 | * Zone JS is required by Angular itself. 56 | */ 57 | import 'zone.js/dist/zone'; // Included with Angular CLI. 58 | 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | 65 | /** 66 | * Date, currency, decimal and percent pipes. 67 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 68 | */ 69 | // import 'intl'; // Run `npm install --save intl`. 70 | /** 71 | * Need to import at least one locale-data with intl. 72 | */ 73 | // import 'intl/locale-data/jsonp/en'; 74 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import '~https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css'; 3 | @import '~https://fonts.googleapis.com/icon?family=Material+Icons'; 4 | @import '~https://fonts.googleapis.com/css?family=Quicksand'; 5 | 6 | html, body, material-app, md-sidenav-container, .my-content { 7 | margin: 0px auto; 8 | width: 100%; 9 | height: 100%; 10 | font-family: 'Quicksand', sans-serif; 11 | background-color: #f9f9f9; 12 | color: #333; 13 | } 14 | h4 { 15 | color: gray; 16 | margin: 5px 0px; 17 | } 18 | a { 19 | text-decoration: none; 20 | } 21 | 22 | .content { 23 | display: block; 24 | position: relative; 25 | } 26 | 27 | .content::after { 28 | content: ""; 29 | background: url('./assets/bg.jpg'); 30 | opacity: 0.04; 31 | top: 0; 32 | left: 0; 33 | bottom: 0; 34 | right: 0; 35 | position: absolute; 36 | z-index: -1; 37 | } 38 | .brand { 39 | color: #FFF; 40 | text-decoration: none; 41 | font-weight: bold; 42 | letter-spacing: 5px; 43 | font-size: 2vmax; 44 | } 45 | .container { 46 | padding: 0px 5px; 47 | } 48 | 49 | md-toolbar-row { 50 | justify-content: space-between; 51 | } 52 | 53 | md-sidenav { 54 | width: 200px; 55 | } 56 | 57 | .old-price { 58 | color: darkred; 59 | text-decoration: line-through; 60 | } 61 | 62 | .loader { 63 | position: absolute; 64 | top: 50%; 65 | left: 50%; 66 | margin-right: -50%; 67 | border: 10px solid #f3f3f3; 68 | border-top: 10px solid #3498db; 69 | border-radius: 50%; 70 | width: 50px; 71 | height: 50px; 72 | animation: spin 2s linear infinite; 73 | } 74 | 75 | @keyframes spin { 76 | 0% { transform: rotate(0deg); } 77 | 100% { transform: rotate(360deg); } 78 | } 79 | 80 | /*Thanks to Twitter Bootstrap*/ 81 | .carousel { 82 | position: relative; 83 | } 84 | .carousel-inner { 85 | position: relative; 86 | overflow: hidden; 87 | width: 100%; 88 | } 89 | .carousel-inner > .item { 90 | display: none; 91 | position: relative; 92 | -webkit-transition: 0.6s ease-in-out left; 93 | transition: 0.6s ease-in-out left; 94 | } 95 | .carousel-inner > .item > img, 96 | .carousel-inner > .item > a > img { 97 | line-height: 1; 98 | } 99 | .carousel-inner > .active, 100 | .carousel-inner > .next, 101 | .carousel-inner > .prev { 102 | display: block; 103 | } 104 | .carousel-inner > .active { 105 | left: 0; 106 | } 107 | .carousel-inner > .next, 108 | .carousel-inner > .prev { 109 | position: absolute; 110 | top: 0; 111 | width: 100%; 112 | } 113 | .carousel-inner > .next { 114 | left: 100%; 115 | } 116 | .carousel-inner > .prev { 117 | left: -100%; 118 | } 119 | .carousel-inner > .next.left, 120 | .carousel-inner > .prev.right { 121 | left: 0; 122 | } 123 | .carousel-inner > .active.left { 124 | left: -100%; 125 | } 126 | .carousel-inner > .active.right { 127 | left: 100%; 128 | } 129 | .carousel-control { 130 | position: absolute; 131 | top: 0; 132 | left: 0; 133 | bottom: 0; 134 | width: 15%; 135 | opacity: .5; 136 | filter: alpha(opacity=50); 137 | font-size: 20px; 138 | color: #fff; 139 | text-align: center; 140 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8); 141 | } 142 | .carousel-control.right { 143 | left: auto; 144 | right: 0; 145 | } 146 | .carousel-control:hover, 147 | .carousel-control:focus { 148 | outline: none; 149 | color: #fff; 150 | text-decoration: none; 151 | opacity: .9; 152 | filter: alpha(opacity=90); 153 | } 154 | .carousel-control .icon-prev, 155 | .carousel-control .icon-next, 156 | .carousel-control .glyphicon-chevron-left, 157 | .carousel-control .glyphicon-chevron-right { 158 | position: absolute; 159 | top: 50%; 160 | z-index: 5; 161 | display: inline-block; 162 | } 163 | .carousel-control .icon-prev, 164 | .carousel-control .glyphicon-chevron-left { 165 | left: 50%; 166 | } 167 | .carousel-control .icon-next, 168 | .carousel-control .glyphicon-chevron-right { 169 | right: 50%; 170 | } 171 | .carousel-control .icon-prev, 172 | .carousel-control .icon-next { 173 | width: 20px; 174 | height: 20px; 175 | margin-top: -10px; 176 | margin-left: -10px; 177 | font-family: serif; 178 | } 179 | .carousel-control .icon-prev:before { 180 | content: '\2039'; 181 | } 182 | .carousel-control .icon-next:before { 183 | content: '\203a'; 184 | } 185 | .carousel-indicators { 186 | position: absolute; 187 | bottom: 10px; 188 | left: 50%; 189 | z-index: 15; 190 | width: 60%; 191 | margin-left: -30%; 192 | padding-left: 0; 193 | list-style: none; 194 | text-align: center; 195 | } 196 | .carousel-indicators li { 197 | display: inline-block; 198 | width: 10px; 199 | height: 10px; 200 | margin: 1px; 201 | text-indent: -999px; 202 | border: 1px solid #fff; 203 | border-radius: 10px; 204 | cursor: pointer; 205 | background-color: #000 \9; 206 | background-color: rgba(0, 0, 0, 0); 207 | } 208 | .carousel-indicators .active { 209 | margin: 0; 210 | width: 12px; 211 | height: 12px; 212 | background-color: #ffffff; 213 | } 214 | .carousel-caption { 215 | position: absolute; 216 | left: 15%; 217 | right: 15%; 218 | bottom: 20px; 219 | z-index: 10; 220 | padding-top: 20px; 221 | padding-bottom: 20px; 222 | color: #fff; 223 | text-align: center; 224 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); 225 | } 226 | .carousel-caption .btn { 227 | text-shadow: none; 228 | } 229 | .carousel-icon { 230 | font-size: 5vmin; 231 | cursor: pointer; 232 | width: auto !important; 233 | height: auto !important; 234 | } 235 | /*End of carousel*/ -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "es2015", 6 | "baseUrl": "", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "baseUrl": "", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "baseUrl": "src", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es5", 12 | "typeRoots": [ 13 | "node_modules/@types" 14 | ], 15 | "lib": [ 16 | "es2016", 17 | "dom" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "eofline": true, 15 | "forin": true, 16 | "import-blacklist": [ 17 | true, 18 | "rxjs" 19 | ], 20 | "import-spacing": true, 21 | "indent": [ 22 | true, 23 | "spaces" 24 | ], 25 | "interface-over-type-literal": true, 26 | "label-position": true, 27 | "max-line-length": [ 28 | true, 29 | 140 30 | ], 31 | "member-access": false, 32 | "member-ordering": [ 33 | true, 34 | "static-before-instance", 35 | "variables-before-functions" 36 | ], 37 | "no-arg": true, 38 | "no-bitwise": true, 39 | "no-console": [ 40 | true, 41 | "debug", 42 | "info", 43 | "time", 44 | "timeEnd", 45 | "trace" 46 | ], 47 | "no-construct": true, 48 | "no-debugger": true, 49 | "no-duplicate-super": true, 50 | "no-empty": false, 51 | "no-empty-interface": true, 52 | "no-eval": true, 53 | "no-inferrable-types": [ 54 | true, 55 | "ignore-params" 56 | ], 57 | "no-misused-new": true, 58 | "no-non-null-assertion": true, 59 | "no-shadowed-variable": true, 60 | "no-string-literal": false, 61 | "no-string-throw": true, 62 | "no-switch-case-fall-through": true, 63 | "no-trailing-whitespace": true, 64 | "no-unnecessary-initializer": true, 65 | "no-unused-expression": true, 66 | "no-use-before-declare": true, 67 | "no-var-keyword": true, 68 | "object-literal-sort-keys": false, 69 | "one-line": [ 70 | true, 71 | "check-open-brace", 72 | "check-catch", 73 | "check-else", 74 | "check-whitespace" 75 | ], 76 | "prefer-const": true, 77 | "quotemark": [ 78 | true, 79 | "single" 80 | ], 81 | "radix": true, 82 | "semicolon": [ 83 | "always" 84 | ], 85 | "triple-equals": [ 86 | true, 87 | "allow-null-check" 88 | ], 89 | "typedef-whitespace": [ 90 | true, 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | } 98 | ], 99 | "typeof-compare": true, 100 | "unified-signatures": true, 101 | "variable-name": false, 102 | "whitespace": [ 103 | true, 104 | "check-branch", 105 | "check-decl", 106 | "check-operator", 107 | "check-separator", 108 | "check-type" 109 | ], 110 | "directive-selector": [ 111 | true, 112 | "attribute", 113 | "app", 114 | "camelCase" 115 | ], 116 | "component-selector": [ 117 | true, 118 | "element", 119 | "app", 120 | "kebab-case" 121 | ], 122 | "use-input-property-decorator": true, 123 | "use-output-property-decorator": true, 124 | "use-host-property-decorator": true, 125 | "no-input-rename": true, 126 | "no-output-rename": true, 127 | "use-life-cycle-interface": true, 128 | "use-pipe-transform-interface": true, 129 | "component-class-suffix": true, 130 | "directive-class-suffix": true, 131 | "no-access-missing-member": true, 132 | "templates-use-public": true, 133 | "invoke-injectable": true 134 | } 135 | } 136 | --------------------------------------------------------------------------------