1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import router from '@ohos.router' 17import { Category, FoodData } from '../model/FoodData' 18import { initializeOnStartup } from '../model/FoodDataModels' 19 20class BasicDataSource implements IDataSource { 21 private listeners: DataChangeListener[] = [] 22 23 public totalCount(): number { 24 return 0 25 } 26 27 public getData(index: number): any { 28 return undefined 29 } 30 31 registerDataChangeListener(listener: DataChangeListener): void { 32 if (this.listeners.indexOf(listener) < 0) { 33 this.listeners.push(listener) 34 } 35 } 36 37 unregisterDataChangeListener(listener: DataChangeListener): void { 38 const pos = this.listeners.indexOf(listener); 39 if (pos >= 0) { 40 this.listeners.splice(pos, 1) 41 } 42 } 43 44 notifyDataReload(): void { 45 this.listeners.forEach(listener => { 46 listener.onDataReloaded() 47 }) 48 } 49 50 notifyDataAdd(index: number): void { 51 this.listeners.forEach(listener => { 52 listener.onDataAdded(index) 53 }) 54 } 55 56 notifyDataChange(index: number): void { 57 this.listeners.forEach(listener => { 58 listener.onDataChanged(index) 59 }) 60 } 61} 62 63class MyDataSource extends BasicDataSource { 64 public dataArray: string[] = [] 65 66 constructor(ele) { 67 super() 68 for (var index = 0;index < ele.length; index++) { 69 this.dataArray.push(ele[index]) 70 } 71 } 72 73 public totalCount(): number { 74 return this.dataArray.length 75 } 76 77 public getData(index: number): any { 78 return this.dataArray[index] 79 } 80 81 public addData(index: number, data: string): void { 82 this.dataArray.splice(index, 0) 83 this.notifyDataAdd(index) 84 } 85} 86 87@Component 88struct FoodListItem { 89 private foodItem: FoodData 90 91 build() { 92 Navigator({ target: 'pages/FoodDetail' }) { 93 Row() { 94 Row() { 95 Image(this.foodItem.image) 96 .objectFit(ImageFit.Contain) 97 .autoResize(false) 98 .height(40) 99 .width(40) 100 } 101 .backgroundColor('#FFf1f3f5') 102 .margin({ right: 16 }) 103 104 Text(this.foodItem.name) 105 .fontSize(14) 106 .flexGrow(1) 107 Blank() 108 Text(this.foodItem.calories + ' kcal') 109 .fontSize(14) 110 } 111 .alignItems(VerticalAlign.Center) 112 .height(64) 113 .width('100%') 114 } 115 .width('100%') 116 .params({ foodId: this.foodItem }) 117 .padding({ right: 24, left: 24 }) 118 } 119} 120 121 122@Component 123struct FoodList { 124 private foodItems: FoodData[] 125 126 build() { 127 Column() { 128 Row() { 129 Text('Food List') 130 .fontSize(20) 131 .margin({ left: 20 }) 132 } 133 .alignItems(VerticalAlign.Center) 134 .justifyContent(FlexAlign.Start) 135 .height('7%') 136 .width('100%') 137 .backgroundColor('#FFf1f3f5') 138 139 List() { 140 LazyForEach(new MyDataSource(this.foodItems), (item, index) => { 141 ListItem() { 142 FoodListItem({ foodItem: item }) 143 } 144 .id('foodListItem' + (index + 1)) 145 }, item => item.id.toString()) 146 } 147 .width('100%') 148 .height('93%') 149 } 150 .width('100%') 151 } 152} 153 154@Component 155struct FoodGridItem { 156 private foodItem: FoodData 157 158 build() { 159 Column() { 160 Row() { 161 Image(this.foodItem.image) 162 .objectFit(ImageFit.Contain) 163 .height(152) 164 .width('100%') 165 }.backgroundColor('#FFf1f3f5') 166 167 Row() { 168 Text(this.foodItem.name) 169 .fontSize(14) 170 .flexGrow(1) 171 .padding({ left: 8 }) 172 Text(this.foodItem.calories + 'kcal') 173 .fontSize(14) 174 .margin({ right: 6 }) 175 } 176 .alignItems(VerticalAlign.Center) 177 .justifyContent(FlexAlign.Start) 178 .height(32) 179 .width('100%') 180 .backgroundColor('#FFe5e5e5') 181 } 182 .height(184) 183 .width('100%') 184 .onClick(() => { 185 router.pushUrl({ url: 'pages/FoodDetail', params: { foodId: this.foodItem } }) 186 }) 187 } 188} 189 190@Component 191struct FoodGrid { 192 private foodItems: FoodData[] 193 private gridRowTemplate: string = '' 194 private heightValue: number 195 196 aboutToAppear() { 197 var rows = Math.round(this.foodItems.length / 2); 198 this.gridRowTemplate = '1fr '.repeat(rows); 199 this.heightValue = rows * 192 - 8; 200 } 201 202 build() { 203 Scroll() { 204 Grid() { 205 LazyForEach(new MyDataSource(this.foodItems), (item: FoodData, index) => { 206 GridItem() { 207 FoodGridItem({ foodItem: item }) 208 } 209 .id('foodGridItem' + (index + 1)) 210 }, (item: FoodData) => item.id.toString()) 211 } 212 .rowsTemplate(this.gridRowTemplate) 213 .columnsTemplate('1fr 1fr') 214 .columnsGap(8) 215 .rowsGap(8) 216 .height(this.heightValue) 217 } 218 .scrollBar(BarState.Off) 219 .padding({ left: 16, right: 16 }) 220 .height('100%') 221 .align(Alignment.Top) 222 } 223} 224 225@Component 226struct FoodCategory { 227 private foodItems: FoodData[] 228 229 build() { 230 Tabs() { 231 TabContent() { 232 FoodGrid({ foodItems: this.foodItems }) 233 }.tabBar('All') 234 235 TabContent() { 236 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Vegetable)) }) 237 }.tabBar('Vegetable') 238 239 TabContent() { 240 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Fruit)) }) 241 }.tabBar('Fruit') 242 243 TabContent() { 244 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Nut)) }) 245 }.tabBar('Nut') 246 247 TabContent() { 248 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Seafood)) }) 249 }.tabBar('Seafood') 250 251 TabContent() { 252 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Dessert)) }) 253 }.tabBar('Dessert') 254 } 255 .width('100%') 256 .barWidth('80%') 257 .barHeight(70) 258 .barMode(BarMode.Scrollable) 259 } 260} 261 262@Entry 263@Component 264struct FoodCategoryList { 265 private foodItems: FoodData[] = initializeOnStartup() 266 @State private showList: boolean = false 267 268 build() { 269 Column() { 270 Stack({ alignContent: Alignment.TopEnd }) { 271 if (this.showList) { 272 FoodList({ foodItems: this.foodItems }) 273 } else { 274 FoodCategory({ foodItems: this.foodItems }) 275 } 276 Image($r('app.media.Switch')) 277 .height(40) 278 .width(24) 279 .objectFit(ImageFit.Contain) 280 .id('switch') 281 .margin({ top: 15, right: 10 }) 282 .onClick(() => { 283 this.showList = !this.showList 284 }) 285 } 286 } 287 .width('100%') 288 .height('100%') 289 } 290} 291