refactor: update pages and widgets to use GetX and PageStandards

This commit is contained in:
Developer
2026-04-08 01:39:03 +08:00
parent 54bab00667
commit e255b5c650
3 changed files with 318 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:mom_kitchen/src/controllers/home_controller.dart';
import 'package:mom_kitchen/src/controllers/cart_controller.dart';
import 'package:mom_kitchen/src/standards/page_standards.dart';
import 'package:mom_kitchen/src/widgets/product_card.dart';
import 'package:mom_kitchen/src/widgets/states/empty_state.dart';
import 'package:mom_kitchen/src/widgets/states/error_state.dart';
import 'package:mom_kitchen/src/widgets/loading_indicator.dart';
import 'package:mom_kitchen/src/widgets/responsive_grid.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final homeController = Get.put(HomeController());
final cartController = Get.put(CartController());
final standards = PageStandards.of(context);
return CupertinoPageScaffold(
backgroundColor: standards.backgroundColor,
child: SafeArea(
child: Obx(() {
if (homeController.isLoading.value) {
return const LoadingIndicator();
}
if (homeController.errorMessage.value.isNotEmpty) {
return ErrorState(
message: homeController.errorMessage.value,
onRetry: () => homeController.loadProducts(),
);
}
return Column(
children: [
_buildSearchBar(homeController, standards),
_buildCategoryFilter(homeController, standards),
Expanded(
child: homeController.filteredProducts.isEmpty
? const EmptyState(
emoji: '🔍',
title: 'No products found',
message: 'Try a different search or category',
)
: _buildProductGrid(
homeController,
cartController,
standards,
),
),
],
);
}),
),
);
}
Widget _buildSearchBar(HomeController controller, PageStandards standards) {
return Padding(
padding: standards.scaledPadding(EdgeInsets.all(16)),
child: Container(
decoration: BoxDecoration(
color: standards.backgroundColor,
borderRadius: BorderRadius.circular(standards.scaledRadius(12)),
border: Border.all(
color: standards.textColor.withOpacity(0.1),
),
),
child: CupertinoSearchTextField(
placeholder: 'Search products...',
style: TextStyle(color: standards.textColor),
placeholderStyle: TextStyle(
color: standards.textColor.withOpacity(0.5),
),
decoration: null,
onChanged: controller.search,
),
),
);
}
Widget _buildCategoryFilter(HomeController controller, PageStandards standards) {
return Obx(() => Container(
height: standards.scaledHeight(44),
padding: EdgeInsets.symmetric(horizontal: standards.scaledWidth(16)),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: controller.categories.length + 1,
itemBuilder: (context, index) {
final isSelected = index == 0
? controller.selectedCategory.value.isEmpty
: controller.selectedCategory.value ==
controller.categories[index - 1];
return Padding(
padding: EdgeInsets.only(right: standards.scaledWidth(8)),
child: GestureDetector(
onTap: () {
if (index == 0) {
controller.selectCategory('');
} else {
controller.selectCategory(controller.categories[index - 1]);
}
},
child: Container(
padding: standards.scaledPadding(
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
decoration: BoxDecoration(
color: isSelected
? standards.primaryColor
: standards.backgroundColor,
borderRadius: BorderRadius.circular(
standards.scaledRadius(20),
),
border: Border.all(
color: isSelected
? standards.primaryColor
: standards.textColor.withOpacity(0.2),
),
),
child: Text(
index == 0 ? 'All' : controller.categories[index - 1],
style: standards.textStyle.copyWith(
color: isSelected
? CupertinoColors.white
: standards.textColor,
fontWeight: FontWeight.w500,
),
),
),
),
);
},
),
));
}
Widget _buildProductGrid(
HomeController homeController,
CartController cartController,
PageStandards standards,
) {
return ResponsiveGrid(
crossAxisCount: 2,
crossAxisCountMedium: 3,
crossAxisCountLarge: 4,
childAspectRatio: 0.75,
spacing: 12,
runSpacing: 12,
children: homeController.filteredProducts
.map((product) => ProductCard(
product: product,
onAddToCart: () => cartController.addProduct(product),
))
.toList(),
);
}
}

View File

@@ -0,0 +1,43 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mom_kitchen/src/standards/page_standards.dart';
class LoadingIndicator extends StatelessWidget {
final String? message;
final double size;
final Color? color;
const LoadingIndicator({
super.key,
this.message,
this.size = 32,
this.color,
});
@override
Widget build(BuildContext context) {
final standards = PageStandards.of(context);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CupertinoActivityIndicator(
radius: standards.scaledRadius(size / 2),
color: color ?? standards.primaryColor,
),
if (message != null)
Padding(
padding: EdgeInsets.only(top: standards.scaledHeight(16)),
child: Text(
message!,
style: standards.textStyle.copyWith(
color: standards.textColor.withOpacity(0.6),
),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,114 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mom_kitchen/src/standards/page_standards.dart';
import 'package:mom_kitchen/src/controllers/home_controller.dart';
class ProductCard extends StatelessWidget {
final ProductModel product;
final VoidCallback? onTap;
final VoidCallback? onAddToCart;
const ProductCard({
super.key,
required this.product,
this.onTap,
this.onAddToCart,
});
@override
Widget build(BuildContext context) {
final standards = PageStandards.of(context);
return GestureDetector(
onTap: onTap,
child: Container(
decoration: BoxDecoration(
color: standards.backgroundColor,
borderRadius: BorderRadius.circular(standards.scaledRadius(16)),
boxShadow: [
BoxShadow(
color: standards.textColor.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildImage(standards),
_buildInfo(standards),
],
),
),
);
}
Widget _buildImage(PageStandards standards) {
return Expanded(
child: Container(
decoration: BoxDecoration(
color: standards.primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.vertical(
top: Radius.circular(standards.scaledRadius(16)),
),
),
child: Center(
child: Text(
product.image,
style: TextStyle(fontSize: standards.scaledFontSize(48)),
),
),
),
);
}
Widget _buildInfo(PageStandards standards) {
return Padding(
padding: standards.scaledPadding(EdgeInsets.all(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
style: standards.textStyle.copyWith(
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: standards.scaledHeight(4)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'\$${product.price.toStringAsFixed(2)}',
style: standards.primaryTextStyle.copyWith(
fontWeight: FontWeight.bold,
),
),
if (onAddToCart != null)
GestureDetector(
onTap: onAddToCart,
child: Container(
padding: standards.scaledPadding(EdgeInsets.all(6)),
decoration: BoxDecoration(
color: standards.primaryColor,
borderRadius: BorderRadius.circular(
standards.scaledRadius(8),
),
),
child: Icon(
CupertinoIcons.plus,
color: CupertinoColors.white,
size: standards.fontSize,
),
),
),
],
),
],
),
);
}
}