{"version":3,"file":"src_app_modules_menu_menu_module_ts.448e27c8f060d55b.js","mappings":"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","names":["DisplayOccasionType","Collection","Delivery","Dinein","Takeaway","MenuComponent","_MenuComponent","AndroWebCoreComponent","constructor","router","_datePipe","_seoService","_menuService","_siteService","_toastService","_basketService","_activatedRoute","_checkoutService","_navigatorService","_menuHelperService","_menuDealHelperService","_structuredDataService","_menuVariantHelperService","super","this","isLoading","navigationSectionType","NavigationSectionType","orderOccasion","OrderOccasion","_scrollDelay","showWebSectionImages","tenant","SuppressProductImages","ngOnInit","handleRouteParams","updatePageSEO","trackCurrentSite","getCurrentBasketBySiteId","trackCurrentMenu","trackCurrentBasket","trackNotifications","ngAfterViewInit","queryParams","pipe","filter","params","openBasket","takeUntil","destroy$","subscribe","basketModalContent","ngOnDestroy","_seoSet","restore","highlightCategoryName","visibleElement","getCategoryInView","name","nativeElement","id","highlightedCategoryName","scrollSectionButtonInToView","toggleSearchBar","showSearchBarExpanded","setSearchFieldFocus","searchText","navigateToDisplayGroup","$event","menuSection","preventDefault","customerName","clean","navigate","getSectionUrl","scrollToWebSection","updateSeoTitleAndDescription","currentSite","occasion","navigateToAndromeda","window","open","openWantedTimeModal","modal","openDialog","width","template","options","height","isTablet","panelClass","position","right","top","isShortDevice","menuUpdates","menu$","menu","noMenu","sections","getMenuSections","buildStructuredData","getProductSections","map","x","mapSectionToMenuSectionView","section","cleanName","Name","description","Description","Id","menuItems","mapToMenuItemView","imageBase","getMenuImageVisualAsset","data","isMobile","href","sectionName","generateRoutePath","_location","Menu","wantedTime","getWantedTimeOrLeadTime","basket","getProductsForSectionAndOccasion","Products","product","mapProductToMenuItemView","getDealsForSectionAndOccasion","Deals","RequiresUnlock","deal","mapDealToMenuItemView","i","available","sort","a","b","localeCompare","sequence","priceSummary","getPriceSummaryForVariants","Variants","outOfStock","every","variant","OutOfStock","Sequence","nutritionSummary","getNutritionSummary","areVariantsAvailableForOccasion","price","split","join","type","defaultVariantSummary","getVariantOptionsPathText","getDefaultVariant","productOptionsById","variants","upselling","Upselling","getMinPriceForDeal","availableForOccasion","Availability","Values","getPricePrefixForDeal","toFixed","groupName","element","document","getElementById","setTimeout","scrollIntoView","behavior","block","inline","trackBasketCount","total","length","Items","forEach","item","Product","Quantity","currentBasketCount","passedElements","_categoryElements","midWayOfScreen","body","clientHeight","getBoundingClientRect","push","pop","snapshot","paramMap","get","changeTakeAwayToCollection","capitalizedOccasion","charAt","toUpperCase","slice","trackTrace","SeverityLevel","Warning","generateHomePath","decodeURI","location","pathname","siteId","getSiteIdByLocation","jsonStructuredData","buildMenuStructuredData","jsonScript","createElement","setAttribute","textContent","head","appendChild","useDefault","updateTitle","address","_a","Address","locationDetails","Town","Postcode","updateDescription","replaceSEOStrings","changeCollectionToTakeAway","_b","menuPageSEO","PageSeos","find","seo","PageName","toLowerCase","Title","updateText","includes","replace","currentSite$","site","toLocaleLowerCase","setCurrentSiteBySiteId","_this","clearOldBasket","clearOldAndCreateNewBasket","_ref","error","trackException","goHome","next","_asyncToGenerator","Error","IsModifiable","OrderId","deleteOrderById","catch","_x","apply","arguments","currentBasket$","isNewBasket","getAvailableOrderDates","basketWantedTime","getWantedTime","basketTotal","Charges","ChargeType","ChargeTypes","Total","Price","Amount","menuValue","activeNotifications$","notifications","url","showToast","ToastTypes","scrollTo","offsetTop","parent","catBar","offsetHeight","_searchElement","focus","searchFocusDelay","WantedTimeUtc","_date","Date","replaceZuluTime","transform","isToday","date","today","getDate","getMonth","_this2","dates","getTimeSlotsForBasket","isStoreOpen","Dates","AllowAsap","nextDate","setDate","lastValueFrom","getBasketsAvailableTimes","flatMap","Time","ViewChildren","args","ViewChild","HostListener","__decorate","Component","animations","trigger","transition","style","fontSize","animate","selector","__metadata","Router","DatePipe","SEOService","MenuService","SiteService","ToastsService","BasketService","ActivatedRoute","CheckoutService","NavigatorService","MenuHelperService","MenuDealHelperService","StructuredDataService","MenuVariantHelperService","ProductsDialogEntryComponent","_ProductsDialogEntryComponent","_router","toTitleCase","_group","productView","imageSource","isInDeal","allergens","getAllergenSummary","Allergens","save","event","onSave","updateProductSeoTitleAndDescription","openProductDialog","close","_dialogRef","response","addProductToBasket","itemPrice","HttpStatusCodeHandler","isSuccessResponse","config","ariaModal","_productModal","afterClosed","productId","productName","routePath","displayGroup","resetSEO","products_dialog_entry_component_metadata","DealsDialogEntryComponent","_DealsDialogEntryComponent","routeOccasion","group","openDealsModal","dealsPageSEO","title","result","deals_dialog_entry_component_metadata","routes","children","component","path","resolve","siteResolver","SiteResolver","MenuRoutingModule","NgModule","exports","RouterModule","imports","forChild","MenuCardComponent","_MenuCardComponent","_analyticsService","showImages","ngOnChanges","changes","_notification","trackNotification","getRoutePath","goToItemPage","menuItem","_isStoreOpen","openDisallowedModal","trackClickMenuItem","navigateByUrl","openUpsellModal","goToProductPage","goToDealPage","getDealRoutePath","addItemToBasket","stopPropagation","isProductSimple","payload","Modifiers","Item","Prices","Occasion","_occasion","_customerGroupName","_disallowedModal","autoFocus","disableClose","subscriptions$","activeNotification","unsubscribe","getProductRoutePath","dealId","getLocationBySiteId","_siteId","upsellOptions","Ids","mapToProductUpsellOption","upsellPrompt","Prompt","upsellDialogRef","_upsellModal","maxHeight","originalPrice","_wantedTime","Math","round","Number","EPSILON","trackClickProduct","Input","menu_card_component_metadata","AnalyticsService","FilterMenuItemsPipe","searchTerm","trim","lowerSearchTerm","menuItemHasSearchTerm","some","Pipe","standalone","DealUpsellModalComponent","_DealUpsellModalComponent","prompt","_onSelectDeal","EventEmitter","_onSelectMenuItem","selectDeal","emit","dialogRef","selectMenuItem","required","Output","deal_upsell_modal_component_metadata","MenuModule","declarations","CommonModule","SharedComponentsModule","WantedTimePickerComponent","___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___","__webpack_require__","___CSS_LOADER_EXPORT___","___CSS_LOADER_API_IMPORT___","module","toString"],"ignoreList":[],"sourceRoot":"webpack:///","sources":["./src/app/models/display-occasion-type.ts","./src/app/modules/menu/menu.component.ts","./src/app/modules/menu/components/products-dialog-entry/products-dialog-entry.component.ts","./src/app/modules/menu/components/deals-dialog-entry/deals-dialog-entry.component.ts","./src/app/modules/menu/menu-routing.module.ts","./src/app/modules/menu/components/menu-card/menu-card.component.ts","./src/app/modules/menu/pipes/menu-sections-filter.ts","./src/app/modules/menu/components/deal-upsell-modal/deal-upsell-modal.component.ts","./src/app/modules/menu/menu.module.ts","./src/app/modules/menu/components/deal-upsell-modal/deal-upsell-modal.component.css","./src/app/modules/menu/components/menu-card/menu-card.component.scss","./src/app/modules/menu/menu.component.scss"],"sourcesContent":["export enum DisplayOccasionType {\r\n Collection = 'Collection',\r\n Delivery = 'Delivery',\r\n Dinein = 'DineIn',\r\n Takeaway = 'Takeaway'\r\n}\r\n","import { ActivatedRoute, Params, Router } from '@angular/router';\r\nimport { AfterViewInit, Component, ElementRef, HostListener, OnDestroy, OnInit, QueryList, TemplateRef, ViewChild, ViewChildren } from '@angular/core';\r\nimport { ToastsService } from '@app/shared/services/toasts.service';\r\nimport { AndroWebCoreComponent } from '@app/core/AndroWebCoreComponent';\r\nimport { Basket } from '@app/models/basket';\r\nimport { BasketService } from '@app/api/basket.service';\r\nimport { CheckoutService } from '@app/api/checkout.service';\r\nimport { DisplayOccasionType } from '@app/models/display-occasion-type';\r\nimport { MenuService } from '@app/api/menu.service';\r\nimport { NavigationSectionType } from '@app/models/navigation/navigation-section-type';\r\nimport { NavigatorService } from '@app/core/navigator.service';\r\nimport { OrderOccasion } from '@app/models/order-occasion';\r\nimport { PageSEO } from '@app/models/page-seo';\r\nimport { SEOService } from '@app/shared/services/seo.service';\r\nimport { SeverityLevel } from '@microsoft/applicationinsights-web';\r\nimport { Site } from '@app/models/site';\r\nimport { SiteService } from '@app/api/site.service';\r\nimport { DatePipe } from '@angular/common';\r\nimport { BasketItem } from '@app/models/basket/basket-item';\r\nimport { ChargeTypes } from '@app/models/charge-types';\r\nimport { MatDialogConfig } from '@angular/material/dialog';\r\nimport { Charge } from '@app/models/Charge';\r\nimport { IDictionary } from '@app/models/IDictionary';\r\nimport { Observable, lastValueFrom, takeUntil } from 'rxjs';\r\nimport { filter } from 'rxjs/operators';\r\nimport { trigger, transition, style, animate } from '@angular/animations';\r\nimport { INotification } from '@app/models/INotification';\r\nimport { ToastTypes } from '@app/models/ToastTypes.enum';\r\nimport { IDaysTimeSlots } from '@app/models/wanted-time-picker/IDaysTimeSlots';\r\nimport { BasketAvailableTime } from '@app/models/basket-available-time';\r\nimport { Address } from '@app/models/Address';\r\nimport { MenuItemView } from '@app/models/menu/menu-item-view';\r\nimport { MenuSectionView } from '@app/models/menu/menu-section-view';\r\nimport { MenuHelperService } from '@app/shared/services/menu-helper/menu-helper.service';\r\nimport { Deal } from '@app/models/menu/deal';\r\nimport { Product } from '@app/models/menu/product';\r\nimport { MenuSection } from '@app/models/menu/menu-section';\r\nimport { Menu } from '@app/models/menu/menu';\r\nimport { MenuDealHelperService } from '@app/shared/services/menu-deal-helper/menu-deal-helper.service';\r\nimport { MenuVariantHelperService } from '@app/shared/services/menu-variant-helper/menu-variant-helper.service';\r\nimport { StructuredDataService } from '@app/shared/services/structured-data/structured-data.service';\r\nimport { getWantedTimeOrLeadTime } from '@app/shared/utils/date-utils';\r\n\r\n@Component({\r\n animations: [\r\n trigger('valueAnimation', [\r\n transition(':increment', [\r\n style({ fontSize: '22px' }),\r\n animate('0.5s ease', style('*'))\r\n ]\r\n ),\r\n transition(':decrement', [\r\n style({ fontSize: '22px' }),\r\n animate('0.5s ease', style('*'))\r\n ]\r\n )\r\n ])\r\n ],\r\n selector: 'app-menu',\r\n styleUrls: ['./menu.component.scss'],\r\n templateUrl: './menu.component.html'\r\n})\r\nexport class MenuComponent extends AndroWebCoreComponent implements OnInit, OnDestroy, AfterViewInit {\r\n @ViewChildren('categoryElement') private _categoryElements: QueryList;\r\n @ViewChild('search') private _searchElement: ElementRef;\r\n @ViewChild('basketModalContent') private basketModalContent: TemplateRef;\r\n\r\n public siteId: string;\r\n public searchText: string;\r\n public occasion: OrderOccasion;\r\n public highlightedCategoryName: string;\r\n public noMenu: boolean;\r\n public showSearchBarExpanded: boolean;\r\n public isLoading: boolean = true;\r\n public isStoreOpen: boolean;\r\n public navigationSectionType: typeof NavigationSectionType = NavigationSectionType;\r\n public basketWantedTime: string;\r\n public basket: Basket;\r\n public basketTotal: number;\r\n public notifications: IDictionary>;\r\n public currentBasketCount: number;\r\n public currentSite: Site;\r\n public orderOccasion: typeof OrderOccasion = OrderOccasion;\r\n public sections: MenuSectionView[];\r\n public showWebSectionImages: boolean;\r\n\r\n private _location: string;\r\n private _seoSet: boolean;\r\n private _scrollDelay: number = 200;\r\n\r\n constructor(\r\n public router: Router,\r\n private _datePipe: DatePipe,\r\n private _seoService: SEOService,\r\n private _menuService: MenuService,\r\n private _siteService: SiteService,\r\n private _toastService: ToastsService,\r\n private _basketService: BasketService,\r\n private _activatedRoute: ActivatedRoute,\r\n private _checkoutService: CheckoutService,\r\n private _navigatorService: NavigatorService,\r\n private _menuHelperService: MenuHelperService,\r\n private _menuDealHelperService: MenuDealHelperService,\r\n private _structuredDataService: StructuredDataService,\r\n private _menuVariantHelperService: MenuVariantHelperService\r\n ) {\r\n super();\r\n this.showWebSectionImages = this.tenant.SuppressProductImages;\r\n }\r\n\r\n ngOnInit() {\r\n this.handleRouteParams();\r\n this.updatePageSEO(false);\r\n this.trackCurrentSite();\r\n this.getCurrentBasketBySiteId();\r\n this.trackCurrentMenu();\r\n this.trackCurrentBasket();\r\n this.trackNotifications();\r\n }\r\n\r\n ngAfterViewInit() {\r\n this._activatedRoute.queryParams\r\n .pipe(\r\n filter((params: Params) => params.openBasket),\r\n takeUntil(this.destroy$)\r\n )\r\n .subscribe(() => {\r\n this.openBasket(this.basketModalContent);\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n super.ngOnDestroy();\r\n\r\n if (this._seoSet) {\r\n this._seoService.restore();\r\n }\r\n }\r\n\r\n /**\r\n * updates which category (web section) is highlighted whilst the user scrolls\r\n * @param $event\r\n */\r\n @HostListener('window:scroll')\r\n public highlightCategoryName(): void {\r\n const visibleElement: ElementRef = this.getCategoryInView();\r\n const name: string = visibleElement ? visibleElement.nativeElement.id : '';\r\n\r\n if (this.highlightedCategoryName !== name) {\r\n this.highlightedCategoryName = name;\r\n this.scrollSectionButtonInToView(name);\r\n }\r\n }\r\n\r\n /**\r\n * sets showSearchBarExpanded to true\r\n */\r\n public toggleSearchBar(): void {\r\n this.showSearchBarExpanded = !this.showSearchBarExpanded;\r\n\r\n if (this.showSearchBarExpanded) {\r\n this.setSearchFieldFocus();\r\n } else {\r\n this.searchText = '';\r\n }\r\n }\r\n\r\n /**\r\n * navigates to the displayGroup with the matching name\r\n * @param $event\r\n * @param menuSection\r\n */\r\n public navigateToDisplayGroup($event: MouseEvent, menuSection: MenuSectionView): void {\r\n $event.preventDefault();\r\n const customerName: string = this._navigatorService.clean(menuSection.name);\r\n this.router.navigate([this.getSectionUrl(customerName)]);\r\n this.highlightedCategoryName = customerName;\r\n this.scrollSectionButtonInToView(customerName);\r\n this.scrollToWebSection(customerName);\r\n this._seoService.updateSeoTitleAndDescription(this.currentSite, this.occasion, menuSection);\r\n }\r\n\r\n /**\r\n * opens `https://andromedapos.com/` in a new tab\r\n */\r\n public navigateToAndromeda(): void {\r\n window.open('https://andromedapos.com/');\r\n }\r\n\r\n /**\r\n * opens the order wanted time modal\r\n */\r\n public openWantedTimeModal(modal: TemplateRef): void {\r\n this.openDialog(modal, 'order-wanted-time-modal', { width: '' });\r\n }\r\n\r\n /**\r\n * opens a mat dialog with the basket template inside\r\n */\r\n public openBasket(template: TemplateRef): void {\r\n const options: MatDialogConfig = {\r\n height: this.isTablet ? '100%' : '90%',\r\n panelClass: 'basket-modal-window',\r\n position: {\r\n right: this.isTablet ? '0px' : '35px',\r\n top: this.isTablet ? '0' : (this.isShortDevice ? '45px' : '75px')\r\n },\r\n width: this.isTablet ? '100%' : '580px'\r\n };\r\n\r\n this.openDialog(template, 'basket-modal', options);\r\n }\r\n\r\n /**\r\n * tracks the current menu.\r\n */\r\n private trackCurrentMenu(): void {\r\n let menuUpdates: number = 0;\r\n\r\n this._menuService.menu$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((menu: Menu) => {\r\n this.noMenu = !menu;\r\n\r\n menuUpdates++;\r\n\r\n if (this.noMenu) {\r\n if (menuUpdates > 1) {\r\n this.isLoading = false;\r\n }\r\n\r\n return;\r\n }\r\n\r\n this.sections = this.getMenuSections(menu);\r\n this.buildStructuredData(menu);\r\n this.updatePageSEO(true);\r\n this.isLoading = false;\r\n });\r\n }\r\n\r\n /**\r\n * returns the menu sections for the given menu\r\n * @param menu\r\n */\r\n private getMenuSections(menu: Menu): MenuSectionView[] {\r\n return this._menuHelperService.getProductSections(menu, this.occasion).map((x: MenuSection) => this.mapSectionToMenuSectionView(x, menu));\r\n }\r\n\r\n /**\r\n * maps a MenuSection to a MenuSectionView\r\n * @param section\r\n * @param menu\r\n */\r\n private mapSectionToMenuSectionView(section: MenuSection, menu: Menu): MenuSectionView {\r\n const cleanName: string = this._navigatorService.clean(section.Name);\r\n\r\n return {\r\n name: section.Name,\r\n cleanName,\r\n description: section.Description,\r\n id: section.Id,\r\n menuItems: this.mapToMenuItemView(section, menu),\r\n imageBase: this.getMenuImageVisualAsset({ data: section, height: this.isMobile ? 99 : 185 }),\r\n href: this.getSectionUrl(cleanName)\r\n };\r\n }\r\n\r\n /**\r\n * returns the url for the given section\r\n * @param sectionName - needs to be a clean name {@link NavigatorService.clean}\r\n */\r\n private getSectionUrl(sectionName: string): string {\r\n return this._navigatorService.generateRoutePath(this._location, this.occasion, NavigationSectionType.Menu, sectionName);\r\n }\r\n\r\n /**\r\n * maps the products and deals to a MenuItemView\r\n */\r\n private mapToMenuItemView(section: MenuSection, menu: Menu): MenuItemView[] {\r\n const wantedTime: Date = getWantedTimeOrLeadTime(this.occasion, this.currentSite, this.basket);\r\n\r\n const products: MenuItemView[] = this._menuHelperService.getProductsForSectionAndOccasion(section, OrderOccasion[this.occasion], menu.Products)\r\n .map((product: Product) => this.mapProductToMenuItemView(product, wantedTime));\r\n\r\n const deals: MenuItemView[] = this._menuHelperService.getDealsForSectionAndOccasion(section, OrderOccasion[this.occasion], menu.Deals)\r\n .filter((x: Deal) => !x.RequiresUnlock)\r\n .map((deal: Deal) => this.mapDealToMenuItemView(deal, wantedTime));\r\n\r\n return [...products, ...deals]\r\n .filter((i: MenuItemView) => i.available)\r\n .sort((a: MenuItemView, b: MenuItemView) => a.name.localeCompare(b.name))\r\n .sort((a: MenuItemView, b: MenuItemView) => (a.sequence ?? 0) - (b.sequence ?? 0));\r\n }\r\n\r\n /**\r\n * maps a product to a MenuItemView\r\n * @param product\r\n * @param wantedTime\r\n */\r\n private mapProductToMenuItemView(product: Product, wantedTime: Date): MenuItemView {\r\n const priceSummary = this._menuVariantHelperService.getPriceSummaryForVariants(product.Variants, OrderOccasion[this.occasion]);\r\n return {\r\n id: product.Id,\r\n outOfStock: product.Variants.every((variant) => variant.OutOfStock),\r\n imageBase: this.getMenuImageVisualAsset({ data: product, height: this.isMobile ? 99 : 185 }),\r\n sequence: product.Sequence,\r\n name: product.Name,\r\n description: product.Description,\r\n nutritionSummary: this._menuVariantHelperService.getNutritionSummary(product.Variants, false),\r\n available: this._menuVariantHelperService.areVariantsAvailableForOccasion(product.Variants, OrderOccasion[this.occasion], wantedTime),\r\n priceSummary,\r\n price: +(priceSummary.split('from ').join('').split('£').join('')),\r\n type: 'product',\r\n defaultVariantSummary: this._menuHelperService.getVariantOptionsPathText(\r\n this._menuVariantHelperService.getDefaultVariant(product.Variants),\r\n this._menuService.productOptionsById\r\n ),\r\n variants: product.Variants,\r\n upselling: product.Upselling\r\n };\r\n }\r\n\r\n /**\r\n * maps a deal to a MenuItemView\r\n */\r\n private mapDealToMenuItemView(deal: Deal, wantedTime: Date): MenuItemView {\r\n const price = this._menuDealHelperService.getMinPriceForDeal(deal, OrderOccasion[this.occasion]);\r\n return {\r\n id: deal.Id,\r\n outOfStock: deal.OutOfStock,\r\n imageBase: this.getMenuImageVisualAsset({ data: deal, height: this.isMobile ? 99 : 185 }),\r\n sequence: deal.Sequence,\r\n name: deal.Name,\r\n description: deal.Description,\r\n available: this._menuHelperService.availableForOccasion(deal.Availability?.Values, OrderOccasion[this.occasion], wantedTime),\r\n priceSummary: this._menuDealHelperService.getPricePrefixForDeal(deal) + price.toFixed(2),\r\n price,\r\n type: 'deal'\r\n };\r\n }\r\n\r\n /**\r\n * scroll into view of the given group\r\n * @param groupName\r\n */\r\n private scrollSectionButtonInToView(groupName: string): void {\r\n const element: HTMLElement = document.getElementById(`li-${groupName}`);\r\n\r\n if (element) {\r\n setTimeout(() => {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });\r\n }, 100);\r\n }\r\n }\r\n\r\n /**\r\n * tracks the basket total.\r\n * @param basket\r\n */\r\n private trackBasketCount(basket: Basket): void {\r\n if (basket) {\r\n let total: number = basket.Deals?.length ?? 0;\r\n basket.Items?.forEach((item: BasketItem) => total += item.Product.Quantity);\r\n\r\n if (this.currentBasketCount !== total) {\r\n this.currentBasketCount = total;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * returns the category (web-section) that is in the top 50% of the users view.\r\n */\r\n private getCategoryInView(): ElementRef {\r\n const passedElements: ElementRef[] = [];\r\n\r\n this._categoryElements.forEach((element: ElementRef) => {\r\n const midWayOfScreen: number = document.body.clientHeight / 2;\r\n\r\n if (element.nativeElement.getBoundingClientRect().top < midWayOfScreen) {\r\n passedElements.push(element);\r\n }\r\n });\r\n\r\n return passedElements.pop();\r\n }\r\n\r\n /**\r\n * Pulls out the siteId, groupFilter and returnUrl from the parameters in the current url if any are present\r\n */\r\n private handleRouteParams(): void {\r\n if (this._activatedRoute.snapshot.paramMap.get('occasion')) {\r\n const occasion = this._navigatorService.changeTakeAwayToCollection(this._activatedRoute.snapshot.paramMap.get('occasion'));\r\n const capitalizedOccasion = occasion.charAt(0).toUpperCase() + occasion.slice(1);\r\n this.occasion = DisplayOccasionType[capitalizedOccasion];\r\n\r\n // if we don't know the occasion type, redirect home so the user can select\r\n if (!this.occasion) {\r\n this.trackTrace('Unknown occasion type, user redirected to home', SeverityLevel.Warning);\r\n this.router.navigate([this._navigatorService.generateHomePath()]);\r\n }\r\n }\r\n\r\n if (!this._activatedRoute.snapshot.paramMap.get('displayGroup')) {\r\n this.router.navigate([`${decodeURI(location.pathname)}/all`]);\r\n }\r\n\r\n if (this._activatedRoute.snapshot.paramMap.get('location')) {\r\n this._location = this._activatedRoute.snapshot.paramMap.get('location');\r\n this.siteId = this._navigatorService.getSiteIdByLocation(this._location);\r\n }\r\n\r\n if (!this.siteId || this.siteId === '') {\r\n this.router.navigate([this._navigatorService.generateHomePath()]);\r\n }\r\n }\r\n\r\n /**\r\n * builds the structured data for the menu\r\n */\r\n private buildStructuredData(menu: Menu): void {\r\n const jsonStructuredData: string = this._structuredDataService.buildMenuStructuredData(menu, this.occasion);\r\n\r\n if (jsonStructuredData) {\r\n const jsonScript: HTMLScriptElement = document.createElement('script');\r\n jsonScript.setAttribute('type', 'application/ld+json');\r\n jsonScript.textContent = jsonStructuredData;\r\n document.head.appendChild(jsonScript);\r\n }\r\n }\r\n\r\n /**\r\n * updates the websites title and meta description\r\n * @param useDefault\r\n */\r\n private updatePageSEO(useDefault: boolean): void {\r\n if (useDefault) {\r\n this._seoSet = true;\r\n if (this.currentSite && this.occasion) {\r\n this._seoService.updateSeoTitleAndDescription(this.currentSite, this.occasion);\r\n } else {\r\n this._seoService.updateTitle('{{TenantWebsiteName}} - menu');\r\n }\r\n\r\n const address: Address = this.currentSite?.Address;\r\n const locationDetails: string = address\r\n ? `${address.Town ? `in ${address.Town} ` : ''} ${(address.Town || !address.Postcode) ? address.Postcode : `in ${address.Postcode}`}`\r\n : '';\r\n\r\n this._seoService.updateDescription(this.replaceSEOStrings(`See our ${ this._navigatorService.changeCollectionToTakeAway(this.occasion) } menu in ${locationDetails}.\r\n Choose from our wide range of {{allMenuCategories}} from ${this.currentSite?.Name}.`));\r\n } else {\r\n const menuPageSEO = this.tenant.PageSeos.find((seo: PageSEO) => seo.PageName.toLowerCase() === 'menu');\r\n\r\n if (menuPageSEO) {\r\n this._seoSet = true;\r\n this._seoService.updateTitle(this.replaceSEOStrings(menuPageSEO.Title));\r\n this._seoService.updateDescription(this.replaceSEOStrings(menuPageSEO.Description));\r\n } else {\r\n this.updatePageSEO(true);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * replaces well defined hardcoded strings with matching details for the current site/menu\r\n * @param updateText\r\n */\r\n private replaceSEOStrings(updateText: string): string {\r\n if (updateText.includes('{{allMenuCategories}}') && this.sections?.length > 0) {\r\n return updateText.replace('{{allMenuCategories}}', this.sections.map((x: MenuSectionView) => x.name).join(', '));\r\n }\r\n\r\n return updateText;\r\n }\r\n\r\n /**\r\n * tracks the current site.\r\n */\r\n private trackCurrentSite(): void {\r\n this._siteService.currentSite$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((site: Site) => {\r\n this.currentSite = site;\r\n });\r\n\r\n if (!this.currentSite || this.currentSite.Id.toLocaleLowerCase() !== this.siteId.toLocaleLowerCase()) {\r\n this._siteService.setCurrentSiteBySiteId(this.siteId);\r\n }\r\n }\r\n\r\n /**\r\n * gets the current basket\r\n * @param retried\r\n */\r\n private getCurrentBasketBySiteId(): void {\r\n const clearOldBasket = () => this._basketService.clearOldAndCreateNewBasket(this.siteId);\r\n\r\n this._basketService.getCurrentBasketBySiteId(this.siteId, OrderOccasion[this.occasion])\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe({\r\n error: (error) => {\r\n this.trackException(error, true);\r\n this.goHome();\r\n },\r\n next: async (basket: Basket) => {\r\n if (!basket) {\r\n this.trackTrace('getCurrentBasketBySiteId returned null on menu page', SeverityLevel.Error);\r\n this.goHome();\r\n return;\r\n }\r\n\r\n if (basket.IsModifiable) {\r\n return;\r\n }\r\n\r\n if (!basket.OrderId) {\r\n await clearOldBasket();\r\n return;\r\n }\r\n\r\n this.basket = null;\r\n await this._checkoutService.deleteOrderById(basket.OrderId).catch(async () => await clearOldBasket());\r\n this.getCurrentBasketBySiteId();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * tracks the current basket\r\n */\r\n private trackCurrentBasket(): void {\r\n this._basketService.currentBasket$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((basket: Basket) => {\r\n const isNewBasket: boolean = !this.basket || !basket || this.basket.Id !== basket.Id;\r\n\r\n this.basket = basket;\r\n\r\n if (!basket) {\r\n return;\r\n }\r\n\r\n if (isNewBasket) {\r\n this.getAvailableOrderDates();\r\n }\r\n\r\n this.trackBasketCount(basket);\r\n this.basketWantedTime = this.getWantedTime();\r\n this.basketTotal = this.basket.Charges?.find((x: Charge) => x.ChargeType === ChargeTypes.Total)?.Price.Amount ?? 0;\r\n\r\n if (this._menuService.menuValue) {\r\n this.sections = this.getMenuSections(this._menuService.menuValue);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * tracks the active notifications\r\n */\r\n private trackNotifications(): void {\r\n this._toastService.activeNotifications$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((x: IDictionary>) => {\r\n this.notifications = x;\r\n });\r\n }\r\n\r\n /**\r\n * returns the user to the home page.\r\n */\r\n private goHome(): void {\r\n if (!this.router.url.includes('/menu')) {\r\n return;\r\n }\r\n\r\n this._toastService.showToast(ToastTypes.error, 'Something\\'s gone wrong');\r\n this.router.navigate([this._navigatorService.generateHomePath()]);\r\n }\r\n\r\n /**\r\n * scrolls to the given web section (`groupName`)\r\n */\r\n private scrollToWebSection(groupName: string): void {\r\n const element: HTMLElement = document.getElementById(groupName);\r\n\r\n if (!element) {\r\n return;\r\n }\r\n\r\n if (this.isMobile) {\r\n setTimeout(() => window.scrollTo({ behavior: 'smooth', top: element.offsetTop }), this._scrollDelay);\r\n return;\r\n }\r\n\r\n const parent: HTMLElement = document.getElementById('menu-content');\r\n const catBar: HTMLElement = document.getElementById('categories-bar');\r\n parent.scrollTo({ behavior: 'smooth', top: element.offsetTop - catBar.offsetHeight });\r\n }\r\n\r\n /**\r\n * sets a focus to a search filed\r\n */\r\n private setSearchFieldFocus(): void {\r\n const searchFocusDelay: number = 10;\r\n setTimeout(() => this._searchElement.nativeElement.focus(), searchFocusDelay);\r\n }\r\n\r\n /**\r\n * returns the baskets wanted time formatted as HH:mm or 'ASAP'.\r\n */\r\n private getWantedTime(): string {\r\n if (this.basket.WantedTimeUtc) {\r\n const _date = new Date(this.replaceZuluTime(this.basket.WantedTimeUtc));\r\n return this._datePipe.transform(_date, this.isToday(_date) ? 'HH:mm' : 'EEE dd/MM HH:mm');\r\n } else {\r\n return 'ASAP';\r\n }\r\n }\r\n\r\n private isToday(date: Date): boolean {\r\n const today = new Date();\r\n return date.getDate() === today.getDate() && date.getMonth() === today.getMonth();\r\n }\r\n\r\n /**\r\n * updates the `IsStoreOpen` property\r\n */\r\n private async getAvailableOrderDates(): Promise {\r\n const dates: IDaysTimeSlots = await this._basketService.getTimeSlotsForBasket(this.basket.Id, true);\r\n this.isStoreOpen = dates.Dates?.length > 0 || dates.AllowAsap;\r\n\r\n if (!this.isStoreOpen) {\r\n const nextDate = new Date();\r\n nextDate.setDate(nextDate.getDate() + 1);\r\n const times: BasketAvailableTime[] = await lastValueFrom(this._basketService.getBasketsAvailableTimes(this.basket.Id, nextDate, true));\r\n const hasTimes = times.flatMap((x: BasketAvailableTime) => x.Time).filter((x: string) => x < '06:00:00').length > 0;\r\n\r\n if (hasTimes) {\r\n this.isStoreOpen = true;\r\n }\r\n }\r\n }\r\n}\r\n","import { AfterViewInit, Component, OnDestroy, TemplateRef, ViewChild } from '@angular/core';\r\nimport { MatDialogConfig, MatDialogRef } from '@angular/material/dialog';\r\nimport { ActivatedRoute, Params, Router } from '@angular/router';\r\nimport { HttpStatusCodeHandler } from '@app/core/http.status.codes';\r\nimport { NavigatorService } from '@app/core/navigator.service';\r\nimport { DisplayOccasionType } from '@app/models/display-occasion-type';\r\nimport { NavigationSectionType } from '@app/models/navigation/navigation-section-type';\r\nimport { OrderOccasion } from '@app/models/order-occasion';\r\nimport { BasketService } from '@app/api/basket.service';\r\nimport { MenuService } from '@app/api/menu.service';\r\nimport { takeUntil } from 'rxjs';\r\nimport { ProductAddEvent } from '@app/models/product/product-add-event';\r\nimport { ProductView } from '@app/models/product/product-view';\r\nimport { MenuHelperService } from '@app/shared/services/menu-helper/menu-helper.service';\r\nimport { SEOService } from '@app/shared/services/seo.service';\r\nimport { SiteService } from '@app/api/site.service';\r\nimport { AndroWebCoreComponent } from '@app/core/AndroWebCoreComponent';\r\nimport { Menu } from '@app/models/menu/menu';\r\nimport { Product } from '@app/models/menu/product';\r\n\r\n@Component({\r\n template: `\r\n \r\n \r\n \r\n `\r\n})\r\nexport class ProductsDialogEntryComponent extends AndroWebCoreComponent implements AfterViewInit, OnDestroy {\r\n @ViewChild('ProductModal') private _productModal: TemplateRef;\r\n\r\n public productView: ProductView;\r\n public orderOccasion: OrderOccasion;\r\n\r\n private _dialogRef: MatDialogRef;\r\n\r\n private _seoSet: boolean;\r\n private _group: string;\r\n\r\n constructor(\r\n private _router: Router,\r\n private _seoService: SEOService,\r\n private _menuService: MenuService,\r\n private _siteService: SiteService,\r\n private _basketService: BasketService,\r\n private _activatedRoute: ActivatedRoute,\r\n private _navigatorService: NavigatorService,\r\n private _menuHelperService: MenuHelperService\r\n ) {\r\n super();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this._menuService.menu$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((menu: Menu) => {\r\n if (!menu) {\r\n return;\r\n }\r\n\r\n const id = this._activatedRoute.snapshot.paramMap.get('productId');\r\n const location = this._activatedRoute.snapshot.paramMap.get('location');\r\n const occasion: string = this._navigatorService.changeTakeAwayToCollection(this._activatedRoute.snapshot.paramMap.get('occasion'));\r\n this.orderOccasion = DisplayOccasionType[this._navigatorService.toTitleCase(occasion)];\r\n this._group = this._activatedRoute.snapshot.paramMap.get('displayGroup');\r\n\r\n const product = menu.Products.find((x: Product) => x.Id === id);\r\n\r\n if (!product) {\r\n return;\r\n }\r\n\r\n this.productView = {\r\n name: product.Name,\r\n description: product.Description,\r\n href: this._navigatorService.generateRoutePath(location, this.orderOccasion, NavigationSectionType.Menu, this._group),\r\n imageSource: this.getMenuImageVisualAsset({ data: product, height: 244 }),\r\n isInDeal: false,\r\n allergens: this._menuHelperService.getAllergenSummary(product.Allergens),\r\n variants: product.Variants,\r\n upselling: product.Upselling,\r\n save: (event: ProductAddEvent) => this.onSave(event)\r\n };\r\n\r\n this._seoService.updateProductSeoTitleAndDescription(\r\n this._siteService.currentSite,\r\n this.orderOccasion,\r\n this._group,\r\n this.productView\r\n );\r\n this._seoSet = true;\r\n\r\n this.openProductDialog();\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n super.ngOnDestroy();\r\n if (this._seoSet) {\r\n this._seoService.restore();\r\n }\r\n }\r\n\r\n public close(): void {\r\n this._dialogRef.close();\r\n }\r\n\r\n /**\r\n * saves the product to the basket\r\n * @param event\r\n */\r\n private async onSave(event: ProductAddEvent): Promise {\r\n if (!event) {\r\n return;\r\n }\r\n\r\n const response = await this._basketService.addProductToBasket(event.item, this.productView.name, this._group, event.itemPrice);\r\n\r\n if (HttpStatusCodeHandler.isSuccessResponse(response)) {\r\n this.close();\r\n }\r\n }\r\n\r\n /**\r\n * opens the product component in a dialog.\r\n */\r\n private openProductDialog(): void {\r\n const config: MatDialogConfig = {\r\n height: this.isMobile ? '100%' : '',\r\n panelClass: ['custom-dialog-two-container', 'product-modal'],\r\n width: this.isMobile ? '100%' : '450px',\r\n ariaModal: false\r\n };\r\n\r\n this._dialogRef = this.openDialog(this._productModal, 'productsModal', config);\r\n\r\n this._dialogRef.afterClosed()\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe(() => {\r\n const params: Params = this._activatedRoute.snapshot.params;\r\n\r\n if (params && (params.productId || params.productName)) {\r\n const routePath: string = this._navigatorService.generateRoutePath(params.location, params.occasion, NavigationSectionType.Menu, params.displayGroup);\r\n this._router.navigate([routePath]);\r\n }\r\n\r\n this.resetSEO();\r\n });\r\n }\r\n\r\n /**\r\n * Restores the title and description\r\n */\r\n private resetSEO(): void {\r\n if (this._seoSet) {\r\n this._seoService.restore();\r\n }\r\n\r\n this._seoSet = false;\r\n }\r\n}\r\n","import { AfterViewInit, Component, OnDestroy, TemplateRef, ViewChild } from '@angular/core';\r\nimport { MatDialogConfig, MatDialogRef } from '@angular/material/dialog';\r\nimport { ActivatedRoute, Params, Router } from '@angular/router';\r\nimport { AndroWebCoreComponent } from '@app/core/AndroWebCoreComponent';\r\nimport { NavigatorService } from '@app/core/navigator.service';\r\nimport { DisplayOccasionType } from '@app/models/display-occasion-type';\r\nimport { NavigationSectionType } from '@app/models/navigation/navigation-section-type';\r\nimport { OrderOccasion } from '@app/models/order-occasion';\r\nimport { PageSEO } from '@app/models/page-seo';\r\nimport { MenuService } from '@app/api/menu.service';\r\nimport { SEOService } from '@app/shared/services/seo.service';\r\nimport { takeUntil } from 'rxjs';\r\nimport { Deal } from '@app/models/menu/deal';\r\nimport { Menu } from '@app/models/menu/menu';\r\n\r\n@Component({\r\n template: `\r\n \r\n \r\n \r\n `\r\n})\r\nexport class DealsDialogEntryComponent extends AndroWebCoreComponent implements AfterViewInit, OnDestroy {\r\n @ViewChild('ProductModal') private _productModal: TemplateRef;\r\n\r\n public deal: Deal;\r\n public orderOccasion: OrderOccasion;\r\n public group: string;\r\n\r\n private _dialogRef: MatDialogRef;\r\n private _seoSet: boolean;\r\n\r\n constructor(\r\n private _router: Router,\r\n private _seoService: SEOService,\r\n private _menuService: MenuService,\r\n private _activatedRoute: ActivatedRoute,\r\n private _navigatorService: NavigatorService\r\n ) {\r\n super();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this.updatePageSEO(true);\r\n\r\n this._menuService.menu$\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe((menu: Menu) => {\r\n if (!menu) {\r\n return;\r\n }\r\n\r\n // const location = this._activatedRoute.snapshot.paramMap.get('location');\r\n const routeOccasion: string = this._navigatorService.changeTakeAwayToCollection(this._activatedRoute.snapshot.paramMap.get('occasion'));\r\n this.orderOccasion = DisplayOccasionType[this._navigatorService.toTitleCase(routeOccasion)];\r\n this.group = this._activatedRoute.snapshot.paramMap.get('displayGroup');\r\n this.deal = menu.Deals.find((x: Deal) => x.Id === this._activatedRoute.snapshot.paramMap.get('dealId'));\r\n this.updatePageSEO(false);\r\n this.openDealsModal();\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n super.ngOnDestroy();\r\n if (this._seoSet) {\r\n this._seoService.restore();\r\n }\r\n }\r\n\r\n /**\r\n * closes the dialog.\r\n */\r\n public close(): void {\r\n this._dialogRef.close();\r\n }\r\n\r\n /**\r\n * Takes a string with a well defined placeholder ( '{{dealName}}' ) and replaces the placeholder with the deals name then returns the updated value\r\n * @param useDefault - determines whether the default meta title and description text should be used or not\r\n */\r\n private updatePageSEO(useDefault: boolean): void {\r\n if (!useDefault) {\r\n const dealsPageSEO = this.tenant.PageSeos.find((seo: PageSEO) => seo.PageName.toLowerCase() === 'deals');\r\n\r\n if (dealsPageSEO) {\r\n this._seoSet = true;\r\n this._seoService.updateTitle(this.replaceSEOStrings(dealsPageSEO.Title));\r\n this._seoService.updateDescription(this.replaceSEOStrings(dealsPageSEO.Description));\r\n return;\r\n }\r\n }\r\n\r\n const title: string = this.replaceSEOStrings('{{dealName}} - {{TenantWebsiteName}}');\r\n this._seoService.updateTitle(title);\r\n this._seoService.updateDescription('{{TenantWebsiteName}} fresh food prepared daily');\r\n this._seoSet = true;\r\n }\r\n\r\n /**\r\n * takes a string with a well defined placeholder ( '{{dealName}}' ) and replaces the placeholder with the deals name then returns the updated value\r\n * @param updateText - the text string with a well defined placeholder\r\n */\r\n private replaceSEOStrings(updateText: string): string {\r\n let result = '';\r\n\r\n if (this.deal?.Name && updateText.includes('{{dealName}}')) {\r\n result = result\r\n ? result.replace('{{dealName}}', this.deal.Name)\r\n : updateText.replace('{{dealName}}', this.deal.Name);\r\n }\r\n\r\n return result ?? updateText;\r\n }\r\n\r\n /**\r\n * opens the product component in a dialog.\r\n */\r\n private openDealsModal(): void {\r\n const config: MatDialogConfig = {\r\n height: this.isMobile ? '100%' : '',\r\n panelClass: ['custom-dialog-two-container', 'product-modal'],\r\n width: this.isMobile ? '100%' : '450px',\r\n ariaModal: false\r\n };\r\n\r\n this._dialogRef = this.openDialog(this._productModal, 'productsModal', config);\r\n\r\n this._dialogRef.afterClosed()\r\n .pipe(takeUntil(this.destroy$))\r\n .subscribe(() => {\r\n const params: Params = this._activatedRoute.snapshot.params;\r\n\r\n if (params && (params.productId || params.productName)) {\r\n const routePath: string = this._navigatorService.generateRoutePath(params.location, params.occasion, NavigationSectionType.Menu, params.displayGroup);\r\n this._router.navigate([routePath]);\r\n }\r\n });\r\n }\r\n}\r\n","import { RouterModule, Routes } from '@angular/router';\r\n\r\nimport { MenuComponent } from '@app/modules/menu/menu.component';\r\nimport { NgModule } from '@angular/core';\r\nimport { SiteResolver } from '@app/core/site.service.resolver';\r\nimport { ProductsDialogEntryComponent } from '@app/modules/menu/components/products-dialog-entry/products-dialog-entry.component';\r\nimport { DealsDialogEntryComponent } from '@app/modules/menu/components/deals-dialog-entry/deals-dialog-entry.component';\r\n\r\nconst routes: Routes = [\r\n {\r\n children: [\r\n {\r\n component: ProductsDialogEntryComponent,\r\n path: ':productName/:productId'\r\n },\r\n {\r\n component: DealsDialogEntryComponent,\r\n path: 'offers/:productName/:dealId'\r\n }\r\n ],\r\n component: MenuComponent,\r\n path: ':displayGroup',\r\n resolve: {\r\n siteResolver: SiteResolver\r\n }\r\n },\r\n {\r\n component: MenuComponent,\r\n path: '',\r\n resolve: {\r\n siteResolver: SiteResolver\r\n }\r\n }\r\n];\r\n\r\n@NgModule({\r\n exports: [RouterModule],\r\n imports: [RouterModule.forChild(routes)]\r\n})\r\nexport class MenuRoutingModule { }\r\n","import { Component, Input, OnChanges, SimpleChanges, TemplateRef, ViewChild } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { AndroWebCoreComponent } from '@app/core/AndroWebCoreComponent';\r\nimport { NavigatorService } from '@app/core/navigator.service';\r\nimport { INotification } from '@app/models/INotification';\r\nimport { NavigationSectionType } from '@app/models/navigation/navigation-section-type';\r\nimport { AnalyticsService } from '@app/app-initialisers/analytics-service/analytics.service';\r\nimport { BasketService } from '@app/api/basket.service';\r\nimport { Observable } from 'rxjs';\r\nimport { BasketItemCreate } from '@app/models/basket/BasketItemCreate';\r\nimport { OrderOccasion } from '@app/models/order-occasion';\r\nimport { MenuItemView } from '@app/models/menu/menu-item-view';\r\nimport { MenuHelperService } from '@app/shared/services/menu-helper/menu-helper.service';\r\nimport { MenuService } from '@app/api/menu.service';\r\nimport { Deal } from '@app/models/menu/deal';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { MenuDealHelperService } from '@app/shared/services/menu-deal-helper/menu-deal-helper.service';\r\nimport { MenuVariantHelperService } from '@app/shared/services/menu-variant-helper/menu-variant-helper.service';\r\nimport { OccasionPrice } from '@app/models/menu/occasion-price';\r\nimport { ProductUpsellOption } from '@app/modules/menu/components/deal-upsell-modal/deal-upsell-modal.component';\r\n\r\n@Component({\r\n selector: 'app-menu-card',\r\n styleUrls: ['./menu-card.component.scss'],\r\n templateUrl: './menu-card.component.html'\r\n})\r\nexport class MenuCardComponent extends AndroWebCoreComponent implements OnChanges {\r\n @ViewChild('futureOrdersDisallowed') private _disallowedModal: TemplateRef;\r\n @ViewChild('upsellModal') private _upsellModal: TemplateRef;\r\n\r\n @Input() public menuItem: MenuItemView;\r\n\r\n @Input('occasion') private _occasion: OrderOccasion;\r\n @Input('siteId') private _siteId: string;\r\n @Input('isStoreOpen') private _isStoreOpen: boolean;\r\n @Input('customerGroupName') private _customerGroupName: string;\r\n @Input('notification') private _notification?: Observable;\r\n @Input('wantedTime') public _wantedTime: string;\r\n\r\n public showImages: boolean;\r\n public activeNotification: INotification;\r\n public routePath: string;\r\n public upsellPrompt: string;\r\n public upsellOptions: { name: string; deal: Deal; }[];\r\n public upsellDialogRef: MatDialogRef;\r\n\r\n constructor(\r\n private _router: Router,\r\n private _menuService: MenuService,\r\n private _basketService: BasketService,\r\n private _analyticsService: AnalyticsService,\r\n private _navigatorService: NavigatorService,\r\n private _menuHelperService: MenuHelperService,\r\n private _menuDealHelperService: MenuDealHelperService,\r\n private _menuVariantHelperService: MenuVariantHelperService\r\n ) {\r\n super();\r\n this.showImages = !this.tenant.SuppressProductImages;\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes._notification) {\r\n this.trackNotification();\r\n }\r\n\r\n this.routePath = this.getRoutePath();\r\n }\r\n\r\n /**\r\n * adds the product to basket if the store is open. Opens the disallowed modal if not.\r\n * @param $event\r\n */\r\n public goToItemPage(): void {\r\n if (!this.menuItem.available || this.menuItem.outOfStock) {\r\n return;\r\n }\r\n\r\n if (!this._isStoreOpen) {\r\n this.openDisallowedModal();\r\n return;\r\n }\r\n\r\n if (this.menuItem.type === 'deal') {\r\n this.trackClickMenuItem();\r\n this._router.navigateByUrl(this.routePath);\r\n return;\r\n }\r\n\r\n if (this.menuItem.upselling) {\r\n this.openUpsellModal();\r\n return;\r\n }\r\n\r\n this.goToProductPage();\r\n }\r\n\r\n /**\r\n * navigates to the product page.\r\n */\r\n public goToProductPage(): void {\r\n this.trackClickMenuItem();\r\n this._router.navigateByUrl(this.routePath);\r\n }\r\n\r\n /**\r\n * navigates to the deal page.\r\n * @param path\r\n */\r\n public goToDealPage(deal: Deal): void {\r\n this.trackClickMenuItem();\r\n this._router.navigateByUrl(this.getDealRoutePath(deal.Id));\r\n }\r\n\r\n /**\r\n * adds the product to basket if the item is simple and addStraightToBasket is true or opens the product page.\r\n * @param addStraightToBasket\r\n */\r\n public async addItemToBasket($event?: MouseEvent): Promise {\r\n if ($event) {\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n\r\n if (this.menuItem.type === 'deal' || !this._menuVariantHelperService.isProductSimple(this.menuItem.variants!)) {\r\n this.goToItemPage();\r\n return;\r\n }\r\n\r\n if (this.menuItem.upselling) {\r\n this.openUpsellModal();\r\n return;\r\n }\r\n\r\n const payload: BasketItemCreate = {\r\n Modifiers: [],\r\n Product: {\r\n Item: this.menuItem.variants[0].Id,\r\n Quantity: 1\r\n }\r\n };\r\n\r\n const price = this.menuItem.variants[0].Prices.find((x: OccasionPrice) => x.Occasion === this._occasion)?.Amount;\r\n await this._basketService.addProductToBasket(payload, this.menuItem.name, this._customerGroupName, price);\r\n }\r\n\r\n /**\r\n * opens the disallowed modal.\r\n */\r\n private openDisallowedModal(): void {\r\n this.openDialog(this._disallowedModal, 'future-orders-disallowed-modal', {\r\n autoFocus: false,\r\n disableClose: false,\r\n width: this.isMobile ? '100%' : ''\r\n });\r\n }\r\n\r\n /**\r\n * subscribes to {@link notification} and updates the {@link activeNotification} property.\r\n */\r\n private trackNotification(): void {\r\n if (this.subscriptions$['MenuDisplayGroupCard-ngOnChanges-notification']) {\r\n return;\r\n }\r\n\r\n this.subscriptions$['MenuDisplayGroupCard-ngOnChanges-notification']\r\n = this._notification?.subscribe((x: INotification) => {\r\n this.activeNotification = x;\r\n\r\n if (!this.activeNotification) {\r\n this.subscriptions$['MenuDisplayGroupCard-ngOnChanges-notification'].unsubscribe();\r\n this.subscriptions$['MenuDisplayGroupCard-ngOnChanges-notification'] = null;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * returns the url of the product.\r\n */\r\n private getRoutePath(): string {\r\n const routePath: string = this.menuItem.type === 'deal'\r\n ? this.getDealRoutePath(this.menuItem.id)\r\n : this.getProductRoutePath(this.menuItem.id);\r\n return routePath;\r\n }\r\n\r\n /**\r\n * returns the url of the deal.\r\n * @param dealId\r\n */\r\n private getDealRoutePath(dealId: string): string {\r\n const location: string = this._navigatorService.getLocationBySiteId(this._siteId);\r\n\r\n return this._navigatorService.generateRoutePath(\r\n location,\r\n this._occasion,\r\n NavigationSectionType.Menu,\r\n this._customerGroupName,\r\n this.menuItem.name,\r\n null,\r\n dealId\r\n );\r\n }\r\n\r\n /**\r\n * returns the url of the product.\r\n * @param productId\r\n */\r\n private getProductRoutePath(productId: string): string {\r\n const location: string = this._navigatorService.getLocationBySiteId(this._siteId);\r\n\r\n return this._navigatorService.generateRoutePath(\r\n location,\r\n this._occasion,\r\n NavigationSectionType.Menu,\r\n this._customerGroupName,\r\n this._navigatorService.clean(this.menuItem.name?.split(' ').join('-')),\r\n productId\r\n );\r\n }\r\n\r\n /**\r\n * opens the upsell modal.\r\n */\r\n private openUpsellModal(): void {\r\n this.upsellOptions = this.menuItem.upselling.Deals.Ids\r\n .map((id: string) => this.mapToProductUpsellOption(id, this.menuItem.price))\r\n .filter((x: ProductUpsellOption) => x);\r\n\r\n if (this.upsellOptions.length === 0) {\r\n this.goToProductPage();\r\n return;\r\n }\r\n\r\n this.upsellPrompt = this.menuItem.upselling.Deals.Prompt ?? 'Would you like to make it a meal?';\r\n\r\n this.upsellDialogRef = this.openDialog(this._upsellModal, 'upsell-modal', {\r\n autoFocus: false,\r\n disableClose: false,\r\n width: this.isMobile ? '100%' : '',\r\n maxHeight: '100%'\r\n });\r\n }\r\n\r\n /**\r\n * maps the deal id to a product upsell option.\r\n * @param dealId\r\n * @param originalPrice the original price of the product.\r\n */\r\n private mapToProductUpsellOption(dealId: string, originalPrice: number): ProductUpsellOption {\r\n const deal: Deal = this._menuService.menuValue.Deals.find((x) => x.Id === dealId);\r\n\r\n if (!deal || deal.OutOfStock || deal.RequiresUnlock) {\r\n return null;\r\n }\r\n\r\n const wantedTime = this._wantedTime ? new Date(this._wantedTime) : null;\r\n const isAvailable = this._menuHelperService.availableForOccasion(deal.Availability?.Values, OrderOccasion[this._occasion], wantedTime);\r\n\r\n if (!isAvailable) {\r\n return null;\r\n }\r\n\r\n const price = this._menuDealHelperService.getMinPriceForDeal(deal, this._occasion);\r\n const currency = '£';\r\n const total = Math.round((price - originalPrice + Number.EPSILON) * 100) / 100;\r\n\r\n return {\r\n name: total > 0 ? `${deal.Name} +${currency}${total.toFixed(2)}` : deal.Name,\r\n deal: deal\r\n };\r\n }\r\n\r\n private trackClickMenuItem(): void {\r\n this._analyticsService.trackClickProduct(\r\n this.menuItem.name,\r\n this.menuItem.id,\r\n this._customerGroupName,\r\n this.menuItem.price,\r\n 'GBP'\r\n );\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { MenuItemView } from '@app/models/menu/menu-item-view';\r\nimport { MenuSectionView } from '@app/models/menu/menu-section-view';\r\n\r\n@Pipe({\r\n name: 'filterMenuItems',\r\n standalone: true\r\n})\r\nexport class FilterMenuItemsPipe implements PipeTransform {\r\n transform(sections: MenuSectionView[], searchTerm: string): MenuSectionView[] {\r\n if (!sections || !searchTerm || !searchTerm.trim()) {\r\n return sections;\r\n }\r\n\r\n const lowerSearchTerm = searchTerm.toLowerCase();\r\n const menuItemHasSearchTerm = (item: MenuItemView) => item.name.toLowerCase().includes(lowerSearchTerm)\r\n || item.description?.toLowerCase().includes(lowerSearchTerm);\r\n\r\n return sections\r\n .filter((x: MenuSectionView) => x.menuItems.some(menuItemHasSearchTerm))\r\n .map((x: MenuSectionView) => ({\r\n ...x,\r\n menuItems: x.menuItems.filter(menuItemHasSearchTerm)\r\n }));\r\n }\r\n}\r\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { Deal } from '@app/models/menu/deal';\r\nimport { MenuItemView } from '@app/models/menu/menu-item-view';\r\n\r\nexport type ProductUpsellOption = {\r\n name: string;\r\n deal: Deal;\r\n};\r\n\r\n@Component({\r\n selector: 'app-deal-upsell-modal',\r\n templateUrl: './deal-upsell-modal.component.html',\r\n styleUrls: ['./deal-upsell-modal.component.css'],\r\n standalone: true\r\n})\r\nexport class DealUpsellModalComponent {\r\n @Input({ required: true }) public prompt: string = 'Would you like to make it a meal?';\r\n @Input({ required: true }) public options: ProductUpsellOption[];\r\n @Input({ required: true }) public menuItem: MenuItemView;\r\n @Input({ required: true }) public dialogRef: MatDialogRef;\r\n\r\n @Output('onSelectDeal') private _onSelectDeal = new EventEmitter();\r\n @Output('onSelectMenuItem') private _onSelectMenuItem = new EventEmitter();\r\n\r\n constructor() {}\r\n\r\n public selectDeal(deal: Deal): void {\r\n this._onSelectDeal.emit(deal);\r\n this.dialogRef.close();\r\n }\r\n\r\n public selectMenuItem(): void {\r\n this._onSelectMenuItem.emit();\r\n this.dialogRef.close();\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { MenuComponent } from '@app/modules/menu/menu.component';\r\nimport { MenuRoutingModule } from '@app/modules/menu/menu-routing.module';\r\nimport { SharedComponentsModule } from '@app/shared/components/shared-components.module';\r\nimport { ProductsDialogEntryComponent } from '@app/modules/menu/components/products-dialog-entry/products-dialog-entry.component';\r\nimport { DealsDialogEntryComponent } from '@app/modules/menu/components/deals-dialog-entry/deals-dialog-entry.component';\r\nimport { MenuCardComponent } from '@app/modules/menu/components/menu-card/menu-card.component';\r\nimport { FilterMenuItemsPipe } from '@app/modules/menu/pipes/menu-sections-filter';\r\nimport { WantedTimePickerComponent } from '@app/shared/components/wanted-time/wanted-time-picker/wanted-time-picker.component';\r\nimport { DealUpsellModalComponent } from '@app/modules/menu/components/deal-upsell-modal/deal-upsell-modal.component';\r\n@NgModule({\r\n declarations: [\r\n MenuComponent,\r\n ProductsDialogEntryComponent,\r\n DealsDialogEntryComponent,\r\n MenuCardComponent\r\n ],\r\n imports: [\r\n CommonModule,\r\n MenuRoutingModule,\r\n SharedComponentsModule,\r\n WantedTimePickerComponent,\r\n FilterMenuItemsPipe,\r\n DealUpsellModalComponent\r\n ]\r\n})\r\nexport class MenuModule {}\r\n","// Imports\nvar ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ = require(\"../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `section.deal-upsell-modal {\r\n padding: 20px;\r\n}\r\n\r\nsection.deal-upsell-modal ul {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n max-height: calc(100vh - 185px);\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n margin-top: -5px;\r\n}\r\n\r\n.upsell-option {\r\n font-size: 14px;\r\n border: thin solid rgba(0, 0, 0, 0.12);\r\n margin: 5px 0 10px;\r\n padding: 20px;\r\n width: 100%;\r\n text-align: center;\r\n cursor: pointer;\r\n border-radius: 8px;\r\n list-style: none;\r\n background-color: #ffe6cc;\r\n}\r\n`, \"\"]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ = require(\"../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `:root {\n --footer-background-colour: #333333;\n --footer-link-colour: #fff;\n --nav-bar-background-colour: #fff;\n --product-content-padding: 0 10px;\n}\n\n.menu-card-content-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n}\n.menu-card-content-description {\n font-size: 14px;\n margin-bottom: 0;\n}\n.menu-card-content-title {\n font-family: Tenant-Bold, Courier, Helvetica, sans-serif;\n font-size: 17px;\n margin: 3px 0;\n}\n.menu-card-image {\n min-height: 185px;\n min-width: 328px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 5px;\n}\n.menu-card-image img {\n max-width: 100%;\n}\n\n.menu-card-price {\n display: flex;\n font-family: Tenant-Bold, Courier, Helvetica, sans-serif;\n justify-content: space-between;\n padding: 5px 0;\n}\n\n.menu-card-price-amount .mat-icon {\n height: 20px;\n width: 20px;\n font-size: 20px;\n}\n\n.menu-card-price-amount:not(:disabled) {\n color: #fff;\n}\n\n.menu-card-add-button:not(:disabled) {\n background-color: #E3000E;\n}\n\n.menu-card-add-button {\n width: 100%;\n height: 36px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n overflow: hidden;\n}\n\n.menu-card-add-button.notify {\n background-color: #0D6EFD;\n}\n\n.menu-card-content {\n margin-bottom: 3px;\n}\n\n.flex-row.menu-card-add-button-inner {\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.flex-row.menu-card-add-button-inner span {\n margin: 0 2px;\n}\n\n.no-pointer-events {\n pointer-events: none;\n}\n\n.category {\n align-items: center;\n display: flex;\n flex-direction: column;\n}\n.category-item {\n background-color: #fff;\n border: 1px solid #e8e8e8;\n border-radius: 6px;\n box-shadow: 0 0 25px 1px rgba(53, 53, 53, 0.25);\n margin: 0 15px 35px;\n max-width: 350px;\n padding: 10px;\n display: flex;\n flex-direction: column;\n cursor: pointer;\n}\n\n.menu-card-imageless {\n width: 328px;\n}\n\n.category-item-unavaliable {\n opacity: 0.75;\n}\n\n.menu-card-content-nutrition {\n font-size: 12px;\n}\n\n@media screen and (max-width: 1023px) {\n .menu-card-image {\n min-height: 185px;\n min-width: 328px;\n }\n}\n@media screen and (max-width: 479px) {\n .menu-card-image {\n min-height: 95px;\n min-width: 170px;\n }\n .menu-card.category-item {\n margin: 0 10px 20px;\n }\n h3.menu-card-content-title {\n margin: 0;\n font-size: 14px !important;\n }\n p.menu-card-content-description {\n font-size: 10px;\n padding: 0 3px;\n }\n .menu-card.category-item {\n margin: 0 2px 5px;\n padding: 1px;\n overflow: hidden;\n width: 100%;\n }\n .menu-card-price {\n padding: 1px 0;\n }\n .menu-card-price-amount {\n font-size: 11px;\n }\n .menu-card-price-amount .mat-icon {\n height: 15px;\n width: 15px;\n margin-top: 0;\n font-size: 15px;\n }\n .menu-card-add-button {\n height: 30px;\n }\n .menu-card-imageless {\n width: unset;\n }\n .menu-card-imageless .menu-card-price {\n padding: 5px 0;\n }\n}\n@media screen and (max-width: 479px) and (max-width: 340px) {\n .menu-card.category-item {\n width: 300px;\n }\n .menu-card-image {\n min-width: unset;\n min-height: 156px;\n }\n}`, \"\"]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `:root {\n --footer-background-colour: #333333;\n --footer-link-colour: #fff;\n --nav-bar-background-colour: #fff;\n --product-content-padding: 0 10px;\n}\n\n:host {\n overflow: auto;\n}\n\n.menu {\n align-items: center;\n display: flex;\n flex-direction: column;\n justify-content: center;\n height: 100%;\n}\n.menu-loading {\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-top: -130px;\n}\n\n.app-display-group-card-component {\n display: flex;\n}\n\n.menu-content {\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n width: 100%;\n}\n.menu-content-products {\n display: flex;\n flex-direction: column;\n}\n.menu-content-products-announcement {\n max-width: 100%;\n padding: 15px;\n text-align: center;\n}\n.menu-content-products-allergens {\n color: #E3000E;\n max-width: 100%;\n padding: 15px;\n text-align: center;\n}\n.menu-content .category {\n align-items: center;\n display: flex;\n flex-direction: column;\n scroll-margin-top: 45px;\n}\n.menu-content .category-item {\n background-color: #fff;\n border: 1px solid #e8e8e8;\n border-radius: 6px;\n box-shadow: 0 0 25px 1px rgba(53, 53, 53, 0.25);\n margin: 0 15px 35px;\n max-width: 350px;\n padding: 10px;\n display: flex;\n flex-direction: column;\n}\n.menu-content .category-item-list {\n display: flex;\n flex-direction: column;\n width: 1140px;\n}\n.menu-content .category-item-list-items {\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n}\n.menu-content .category-name {\n font-family: Tenant-Bold, Courier, Helvetica, sans-serif;\n font-size: 20px;\n}\n\n.menu-header {\n background-color: #dbdfe6;\n width: 100%;\n}\n.menu-header-content {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n list-style-type: none;\n margin: 0;\n padding: 0;\n}\n.menu-header-content-item {\n padding: 10px 5px 0;\n display: flex;\n align-items: baseline;\n}\n.menu-header-content-item-link.search {\n padding: 12px;\n border-radius: 50%;\n margin-bottom: 0 !important;\n margin-top: 4px;\n}\n.menu-header-content-item-link.search-input {\n border: none;\n border-bottom-left-radius: 15px;\n border-top-left-radius: 15px;\n height: 36px;\n padding: 0 0 0 10px;\n transition: 0.3s ease-in-out;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.menu-header-content-item-link.search-input::-ms-clear {\n display: none;\n width: 0;\n height: 0;\n}\n\n.menu-header-content-item-link.icon {\n align-items: center;\n border: none;\n display: flex;\n height: 22px;\n justify-content: center;\n width: 22px;\n}\n.menu-header-content-item-link.icon.search {\n padding: 15px;\n border-radius: 50%;\n background-color: #443635;\n color: #fff;\n font-size: 20px;\n margin-top: 0;\n}\n.menu-header-content-item-link.icon.close {\n opacity: 0.5;\n font-size: 18px;\n}\n.menu-header-content-item-link.icon.close:hover {\n opacity: 0.8;\n}\n\n.menu-header-content-item:last-of-type {\n padding-bottom: 10px;\n}\n\n.input-group {\n display: none;\n transition: 0.7s ease-in-out;\n}\n.input-group-text {\n align-items: center;\n background-color: #fff;\n border: none;\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n cursor: pointer;\n display: flex;\n height: 36px;\n padding-left: 0;\n padding-right: 4px;\n}\n\n.input-group-append:last-of-type .input-group-text {\n border-bottom-right-radius: 16px;\n border-top-right-radius: 16px;\n}\n\n.expanded {\n align-items: center;\n border-radius: 12px !important;\n display: flex;\n flex-direction: row;\n margin-top: 0 !important;\n padding: 9px !important;\n}\n.expanded-input {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n transition: 0.7s ease-in-out;\n}\n.expanded-icon {\n display: none !important;\n}\n\n.input-group.mb-3 {\n margin-bottom: 0 !important;\n}\n\ndiv#search-results-target {\n padding: 10px;\n}\n\n.sort {\n display: flex;\n justify-content: center;\n text-align: end;\n}\n.sort-header {\n width: 1140px;\n padding: 0 0.5%;\n}\n.sort-header-text {\n cursor: pointer;\n float: right;\n padding: 5px;\n text-align: end;\n width: 150px;\n}\n.sort-cards {\n background-color: #fff;\n box-shadow: 0 2px 8px 2px rgba(0, 0, 0, 0.175);\n border: thin solid rgba(0, 0, 0, 0.15);\n border-radius: 6px;\n cursor: pointer;\n margin: 0px 0 0 20px;\n padding: 10px 15px;\n}\n.sort-cards-ul {\n list-style-type: none;\n margin-bottom: 0;\n padding: 0;\n}\n.sort-cards-li {\n margin-bottom: 8px;\n}\n.sort-cards-li:last-of-type {\n margin-bottom: 0;\n}\n.sort-cards-li:hover {\n box-shadow: 0 2px 2px -2px #E3000E;\n}\n\n.menu-page-footer {\n height: 35px;\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.menu-page-footer-branding {\n display: flex;\n align-items: center;\n overflow: hidden;\n color: #000045;\n padding-left: 4px;\n cursor: pointer;\n}\n.menu-page-footer-branding-img {\n max-height: 46px;\n margin-left: -13px;\n margin-bottom: 3px;\n}\n.menu-page-footer-branding-text {\n font-size: 12px;\n font-weight: 600;\n}\n.menu-page-footer-legal-links {\n height: 100%;\n display: flex;\n align-items: center;\n}\n.menu-page-footer-legal-links-item {\n margin-bottom: 0 !important;\n font-size: 13px;\n margin-top: -1px;\n cursor: pointer;\n color: #000045;\n padding: 0 3px;\n}\n.menu-page-footer-legal-links-item:hover {\n text-decoration: underline;\n}\n\n.category-item-list div {\n display: flex;\n}\n\n.websection-header-group {\n margin: 10px 16px;\n color: #fff;\n background-color: #424858;\n align-items: center;\n padding: 10px;\n}\n.websection-header-group div {\n display: flex;\n flex-direction: column;\n}\n.websection-header-group h1 {\n margin-bottom: 0;\n}\n.websection-header-group img {\n max-width: 125px;\n margin-right: 10px;\n}\n\n.order-wanted-details {\n height: 31px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.menu-header.sticky {\n top: 0;\n}\n\n.basket-footer.button-action-1.sticky {\n bottom: 0;\n z-index: 2;\n height: 45px;\n display: flex;\n align-items: center;\n padding: 5px;\n border-radius: 0;\n width: 100%;\n border-top: thin solid #fff;\n}\n.basket-footer.button-action-1.sticky span {\n flex: 1;\n text-transform: uppercase;\n text-align: center;\n}\n.basket-footer.button-action-1.sticky div {\n display: flex;\n margin: 0 10px;\n}\n.basket-footer.button-action-1.sticky samp {\n margin: 0 5px;\n}\n\n.order-wanted-details .wanted-time-change-button {\n margin-left: 5px;\n}\n\n.order-wanted-details .basket-delivery-time-icon {\n border-radius: 12px;\n}\n\n.order-wanted-details span:nth-child(2) {\n margin-left: 4px;\n}\n\n@media screen and (max-width: 1023px) {\n .menu-card-image {\n min-height: 185px;\n min-width: 328px;\n }\n .menu-header {\n min-height: 69px;\n overflow-x: auto;\n overflow-y: hidden;\n width: 100%;\n }\n .menu-header-content {\n white-space: nowrap;\n flex-wrap: nowrap;\n justify-content: unset;\n max-height: 100%;\n }\n .menu-header-content-item {\n margin: 10px 2px;\n padding: 0 3px;\n }\n}\n@media screen and (max-width: 479px) {\n .menu-header {\n height: 45px;\n min-height: 45px;\n }\n .menu-header-content-item {\n margin: 0 2px;\n }\n .menu-header-content-item .button-menu-cat {\n padding: 8px 30px;\n }\n .menu-header-content-item-link.search.button-menu-cat {\n padding: 6px;\n }\n .menu-header-content-item-link.search.button-menu-cat.disable-select.expanded {\n padding: 3px 5px !important;\n }\n .menu-card.category-item {\n margin: 0 10px 20px !important;\n }\n .menu-content {\n overflow-y: unset;\n padding-bottom: 45px;\n }\n .menu-content .category-item-list {\n justify-content: center;\n }\n .menu-content-products-allergens {\n padding-bottom: 0;\n text-align: center;\n }\n p:last-of-type {\n margin-bottom: 0;\n }\n .menu-page-footer {\n font-size: 12px;\n }\n .websection-header-group {\n margin: 5px 10px 2px;\n padding: 5px;\n }\n .websection-header-group img {\n width: 85px;\n margin-right: 5px;\n }\n .websection-header-group h2 {\n margin-bottom: 4px;\n font-size: 16px;\n }\n .websection-header-group span {\n font-size: 13px;\n }\n .app-display-group-card-component {\n width: 100%;\n max-width: calc(50% - 5px);\n box-sizing: border-box;\n }\n .category-item-list-items {\n justify-content: center;\n }\n}\n@media screen and (max-width: 479px) and (max-width: 340px) {\n .menu-card.category-item {\n width: 97%;\n }\n .menu-card-image {\n min-width: unset;\n min-height: 185px;\n }\n}\n@media screen and (max-width: 1140px) {\n .sort-header, .menu-content .category-item-list {\n width: 760px;\n }\n}\n@media screen and (max-width: 760px) {\n .menu-content .category-item-list {\n justify-content: center;\n width: 100%;\n }\n .sort {\n justify-content: flex-end;\n }\n .sort-cards {\n margin: 0;\n }\n .sort-header {\n padding-right: 2%;\n width: unset;\n }\n}`, \"\"]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n"],"x_google_ignoreList":[]}