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 .key('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.push({ 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 .key('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 } 221} 222 223@Component 224struct FoodCategory { 225 private foodItems: FoodData[] 226 227 build() { 228 Tabs() { 229 TabContent() { 230 FoodGrid({ foodItems: this.foodItems }) 231 }.tabBar('All') 232 233 TabContent() { 234 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Vegetable)) }) 235 }.tabBar('Vegetable') 236 237 TabContent() { 238 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Fruit)) }) 239 }.tabBar('Fruit') 240 241 TabContent() { 242 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Nut)) }) 243 }.tabBar('Nut') 244 245 TabContent() { 246 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Seafood)) }) 247 }.tabBar('Seafood') 248 249 TabContent() { 250 FoodGrid({ foodItems: this.foodItems.filter(item => (item.category === Category.Dessert)) }) 251 }.tabBar('Dessert') 252 } 253 .width('100%') 254 .barWidth('80%') 255 .barHeight(70) 256 .barMode(BarMode.Scrollable) 257 } 258} 259 260@Entry 261@Component 262struct FoodCategoryList { 263 private foodItems: FoodData[] = initializeOnStartup() 264 @State private showList: boolean = false 265 266 build() { 267 Column() { 268 Stack({ alignContent: Alignment.TopEnd }) { 269 if (this.showList) { 270 FoodList({ foodItems: this.foodItems }) 271 } else { 272 FoodCategory({ foodItems: this.foodItems }) 273 } 274 Image($r('app.media.Switch')) 275 .height(40) 276 .width(24) 277 .objectFit(ImageFit.Contain) 278 .key('switch') 279 .margin({ top: 15, right: 10 }) 280 .onClick(() => { 281 this.showList = !this.showList 282 }) 283 } 284 } 285 .width('100%') 286 .height('100%') 287 } 288} 289