| @@ -1,17 +1,39 @@ | |||
| <ion-content *ngIf="mall_details"> | |||
| <ion-content [scrollEvents]="true" *ngIf="mall_details" (ionScroll)="onScroll($event)"> | |||
| <div class="header-bar" [ngClass]="{'active' : show_top_bar }"> | |||
| <div class="heading-holder"> | |||
| <button (click)="back()"> <ion-icon name="arrow-back"></ion-icon> </button> | |||
| <h3> {{ mall_details.name }} </h3> | |||
| </div> | |||
| <div class="stats-holder"> | |||
| <div class="stat"> <ion-icon name="star"></ion-icon> {{ mall_details.rating }} </div> | |||
| <div class="stat"> <ion-icon name="pin"></ion-icon> {{ mall_details.distance }} km</div> | |||
| </div> | |||
| <div class="utilities-buttons-holder"> | |||
| <button [ngClass]="{'active' : mall_details.is_bookmarked }" (click)="toggleBookmark(mall_details)"> <ion-icon name="bookmark"></ion-icon> </button> | |||
| <button> <ion-icon name="share"></ion-icon> </button> | |||
| <a target="_blank" href="https://maps.google.com/?q={{ mall_details.location.latitude }},{{ mall_details.location.longitude }}"> | |||
| <ion-icon name="navigate"></ion-icon> | |||
| </a> | |||
| </div> | |||
| </div> | |||
| <div class="upfold-holder"> | |||
| <img src="{{ mall_details.image_url }}"> | |||
| <div class="icons-holder"> | |||
| <div> | |||
| <button> <ion-icon name="arrow-back"></ion-icon> </button> | |||
| <button (click)="back()"> <ion-icon name="arrow-back"></ion-icon> </button> | |||
| </div> | |||
| <div> | |||
| <button [ngClass]="{'active' : mall_details.is_bookmarked }"> <ion-icon name="bookmark"></ion-icon> </button> | |||
| <button [ngClass]="{'active' : mall_details.is_bookmarked }" (click)="toggleBookmark(mall_details)"> | |||
| <ion-icon name="bookmark"></ion-icon> | |||
| </button> | |||
| <button> <ion-icon name="share"></ion-icon> </button> | |||
| </div> | |||
| </div> | |||
| <div class="icons-holder navigate-button"> | |||
| <button> <ion-icon name="navigate"></ion-icon> </button> | |||
| <a target="_blank" href="https://maps.google.com/?q={{ mall_details.location.latitude }},{{ mall_details.location.longitude }}"> | |||
| <ion-icon name="navigate"></ion-icon> | |||
| </a> | |||
| </div> | |||
| </div> | |||
| <div class="card-holder"> | |||
| @@ -27,9 +49,93 @@ | |||
| <div class="tabs-holder" [ngClass]="{ 'right' : selected_tab === 'shopping' }"> | |||
| <button class="tab" [ngClass]="{ 'active' : selected_tab === 'food' }" | |||
| (click)="selected_tab = 'food'"> FOOD OFFERS </button> | |||
| (click)="selected_tab = 'food'"> FOOD OUTLETS </button> | |||
| <button class="tab" [ngClass]="{ 'active' : selected_tab === 'shopping' }" | |||
| (click)="selected_tab = 'shopping'"> SHOPPING OFFERS </button> | |||
| (click)="selected_tab = 'shopping'"> SHOPS </button> | |||
| </div> | |||
| <div class="results-utilities-holder"> | |||
| <h5 *ngIf="mall_details"> {{ mall_details.outlets.length }} OUTLETS </h5> | |||
| <ion-button color="default" fill="clear"> SORT / FILTER </ion-button> | |||
| </div> | |||
| <ion-list lines="none" class="result-list" *ngIf="selected_tab === 'food'"> | |||
| <ion-item *ngFor="let outlet of mall_details.outlets" [ngClass]="{'show' : outlet.is_food_outlet }"> | |||
| <img src="{{ outlet.image_url }}" slot="start"> | |||
| <ion-label> | |||
| <h3> | |||
| {{ outlet.name }} | |||
| <div class="rating-holder"> | |||
| <ion-icon name="star"></ion-icon> {{ outlet.rating }} | |||
| </div> | |||
| <ion-icon name="bookmark" [ngClass]="{'active' : outlet.is_bookmarked }"></ion-icon> | |||
| </h3> | |||
| <p class="description"> | |||
| {{ outlet.description }} | |||
| <button class="share-button"> | |||
| <ion-icon name="share"></ion-icon> | |||
| </button> | |||
| </p> | |||
| <div class="offers-holder"> | |||
| <div class="offer"> | |||
| <span *ngIf="outlet.is_food_outlet"> <ion-icon name="restaurant"></ion-icon> Food </span> | |||
| <span *ngIf="!outlet.is_food_outlet"> <ion-icon name="basket"></ion-icon> Shopping </span> | |||
| Offers: <strong> {{ outlet.offers.length }} </strong> | |||
| </div> | |||
| </div> | |||
| </ion-label> | |||
| </ion-item> | |||
| </ion-list> | |||
| <ion-list lines="none" class="result-list" *ngIf="selected_tab === 'shopping'"> | |||
| <ion-item *ngFor="let outlet of mall_details.outlets" [ngClass]="{'show' : !outlet.is_food_outlet }"> | |||
| <img src="{{ outlet.image_url }}" slot="start"> | |||
| <ion-label> | |||
| <h3> | |||
| {{ outlet.name }} | |||
| <div class="rating-holder"> | |||
| <ion-icon name="star"></ion-icon> {{ outlet.rating }} | |||
| </div> | |||
| <ion-icon name="bookmark" [ngClass]="{'active' : outlet.is_bookmarked }"></ion-icon> | |||
| </h3> | |||
| <p class="description"> | |||
| {{ outlet.description }} | |||
| <button class="share-button"> | |||
| <ion-icon name="share"></ion-icon> | |||
| </button> | |||
| </p> | |||
| <div class="offers-holder"> | |||
| <div class="offer"> | |||
| <span *ngIf="outlet.is_food_outlet"> <ion-icon name="restaurant"></ion-icon> Food </span> | |||
| <span *ngIf="!outlet.is_food_outlet"> <ion-icon name="basket"></ion-icon> Shopping </span> | |||
| Offers: <strong> {{ outlet.offers.length }} </strong> | |||
| </div> | |||
| </div> | |||
| </ion-label> | |||
| </ion-item> | |||
| </ion-list> | |||
| <div class="advertisement-slots"> | |||
| <figure> | |||
| <img src="https://static.couponspy.in/picture/coupon/89472.jpg"> | |||
| </figure> | |||
| <figure> | |||
| <img src="https://content.adidas.co.in/static/sign_up_popup/sign_up_popup.jpg"> | |||
| </figure> | |||
| <figure> | |||
| <img src="https://fsmc.s3.amazonaws.com/a/90804/adidas.jpg"> | |||
| </figure> | |||
| <figure> | |||
| <img src="https://static.couponspy.in/picture/coupon/89472.jpg"> | |||
| </figure> | |||
| <figure> | |||
| <img src="https://static.couponspy.in/picture/coupon/89472.jpg"> | |||
| </figure> | |||
| </div> | |||
| </ion-content> | |||
| @@ -1,3 +1,84 @@ | |||
| .header-bar { | |||
| background-image: url('../../assets/custom/background-2.svg'); | |||
| background-size: cover; | |||
| background-repeat: no-repeat; | |||
| background-position: left top; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| padding: 15px; | |||
| height: 75px; | |||
| z-index: 2; | |||
| pointer-events: none; | |||
| opacity: 0; | |||
| top: 0; | |||
| left: 0; | |||
| width: 100%; | |||
| position: fixed; | |||
| transition: opacity 0.5s; | |||
| box-shadow: 0px 3px 5px var(--brand-grey); | |||
| &.active { | |||
| opacity: 1; | |||
| pointer-events: all; | |||
| } | |||
| .heading-holder { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| button, a { | |||
| background-color: white; | |||
| color: var(--brand-blue); | |||
| font-size: 18px; | |||
| padding: 5px; | |||
| border-radius: 50%; | |||
| height: 30px; | |||
| width: 30px; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| &.active { | |||
| color: white; | |||
| background-color: var(--brand-blue); | |||
| } | |||
| } | |||
| h3 { | |||
| font-size: 16px; | |||
| color: white; | |||
| letter-spacing: 0.5px; | |||
| margin-left: 10px; | |||
| font-weight: 600; | |||
| } | |||
| .stats-holder { | |||
| font-size: 10px; | |||
| color: white; | |||
| display: flex; | |||
| align-items: center; | |||
| .stat { | |||
| margin-left: 10px; | |||
| } | |||
| } | |||
| .utilities-buttons-holder { | |||
| position: absolute; | |||
| right: 15px; | |||
| bottom: -15px; | |||
| display: flex; | |||
| align-items: center; | |||
| button, a { | |||
| margin-left: 10px; | |||
| box-shadow: 0px 3px 5px var(--brand-grey); | |||
| } | |||
| } | |||
| } | |||
| .upfold-holder { | |||
| position: relative; | |||
| height: 45vh; | |||
| @@ -17,9 +98,15 @@ | |||
| left: 86%; | |||
| bottom: 30px; | |||
| width: auto; | |||
| a { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| } | |||
| button { | |||
| button, a { | |||
| background-color: white; | |||
| color: var(--brand-blue); | |||
| font-size: 18px; | |||
| @@ -135,3 +222,71 @@ | |||
| } | |||
| } | |||
| } | |||
| .result-list { | |||
| ion-item { | |||
| display: none; | |||
| &.show { | |||
| display: block; | |||
| } | |||
| h3 .rating-holder { | |||
| font-size: 9px; | |||
| margin-left: auto; | |||
| align-self: flex-start; | |||
| display: flex; | |||
| align-items: flex-end; | |||
| margin-right: 10px; | |||
| ion-icon { | |||
| font-size: 12px; | |||
| margin-right: 3px; | |||
| } | |||
| } | |||
| .offers-holder { | |||
| border-bottom: 0; | |||
| border-top: 1px solid #efefef; | |||
| .offer { | |||
| ion-icon { | |||
| color: var(--brand-grey); | |||
| transform: scale(1.1); | |||
| } | |||
| } | |||
| } | |||
| .description { | |||
| margin: 5px 0; | |||
| .share-button { | |||
| float: right; | |||
| font-size: 14px; | |||
| background-color: transparent; | |||
| border: 0px; | |||
| color: var(--brand-dark-grey); | |||
| padding: 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .advertisement-slots { | |||
| white-space: nowrap; | |||
| width: 100%; | |||
| overflow-x: auto; | |||
| figure { | |||
| margin: 0; | |||
| display: inline-block; | |||
| width: 100px; | |||
| height: 100px; | |||
| margin: 0 5px; | |||
| img { | |||
| object-fit: cover; | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import { ActivatedRoute, Router } from '@angular/router'; | |||
| import { Mall, MallService } from '../services/mall.service'; | |||
| import { Location } from '@angular/common'; | |||
| @Component({ | |||
| selector: 'app-mall-details', | |||
| @@ -10,11 +11,13 @@ import { Mall, MallService } from '../services/mall.service'; | |||
| export class MallDetailsPage implements OnInit { | |||
| mall_details: Mall; | |||
| selected_tab: string = 'food'; | |||
| show_top_bar: boolean = false; | |||
| constructor( | |||
| private mallService: MallService, | |||
| private route: ActivatedRoute, | |||
| private router: Router | |||
| private router: Router, | |||
| private location: Location | |||
| ) { } | |||
| ngOnInit() { | |||
| @@ -25,4 +28,30 @@ export class MallDetailsPage implements OnInit { | |||
| }); | |||
| } | |||
| refresh() { | |||
| let mall_id = this.route.snapshot.paramMap.get('mall_id'); | |||
| this.mallService.getMallByID(mall_id).then((data: Mall) => { | |||
| this.mall_details = data; | |||
| }); | |||
| } | |||
| back() { | |||
| this.location.back(); | |||
| } | |||
| toggleBookmark(mall_details: Mall) { | |||
| mall_details.is_bookmarked = !mall_details.is_bookmarked; | |||
| this.mallService.updateMallDetails(mall_details).then(() => this.refresh()); | |||
| } | |||
| onScroll(event: any) { | |||
| if (event.detail.scrollTop > 100) { | |||
| this.show_top_bar = true; | |||
| } else { | |||
| this.show_top_bar = false; | |||
| } | |||
| } | |||
| } | |||
| @@ -15,11 +15,11 @@ | |||
| </div> | |||
| <div class="results-utilities-holder"> | |||
| <h5> 15 MALLS </h5> | |||
| <h5 *ngIf="malls"> {{ malls.length }} MALLS </h5> | |||
| <ion-button color="default" fill="clear"> SORT / FILTER </ion-button> | |||
| </div> | |||
| <ion-list lines="none" class="malls-list"> | |||
| <ion-list lines="none" class="result-list"> | |||
| <ion-item *ngFor="let mall of malls" (click)="showMallDetails(mall)"> | |||
| <img src="{{ mall.image_url }}" slot="start"> | |||
| <ion-label> | |||
| @@ -69,7 +69,7 @@ | |||
| <a> Know More </a> | |||
| </section> | |||
| <ion-list lines="none" class="malls-list"> | |||
| <ion-list lines="none" class="result-list"> | |||
| <ion-item *ngFor="let mall of malls" (click)="showMallDetails(mall)"> | |||
| <img src="{{ mall.image_url }}" slot="start"> | |||
| <ion-label> | |||
| @@ -116,7 +116,7 @@ | |||
| <button> <ion-icon src="assets/custom/food-4.svg"></ion-icon> <span> Cake </span> </button> | |||
| </div> | |||
| <ion-list lines="none" class="malls-list"> | |||
| <ion-list lines="none" class="result-list"> | |||
| <ion-item *ngFor="let mall of malls" (click)="showMallDetails(mall)"> | |||
| <img src="{{ mall.image_url }}" slot="start"> | |||
| <ion-label> | |||
| @@ -62,116 +62,6 @@ | |||
| } | |||
| } | |||
| .results-utilities-holder { | |||
| display: flex; | |||
| width: 100%; | |||
| margin: 10px auto 0; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| font-weight: bold; | |||
| &.no-padding { | |||
| margin: 0 auto; | |||
| } | |||
| 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; | |||
| &.active { | |||
| color: var(--brand-blue); | |||
| } | |||
| } | |||
| } | |||
| .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 { | |||
| height: 150px; | |||
| background-image: url('../../assets/custom/background-2.svg'); | |||
| @@ -10,8 +10,9 @@ type Outlet = { | |||
| id: string, | |||
| image_url?: string, | |||
| name: string, | |||
| type: string, | |||
| description: string, | |||
| offers: Array<Offer>, | |||
| is_food_outlet: boolean, | |||
| is_bookmarked: boolean, | |||
| rating: number, | |||
| }; | |||
| @@ -44,7 +45,29 @@ export class MallService { | |||
| is_archived: false, | |||
| image_url: 'https://www.gopalanmall.com/images/mall-arcade-01.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.', | |||
| outlets: [], | |||
| outlets: [{ | |||
| id: '0001', | |||
| image_url: 'https://images.markets.businessinsider.com/image/5a74835585cdd489228b47be-900/shutterstock643079686.jpg', | |||
| name: 'McDonalds', | |||
| description: 'Veg / Non-Veg Food Restaurant', | |||
| offers: [{ | |||
| name: 'McDonalds Offer', | |||
| description: 'Get 25% offer on you first meal', | |||
| coupon_code: 'MCD25F', | |||
| }], | |||
| is_food_outlet: true, | |||
| is_bookmarked: false, | |||
| rating: 3.5, | |||
| }, { | |||
| id: '0002', | |||
| image_url: 'https://pbs.twimg.com/profile_images/354890582/symbol.jpg', | |||
| name: 'Shopper\'s stop', | |||
| description: 'Clothing store', | |||
| offers: [], | |||
| is_food_outlet: false, | |||
| is_bookmarked: true, | |||
| rating: 4.8, | |||
| }], | |||
| offer_collection: [{ | |||
| name: 'Food', | |||
| offers: [{ | |||
| @@ -116,4 +139,13 @@ export class MallService { | |||
| public async getMallByID(id: string) { | |||
| return this.malls.find((mall) => mall.id === id); | |||
| } | |||
| public async updateMallDetails(mall_details: Mall) { | |||
| for (let i = 0; i < this.malls.length; i += 1) { | |||
| if (this.malls[i].id === mall_details.id) { | |||
| this.malls[i] = mall_details; | |||
| } | |||
| } | |||
| return this.malls; | |||
| } | |||
| } | |||
| @@ -168,3 +168,113 @@ header, h1, h2, h3, h4, h5 { | |||
| opacity: 0.5; | |||
| } | |||
| } | |||
| .results-utilities-holder { | |||
| display: flex; | |||
| width: 100%; | |||
| margin: 10px auto 0; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| font-weight: bold; | |||
| &.no-padding { | |||
| margin: 0 auto; | |||
| } | |||
| h5 { | |||
| margin: 0 0 0 10px; | |||
| color: var(--brand-grey); | |||
| font-size: 10px; | |||
| } | |||
| ion-button { | |||
| margin: 0; | |||
| font-size: 10px; | |||
| padding: 0; | |||
| } | |||
| } | |||
| .result-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; | |||
| &.active { | |||
| color: var(--brand-blue); | |||
| } | |||
| } | |||
| } | |||
| .description { | |||
| font-size: 10px; | |||
| color: var(--brand-grey); | |||
| } | |||
| .offers-holder { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| color: var(--brand-yellow); | |||
| letter-spacing: 0.5px; | |||
| border-bottom: 1px solid #efefef; | |||
| 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); | |||
| } | |||
| } | |||
| } | |||
| } | |||