| @@ -2,9 +2,10 @@ import { NgModule } from '@angular/core'; | |||
| import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; | |||
| const routes: Routes = [ | |||
| { path: '', redirectTo: 'onboarding', pathMatch: 'full' }, | |||
| { path: '', redirectTo: 'login', pathMatch: 'full' }, | |||
| { path: 'onboarding', loadChildren: './onboarding/onboarding.module#OnboardingPageModule' }, | |||
| { path: 'login', loadChildren: './login/login.module#LoginPageModule' }, | |||
| { path: 'malls', loadChildren: './malls/malls.module#MallsPageModule' }, | |||
| ]; | |||
| @NgModule({ | |||
| @@ -1,14 +0,0 @@ | |||
| <ion-header> | |||
| <ion-toolbar> | |||
| <ion-title> | |||
| Ionic Blank | |||
| </ion-title> | |||
| </ion-toolbar> | |||
| </ion-header> | |||
| <ion-content> | |||
| <div class="ion-padding"> | |||
| The world is your oyster. | |||
| <p>If you get lost, the <a target="_blank" rel="noopener" href="https://ionicframework.com/docs/">docs</a> will be your guide.</p> | |||
| </div> | |||
| </ion-content> | |||
| @@ -1 +0,0 @@ | |||
| @@ -1,24 +0,0 @@ | |||
| import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { IonicModule } from '@ionic/angular'; | |||
| import { HomePage } from './home.page'; | |||
| describe('HomePage', () => { | |||
| let component: HomePage; | |||
| let fixture: ComponentFixture<HomePage>; | |||
| beforeEach(async(() => { | |||
| TestBed.configureTestingModule({ | |||
| declarations: [ HomePage ], | |||
| imports: [IonicModule.forRoot()] | |||
| }).compileComponents(); | |||
| fixture = TestBed.createComponent(HomePage); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| })); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -1,12 +0,0 @@ | |||
| import { Component } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-home', | |||
| templateUrl: 'home.page.html', | |||
| styleUrls: ['home.page.scss'], | |||
| }) | |||
| export class HomePage { | |||
| constructor() {} | |||
| } | |||
| @@ -23,7 +23,7 @@ | |||
| <a class="forgot-link"> Forgot Password? </a> | |||
| <ion-button class="login-button" shape="round" size="block"> Sign In </ion-button> | |||
| <ion-button class="login-button" shape="round" size="block" (click)="login()"> Sign In </ion-button> | |||
| <p class="signin-description"> Don't have account? <a (click)="signup()">Sign Up</a> </p> | |||
| </section> | |||
| @@ -45,7 +45,7 @@ header { | |||
| ion-icon { | |||
| font-size: 20px; | |||
| margin: 0 15px; | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| } | |||
| input { | |||
| @@ -61,7 +61,7 @@ header { | |||
| .forgot-link { | |||
| font-weight: bold; | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| font-size: 10px; | |||
| letter-spacing: 0.5px; | |||
| width: 85%; | |||
| @@ -70,7 +70,7 @@ header { | |||
| } | |||
| .login-button { | |||
| --background: var(--brand-voilet); | |||
| --background: var(--brand-blue); | |||
| text-transform: none; | |||
| width: 85%; | |||
| margin: 0 auto 20px; | |||
| @@ -89,7 +89,7 @@ header { | |||
| margin: 0 auto 20px; | |||
| a { | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| font-family: 'M PLUS Rounded 1c'; | |||
| font-weight: bold; | |||
| } | |||
| @@ -25,4 +25,8 @@ export class LoginPage implements OnInit { | |||
| this.router.navigate(['/onboarding']); | |||
| } | |||
| login() { | |||
| this.router.navigate(['/malls']); | |||
| } | |||
| } | |||
| @@ -1,23 +1,26 @@ | |||
| import { NgModule } from '@angular/core'; | |||
| import { CommonModule } from '@angular/common'; | |||
| import { IonicModule } from '@ionic/angular'; | |||
| import { FormsModule } from '@angular/forms'; | |||
| import { RouterModule } from '@angular/router'; | |||
| import { Routes, RouterModule } from '@angular/router'; | |||
| import { IonicModule } from '@ionic/angular'; | |||
| import { MallsPage } from './malls.page'; | |||
| import { HomePage } from './home.page'; | |||
| const routes: Routes = [ | |||
| { | |||
| path: '', | |||
| component: MallsPage | |||
| } | |||
| ]; | |||
| @NgModule({ | |||
| imports: [ | |||
| CommonModule, | |||
| FormsModule, | |||
| IonicModule, | |||
| RouterModule.forChild([ | |||
| { | |||
| path: '', | |||
| component: HomePage | |||
| } | |||
| ]) | |||
| RouterModule.forChild(routes) | |||
| ], | |||
| declarations: [HomePage] | |||
| declarations: [MallsPage] | |||
| }) | |||
| export class HomePageModule {} | |||
| export class MallsPageModule {} | |||
| @@ -0,0 +1,66 @@ | |||
| <ion-content> | |||
| <section class="header-bar"> | |||
| <h2> Find malls near you </h2> | |||
| <button> <ion-icon name="search"></ion-icon> </button> | |||
| </section> | |||
| <div class="tabs-holder"> | |||
| <button (click)="selected_tab = 'you'" class="tab" [ngClass]="{'active' : selected_tab === 'you'}"> For you </button> | |||
| <button (click)="selected_tab = 'recomended'" class="tab" [ngClass]="{'active' : selected_tab === 'recomended'}"> Recommended </button> | |||
| <button (click)="selected_tab = 'trendy'" class="tab" [ngClass]="{'active' : selected_tab === 'trendy'}"> Trendy </button> | |||
| <button (click)="selected_tab = 'recent'" class="tab" [ngClass]="{'active' : selected_tab === 'recent'}"> Recent </button> | |||
| </div> | |||
| <div class="results-utilities-holder"> | |||
| <h5> 15 MALLS </h5> | |||
| <ion-button color="default" fill="clear"> SORT / FILTER </ion-button> | |||
| </div> | |||
| <ion-list lines="none" class="malls-list"> | |||
| <ion-item *ngFor="let mall of malls"> | |||
| <img src="{{ mall.image_url }}" slot="start"> | |||
| <ion-label> | |||
| <h3> {{ mall.name }} <ion-icon name="bookmark" [ngClass]="{'active' : mall.is_bookmarked }"></ion-icon> </h3> | |||
| <p class="description"> {{ mall.description }} </p> | |||
| <div class="offers-holder"> | |||
| <div class="offer" *ngFor="let offer of mall.offers_collection"> | |||
| {{ offer.name }}: <strong> {{ offer.offer.length }} </strong> | |||
| </div> | |||
| </div> | |||
| <div class="utilities-holder"> | |||
| <div class="container"> | |||
| <div class="utility"> | |||
| <ion-icon name="star"></ion-icon> {{ mall.rating }} | |||
| </div> | |||
| <div class="utility"> | |||
| <ion-icon name="pin"></ion-icon> {{ mall.distance }} km | |||
| </div> | |||
| </div> | |||
| <div class="container"> | |||
| <button class="utility-button"> | |||
| <ion-icon name="share"></ion-icon> | |||
| </button> | |||
| <a class="utility-button" target="_blank" | |||
| href="https://maps.google.com/?q={{ mall.location.latitude }},{{ mall.location.longitude }}"> | |||
| <ion-icon name="navigate"></ion-icon> | |||
| </a> | |||
| </div> | |||
| </div> | |||
| </ion-label> | |||
| </ion-item> | |||
| </ion-list> | |||
| <section class="advertisement"> | |||
| <div class="heading-holder"> | |||
| <img src="assets/custom/logo.svg"> | |||
| <header> | |||
| MALL FASTRACK - <span> Get your food faster then any others </span> | |||
| </header> | |||
| </div> | |||
| <p class="description"> | |||
| Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta eius molestiae ipsum fugit velit voluptatem vel ad ut debitis earum, nostrum numquam odio maxime eaque corporis! Non et cumque, dignissimos. | |||
| </p> | |||
| <a> Know More </a> | |||
| </section> | |||
| </ion-content> | |||
| @@ -0,0 +1,200 @@ | |||
| .header-bar { | |||
| background-color: var(--brand-blue); | |||
| color: white; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| padding: 20px; | |||
| align-items: center; | |||
| h2 { | |||
| font-size: 20px; | |||
| margin: 0; | |||
| } | |||
| button { | |||
| margin: 0; | |||
| border-radius: 50%; | |||
| color: var(--brand-blue); | |||
| width: 40px; | |||
| height: 40px; | |||
| background-color: white; | |||
| font-size: 20px; | |||
| } | |||
| } | |||
| .tabs-holder { | |||
| background-color: var(--brand-blue); | |||
| width: 100%; | |||
| padding: 0 20px 20px; | |||
| overflow: scroll; | |||
| white-space: nowrap; | |||
| button { | |||
| display: inline-block; | |||
| border-radius: 20px; | |||
| background-color: transparent; | |||
| color: white; | |||
| font-size: 10px; | |||
| padding: 5px 15px; | |||
| height: 30px; | |||
| margin-right: 10px; | |||
| font-weight: bold; | |||
| &.active { | |||
| background-color: white; | |||
| color: var(--brand-blue); | |||
| } | |||
| } | |||
| } | |||
| .results-utilities-holder { | |||
| display: flex; | |||
| width: 100%; | |||
| margin: 10px auto 0; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| font-weight: bold; | |||
| h5 { | |||
| margin: 0 0 0 10px; | |||
| color: var(--brand-grey); | |||
| font-size: 10px; | |||
| } | |||
| ion-button { | |||
| margin: 0; | |||
| font-size: 10px; | |||
| padding: 0; | |||
| } | |||
| } | |||
| .malls-list ion-item { | |||
| margin: 0 0 20px; | |||
| ion-label { | |||
| padding: 0; | |||
| margin: 0; | |||
| } | |||
| img { | |||
| align-self: flex-start; | |||
| width: 70px; | |||
| height: 70px; | |||
| object-fit: cover; | |||
| margin-right: 15px; | |||
| } | |||
| h3 { | |||
| margin: 0; | |||
| color: var(--brand-dark-grey); | |||
| font-weight: 500; | |||
| font-size: 14px; | |||
| letter-spacing: 0.5px; | |||
| text-overflow: ellipsis; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| ion-icon { | |||
| color: var(--brand-grey); | |||
| font-size: 16px; | |||
| } | |||
| } | |||
| .description { | |||
| font-size: 12px; | |||
| color: var(--brand-grey); | |||
| } | |||
| .offers-holder { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| color: var(--brand-yellow); | |||
| letter-spacing: 0.5px; | |||
| border-bottom: 1px solid var(--brand-grey); | |||
| padding: 7px 0; | |||
| margin-bottom: 7px; | |||
| .offer { | |||
| font-size: 10px; | |||
| width: 50%; | |||
| } | |||
| } | |||
| .utilities-holder { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| .container { | |||
| display: flex; | |||
| width: 40%; | |||
| justify-content: space-between; | |||
| .utility { | |||
| width: 50%; | |||
| font-size: 10px; | |||
| color: var(--brand-grey); | |||
| font-weight: bold; | |||
| } | |||
| .utility-button { | |||
| text-align: right; | |||
| width: 50%; | |||
| background-color: transparent; | |||
| border: 0; | |||
| font-size: 16px; | |||
| color: var(--brand-grey); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .advertisement { | |||
| position: sticky; | |||
| bottom: 0; | |||
| left: 0; | |||
| height: 150px; | |||
| background-color: var(--brand-blue); | |||
| color: white; | |||
| padding: 15px; | |||
| width: 100%; | |||
| .heading-holder { | |||
| display: flex; | |||
| width: 100%; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| img { | |||
| width: 45px; | |||
| background-color: white; | |||
| height: 45px; | |||
| border-radius: 50%; | |||
| padding: 10px; | |||
| } | |||
| header { | |||
| margin-left: 15px; | |||
| font-size: 14px; | |||
| font-weight: 500; | |||
| span { | |||
| font-weight: 400; | |||
| font-size: 12px; | |||
| } | |||
| } | |||
| } | |||
| .description { | |||
| font-size: 12px; | |||
| text-overflow: ellipsis; | |||
| overflow: hidden; | |||
| white-space: nowrap; | |||
| } | |||
| a { | |||
| font-size: 12px; | |||
| text-decoration: underline; | |||
| color: white; | |||
| } | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; | |||
| import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { MallsPage } from './malls.page'; | |||
| describe('MallsPage', () => { | |||
| let component: MallsPage; | |||
| let fixture: ComponentFixture<MallsPage>; | |||
| beforeEach(async(() => { | |||
| TestBed.configureTestingModule({ | |||
| declarations: [ MallsPage ], | |||
| schemas: [CUSTOM_ELEMENTS_SCHEMA], | |||
| }) | |||
| .compileComponents(); | |||
| })); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(MallsPage); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,81 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-malls', | |||
| templateUrl: './malls.page.html', | |||
| styleUrls: ['./malls.page.scss'], | |||
| }) | |||
| export class MallsPage implements OnInit { | |||
| selected_tab = 'you'; | |||
| malls = [{ | |||
| id: '00001', | |||
| name: 'Gopalan Mall', | |||
| is_bookmarked: false, | |||
| image_url: 'https://images.jdmagicbox.com/comp/chennai/s2/044pxx44.xx44.171122071536.w6s2/catalogue/v-r-mall-anna-nagar-chennai-malls-jwyyh0m5kq-t.jpg', | |||
| description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', | |||
| offers_collection: [{ | |||
| name: 'Food', | |||
| offer: [{ | |||
| name: 'McDonalds Offer', | |||
| description: 'Get 25% offer on you first meal', | |||
| cupon_code: 'MCD25F' | |||
| }] | |||
| }, { | |||
| name: 'Shopping', | |||
| offer: [] | |||
| }], | |||
| rating: 4.3, | |||
| distance: 2, | |||
| location: { | |||
| latitude: 12.903903292, | |||
| longitude: 34.940349039 | |||
| } | |||
| }, | |||
| { | |||
| id: '00002', | |||
| name: 'Gopalan Mall 2', | |||
| is_bookmarked: false, | |||
| image_url: 'https://images.jdmagicbox.com/comp/chennai/s2/044pxx44.xx44.171122071536.w6s2/catalogue/v-r-mall-anna-nagar-chennai-malls-jwyyh0m5kq-t.jpg', | |||
| description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', | |||
| offers_collection: [{ | |||
| name: 'Food', | |||
| offer: [] | |||
| }, { | |||
| name: 'Shopping', | |||
| offer: [] | |||
| }], | |||
| rating: 4.3, | |||
| distance: 2, | |||
| location: { | |||
| latitude: 12.903903292, | |||
| longitude: 34.940349039 | |||
| } | |||
| }, | |||
| { | |||
| id: '00003', | |||
| name: 'Gopalan Mall 3', | |||
| is_bookmarked: false, | |||
| image_url: 'https://images.jdmagicbox.com/comp/chennai/s2/044pxx44.xx44.171122071536.w6s2/catalogue/v-r-mall-anna-nagar-chennai-malls-jwyyh0m5kq-t.jpg', | |||
| description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', | |||
| offers_collection: [{ | |||
| name: 'Food', | |||
| offer: [] | |||
| }, { | |||
| name: 'Shopping', | |||
| offer: [] | |||
| }], | |||
| rating: 4.3, | |||
| distance: 2, | |||
| location: { | |||
| latitude: 12.903903292, | |||
| longitude: 34.940349039 | |||
| } | |||
| }] | |||
| constructor() { } | |||
| ngOnInit() { | |||
| } | |||
| } | |||
| @@ -189,7 +189,7 @@ | |||
| Thanks for taking your time to create account with us. | |||
| Now this is the fun part, let's explore the app. | |||
| </p> | |||
| <ion-button class="next-button" shape="round"> | |||
| <ion-button class="next-button" shape="round" (click)="enterMalls()"> | |||
| Get Started | |||
| </ion-button> | |||
| </ion-slide> | |||
| @@ -36,7 +36,7 @@ ion-slide { | |||
| } | |||
| .next-button { | |||
| --background: var(--brand-voilet); | |||
| --background: var(--brand-blue); | |||
| text-transform: none; | |||
| width: 85%; | |||
| margin: 0 auto 20px; | |||
| @@ -55,7 +55,7 @@ ion-slide { | |||
| margin: 0 auto 20px; | |||
| a { | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| font-family: 'M PLUS Rounded 1c'; | |||
| font-weight: bold; | |||
| } | |||
| @@ -192,7 +192,7 @@ ion-slide { | |||
| ion-icon { | |||
| font-size: 20px; | |||
| margin: 0 15px; | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| } | |||
| input { | |||
| @@ -232,7 +232,7 @@ ion-slide { | |||
| &.active { | |||
| .check-ball { | |||
| background-color: var(--brand-voilet); | |||
| background-color: var(--brand-blue); | |||
| } | |||
| } | |||
| } | |||
| @@ -252,7 +252,7 @@ ion-slide { | |||
| .icon-holder { | |||
| text-align: center; | |||
| font-size: 5rem; | |||
| color: var(--brand-voilet); | |||
| color: var(--brand-blue); | |||
| margin: 70px auto 0; | |||
| } | |||
| } | |||
| @@ -290,7 +290,7 @@ ion-slide { | |||
| } | |||
| .next-button { | |||
| --color: var(--brand-voilet); | |||
| --color: var(--brand-blue); | |||
| --background: white; | |||
| } | |||
| } | |||
| @@ -71,4 +71,8 @@ export class OnboardingPage implements OnInit { | |||
| this.router.navigate(['/login']); | |||
| } | |||
| enterMalls() { | |||
| this.router.navigate(['/malls']); | |||
| } | |||
| } | |||
| @@ -32,6 +32,7 @@ | |||
| ion-button, button, a, p, div, input { | |||
| font-family: 'Roboto', sans-serif; | |||
| text-transform: none; | |||
| outline: none; | |||
| } | |||
| figure { | |||
| @@ -75,8 +75,11 @@ | |||
| --ion-color-light-shade: #d7d8da; | |||
| --ion-color-light-tint: #f5f6f9; | |||
| --brand-voilet: #8173e6; | |||
| --brand-blue: #8173e6; | |||
| --background-blue: #f5f7fa; | |||
| --brand-grey: #9a9a9a; | |||
| --brand-black: #1b1d1e; | |||
| --brand-blue: #1a4fc2; | |||
| --brand-dark-grey: #666666; | |||
| --brand-yellow: #f79319; | |||
| } | |||