\n Available from {{ schedule.from }} to {{ schedule.to }}\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n\n\n","import { Component } from '@angular/core';\nimport { AsyncPipe, NgFor, NgIf } from '@angular/common';\nimport { ProductCardComponent } from '../../../components/product-card/product-card.component';\nimport { RouterOutlet } from '@angular/router';\nimport { CategoryPageAbstract } from '../../common/category-page.abstract';\nimport { ObserverDirective } from 'src/app/shared/directives/observer/observer.directive';\nimport { ScrollListDirective } from 'src/app/shared/directives/scroll-list/scroll-list.directive';\nimport { ScrollItemDirective } from 'src/app/shared/directives/scroll-list/scroll-item.directive';\n\n@Component({\n selector: 'app-default-category-page',\n templateUrl: './default-category-page.component.html',\n styleUrls: ['./default-category-page.component.scss'],\n standalone: true,\n imports: [\n NgIf,\n NgFor,\n AsyncPipe,\n RouterOutlet,\n ProductCardComponent,\n ObserverDirective,\n ScrollListDirective,\n ScrollItemDirective\n ]\n})\nexport class DefaultCategoryPageComponent extends CategoryPageAbstract { }\n","
\n
\n \n
\n
{{ category.name }}
\n
\n
\n Available from {{ schedule.from }} to {{ schedule.to }}\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n\n\n","import { Component } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { AsyncPipe, NgFor, NgIf } from '@angular/common';\nimport { RouterOutlet } from '@angular/router';\nimport { ProductCardComponent } from '../components/product-card/product-card.component';\nimport { CategoryPageAbstract } from '../../common/category-page.abstract';\nimport { ObserverDirective } from 'src/app/shared/directives/observer/observer.directive';\nimport { ScrollListDirective } from 'src/app/shared/directives/scroll-list/scroll-list.directive';\nimport { ScrollItemDirective } from 'src/app/shared/directives/scroll-list/scroll-item.directive';\n\n@Component({\n selector: 'app-fresh-category-page',\n templateUrl: './fresh-category-page.component.html',\n styleUrls: ['./fresh-category-page.component.scss'],\n standalone: true,\n imports: [\n NgIf,\n NgFor,\n AsyncPipe,\n RouterOutlet,\n ProductCardComponent,\n ObserverDirective,\n ScrollListDirective,\n ScrollItemDirective\n ]\n})\nexport class FreshCategoryPageComponent extends CategoryPageAbstract {\n searchString$: Observable = this.menuListRepository.searchString$;\n}\n","\n \n \n\n","import { Routes } from '@angular/router';\n\nimport { CategoryComponent } from './category.component';\n\nexport const routes: Routes = [\n {\n path: '',\n component: CategoryComponent,\n children: [\n {\n path: ':slug',\n loadComponent: () => import('../product-info/product-info.component')\n },\n ]\n },\n]\n","import { AsyncPipe, NgSwitch, NgSwitchCase } from '@angular/common';\nimport { Component, Input } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { Layout } from 'src/app/api/v1/models';\nimport { ConfigRepository } from '../../shared/repositories/config.repository';\nimport {\n DefaultCategoryPageComponent\n} from '../../layout/default/default-category-page/default-category-page.component';\nimport { FreshCategoryPageComponent } from '../../layout/fresh/fresh-category-page/fresh-category-page.component';\n\n@Component({\n selector: 'app-category',\n templateUrl: './category.component.html',\n standalone: true,\n imports: [\n AsyncPipe,\n NgSwitch,\n NgSwitchCase,\n DefaultCategoryPageComponent,\n FreshCategoryPageComponent,\n ]\n})\nexport class CategoryComponent{\n constructor(\n private config: ConfigRepository,\n ) {}\n @Input() slug: string;\n\n layout$: Observable = this.config.layout$;\n layouts = Layout;\n}\n","import { ConnectableObservable, isObservable, of, Subject } from 'rxjs';\nimport * as i0 from '@angular/core';\nimport { Injectable, InjectionToken } from '@angular/core';\n\nclass DataSource {\n}\n/** Checks whether an object is a data source. */\nfunction isDataSource(value) {\n // Check if the value is a DataSource by observing if it has a connect function. Cannot\n // be checked as an `instanceof DataSource` since people could create their own sources\n // that match the interface, but don't extend DataSource. We also can't use `isObservable`\n // here, because of some internal apps.\n return value && typeof value.connect === 'function' && !(value instanceof ConnectableObservable);\n}\n\n/** DataSource wrapper for a native array. */\nclass ArrayDataSource extends DataSource {\n constructor(_data) {\n super();\n this._data = _data;\n }\n connect() {\n return isObservable(this._data) ? this._data : of(this._data);\n }\n disconnect() { }\n}\n\n/**\n * A repeater that destroys views when they are removed from a\n * {@link ViewContainerRef}. When new items are inserted into the container,\n * the repeater will always construct a new embedded view for each item.\n *\n * @template T The type for the embedded view's $implicit property.\n * @template R The type for the item in each IterableDiffer change record.\n * @template C The type for the context passed to each embedded view.\n */\nclass _DisposeViewRepeaterStrategy {\n applyChanges(changes, viewContainerRef, itemContextFactory, itemValueResolver, itemViewChanged) {\n changes.forEachOperation((record, adjustedPreviousIndex, currentIndex) => {\n let view;\n let operation;\n if (record.previousIndex == null) {\n const insertContext = itemContextFactory(record, adjustedPreviousIndex, currentIndex);\n view = viewContainerRef.createEmbeddedView(insertContext.templateRef, insertContext.context, insertContext.index);\n operation = 1 /* _ViewRepeaterOperation.INSERTED */;\n }\n else if (currentIndex == null) {\n viewContainerRef.remove(adjustedPreviousIndex);\n operation = 3 /* _ViewRepeaterOperation.REMOVED */;\n }\n else {\n view = viewContainerRef.get(adjustedPreviousIndex);\n viewContainerRef.move(view, currentIndex);\n operation = 2 /* _ViewRepeaterOperation.MOVED */;\n }\n if (itemViewChanged) {\n itemViewChanged({\n context: view?.context,\n operation,\n record,\n });\n }\n });\n }\n detach() { }\n}\n\n/**\n * A repeater that caches views when they are removed from a\n * {@link ViewContainerRef}. When new items are inserted into the container,\n * the repeater will reuse one of the cached views instead of creating a new\n * embedded view. Recycling cached views reduces the quantity of expensive DOM\n * inserts.\n *\n * @template T The type for the embedded view's $implicit property.\n * @template R The type for the item in each IterableDiffer change record.\n * @template C The type for the context passed to each embedded view.\n */\nclass _RecycleViewRepeaterStrategy {\n constructor() {\n /**\n * The size of the cache used to store unused views.\n * Setting the cache size to `0` will disable caching. Defaults to 20 views.\n */\n this.viewCacheSize = 20;\n /**\n * View cache that stores embedded view instances that have been previously stamped out,\n * but don't are not currently rendered. The view repeater will reuse these views rather than\n * creating brand new ones.\n *\n * TODO(michaeljamesparsons) Investigate whether using a linked list would improve performance.\n */\n this._viewCache = [];\n }\n /** Apply changes to the DOM. */\n applyChanges(changes, viewContainerRef, itemContextFactory, itemValueResolver, itemViewChanged) {\n // Rearrange the views to put them in the right location.\n changes.forEachOperation((record, adjustedPreviousIndex, currentIndex) => {\n let view;\n let operation;\n if (record.previousIndex == null) {\n // Item added.\n const viewArgsFactory = () => itemContextFactory(record, adjustedPreviousIndex, currentIndex);\n view = this._insertView(viewArgsFactory, currentIndex, viewContainerRef, itemValueResolver(record));\n operation = view ? 1 /* _ViewRepeaterOperation.INSERTED */ : 0 /* _ViewRepeaterOperation.REPLACED */;\n }\n else if (currentIndex == null) {\n // Item removed.\n this._detachAndCacheView(adjustedPreviousIndex, viewContainerRef);\n operation = 3 /* _ViewRepeaterOperation.REMOVED */;\n }\n else {\n // Item moved.\n view = this._moveView(adjustedPreviousIndex, currentIndex, viewContainerRef, itemValueResolver(record));\n operation = 2 /* _ViewRepeaterOperation.MOVED */;\n }\n if (itemViewChanged) {\n itemViewChanged({\n context: view?.context,\n operation,\n record,\n });\n }\n });\n }\n detach() {\n for (const view of this._viewCache) {\n view.destroy();\n }\n this._viewCache = [];\n }\n /**\n * Inserts a view for a new item, either from the cache or by creating a new\n * one. Returns `undefined` if the item was inserted into a cached view.\n */\n _insertView(viewArgsFactory, currentIndex, viewContainerRef, value) {\n const cachedView = this._insertViewFromCache(currentIndex, viewContainerRef);\n if (cachedView) {\n cachedView.context.$implicit = value;\n return undefined;\n }\n const viewArgs = viewArgsFactory();\n return viewContainerRef.createEmbeddedView(viewArgs.templateRef, viewArgs.context, viewArgs.index);\n }\n /** Detaches the view at the given index and inserts into the view cache. */\n _detachAndCacheView(index, viewContainerRef) {\n const detachedView = viewContainerRef.detach(index);\n this._maybeCacheView(detachedView, viewContainerRef);\n }\n /** Moves view at the previous index to the current index. */\n _moveView(adjustedPreviousIndex, currentIndex, viewContainerRef, value) {\n const view = viewContainerRef.get(adjustedPreviousIndex);\n viewContainerRef.move(view, currentIndex);\n view.context.$implicit = value;\n return view;\n }\n /**\n * Cache the given detached view. If the cache is full, the view will be\n * destroyed.\n */\n _maybeCacheView(view, viewContainerRef) {\n if (this._viewCache.length < this.viewCacheSize) {\n this._viewCache.push(view);\n }\n else {\n const index = viewContainerRef.indexOf(view);\n // The host component could remove views from the container outside of\n // the view repeater. It's unlikely this will occur, but just in case,\n // destroy the view on its own, otherwise destroy it through the\n // container to ensure that all the references are removed.\n if (index === -1) {\n view.destroy();\n }\n else {\n viewContainerRef.remove(index);\n }\n }\n }\n /** Inserts a recycled view from the cache at the given index. */\n _insertViewFromCache(index, viewContainerRef) {\n const cachedView = this._viewCache.pop();\n if (cachedView) {\n viewContainerRef.insert(cachedView, index);\n }\n return cachedView || null;\n }\n}\n\n/**\n * Class to be used to power selecting one or more options from a list.\n */\nclass SelectionModel {\n /** Selected values. */\n get selected() {\n if (!this._selected) {\n this._selected = Array.from(this._selection.values());\n }\n return this._selected;\n }\n constructor(_multiple = false, initiallySelectedValues, _emitChanges = true, compareWith) {\n this._multiple = _multiple;\n this._emitChanges = _emitChanges;\n this.compareWith = compareWith;\n /** Currently-selected values. */\n this._selection = new Set();\n /** Keeps track of the deselected options that haven't been emitted by the change event. */\n this._deselectedToEmit = [];\n /** Keeps track of the selected options that haven't been emitted by the change event. */\n this._selectedToEmit = [];\n /** Event emitted when the value has changed. */\n this.changed = new Subject();\n if (initiallySelectedValues && initiallySelectedValues.length) {\n if (_multiple) {\n initiallySelectedValues.forEach(value => this._markSelected(value));\n }\n else {\n this._markSelected(initiallySelectedValues[0]);\n }\n // Clear the array in order to avoid firing the change event for preselected values.\n this._selectedToEmit.length = 0;\n }\n }\n /**\n * Selects a value or an array of values.\n * @param values The values to select\n * @return Whether the selection changed as a result of this call\n * @breaking-change 16.0.0 make return type boolean\n */\n select(...values) {\n this._verifyValueAssignment(values);\n values.forEach(value => this._markSelected(value));\n const changed = this._hasQueuedChanges();\n this._emitChangeEvent();\n return changed;\n }\n /**\n * Deselects a value or an array of values.\n * @param values The values to deselect\n * @return Whether the selection changed as a result of this call\n * @breaking-change 16.0.0 make return type boolean\n */\n deselect(...values) {\n this._verifyValueAssignment(values);\n values.forEach(value => this._unmarkSelected(value));\n const changed = this._hasQueuedChanges();\n this._emitChangeEvent();\n return changed;\n }\n /**\n * Sets the selected values\n * @param values The new selected values\n * @return Whether the selection changed as a result of this call\n * @breaking-change 16.0.0 make return type boolean\n */\n setSelection(...values) {\n this._verifyValueAssignment(values);\n const oldValues = this.selected;\n const newSelectedSet = new Set(values);\n values.forEach(value => this._markSelected(value));\n oldValues\n .filter(value => !newSelectedSet.has(value))\n .forEach(value => this._unmarkSelected(value));\n const changed = this._hasQueuedChanges();\n this._emitChangeEvent();\n return changed;\n }\n /**\n * Toggles a value between selected and deselected.\n * @param value The value to toggle\n * @return Whether the selection changed as a result of this call\n * @breaking-change 16.0.0 make return type boolean\n */\n toggle(value) {\n return this.isSelected(value) ? this.deselect(value) : this.select(value);\n }\n /**\n * Clears all of the selected values.\n * @param flushEvent Whether to flush the changes in an event.\n * If false, the changes to the selection will be flushed along with the next event.\n * @return Whether the selection changed as a result of this call\n * @breaking-change 16.0.0 make return type boolean\n */\n clear(flushEvent = true) {\n this._unmarkAll();\n const changed = this._hasQueuedChanges();\n if (flushEvent) {\n this._emitChangeEvent();\n }\n return changed;\n }\n /**\n * Determines whether a value is selected.\n */\n isSelected(value) {\n return this._selection.has(this._getConcreteValue(value));\n }\n /**\n * Determines whether the model does not have a value.\n */\n isEmpty() {\n return this._selection.size === 0;\n }\n /**\n * Determines whether the model has a value.\n */\n hasValue() {\n return !this.isEmpty();\n }\n /**\n * Sorts the selected values based on a predicate function.\n */\n sort(predicate) {\n if (this._multiple && this.selected) {\n this._selected.sort(predicate);\n }\n }\n /**\n * Gets whether multiple values can be selected.\n */\n isMultipleSelection() {\n return this._multiple;\n }\n /** Emits a change event and clears the records of selected and deselected values. */\n _emitChangeEvent() {\n // Clear the selected values so they can be re-cached.\n this._selected = null;\n if (this._selectedToEmit.length || this._deselectedToEmit.length) {\n this.changed.next({\n source: this,\n added: this._selectedToEmit,\n removed: this._deselectedToEmit,\n });\n this._deselectedToEmit = [];\n this._selectedToEmit = [];\n }\n }\n /** Selects a value. */\n _markSelected(value) {\n value = this._getConcreteValue(value);\n if (!this.isSelected(value)) {\n if (!this._multiple) {\n this._unmarkAll();\n }\n if (!this.isSelected(value)) {\n this._selection.add(value);\n }\n if (this._emitChanges) {\n this._selectedToEmit.push(value);\n }\n }\n }\n /** Deselects a value. */\n _unmarkSelected(value) {\n value = this._getConcreteValue(value);\n if (this.isSelected(value)) {\n this._selection.delete(value);\n if (this._emitChanges) {\n this._deselectedToEmit.push(value);\n }\n }\n }\n /** Clears out the selected values. */\n _unmarkAll() {\n if (!this.isEmpty()) {\n this._selection.forEach(value => this._unmarkSelected(value));\n }\n }\n /**\n * Verifies the value assignment and throws an error if the specified value array is\n * including multiple values while the selection model is not supporting multiple values.\n */\n _verifyValueAssignment(values) {\n if (values.length > 1 && !this._multiple && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMultipleValuesInSingleSelectionError();\n }\n }\n /** Whether there are queued up change to be emitted. */\n _hasQueuedChanges() {\n return !!(this._deselectedToEmit.length || this._selectedToEmit.length);\n }\n /** Returns a value that is comparable to inputValue by applying compareWith function, returns the same inputValue otherwise. */\n _getConcreteValue(inputValue) {\n if (!this.compareWith) {\n return inputValue;\n }\n else {\n for (let selectedValue of this._selection) {\n if (this.compareWith(inputValue, selectedValue)) {\n return selectedValue;\n }\n }\n return inputValue;\n }\n }\n}\n/**\n * Returns an error that reports that multiple values are passed into a selection model\n * with a single value.\n * @docs-private\n */\nfunction getMultipleValuesInSingleSelectionError() {\n return Error('Cannot pass multiple values into SelectionModel with single-value mode.');\n}\n\n/**\n * Class to coordinate unique selection based on name.\n * Intended to be consumed as an Angular service.\n * This service is needed because native radio change events are only fired on the item currently\n * being selected, and we still need to uncheck the previous selection.\n *\n * This service does not *store* any IDs and names because they may change at any time, so it is\n * less error-prone if they are simply passed through when the events occur.\n */\nclass UniqueSelectionDispatcher {\n constructor() {\n this._listeners = [];\n }\n /**\n * Notify other items that selection for the given name has been set.\n * @param id ID of the item.\n * @param name Name of the item.\n */\n notify(id, name) {\n for (let listener of this._listeners) {\n listener(id, name);\n }\n }\n /**\n * Listen for future changes to item selection.\n * @return Function used to deregister listener\n */\n listen(listener) {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter((registered) => {\n return listener !== registered;\n });\n };\n }\n ngOnDestroy() {\n this._listeners = [];\n }\n static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"16.1.1\", ngImport: i0, type: UniqueSelectionDispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }\n static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"16.1.1\", ngImport: i0, type: UniqueSelectionDispatcher, providedIn: 'root' }); }\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"16.1.1\", ngImport: i0, type: UniqueSelectionDispatcher, decorators: [{\n type: Injectable,\n args: [{ providedIn: 'root' }]\n }] });\n\n/**\n * Injection token for {@link _ViewRepeater}. This token is for use by Angular Material only.\n * @docs-private\n */\nconst _VIEW_REPEATER_STRATEGY = new InjectionToken('_ViewRepeater');\n\n/**\n * Generated bundle index. Do not edit.\n */\n\nexport { ArrayDataSource, DataSource, SelectionModel, UniqueSelectionDispatcher, _DisposeViewRepeaterStrategy, _RecycleViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY, getMultipleValuesInSingleSelectionError, isDataSource };\n"],"names":["i0","ctx_r1","currentSize","buttonImage","src","data","name","defaultPrice_r6","ctx_r4","description","ctx_r7","energy","ProductCardComponent_a_0_ng_container_10_ng_container_4_span_4_Template","ProductCardComponent_a_0_ng_container_10_ng_container_4_span_5_Template","ProductCardComponent_a_0_ng_container_10_ng_container_4_span_6_Template","ProductCardComponent_a_0_ng_container_10_ng_container_4_span_7_Template","ctx_r8","portionWeightGrams","measureUnitType","label_r15","ProductCardComponent_a_0_ng_container_10_div_5_div_2_Template","ctx_r9","labels","ProductCardComponent_a_0_ng_container_10_ng_container_3_Template","ProductCardComponent_a_0_ng_container_10_ng_container_4_Template","ProductCardComponent_a_0_ng_container_10_div_5_Template","ctx_r5","length","_r17","ctx_r16","onOpenCard","balance","slug","ProductCardComponent_a_0_div_1_Template","ProductCardComponent_a_0_span_6_Template","ProductCardComponent_a_0_ng_container_7_Template","ProductCardComponent_a_0_div_9_Template","ProductCardComponent_a_0_ng_container_10_Template","_c10","ctx_r0","allergens","defaultPrice$","itemSizes","ProductCardComponent","constructor","this","menuListRepository","inject","MenuListRepository","router","Router","ngOnChanges","prepareData","getDefaultSize","getDefaultPriceObservable","nutritionPerHundredGrams","navigate","categorySlug","static","t","core","Xpm","selectors","inputs","standalone","features","decls","vars","consts","i18n_0","$localize","ProductCardComponent_a_0_Template","ctx","CommonModule","i1","NgOptimizedImage","CurrencyComponent","encapsulation","CategoryPageAbstract","scrollListService","ScrollListService","sessionRepository","SessionRepository","intersectionOptions","rootMargin","threshold","schedule$","activeCategorySchedule$","categories$","menuNavCategories$","pipe","map","categories","filter","c","isScheduleAvailable","items$","showItems$","combineLatestWith","activeLabelFilter$","activeAllergenFilter$","items","activeLabelFilter","activeAllergenFilter","i","some","l","includes","a","reduce","arr","item","set","categoryId","get","concat","Map","shareReplay","activeCategoryIndex$","activeIndexItem$","isSearching$","searchString$","str","ngAfterViewInit","tap","activeCategorySlug","find","id","activeCategoryId","currentCategoryId","setActiveCategory","x","setTimeout","setActiveIndex","untilDestroyed","subscribe","leaveEnd","isSearching","test","url","setActiveCategoryBySlug","lG2","__decorate","UntilDestroy","ScrollItemDirective","elRef","setActive","window","scrollTo","left","top","nativeElement","offsetTop","behavior","ScrollListDirective","activeIndex","changes","firstChange","scrollButtons","contentQueries","rf","dirIndex","schedule_r4","from","to","item_r5","category_r1","_r7","$implicit","ctx_r6","DefaultCategoryPageComponent_div_2_div_4_Template","DefaultCategoryPageComponent_div_2_div_7_Template","DefaultCategoryPageComponent","DefaultCategoryPageComponent_div_2_Template","tmp_0_0","undefined","NgIf","NgFor","AsyncPipe","RouterOutlet","ObserverDirective","schedule_r7","item_r8","FreshCategoryPageComponent_div_0_div_2_ng_container_1_div_4_Template","FreshCategoryPageComponent_div_0_div_2_ng_container_1_div_7_Template","category_r3","data_r1","_r12","ngIf","ctx_r11","FreshCategoryPageComponent_div_0_div_2_ng_container_1_Template","ctx_r2","FreshCategoryPageComponent_div_0_div_2_Template","FreshCategoryPageComponent","FreshCategoryPageComponent_div_0_Template","_c4","routes","path","component","CategoryComponent","config","layout$","layouts","Layout","template","CategoryComponent_app_default_category_page_2_Template","CategoryComponent_app_fresh_category_page_3_Template","Default","Fresh","NgSwitch","NgSwitchCase","children","loadComponent","__webpack_require__","e","then","bind","DataSource","isDataSource","value","connect","ConnectableObservable","ArrayDataSource","_data","super","isObservable","of","disconnect","_RecycleViewRepeaterStrategy","viewCacheSize","_viewCache","applyChanges","viewContainerRef","itemContextFactory","itemValueResolver","itemViewChanged","forEachOperation","record","adjustedPreviousIndex","currentIndex","view","operation","previousIndex","_insertView","viewArgsFactory","_detachAndCacheView","_moveView","context","detach","destroy","cachedView","_insertViewFromCache","viewArgs","createEmbeddedView","templateRef","index","detachedView","_maybeCacheView","move","push","indexOf","remove","pop","insert","SelectionModel","selected","_selected","Array","_selection","values","_multiple","initiallySelectedValues","_emitChanges","compareWith","Set","_deselectedToEmit","_selectedToEmit","changed","Subject","forEach","_markSelected","select","_verifyValueAssignment","_hasQueuedChanges","_emitChangeEvent","deselect","_unmarkSelected","setSelection","oldValues","newSelectedSet","has","toggle","isSelected","clear","flushEvent","_unmarkAll","_getConcreteValue","isEmpty","size","hasValue","sort","predicate","isMultipleSelection","next","source","added","removed","add","delete","inputValue","selectedValue","UniqueSelectionDispatcher","_listeners","notify","listener","listen","registered","ngOnDestroy","ɵfac","ɵprov","token","factory","providedIn","_VIEW_REPEATER_STRATEGY","InjectionToken"],"sourceRoot":"webpack:///"}