HarmonyOS NEXT Development Case: Expiry Date Calculator
zhongcx

zhongcx @zhongcx

About: The best time to plant a tree was 10 years ago, the second-best time is now.

Joined:
Mar 6, 2025

HarmonyOS NEXT Development Case: Expiry Date Calculator

Publish Date: May 11
0 0

Image description

@Entry
@Component
struct ExpiryDateCalculator {
  // State variable for text color, initialized to dark gray
  @State private textColor: string = "#2e2e2e";
  // State variable for shadow border color, initialized to light gray
  @State private shadowColor: string = "#d5d5d5";
  // State variable for base padding value, initialized to 30
  @State private basePadding: number = 30;
  // State variable indicating expiration status, initialized to false
  @State private isExpired: boolean = false;
  // State variable for production date, initialized as empty string
  @State private productionDate: string = "";
  // State variable for expiration date, initialized as empty string
  @State private expiryDate: string = "";
  // State variable for remaining valid days, initialized to 0
  @State private remainingDays: number = 0;
  // Theme color variable, initialized to orange
  @State private themeColor: string | Color = Color.Orange;
  // State variable tracking input focus status
  @State isInputFocused: boolean = false;
  // Watched state variable for input text changes
  @State @Watch('inputChanged') private inputText: string = "9";
  // Watched state variable for selected date
  @State @Watch('inputChanged') private selectedDate: Date = new Date()

  // Lifecycle hook before component appears
  aboutToAppear(): void {
    this.inputChanged()
  }

  // Method to format date as YYYY-MM-DD
  getYearMonthDay(date: Date) {
    const year: string = date.getFullYear().toString().padStart(4, '0');
    const month: string = (date.getMonth() + 1).toString().padStart(2, '0');
    const day: string = date.getDate().toString().padStart(2, '0');
    return `${year}${month}${day}日`;
  }

  // Input change handler
  inputChanged() {
    console.info(`selectedDate:${this.selectedDate}`);
    this.productionDate = this.getYearMonthDay(this.selectedDate);
    let expiryDate: Date = new Date(this.selectedDate);
    expiryDate.setDate(expiryDate.getDate() + Number(this.inputText));
    this.expiryDate = this.getYearMonthDay(expiryDate);
    this.isExpired = expiryDate.getTime() < new Date().getTime();
    const timeDifference = expiryDate.getTime() - new Date().getTime();
    this.remainingDays = Math.ceil(timeDifference / (1000 * 60 * 60 * 24));
  } 

  // UI construction
  build() {
    Column() { 
      Text('Expiry Date Calculator')
        .fontColor(this.textColor)
        .fontSize(18)
        .width('100%')
        .height(50)
        .textAlign(TextAlign.Center)
        .backgroundColor(Color.White)
        .shadow({
          radius: 2,
          color: this.shadowColor,
          offsetX: 0,
          offsetY: 5
        });

      Scroll() {
        Column() {
          // Statistics Display
          Column() {
            Row() {
              Text() {
                Span(`Status: `)
                Span(`${this.isExpired ? 'Expired' : 'Valid'}`)
                  .fontColor(this.isExpired ? "#e74c3c" : "#3ace7d")
              }
              .fontColor(this.textColor)
              .fontSize(16)
              .layoutWeight(1);
            }
            .constraintSize({ minHeight: 45 })
            .justifyContent(FlexAlign.SpaceBetween)
            .width('100%');

            Divider();

            Row() {
              Text() {
                Span(`Days Left: `)
                Span(`${this.remainingDays < 0 ? 0 : this.remainingDays} `).fontColor(Color.Orange)
                Span(' days')
              }
              .fontColor(this.textColor)
              .fontSize(16)
              .layoutWeight(1);
            }
            .constraintSize({ minHeight: 45 })
            .justifyContent(FlexAlign.SpaceBetween)
            .width('100%');

            Divider();

            Row() {
              Text() {
                Span(`Production Date: `)
                Span(`${this.productionDate} `)
              }
              .fontColor(this.textColor)
              .fontSize(16)
              .layoutWeight(1);
            }
            .constraintSize({ minHeight: 45 })
            .justifyContent(FlexAlign.SpaceBetween)
            .width('100%');

            Divider();

            Row() {
              Text() {
                Span(`Expiry Date: `)
                Span(`${this.expiryDate} `)
              }
              .fontColor(this.textColor)
              .fontSize(16)
              .layoutWeight(1);
            }
            .constraintSize({ minHeight: 45 })
            .justifyContent(FlexAlign.SpaceBetween)
            .width('100%');
          }
          .alignItems(HorizontalAlign.Start)
          // ... (remaining UI components with similar translations)
        }
      }
      .scrollBar(BarState.Off)
      .clip(false);
    }
    .height('100%')
    .width('100%')
    .backgroundColor("#f4f8fb");
  }
}
Enter fullscreen mode Exit fullscreen mode

Technical Implementation Details

1. State Management

  • @State Decorator: Manages component-level state changes
  • @Watch Decorator: Automatically triggers inputChanged() on variable updates
  • Reactive UI: Automatic UI refresh on state changes

2. Date Calculation

  • getYearMonthDay(): Formats Date object to localized string
  • inputChanged():
    • Calculates expiration date
    • Determines expiration status
    • Computes remaining days

3. UI Features

  • Responsive Layout:
    • Adaptive spacing using basePadding
    • Percentage-based width/height
  • Visual Feedback:
    • Dynamic color changes for expiration status
    • Input focus highlighting
    • Interactive shadow effects
  • Form Components:
    • TextInput with number validation
    • Calendar picker integration
    • Clear button functionality

4. Styling System

  • Theme color management
  • Dynamic shadow effects
  • Consistent spacing system
  • Conditional styling based on state

Key Features

  1. Real-time calculation updates
  2. Cross-platform compatibility
  3. Interactive date selection
  4. Input validation
  5. Responsive design

Usage Scenarios

  • Food industry quality control
  • Pharmaceutical expiration tracking
  • Retail inventory management
  • Consumer product maintenance

This implementation demonstrates HarmonyOS ArkUI's capabilities in building responsive, data-driven applications with clean state management and modern UI components.

Comments 0 total

    Add comment