• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 curves from '@ohos.curves'
18import { BreakpointSystem, BreakPointType } from '../common/BreakpointSystem'
19import { FoodInfo, Category } from '../model/DataModels'
20import { getFoods, getFoodCategories, getSortedFoodData } from '../model/DataUtil'
21import { Records } from './components/DietRecord'
22
23@Component
24struct FoodListItem {
25  private foodItem: FoodInfo
26
27  build() {
28    Navigator({ target: 'pages/FoodDetail' }) {
29      Row() {
30        Image(this.foodItem.image)
31          .objectFit(ImageFit.Contain)
32          .autoResize(false)
33          .height(40)
34          .width(40)
35          .backgroundColor('#FFf1f3f5')
36          .margin({ right: 16 })
37          .borderRadius(6)
38          .sharedTransition(this.foodItem.letter, {
39            duration: 400,
40            curve: curves.cubicBezier(0.2, 0.2, 0.1, 1.0),
41            delay: 100
42          })
43        Text(this.foodItem.name)
44          .fontSize(14)
45        Blank()
46        Text($r('app.string.calorie_with_kcal_unit', this.foodItem.calories.toString()))
47          .fontSize(14)
48      }
49      .height(64)
50      .width('100%')
51    }
52    .params({ foodId: this.foodItem })
53    .margin({ right: 24, left: 32 })
54  }
55}
56
57@Component
58struct ListModeFoods {
59  private foodItems: FoodInfo[] = getSortedFoodData()
60
61  build() {
62    Column() {
63      Text($r("app.string.title_food_list"))
64        .width('100%')
65        .height(56)
66        .padding({ left: 20 })
67        .backgroundColor('#FF1f3f5')
68        .fontSize(20)
69
70      List() {
71        ForEach(this.foodItems, (item) => {
72          ListItem() {
73            if (item.letter !== undefined) {
74              FoodListItem({ foodItem: item })
75            } else {
76              Text(item)
77                .fontSize(14)
78                .height(48)
79                .margin({ left: 24 })
80                .width('100%')
81            }
82          }
83        })
84      }
85      .layoutWeight(1)
86    }
87  }
88}
89
90@Component
91struct FoodGridItem {
92  private foodItem: FoodInfo
93
94  build() {
95    Column() {
96      Image(this.foodItem.image)
97        .objectFit(ImageFit.Contain)
98        .backgroundColor('#f1f3f5')
99        .height(152)
100        .sharedTransition(this.foodItem.letter, {
101          duration: 400,
102          curve: curves.cubicBezier(0.2, 0.2, 0.1, 1.0),
103          delay: 100
104        })
105      Row() {
106        Text(this.foodItem.name)
107          .fontSize(14)
108        Blank()
109        Text($r('app.string.calorie_with_kcal_unit', this.foodItem.calories.toString()))
110          .fontSize(14)
111          .fontColor(0x99000000)
112      }
113      .padding({ left: 12, right: 12 })
114      .width('100%')
115      .height(32)
116      .backgroundColor('#E5E5E5')
117    }
118    .height(184)
119    .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))
120    .onClick(() => {
121      router.push({ url: 'pages/FoodDetail', params: { foodId: this.foodItem } })
122    })
123  }
124}
125
126@Component
127struct FoodGrid {
128  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'
129  private foodItems: FoodInfo[]
130
131  build() {
132    Grid() {
133      ForEach(this.foodItems, (item: FoodInfo) => {
134        GridItem() {
135          FoodGridItem({ foodItem: item })
136        }
137      })
138    }
139    .columnsTemplate(new BreakPointType({
140      sm: '1fr 1fr',
141      md: '1fr 1fr 1fr',
142      lg: '1fr 1fr 1fr 1fr'
143    }).getValue(this.currentBreakpoint))
144    .columnsGap(8)
145    .rowsGap(8)
146    .padding({ left: 16, right: 16 })
147  }
148}
149
150@Component
151struct CategoryModeFoods {
152  @State currentTabIndex: number = 0
153  private foodItems: FoodInfo[] = getFoods()
154  private foodCategories: Category[] = getFoodCategories()
155
156  @Builder tabBarItemBuilder(value: Resource, index: number) {
157    Text(value)
158      .fontColor(this.currentTabIndex === index ? 'rgba(0,0,0,0.9)' : 'rgba(0,0,0,0.6)')
159      .fontSize(this.currentTabIndex === index ? 24 : 18)
160      .margin({ top: 2 })
161      .height(56)
162  }
163
164  build() {
165    Tabs() {
166      TabContent() {
167        FoodGrid({ foodItems: this.foodItems })
168      }.tabBar(this.tabBarItemBuilder($r('app.string.category_all'), 0))
169
170      ForEach(this.foodCategories, (foodCategory: Category, index) => {
171        TabContent() {
172          FoodGrid({ foodItems: this.foodItems.filter(item => (item.categoryId === foodCategory.id)) })
173        }.tabBar(this.tabBarItemBuilder(foodCategory.name, index + 1))
174      })
175    }
176    .animationDuration(0)
177    .barMode(BarMode.Scrollable)
178    .onChange((index) => {
179      this.currentTabIndex = index
180    })
181  }
182}
183
184@Component
185struct FoodsDisplay {
186  @State isCategoryMode: boolean = true
187
188  build() {
189    Stack({ alignContent: Alignment.TopEnd }) {
190      if (this.isCategoryMode) {
191        CategoryModeFoods()
192      } else {
193        ListModeFoods()
194      }
195      Row() {
196        Image($r("app.media.ic_switch"))
197          .height(24)
198          .width(24)
199          .margin({ left: 24, right: 24 })
200      }
201      .height(56)
202      .backgroundColor(this.isCategoryMode ? Color.White : '#F1F3F5')
203      .onClick(() => {
204        this.isCategoryMode = !this.isCategoryMode
205      })
206    }
207  }
208}
209
210@Entry
211@Component
212struct Home {
213  @State currentTabIndex: number = 0
214  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'
215  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
216
217  @Builder bottomBarItemBuilder(name: Resource, icon: Resource, index: number) {
218    Flex({
219      direction: new BreakPointType({
220        sm: FlexDirection.Column,
221        md: FlexDirection.Row,
222        lg: FlexDirection.Column
223      }).getValue(this.currentBreakpoint),
224      justifyContent: FlexAlign.Center,
225      alignItems: ItemAlign.Center
226    }) {
227      Image(icon)
228        .height(24)
229        .width(24)
230        .fillColor(this.getTabBarColor(index))
231      Text(name)
232        .margin(new BreakPointType({
233          sm: { top: 4 },
234          md: { left: 8 },
235          lg: { top: 4 }
236        }).getValue(this.currentBreakpoint))
237        .fontSize(11)
238        .fontColor(this.getTabBarColor(index))
239    }
240    .width('100%')
241    .height('100%')
242  }
243
244  aboutToAppear() {
245    this.breakpointSystem.register()
246  }
247
248  aboutToDisappear() {
249    this.breakpointSystem.unregister()
250  }
251
252  build() {
253    Tabs({
254      barPosition: new BreakPointType({
255        sm: BarPosition.End,
256        md: BarPosition.End,
257        lg: BarPosition.Start
258      }).getValue(this.currentBreakpoint)
259    }) {
260      TabContent() {
261        FoodsDisplay()
262      }.tabBar(this.bottomBarItemBuilder($r("app.string.tab_bar_home"), $r("app.media.ic_bottom_home"), 0))
263
264      TabContent() {
265        Records()
266      }.tabBar(this.bottomBarItemBuilder($r("app.string.tab_bar_record"), $r("app.media.ic_bottom_record"), 1))
267    }
268    .vertical(new BreakPointType({ sm: false, md: false, lg: true }).getValue(this.currentBreakpoint))
269    .barWidth(new BreakPointType({ sm: '100%', md: '100%', lg: '56vp' }).getValue(this.currentBreakpoint))
270    .barHeight(new BreakPointType({ sm: '56vp', md: '56vp', lg: '60%' }).getValue(this.currentBreakpoint))
271    .animationDuration(0)
272    .onChange((index) => {
273      this.currentTabIndex = index
274    })
275  }
276
277  private getTabBarColor(index: number) {
278    return this.currentTabIndex == index ? $r('app.color.tab_bar_select_color') : $r('app.color.tab_bar_normal_color')
279  }
280}