From 44d48d41d4260d4cf3d8c479a7f145b6f678a0e6 Mon Sep 17 00:00:00 2001 From: Efril Date: Fri, 16 Jan 2026 13:27:09 +0700 Subject: [PATCH] menu page --- lib/common/constant/app_constant.dart | 4 + lib/common/data/service_data.dart | 11 + lib/common/extension/currency_extension.dart | 28 ++ lib/common/extension/extension.dart | 1 + .../components/card/product_card.dart | 149 +++++++ .../components/card/product_empty_card.dart | 36 ++ .../delegate/category_delegate.dart | 106 +++++ .../pages/main/pages/home/home_page.dart | 4 +- .../pages/home/widgets/service_section.dart | 61 +++ lib/presentation/pages/menu/menu_page.dart | 132 ++++++ .../pages/menu/widgets/header.dart | 134 ++++++ .../pages/menu/widgets/product_section.dart | 70 +++ .../merchant_detail/merchant_detail_page.dart | 123 +----- lib/presentation/router/app_router.dart | 3 + lib/presentation/router/app_router.gr.dart | 415 ++++++++++-------- lib/sample/product_sample_data.dart | 121 +++++ pubspec.lock | 8 +- 17 files changed, 1090 insertions(+), 316 deletions(-) create mode 100644 lib/common/data/service_data.dart create mode 100644 lib/common/extension/currency_extension.dart create mode 100644 lib/presentation/components/card/product_card.dart create mode 100644 lib/presentation/components/card/product_empty_card.dart create mode 100644 lib/presentation/components/delegate/category_delegate.dart create mode 100644 lib/presentation/pages/main/pages/home/widgets/service_section.dart create mode 100644 lib/presentation/pages/menu/menu_page.dart create mode 100644 lib/presentation/pages/menu/widgets/header.dart create mode 100644 lib/presentation/pages/menu/widgets/product_section.dart create mode 100644 lib/sample/product_sample_data.dart diff --git a/lib/common/constant/app_constant.dart b/lib/common/constant/app_constant.dart index 33a47ed..8c0a0f3 100644 --- a/lib/common/constant/app_constant.dart +++ b/lib/common/constant/app_constant.dart @@ -1,5 +1,9 @@ +import '../../sample/sample_data.dart'; + class AppConstant { static const String appName = "Enaklo"; static const String coinName = "EnakCoin"; static const String poinName = "EnakPoin"; } + +MerchantModel merchant = merchants.first; diff --git a/lib/common/data/service_data.dart b/lib/common/data/service_data.dart new file mode 100644 index 0000000..5ea518c --- /dev/null +++ b/lib/common/data/service_data.dart @@ -0,0 +1,11 @@ +class Service { + Service({required this.name, required this.description}); + + final String name; + final String description; +} + +List services = [ + Service(name: 'Dine In', description: 'Makan langsung di tempat'), + Service(name: 'Take Away', description: 'Pesan dan bawa pulang'), +]; diff --git a/lib/common/extension/currency_extension.dart b/lib/common/extension/currency_extension.dart new file mode 100644 index 0000000..e53fa46 --- /dev/null +++ b/lib/common/extension/currency_extension.dart @@ -0,0 +1,28 @@ +part of 'extension.dart'; + +extension DoubleExt on double { + String get currencyFormatRpV2 => NumberFormat.currency( + locale: 'id', + symbol: 'Rp ', + decimalDigits: 0, + ).format(this); +} + +extension StringX on String { + String get currencyFormatRp { + final parsedValue = int.tryParse(this) ?? 0; + return NumberFormat.currency( + locale: 'id', + symbol: 'Rp ', + decimalDigits: 0, + ).format(parsedValue); + } +} + +extension IntegerExt on int { + String get currencyFormatRp => NumberFormat.currency( + locale: 'id', + symbol: 'Rp ', + decimalDigits: 0, + ).format(this); +} diff --git a/lib/common/extension/extension.dart b/lib/common/extension/extension.dart index a950fef..ece28c3 100644 --- a/lib/common/extension/extension.dart +++ b/lib/common/extension/extension.dart @@ -3,6 +3,7 @@ import 'package:intl/intl.dart'; import '../../domain/auth/auth.dart'; part 'date_extension.dart'; +part 'currency_extension.dart'; extension StringExt on String { CheckPhoneStatus toCheckPhoneStatus() { diff --git a/lib/presentation/components/card/product_card.dart b/lib/presentation/components/card/product_card.dart new file mode 100644 index 0000000..61e89d6 --- /dev/null +++ b/lib/presentation/components/card/product_card.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../sample/product_sample_data.dart'; + +class ProductCard extends StatelessWidget { + final Product product; + const ProductCard({super.key, required this.product}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.06), + blurRadius: 8, + offset: Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Product image + Expanded( + flex: 3, + child: Stack( + children: [ + Container( + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.backgroundLight, + borderRadius: BorderRadius.vertical( + top: Radius.circular(12), + ), + ), + child: Center( + child: Icon( + Icons.fastfood, + size: 40, + color: AppColor.textLight, + ), + ), + ), + + // Availability overlay + if (!product.isAvailable) + Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: AppColor.black.withOpacity(0.6), + borderRadius: BorderRadius.vertical( + top: Radius.circular(12), + ), + ), + child: Center( + child: Text( + "HABIS", + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + + // Rating badge + Positioned( + top: 8, + right: 8, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 3), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.star, size: 12, color: AppColor.warning), + SizedBox(width: 2), + Text( + "${product.rating}", + style: AppStyle.xs.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + ], + ), + ), + + // Product info + Expanded( + flex: 2, + child: Padding( + padding: EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.name, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + + Spacer(), + + // Price and sold count + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Rp ${product.price.currencyFormatRp}", + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + Text( + "${product.soldCount} terjual", + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/components/card/product_empty_card.dart b/lib/presentation/components/card/product_empty_card.dart new file mode 100644 index 0000000..6304055 --- /dev/null +++ b/lib/presentation/components/card/product_empty_card.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; + +class ProductEmptyCard extends StatelessWidget { + const ProductEmptyCard({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16), + padding: EdgeInsets.all(24), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.borderLight), + ), + child: Center( + child: Column( + children: [ + Icon( + Icons.inventory_2_outlined, + size: 48, + color: AppColor.textLight, + ), + SizedBox(height: 12), + Text( + "Belum ada produk", + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/components/delegate/category_delegate.dart b/lib/presentation/components/delegate/category_delegate.dart new file mode 100644 index 0000000..9a6f050 --- /dev/null +++ b/lib/presentation/components/delegate/category_delegate.dart @@ -0,0 +1,106 @@ +import 'package:flutter/widgets.dart'; + +import '../../../common/theme/theme.dart'; +import '../../../sample/product_sample_data.dart'; + +class SliverCategoryDelegate extends SliverPersistentHeaderDelegate { + final List categories; + final String selectedCategoryId; + final Function(String) onCategoryTap; + + SliverCategoryDelegate({ + required this.categories, + required this.selectedCategoryId, + required this.onCategoryTap, + }); + + @override + double get minExtent => 60; + + @override + double get maxExtent => 60; + + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + return Container( + height: 60, + decoration: BoxDecoration( + color: AppColor.surface, + border: Border( + bottom: BorderSide(color: AppColor.borderLight, width: 1), + ), + ), + child: ListView.builder( + scrollDirection: Axis.horizontal, + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemCount: categories.length, + itemBuilder: (context, index) { + final category = categories[index]; + final isSelected = category.id == selectedCategoryId; + + return GestureDetector( + onTap: () => onCategoryTap(category.id), + child: Container( + margin: EdgeInsets.only(right: 12), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: isSelected ? AppColor.primary : AppColor.backgroundLight, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: isSelected ? AppColor.primary : AppColor.border, + width: 1, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(category.icon, style: AppStyle.md), + SizedBox(width: 8), + Text( + category.name, + style: AppStyle.md.copyWith( + color: isSelected + ? AppColor.textWhite + : AppColor.textPrimary, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(width: 4), + Container( + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: isSelected + ? AppColor.textWhite.withOpacity(0.2) + : AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), + ), + child: Text( + "${category.productCount}", + style: AppStyle.xs.copyWith( + color: isSelected + ? AppColor.textWhite + : AppColor.primary, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ); + }, + ), + ); + } + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { + return oldDelegate is SliverCategoryDelegate && + (oldDelegate.selectedCategoryId != selectedCategoryId || + oldDelegate.categories != categories); + } +} diff --git a/lib/presentation/pages/main/pages/home/home_page.dart b/lib/presentation/pages/main/pages/home/home_page.dart index d92a23c..58eba95 100644 --- a/lib/presentation/pages/main/pages/home/home_page.dart +++ b/lib/presentation/pages/main/pages/home/home_page.dart @@ -8,10 +8,10 @@ import '../../../../../application/customer/customer_point_loader/customer_point import '../../../../../common/theme/theme.dart'; import '../../../../components/image/image.dart'; import '../../../../router/app_router.gr.dart'; -import 'widgets/feature_section.dart'; import 'widgets/lottery_card.dart'; import 'widgets/point_card.dart'; import 'widgets/popular_merchant_section.dart'; +import 'widgets/service_section.dart'; @RoutePage() class HomePage extends StatefulWidget { @@ -52,7 +52,7 @@ class _HomePageState extends State { children: [ _buildHeaderSection(), const SizedBox(height: 70), - HomeFeatureSection(), + HomeServiceSection(), HomeLotteryBanner(onTap: () => context.router.push(DrawRoute())), HomePopularMerchantSection(), ], diff --git a/lib/presentation/pages/main/pages/home/widgets/service_section.dart b/lib/presentation/pages/main/pages/home/widgets/service_section.dart new file mode 100644 index 0000000..f92dce4 --- /dev/null +++ b/lib/presentation/pages/main/pages/home/widgets/service_section.dart @@ -0,0 +1,61 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../../../../common/data/service_data.dart'; +import '../../../../../../common/theme/theme.dart'; +import '../../../../../components/card/gradient_card.dart'; +import '../../../../../router/app_router.gr.dart'; + +class HomeServiceSection extends StatelessWidget { + const HomeServiceSection({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate(services.length, (index) { + return Expanded( + child: Padding( + padding: EdgeInsets.only(right: index == 0 ? 12 : 0), + child: InkWell( + onTap: () => + context.router.push(MenuRoute(service: services[index])), + child: GradientCard( + child: _content( + services[index].name, + services[index].description, + ), + ), + ), + ), + ); + }), + ), + ); + } + + Column _content(String title, String subtitle) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 8), + Text( + subtitle, + style: AppStyle.md.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/menu/menu_page.dart b/lib/presentation/pages/menu/menu_page.dart new file mode 100644 index 0000000..f906711 --- /dev/null +++ b/lib/presentation/pages/menu/menu_page.dart @@ -0,0 +1,132 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../common/data/service_data.dart'; +import '../../../common/theme/theme.dart'; +import '../../../sample/product_sample_data.dart'; +import '../../components/delegate/category_delegate.dart'; +import 'widgets/header.dart'; +import 'widgets/product_section.dart'; + +@RoutePage() +class MenuPage extends StatefulWidget { + final Service service; + const MenuPage({super.key, required this.service}); + + @override + State createState() => _MenuPageState(); +} + +class _MenuPageState extends State { + final ScrollController _scrollController = ScrollController(); + final List _productSectionKeys = []; + + String _selectedCategoryId = ""; + + @override + void initState() { + super.initState(); + _selectedCategoryId = categories.isNotEmpty ? categories.first.id : ""; + + // Initialize keys for each category + for (int i = 0; i < categories.length; i++) { + _productSectionKeys.add(GlobalKey()); + } + } + + void _scrollToCategory(String categoryId) { + setState(() { + _selectedCategoryId = categoryId; + }); + + final categoryIndex = categories.indexWhere((cat) => cat.id == categoryId); + if (categoryIndex >= 0 && categoryIndex < _productSectionKeys.length) { + final key = _productSectionKeys[categoryIndex]; + final context = key.currentContext; + + if (context != null) { + Future.delayed(Duration(milliseconds: 100), () { + if (mounted) { + Scrollable.ensureVisible( + context, + duration: Duration(milliseconds: 500), + curve: Curves.easeInOut, + alignment: 0.1, + ); + } + }); + } + } + } + + List _getProductsByCategory(String categoryId) { + return products + .where((product) => product.categoryId == categoryId) + .toList(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + controller: _scrollController, + slivers: [ + // App Bar with merchant info + SliverAppBar( + expandedHeight: 200, + pinned: true, + backgroundColor: AppColor.primary, + leading: IconButton( + icon: Icon(Icons.arrow_back, color: AppColor.textWhite), + onPressed: () => Navigator.of(context).pop(), + ), + actions: [ + IconButton( + icon: Icon(Icons.share, color: AppColor.textWhite), + onPressed: () {}, + ), + IconButton( + icon: Icon(Icons.favorite_border, color: AppColor.textWhite), + onPressed: () {}, + ), + ], + flexibleSpace: FlexibleSpaceBar( + background: MenuHeader(service: widget.service), + ), + ), + + // Categories (will be pinned) + SliverPersistentHeader( + pinned: true, + delegate: SliverCategoryDelegate( + categories: categories, + selectedCategoryId: _selectedCategoryId, + onCategoryTap: _scrollToCategory, + ), + ), + + // Product sections by category + ...categories.map((category) { + final categoryProducts = _getProductsByCategory(category.id); + final categoryIndex = categories.indexOf(category); + + return SliverToBoxAdapter( + key: _productSectionKeys[categoryIndex], + child: MenuProductSection( + category: category, + categoryProducts: categoryProducts, + ), + ); + }), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/menu/widgets/header.dart b/lib/presentation/pages/menu/widgets/header.dart new file mode 100644 index 0000000..9152d0d --- /dev/null +++ b/lib/presentation/pages/menu/widgets/header.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/constant/app_constant.dart'; +import '../../../../common/data/service_data.dart'; +import '../../../../common/theme/theme.dart'; + +class MenuHeader extends StatelessWidget { + final Service service; + const MenuHeader({super.key, required this.service}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [AppColor.primary, AppColor.primary.withOpacity(0.8)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: Stack( + children: [ + // Background decoration + Positioned( + right: 20, + top: 60, + child: Opacity( + opacity: 0.1, + child: Icon(Icons.store, size: 100, color: AppColor.textWhite), + ), + ), + + // Content + Positioned( + left: 20, + right: 20, + bottom: 20, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Service + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + service.name, + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + Text( + service.description, + style: AppStyle.md.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + + SizedBox(height: 16), + // Merchant + Row( + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.2), + blurRadius: 8, + offset: Offset(0, 4), + ), + ], + ), + child: Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Image.asset(merchant.imageUrl), + ), + ), + ), + SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + merchant.name, + style: AppStyle.h6.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + Text( + merchant.category, + style: AppStyle.md.copyWith( + color: AppColor.textWhite.withOpacity(0.9), + ), + ), + Row(children: [SizedBox(width: 12)]), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: merchant.isOpen + ? AppColor.success + : AppColor.error, + borderRadius: BorderRadius.circular(6), + ), + child: Text( + merchant.isOpen ? "BUKA" : "TUTUP", + style: AppStyle.xs.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/menu/widgets/product_section.dart b/lib/presentation/pages/menu/widgets/product_section.dart new file mode 100644 index 0000000..7c39bd9 --- /dev/null +++ b/lib/presentation/pages/menu/widgets/product_section.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../../sample/product_sample_data.dart'; +import '../../../components/card/product_card.dart'; +import '../../../components/card/product_empty_card.dart'; + +class MenuProductSection extends StatelessWidget { + final ProductCategory category; + final List categoryProducts; + const MenuProductSection({ + super.key, + required this.category, + required this.categoryProducts, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(bottom: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Section header + Padding( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: Row( + children: [ + Text(category.icon, style: AppStyle.h5), + SizedBox(width: 8), + Text( + category.name, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + SizedBox(width: 8), + Text( + "(${categoryProducts.length})", + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ), + ], + ), + ), + + // Products grid + if (categoryProducts.isEmpty) + ProductEmptyCard() + else + GridView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.symmetric(horizontal: 16), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 12, + mainAxisSpacing: 12, + childAspectRatio: 0.75, + ), + itemCount: categoryProducts.length, + itemBuilder: (context, index) { + return ProductCard(product: categoryProducts[index]); + }, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart b/lib/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart index 313a148..37e06d6 100644 --- a/lib/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart +++ b/lib/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart @@ -1,47 +1,9 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../../../common/theme/theme.dart'; +import '../../../../../sample/product_sample_data.dart'; import '../../../../../sample/sample_data.dart'; -// Models -class ProductCategory { - final String id; - final String name; - final String icon; - final int productCount; - - ProductCategory({ - required this.id, - required this.name, - required this.icon, - required this.productCount, - }); -} - -class Product { - final String id; - final String name; - final String description; - final int price; - final String categoryId; - final String imageUrl; - final bool isAvailable; - final double rating; - final int soldCount; - - Product({ - required this.id, - required this.name, - required this.description, - required this.price, - required this.categoryId, - required this.imageUrl, - required this.isAvailable, - required this.rating, - required this.soldCount, - }); -} - @RoutePage() class MerchantDetailPage extends StatefulWidget { final MerchantModel merchant; @@ -58,89 +20,6 @@ class _MerchantDetailPageState extends State { String _selectedCategoryId = ""; - // Sample data - final List categories = [ - ProductCategory(id: "1", name: "Makanan", icon: "🍽️", productCount: 8), - ProductCategory(id: "2", name: "Minuman", icon: "🥤", productCount: 6), - ProductCategory(id: "3", name: "Snack", icon: "🍿", productCount: 5), - ProductCategory(id: "4", name: "Es Krim", icon: "🍦", productCount: 4), - ProductCategory(id: "5", name: "Paket", icon: "📦", productCount: 3), - ]; - - final List products = [ - // Makanan - Product( - id: "1", - name: "Nasi Gudeg", - description: "Gudeg khas Yogyakarta dengan ayam dan telur", - price: 25000, - categoryId: "1", - imageUrl: "https://via.placeholder.com/150", - isAvailable: true, - rating: 4.5, - soldCount: 50, - ), - Product( - id: "2", - name: "Soto Ayam", - description: "Soto ayam kuning dengan nasi dan kerupuk", - price: 18000, - categoryId: "1", - imageUrl: "https://via.placeholder.com/150", - isAvailable: true, - rating: 4.3, - soldCount: 75, - ), - Product( - id: "3", - name: "Gado-gado", - description: "Gado-gado segar dengan bumbu kacang", - price: 15000, - categoryId: "1", - imageUrl: "https://via.placeholder.com/150", - isAvailable: false, - rating: 4.2, - soldCount: 30, - ), - - // Minuman - Product( - id: "4", - name: "Es Teh Manis", - description: "Es teh manis segar", - price: 5000, - categoryId: "2", - imageUrl: "https://via.placeholder.com/150", - isAvailable: true, - rating: 4.0, - soldCount: 120, - ), - Product( - id: "5", - name: "Jus Jeruk", - description: "Jus jeruk segar tanpa gula tambahan", - price: 12000, - categoryId: "2", - imageUrl: "https://via.placeholder.com/150", - isAvailable: true, - rating: 4.4, - soldCount: 45, - ), - - // Snack - Product( - id: "6", - name: "Keripik Pisang", - description: "Keripik pisang renyah dan manis", - price: 8000, - categoryId: "3", - imageUrl: "https://via.placeholder.com/150", - isAvailable: true, - rating: 4.1, - soldCount: 25, - ), - ]; - @override void initState() { super.initState(); diff --git a/lib/presentation/router/app_router.dart b/lib/presentation/router/app_router.dart index 5644e54..814a809 100644 --- a/lib/presentation/router/app_router.dart +++ b/lib/presentation/router/app_router.dart @@ -74,5 +74,8 @@ class AppRouter extends RootStackRouter { // Mini Games AutoRoute(page: FerrisWheelRoute.page), AutoRoute(page: MisteryBoxRoute.page), + + // Menu + AutoRoute(page: MenuRoute.page), ]; } diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index 1d18605..041cab9 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -9,27 +9,28 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i35; +import 'package:auto_route/auto_route.dart' as _i36; +import 'package:enaklo/common/data/service_data.dart' as _i38; import 'package:enaklo/presentation/pages/account/account_my/account_my_page.dart' as _i1; import 'package:enaklo/presentation/pages/account/address/address_page.dart' as _i2; import 'package:enaklo/presentation/pages/account/payment/payment_page.dart' - as _i25; + as _i26; import 'package:enaklo/presentation/pages/auth/create_password/create_password_page.dart' as _i5; import 'package:enaklo/presentation/pages/auth/login/login_page.dart' as _i14; -import 'package:enaklo/presentation/pages/auth/otp/otp_page.dart' as _i23; +import 'package:enaklo/presentation/pages/auth/otp/otp_page.dart' as _i24; import 'package:enaklo/presentation/pages/auth/password/password_page.dart' - as _i24; -import 'package:enaklo/presentation/pages/auth/pin/pin_page.dart' as _i26; + as _i25; +import 'package:enaklo/presentation/pages/auth/pin/pin_page.dart' as _i27; import 'package:enaklo/presentation/pages/auth/register/register_page.dart' - as _i30; + as _i31; import 'package:enaklo/presentation/pages/coin/coin_page.dart' as _i4; import 'package:enaklo/presentation/pages/coin/pages/coin_history_page.dart' as _i3; import 'package:enaklo/presentation/pages/coin/pages/product_redeem/product_redeem_page.dart' - as _i28; + as _i29; import 'package:enaklo/presentation/pages/draw/draw_page.dart' as _i9; import 'package:enaklo/presentation/pages/draw/pages/draw_detail/draw_detail_page.dart' as _i6; @@ -45,41 +46,42 @@ import 'package:enaklo/presentation/pages/main/main_page.dart' as _i15; import 'package:enaklo/presentation/pages/main/pages/home/home_page.dart' as _i13; import 'package:enaklo/presentation/pages/main/pages/order/order_page.dart' - as _i22; + as _i23; import 'package:enaklo/presentation/pages/main/pages/profile/profile_page.dart' - as _i29; + as _i30; import 'package:enaklo/presentation/pages/main/pages/voucher/voucher_page.dart' - as _i34; -import 'package:enaklo/presentation/pages/merchant/merchant_page.dart' as _i17; + as _i35; +import 'package:enaklo/presentation/pages/menu/menu_page.dart' as _i16; +import 'package:enaklo/presentation/pages/merchant/merchant_page.dart' as _i18; import 'package:enaklo/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart' - as _i16; + as _i17; import 'package:enaklo/presentation/pages/mini_games/ferris_wheel/ferris_wheel_page.dart' as _i12; import 'package:enaklo/presentation/pages/mini_games/mistery_box/mistery_box_page.dart' - as _i18; -import 'package:enaklo/presentation/pages/notification/notification_page.dart' as _i19; -import 'package:enaklo/presentation/pages/onboarding/onboarding_page.dart' +import 'package:enaklo/presentation/pages/notification/notification_page.dart' as _i20; -import 'package:enaklo/presentation/pages/order/order_detail/order_detail_page.dart' +import 'package:enaklo/presentation/pages/onboarding/onboarding_page.dart' as _i21; -import 'package:enaklo/presentation/pages/point/point_page.dart' as _i27; -import 'package:enaklo/presentation/pages/reward/reward_page.dart' as _i31; -import 'package:enaklo/presentation/pages/splash/splash_page.dart' as _i32; +import 'package:enaklo/presentation/pages/order/order_detail/order_detail_page.dart' + as _i22; +import 'package:enaklo/presentation/pages/point/point_page.dart' as _i28; +import 'package:enaklo/presentation/pages/reward/reward_page.dart' as _i32; +import 'package:enaklo/presentation/pages/splash/splash_page.dart' as _i33; import 'package:enaklo/presentation/pages/voucher/voucher_detail/voucher_detail_page.dart' - as _i33; -import 'package:enaklo/sample/sample_data.dart' as _i37; -import 'package:flutter/material.dart' as _i36; + as _i34; +import 'package:enaklo/sample/sample_data.dart' as _i39; +import 'package:flutter/material.dart' as _i37; /// generated route for /// [_i1.AccountMyPage] -class AccountMyRoute extends _i35.PageRouteInfo { - const AccountMyRoute({List<_i35.PageRouteInfo>? children}) +class AccountMyRoute extends _i36.PageRouteInfo { + const AccountMyRoute({List<_i36.PageRouteInfo>? children}) : super(AccountMyRoute.name, initialChildren: children); static const String name = 'AccountMyRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i1.AccountMyPage(); @@ -89,13 +91,13 @@ class AccountMyRoute extends _i35.PageRouteInfo { /// generated route for /// [_i2.AddressPage] -class AddressRoute extends _i35.PageRouteInfo { - const AddressRoute({List<_i35.PageRouteInfo>? children}) +class AddressRoute extends _i36.PageRouteInfo { + const AddressRoute({List<_i36.PageRouteInfo>? children}) : super(AddressRoute.name, initialChildren: children); static const String name = 'AddressRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i2.AddressPage(); @@ -105,13 +107,13 @@ class AddressRoute extends _i35.PageRouteInfo { /// generated route for /// [_i3.CoinHistoryPage] -class CoinHistoryRoute extends _i35.PageRouteInfo { - const CoinHistoryRoute({List<_i35.PageRouteInfo>? children}) +class CoinHistoryRoute extends _i36.PageRouteInfo { + const CoinHistoryRoute({List<_i36.PageRouteInfo>? children}) : super(CoinHistoryRoute.name, initialChildren: children); static const String name = 'CoinHistoryRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i3.CoinHistoryPage(); @@ -121,13 +123,13 @@ class CoinHistoryRoute extends _i35.PageRouteInfo { /// generated route for /// [_i4.CoinPage] -class CoinRoute extends _i35.PageRouteInfo { - const CoinRoute({List<_i35.PageRouteInfo>? children}) +class CoinRoute extends _i36.PageRouteInfo { + const CoinRoute({List<_i36.PageRouteInfo>? children}) : super(CoinRoute.name, initialChildren: children); static const String name = 'CoinRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i4.CoinPage(); @@ -137,11 +139,11 @@ class CoinRoute extends _i35.PageRouteInfo { /// generated route for /// [_i5.CreatePasswordPage] -class CreatePasswordRoute extends _i35.PageRouteInfo { +class CreatePasswordRoute extends _i36.PageRouteInfo { CreatePasswordRoute({ - _i36.Key? key, + _i37.Key? key, required String registrationToken, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( CreatePasswordRoute.name, args: CreatePasswordRouteArgs( @@ -153,11 +155,11 @@ class CreatePasswordRoute extends _i35.PageRouteInfo { static const String name = 'CreatePasswordRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i35.WrappedRoute( + return _i36.WrappedRoute( child: _i5.CreatePasswordPage( key: args.key, registrationToken: args.registrationToken, @@ -170,7 +172,7 @@ class CreatePasswordRoute extends _i35.PageRouteInfo { class CreatePasswordRouteArgs { const CreatePasswordRouteArgs({this.key, required this.registrationToken}); - final _i36.Key? key; + final _i37.Key? key; final String registrationToken; @@ -182,13 +184,13 @@ class CreatePasswordRouteArgs { /// generated route for /// [_i6.DrawDetailPage] -class DrawDetailRoute extends _i35.PageRouteInfo { - const DrawDetailRoute({List<_i35.PageRouteInfo>? children}) +class DrawDetailRoute extends _i36.PageRouteInfo { + const DrawDetailRoute({List<_i36.PageRouteInfo>? children}) : super(DrawDetailRoute.name, initialChildren: children); static const String name = 'DrawDetailRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i6.DrawDetailPage(); @@ -198,13 +200,13 @@ class DrawDetailRoute extends _i35.PageRouteInfo { /// generated route for /// [_i7.DrawInfoPage] -class DrawInfoRoute extends _i35.PageRouteInfo { - const DrawInfoRoute({List<_i35.PageRouteInfo>? children}) +class DrawInfoRoute extends _i36.PageRouteInfo { + const DrawInfoRoute({List<_i36.PageRouteInfo>? children}) : super(DrawInfoRoute.name, initialChildren: children); static const String name = 'DrawInfoRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i7.DrawInfoPage(); @@ -214,13 +216,13 @@ class DrawInfoRoute extends _i35.PageRouteInfo { /// generated route for /// [_i8.DrawMyNumberPage] -class DrawMyNumberRoute extends _i35.PageRouteInfo { - const DrawMyNumberRoute({List<_i35.PageRouteInfo>? children}) +class DrawMyNumberRoute extends _i36.PageRouteInfo { + const DrawMyNumberRoute({List<_i36.PageRouteInfo>? children}) : super(DrawMyNumberRoute.name, initialChildren: children); static const String name = 'DrawMyNumberRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i8.DrawMyNumberPage(); @@ -230,13 +232,13 @@ class DrawMyNumberRoute extends _i35.PageRouteInfo { /// generated route for /// [_i9.DrawPage] -class DrawRoute extends _i35.PageRouteInfo { - const DrawRoute({List<_i35.PageRouteInfo>? children}) +class DrawRoute extends _i36.PageRouteInfo { + const DrawRoute({List<_i36.PageRouteInfo>? children}) : super(DrawRoute.name, initialChildren: children); static const String name = 'DrawRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i9.DrawPage(); @@ -246,13 +248,13 @@ class DrawRoute extends _i35.PageRouteInfo { /// generated route for /// [_i10.DrawTodayPage] -class DrawTodayRoute extends _i35.PageRouteInfo { - const DrawTodayRoute({List<_i35.PageRouteInfo>? children}) +class DrawTodayRoute extends _i36.PageRouteInfo { + const DrawTodayRoute({List<_i36.PageRouteInfo>? children}) : super(DrawTodayRoute.name, initialChildren: children); static const String name = 'DrawTodayRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i10.DrawTodayPage(); @@ -262,13 +264,13 @@ class DrawTodayRoute extends _i35.PageRouteInfo { /// generated route for /// [_i11.DrawWinnerPage] -class DrawWinnerRoute extends _i35.PageRouteInfo { - const DrawWinnerRoute({List<_i35.PageRouteInfo>? children}) +class DrawWinnerRoute extends _i36.PageRouteInfo { + const DrawWinnerRoute({List<_i36.PageRouteInfo>? children}) : super(DrawWinnerRoute.name, initialChildren: children); static const String name = 'DrawWinnerRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i11.DrawWinnerPage(); @@ -278,29 +280,29 @@ class DrawWinnerRoute extends _i35.PageRouteInfo { /// generated route for /// [_i12.FerrisWheelPage] -class FerrisWheelRoute extends _i35.PageRouteInfo { - const FerrisWheelRoute({List<_i35.PageRouteInfo>? children}) +class FerrisWheelRoute extends _i36.PageRouteInfo { + const FerrisWheelRoute({List<_i36.PageRouteInfo>? children}) : super(FerrisWheelRoute.name, initialChildren: children); static const String name = 'FerrisWheelRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return _i35.WrappedRoute(child: const _i12.FerrisWheelPage()); + return _i36.WrappedRoute(child: const _i12.FerrisWheelPage()); }, ); } /// generated route for /// [_i13.HomePage] -class HomeRoute extends _i35.PageRouteInfo { - const HomeRoute({List<_i35.PageRouteInfo>? children}) +class HomeRoute extends _i36.PageRouteInfo { + const HomeRoute({List<_i36.PageRouteInfo>? children}) : super(HomeRoute.name, initialChildren: children); static const String name = 'HomeRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i13.HomePage(); @@ -310,29 +312,29 @@ class HomeRoute extends _i35.PageRouteInfo { /// generated route for /// [_i14.LoginPage] -class LoginRoute extends _i35.PageRouteInfo { - const LoginRoute({List<_i35.PageRouteInfo>? children}) +class LoginRoute extends _i36.PageRouteInfo { + const LoginRoute({List<_i36.PageRouteInfo>? children}) : super(LoginRoute.name, initialChildren: children); static const String name = 'LoginRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return _i35.WrappedRoute(child: const _i14.LoginPage()); + return _i36.WrappedRoute(child: const _i14.LoginPage()); }, ); } /// generated route for /// [_i15.MainPage] -class MainRoute extends _i35.PageRouteInfo { - const MainRoute({List<_i35.PageRouteInfo>? children}) +class MainRoute extends _i36.PageRouteInfo { + const MainRoute({List<_i36.PageRouteInfo>? children}) : super(MainRoute.name, initialChildren: children); static const String name = 'MainRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { return const _i15.MainPage(); @@ -341,12 +343,49 @@ class MainRoute extends _i35.PageRouteInfo { } /// generated route for -/// [_i16.MerchantDetailPage] -class MerchantDetailRoute extends _i35.PageRouteInfo { +/// [_i16.MenuPage] +class MenuRoute extends _i36.PageRouteInfo { + MenuRoute({ + _i37.Key? key, + required _i38.Service service, + List<_i36.PageRouteInfo>? children, + }) : super( + MenuRoute.name, + args: MenuRouteArgs(key: key, service: service), + initialChildren: children, + ); + + static const String name = 'MenuRoute'; + + static _i36.PageInfo page = _i36.PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return _i16.MenuPage(key: args.key, service: args.service); + }, + ); +} + +class MenuRouteArgs { + const MenuRouteArgs({this.key, required this.service}); + + final _i37.Key? key; + + final _i38.Service service; + + @override + String toString() { + return 'MenuRouteArgs{key: $key, service: $service}'; + } +} + +/// generated route for +/// [_i17.MerchantDetailPage] +class MerchantDetailRoute extends _i36.PageRouteInfo { MerchantDetailRoute({ - _i36.Key? key, - required _i37.MerchantModel merchant, - List<_i35.PageRouteInfo>? children, + _i37.Key? key, + required _i39.MerchantModel merchant, + List<_i36.PageRouteInfo>? children, }) : super( MerchantDetailRoute.name, args: MerchantDetailRouteArgs(key: key, merchant: merchant), @@ -355,11 +394,11 @@ class MerchantDetailRoute extends _i35.PageRouteInfo { static const String name = 'MerchantDetailRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i16.MerchantDetailPage(key: args.key, merchant: args.merchant); + return _i17.MerchantDetailPage(key: args.key, merchant: args.merchant); }, ); } @@ -367,9 +406,9 @@ class MerchantDetailRoute extends _i35.PageRouteInfo { class MerchantDetailRouteArgs { const MerchantDetailRouteArgs({this.key, required this.merchant}); - final _i36.Key? key; + final _i37.Key? key; - final _i37.MerchantModel merchant; + final _i39.MerchantModel merchant; @override String toString() { @@ -378,76 +417,76 @@ class MerchantDetailRouteArgs { } /// generated route for -/// [_i17.MerchantPage] -class MerchantRoute extends _i35.PageRouteInfo { - const MerchantRoute({List<_i35.PageRouteInfo>? children}) +/// [_i18.MerchantPage] +class MerchantRoute extends _i36.PageRouteInfo { + const MerchantRoute({List<_i36.PageRouteInfo>? children}) : super(MerchantRoute.name, initialChildren: children); static const String name = 'MerchantRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i17.MerchantPage(); + return const _i18.MerchantPage(); }, ); } /// generated route for -/// [_i18.MisteryBoxPage] -class MisteryBoxRoute extends _i35.PageRouteInfo { - const MisteryBoxRoute({List<_i35.PageRouteInfo>? children}) +/// [_i19.MisteryBoxPage] +class MisteryBoxRoute extends _i36.PageRouteInfo { + const MisteryBoxRoute({List<_i36.PageRouteInfo>? children}) : super(MisteryBoxRoute.name, initialChildren: children); static const String name = 'MisteryBoxRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i18.MisteryBoxPage(); + return const _i19.MisteryBoxPage(); }, ); } /// generated route for -/// [_i19.NotificationPage] -class NotificationRoute extends _i35.PageRouteInfo { - const NotificationRoute({List<_i35.PageRouteInfo>? children}) +/// [_i20.NotificationPage] +class NotificationRoute extends _i36.PageRouteInfo { + const NotificationRoute({List<_i36.PageRouteInfo>? children}) : super(NotificationRoute.name, initialChildren: children); static const String name = 'NotificationRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i19.NotificationPage(); + return const _i20.NotificationPage(); }, ); } /// generated route for -/// [_i20.OnboardingPage] -class OnboardingRoute extends _i35.PageRouteInfo { - const OnboardingRoute({List<_i35.PageRouteInfo>? children}) +/// [_i21.OnboardingPage] +class OnboardingRoute extends _i36.PageRouteInfo { + const OnboardingRoute({List<_i36.PageRouteInfo>? children}) : super(OnboardingRoute.name, initialChildren: children); static const String name = 'OnboardingRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i20.OnboardingPage(); + return const _i21.OnboardingPage(); }, ); } /// generated route for -/// [_i21.OrderDetailPage] -class OrderDetailRoute extends _i35.PageRouteInfo { +/// [_i22.OrderDetailPage] +class OrderDetailRoute extends _i36.PageRouteInfo { OrderDetailRoute({ - _i36.Key? key, - required _i22.Order order, - List<_i35.PageRouteInfo>? children, + _i37.Key? key, + required _i23.Order order, + List<_i36.PageRouteInfo>? children, }) : super( OrderDetailRoute.name, args: OrderDetailRouteArgs(key: key, order: order), @@ -456,11 +495,11 @@ class OrderDetailRoute extends _i35.PageRouteInfo { static const String name = 'OrderDetailRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i21.OrderDetailPage(key: args.key, order: args.order); + return _i22.OrderDetailPage(key: args.key, order: args.order); }, ); } @@ -468,9 +507,9 @@ class OrderDetailRoute extends _i35.PageRouteInfo { class OrderDetailRouteArgs { const OrderDetailRouteArgs({this.key, required this.order}); - final _i36.Key? key; + final _i37.Key? key; - final _i22.Order order; + final _i23.Order order; @override String toString() { @@ -479,29 +518,29 @@ class OrderDetailRouteArgs { } /// generated route for -/// [_i22.OrderPage] -class OrderRoute extends _i35.PageRouteInfo { - const OrderRoute({List<_i35.PageRouteInfo>? children}) +/// [_i23.OrderPage] +class OrderRoute extends _i36.PageRouteInfo { + const OrderRoute({List<_i36.PageRouteInfo>? children}) : super(OrderRoute.name, initialChildren: children); static const String name = 'OrderRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i22.OrderPage(); + return const _i23.OrderPage(); }, ); } /// generated route for -/// [_i23.OtpPage] -class OtpRoute extends _i35.PageRouteInfo { +/// [_i24.OtpPage] +class OtpRoute extends _i36.PageRouteInfo { OtpRoute({ - _i36.Key? key, + _i37.Key? key, required String registrationToken, required String phoneNumber, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( OtpRoute.name, args: OtpRouteArgs( @@ -514,12 +553,12 @@ class OtpRoute extends _i35.PageRouteInfo { static const String name = 'OtpRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i35.WrappedRoute( - child: _i23.OtpPage( + return _i36.WrappedRoute( + child: _i24.OtpPage( key: args.key, registrationToken: args.registrationToken, phoneNumber: args.phoneNumber, @@ -536,7 +575,7 @@ class OtpRouteArgs { required this.phoneNumber, }); - final _i36.Key? key; + final _i37.Key? key; final String registrationToken; @@ -549,12 +588,12 @@ class OtpRouteArgs { } /// generated route for -/// [_i24.PasswordPage] -class PasswordRoute extends _i35.PageRouteInfo { +/// [_i25.PasswordPage] +class PasswordRoute extends _i36.PageRouteInfo { PasswordRoute({ - _i36.Key? key, + _i37.Key? key, required String phoneNumber, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( PasswordRoute.name, args: PasswordRouteArgs(key: key, phoneNumber: phoneNumber), @@ -563,12 +602,12 @@ class PasswordRoute extends _i35.PageRouteInfo { static const String name = 'PasswordRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i35.WrappedRoute( - child: _i24.PasswordPage(key: args.key, phoneNumber: args.phoneNumber), + return _i36.WrappedRoute( + child: _i25.PasswordPage(key: args.key, phoneNumber: args.phoneNumber), ); }, ); @@ -577,7 +616,7 @@ class PasswordRoute extends _i35.PageRouteInfo { class PasswordRouteArgs { const PasswordRouteArgs({this.key, required this.phoneNumber}); - final _i36.Key? key; + final _i37.Key? key; final String phoneNumber; @@ -588,29 +627,29 @@ class PasswordRouteArgs { } /// generated route for -/// [_i25.PaymentPage] -class PaymentRoute extends _i35.PageRouteInfo { - const PaymentRoute({List<_i35.PageRouteInfo>? children}) +/// [_i26.PaymentPage] +class PaymentRoute extends _i36.PageRouteInfo { + const PaymentRoute({List<_i36.PageRouteInfo>? children}) : super(PaymentRoute.name, initialChildren: children); static const String name = 'PaymentRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i25.PaymentPage(); + return const _i26.PaymentPage(); }, ); } /// generated route for -/// [_i26.PinPage] -class PinRoute extends _i35.PageRouteInfo { +/// [_i27.PinPage] +class PinRoute extends _i36.PageRouteInfo { PinRoute({ - _i36.Key? key, + _i37.Key? key, bool isCreatePin = true, String? title, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( PinRoute.name, args: PinRouteArgs(key: key, isCreatePin: isCreatePin, title: title), @@ -619,13 +658,13 @@ class PinRoute extends _i35.PageRouteInfo { static const String name = 'PinRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const PinRouteArgs(), ); - return _i26.PinPage( + return _i27.PinPage( key: args.key, isCreatePin: args.isCreatePin, title: args.title, @@ -637,7 +676,7 @@ class PinRoute extends _i35.PageRouteInfo { class PinRouteArgs { const PinRouteArgs({this.key, this.isCreatePin = true, this.title}); - final _i36.Key? key; + final _i37.Key? key; final bool isCreatePin; @@ -650,29 +689,29 @@ class PinRouteArgs { } /// generated route for -/// [_i27.PointPage] -class PointRoute extends _i35.PageRouteInfo { - const PointRoute({List<_i35.PageRouteInfo>? children}) +/// [_i28.PointPage] +class PointRoute extends _i36.PageRouteInfo { + const PointRoute({List<_i36.PageRouteInfo>? children}) : super(PointRoute.name, initialChildren: children); static const String name = 'PointRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i27.PointPage(); + return const _i28.PointPage(); }, ); } /// generated route for -/// [_i28.ProductRedeemPage] -class ProductRedeemRoute extends _i35.PageRouteInfo { +/// [_i29.ProductRedeemPage] +class ProductRedeemRoute extends _i36.PageRouteInfo { ProductRedeemRoute({ - _i36.Key? key, + _i37.Key? key, required _i4.Product product, required _i4.PointCard pointCard, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( ProductRedeemRoute.name, args: ProductRedeemRouteArgs( @@ -685,11 +724,11 @@ class ProductRedeemRoute extends _i35.PageRouteInfo { static const String name = 'ProductRedeemRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i28.ProductRedeemPage( + return _i29.ProductRedeemPage( key: args.key, product: args.product, pointCard: args.pointCard, @@ -705,7 +744,7 @@ class ProductRedeemRouteArgs { required this.pointCard, }); - final _i36.Key? key; + final _i37.Key? key; final _i4.Product product; @@ -718,28 +757,28 @@ class ProductRedeemRouteArgs { } /// generated route for -/// [_i29.ProfilePage] -class ProfileRoute extends _i35.PageRouteInfo { - const ProfileRoute({List<_i35.PageRouteInfo>? children}) +/// [_i30.ProfilePage] +class ProfileRoute extends _i36.PageRouteInfo { + const ProfileRoute({List<_i36.PageRouteInfo>? children}) : super(ProfileRoute.name, initialChildren: children); static const String name = 'ProfileRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return _i35.WrappedRoute(child: const _i29.ProfilePage()); + return _i36.WrappedRoute(child: const _i30.ProfilePage()); }, ); } /// generated route for -/// [_i30.RegisterPage] -class RegisterRoute extends _i35.PageRouteInfo { +/// [_i31.RegisterPage] +class RegisterRoute extends _i36.PageRouteInfo { RegisterRoute({ - _i36.Key? key, + _i37.Key? key, required String phoneNumber, - List<_i35.PageRouteInfo>? children, + List<_i36.PageRouteInfo>? children, }) : super( RegisterRoute.name, args: RegisterRouteArgs(key: key, phoneNumber: phoneNumber), @@ -748,12 +787,12 @@ class RegisterRoute extends _i35.PageRouteInfo { static const String name = 'RegisterRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i35.WrappedRoute( - child: _i30.RegisterPage(key: args.key, phoneNumber: args.phoneNumber), + return _i36.WrappedRoute( + child: _i31.RegisterPage(key: args.key, phoneNumber: args.phoneNumber), ); }, ); @@ -762,7 +801,7 @@ class RegisterRoute extends _i35.PageRouteInfo { class RegisterRouteArgs { const RegisterRouteArgs({this.key, required this.phoneNumber}); - final _i36.Key? key; + final _i37.Key? key; final String phoneNumber; @@ -773,65 +812,65 @@ class RegisterRouteArgs { } /// generated route for -/// [_i31.RewardPage] -class RewardRoute extends _i35.PageRouteInfo { - const RewardRoute({List<_i35.PageRouteInfo>? children}) +/// [_i32.RewardPage] +class RewardRoute extends _i36.PageRouteInfo { + const RewardRoute({List<_i36.PageRouteInfo>? children}) : super(RewardRoute.name, initialChildren: children); static const String name = 'RewardRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i31.RewardPage(); + return const _i32.RewardPage(); }, ); } /// generated route for -/// [_i32.SplashPage] -class SplashRoute extends _i35.PageRouteInfo { - const SplashRoute({List<_i35.PageRouteInfo>? children}) +/// [_i33.SplashPage] +class SplashRoute extends _i36.PageRouteInfo { + const SplashRoute({List<_i36.PageRouteInfo>? children}) : super(SplashRoute.name, initialChildren: children); static const String name = 'SplashRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i32.SplashPage(); + return const _i33.SplashPage(); }, ); } /// generated route for -/// [_i33.VoucherDetailPage] -class VoucherDetailRoute extends _i35.PageRouteInfo { - const VoucherDetailRoute({List<_i35.PageRouteInfo>? children}) +/// [_i34.VoucherDetailPage] +class VoucherDetailRoute extends _i36.PageRouteInfo { + const VoucherDetailRoute({List<_i36.PageRouteInfo>? children}) : super(VoucherDetailRoute.name, initialChildren: children); static const String name = 'VoucherDetailRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i33.VoucherDetailPage(); + return const _i34.VoucherDetailPage(); }, ); } /// generated route for -/// [_i34.VoucherPage] -class VoucherRoute extends _i35.PageRouteInfo { - const VoucherRoute({List<_i35.PageRouteInfo>? children}) +/// [_i35.VoucherPage] +class VoucherRoute extends _i36.PageRouteInfo { + const VoucherRoute({List<_i36.PageRouteInfo>? children}) : super(VoucherRoute.name, initialChildren: children); static const String name = 'VoucherRoute'; - static _i35.PageInfo page = _i35.PageInfo( + static _i36.PageInfo page = _i36.PageInfo( name, builder: (data) { - return const _i34.VoucherPage(); + return const _i35.VoucherPage(); }, ); } diff --git a/lib/sample/product_sample_data.dart b/lib/sample/product_sample_data.dart new file mode 100644 index 0000000..d255d99 --- /dev/null +++ b/lib/sample/product_sample_data.dart @@ -0,0 +1,121 @@ +// Models +class ProductCategory { + final String id; + final String name; + final String icon; + final int productCount; + + ProductCategory({ + required this.id, + required this.name, + required this.icon, + required this.productCount, + }); +} + +class Product { + final String id; + final String name; + final String description; + final int price; + final String categoryId; + final String imageUrl; + final bool isAvailable; + final double rating; + final int soldCount; + + Product({ + required this.id, + required this.name, + required this.description, + required this.price, + required this.categoryId, + required this.imageUrl, + required this.isAvailable, + required this.rating, + required this.soldCount, + }); +} + +// Sample data +final List categories = [ + ProductCategory(id: "1", name: "Makanan", icon: "🍽️", productCount: 8), + ProductCategory(id: "2", name: "Minuman", icon: "🥤", productCount: 6), + ProductCategory(id: "3", name: "Snack", icon: "🍿", productCount: 5), + ProductCategory(id: "4", name: "Es Krim", icon: "🍦", productCount: 4), + ProductCategory(id: "5", name: "Paket", icon: "📦", productCount: 3), +]; + +final List products = [ + // Makanan + Product( + id: "1", + name: "Nasi Gudeg", + description: "Gudeg khas Yogyakarta dengan ayam dan telur", + price: 25000, + categoryId: "1", + imageUrl: "https://via.placeholder.com/150", + isAvailable: true, + rating: 4.5, + soldCount: 50, + ), + Product( + id: "2", + name: "Soto Ayam", + description: "Soto ayam kuning dengan nasi dan kerupuk", + price: 18000, + categoryId: "1", + imageUrl: "https://via.placeholder.com/150", + isAvailable: true, + rating: 4.3, + soldCount: 75, + ), + Product( + id: "3", + name: "Gado-gado", + description: "Gado-gado segar dengan bumbu kacang", + price: 15000, + categoryId: "1", + imageUrl: "https://via.placeholder.com/150", + isAvailable: false, + rating: 4.2, + soldCount: 30, + ), + + // Minuman + Product( + id: "4", + name: "Es Teh Manis", + description: "Es teh manis segar", + price: 5000, + categoryId: "2", + imageUrl: "https://via.placeholder.com/150", + isAvailable: true, + rating: 4.0, + soldCount: 120, + ), + Product( + id: "5", + name: "Jus Jeruk", + description: "Jus jeruk segar tanpa gula tambahan", + price: 12000, + categoryId: "2", + imageUrl: "https://via.placeholder.com/150", + isAvailable: true, + rating: 4.4, + soldCount: 45, + ), + + // Snack + Product( + id: "6", + name: "Keripik Pisang", + description: "Keripik pisang renyah dan manis", + price: 8000, + categoryId: "3", + imageUrl: "https://via.placeholder.com/150", + isAvailable: true, + rating: 4.1, + soldCount: 25, + ), +]; diff --git a/pubspec.lock b/pubspec.lock index 750851a..eeccb95 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -724,10 +724,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -1121,10 +1121,10 @@ packages: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.7" time: dependency: transitive description: