DEV Community

Lin
Lin

Posted on

Imitation Box Horse - Home Product Flow (7)

Technical Stack
Appgallery Connect
Development Preparation
In the previous section, we implemented the home page banner module. Now, we need to add a product list module to the home page. As a crucial part of a shopping app, the product list should be designed to support complex logic in the future, including image display, coupon integration, purchase limits, direct discounts, original prices, and more. While the list layout is compact, detailed product information will be shown on the product detail page after clicking.
Code Implementation

  1. Create Product Table (home_product_list) json { "objectTypeName": "home_product_list", "fields": [ {"fieldName": "id", "fieldType": "Integer", "notNull": true, "belongPrimaryKey": true}, {"fieldName": "goods_list_id", "fieldType": "Integer", "notNull": true, "defaultValue": 0}, {"fieldName": "url", "fieldType": "String"}, {"fieldName": "name", "fieldType": "Text"}, {"fieldName": "price", "fieldType": "Double"}, {"fieldName": "original_price", "fieldType": "Double"}, {"fieldName": "amount", "fieldType": "Integer"}, {"fieldName": "text_message", "fieldType": "String"}, {"fieldName": "parameter", "fieldType": "String"}, {"fieldName": "delivery_time", "fieldType": "String"}, {"fieldName": "endTime", "fieldType": "String"}, {"fieldName": "sales_volume", "fieldType": "Integer"}, {"fieldName": "space_id", "fieldType": "Integer"}, {"fieldName": "max_loop_amount", "fieldType": "Integer"}, {"fieldName": "promotion_spread_price", "fieldType": "Double"}, {"fieldName": "coupon_id", "fieldType": "Integer"} ], "indexes": [ {"indexName": "field1IndexId", "indexList": [{"fieldName":"id","sortType":"ASC"}]} ], "permissions": [ {"role": "World", "rights": ["Read"]}, {"role": "Authenticated", "rights": ["Read", "Upsert"]}, {"role": "Creator", "rights": ["Read", "Upsert", "Delete"]}, {"role": "Administrator", "rights": ["Read", "Upsert", "Delete"]} ] }
  2. Populate Product Data json { "cloudDBZoneName": "default", "objectTypeName": "home_product_list", "objects": [ { "id": 10, "goods_list_id": 1, "url": "Online Image URL", "name": "Hongyan Strawberries", "price": 10.5, "original_price": 18.5, "amount": 10, "text_message": "Special Price", "parameter": "Refrigerated", "delivery_time": "Shipped within 24 hours after payment", "endTime": "Limited Time Offer | Ends 2025-05-18 10:00", "sales_volume": 9812, "space_id": 10, "max_loop_amount": 10, "promotion_spread_price": 5, "coupon_id": 10 }, { "id": 20, "goods_list_id": 1, "url": "Online Image URL", "name": "Kirin Melon", "price": 2.8, "original_price": 5.9, "amount": 1, "text_message": "Seasonal New Product", "parameter": "Refrigerated", "delivery_time": "Shipped within 24 hours after payment", "endTime": "Limited Time Offer | Ends 2025-05-18 10:00", "sales_volume": 9812, "space_id": 11, "max_loop_amount": 10, "promotion_spread_price": 0, "coupon_id": 10 } ] }
  3. Data Query Implementation typescript @State homeProduct: HomeProductList[] = []; // Product list data

async fetchProductData() {
try {
let databaseZone = cloudDatabase.zone('default');
let home_product = new cloudDatabase.DatabaseQuery(home_product_list);
let list7 = await databaseZone.query(home_product);
let json7 = JSON.stringify(list7);
let data7: HomeProductList[] = JSON.parse(json7);
this.homeProduct = data7;
} catch (err) {
hilog.error(0x0000, 'testTag', Failed to query product data: ${err});
}
}

  1. Product List Component (WaterFlowGoods.ets) typescript import { HomeProductList } from "../entity/home_product_list"

@Component
@Preview
export struct WaterFlowGoods {
@link goodsList: Array
@State columns: number = 2

build() {
WaterFlow() {
ForEach(this.goodsList, (item: HomeProductList, index) => {
FlowItem() {
Column() {
Image(item.url)
.width('100%')
.aspectRatio(1)
.objectFit(ImageFit.Cover)
.borderRadius({ topLeft: 10, topRight: 10 })

        Column() {
          Text(item.name)
            .fontSize(16)
            .fontColor('#333')
            .margin({ bottom: 4 })

          Text(item.text_message)
            .fontSize(12)
            .fontColor('#666')
            .margin({ bottom: 8 })

          Text("Up to ¥" + item.promotion_spread_price + " Off")
            .fontSize(12)
            .fontColor('#ffffff')
            .visibility(item.promotion_spread_price > 0 ? Visibility.Visible : Visibility.None)
            .margin({ bottom: 8 })
            .padding({ left: 5, right: 5, top: 2, bottom: 2 })
            .linearGradient({
              angle: 90,
              colors: [[0xff0000, 0], [0xff6666, 0.2], [0xff6666, 1]]
            })

          Row() {
            Text("Purchase Limit")
              .width(40)
              .fontSize(12)
              .borderRadius(20)
              .backgroundColor("#FB424C")
              .padding(3)
              .textAlign(TextAlign.Center)
            Text("Limit " + item.max_loop_amount + " per person")
              .margin({ left: 5 })
              .fontSize(12)
              .fontColor("#FB424C")
          }
          .borderRadius(20)
          .padding({ top: 2, bottom: 2, right: 10 })
          .backgroundColor("#FEE3E3")
          .visibility(item.amount > 0 ? Visibility.Visible : Visibility.None)

          Row() {
            Text() {
              Span("¥")
                .fontColor(Color.Red)
                .fontSize(14)
              Span(String(item.price))
                .fontSize(16)
                .fontColor(Color.Red)
            }
            Text(String(item.original_price))
              .fontSize(12)
              .fontColor('#999')
              .decoration({
                type: TextDecorationType.LineThrough,
                color: Color.Gray
              })
              .margin({ left: 10 })

            Blank()
            Column() {
              Image($r('app.media.cart'))
                .width(20)
                .height(20)
            }
            .justifyContent(FlexAlign.Center)
            .width(36)
            .height(36)
            .backgroundColor("#ff2bd2fa")
            .borderRadius(18)
          }
          .margin({ top: 10 })
          .width('100%')
          .justifyContent(FlexAlign.SpaceBetween)
        }
        .alignItems(HorizontalAlign.Start)
        .padding(12)
      }
      .backgroundColor(Color.White)
      .borderRadius(12)
      .onClick(() => {
        // Navigate to product detail page
      })
    }
    .margin({ bottom: 12 })
  })
}
.padding(10)
.columnsTemplate('1fr 1fr')
.columnsGap(12)
.onAreaChange((oldVal, newVal) => {
  this.columns = newVal.width > 600 ? 2 : 1; // Responsive layout
})
Enter fullscreen mode Exit fullscreen mode

}
}

  1. Integrate into Home Page
    typescript
    // In the home page component
    build() {
    Column() {
    // Other modules...

    // Product list component
    WaterFlowGoods({ goodsList: this.homeProduct })

    // Remaining content...
    }
    }

This implementation completes the home page product list, providing a foundation for future features like coupon redemption, inventory management, and detailed product navigation.

Top comments (0)