dev #2
BIN
assets/icons/dine_in.png
Normal file
BIN
assets/icons/dine_in.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 332 KiB |
BIN
assets/icons/takeaway.png
Normal file
BIN
assets/icons/takeaway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 367 KiB |
@ -1,11 +1,26 @@
|
|||||||
|
import '../../presentation/components/assets/assets.gen.dart';
|
||||||
|
|
||||||
class Service {
|
class Service {
|
||||||
Service({required this.name, required this.description});
|
Service({
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.imagePath,
|
||||||
|
});
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
|
final String imagePath;
|
||||||
final String description;
|
final String description;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Service> services = [
|
List<Service> services = [
|
||||||
Service(name: 'Dine In', description: 'Makan langsung di tempat'),
|
Service(
|
||||||
Service(name: 'Take Away', description: 'Pesan dan bawa pulang'),
|
name: 'Dine In',
|
||||||
|
description: 'Makan langsung di tempat',
|
||||||
|
imagePath: Assets.icons.dineIn.path,
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name: 'Take Away',
|
||||||
|
description: 'Pesan dan bawa pulang',
|
||||||
|
imagePath: Assets.icons.dineIn.path,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class ThemeApp {
|
|||||||
foregroundColor: AppColor.textPrimary,
|
foregroundColor: AppColor.textPrimary,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
titleTextStyle: AppStyle.xl.copyWith(
|
titleTextStyle: AppStyle.xl.copyWith(
|
||||||
color: AppColor.primary,
|
color: AppColor.textPrimary,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
@ -60,6 +60,15 @@ class ThemeApp {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
foregroundColor: AppColor.primary,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(color: AppColor.border),
|
||||||
|
borderRadius: BorderRadiusGeometry.circular(AppValue.borderRadius),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: _inputBorder,
|
border: _inputBorder,
|
||||||
focusedBorder: _inputBorder.copyWith(
|
focusedBorder: _inputBorder.copyWith(
|
||||||
|
|||||||
@ -43,6 +43,20 @@ class $AssetsAudioGen {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class $AssetsIconsGen {
|
||||||
|
const $AssetsIconsGen();
|
||||||
|
|
||||||
|
/// File path: assets/icons/dine_in.png
|
||||||
|
AssetGenImage get dineIn => const AssetGenImage('assets/icons/dine_in.png');
|
||||||
|
|
||||||
|
/// File path: assets/icons/takeaway.png
|
||||||
|
AssetGenImage get takeaway =>
|
||||||
|
const AssetGenImage('assets/icons/takeaway.png');
|
||||||
|
|
||||||
|
/// List of all assets
|
||||||
|
List<AssetGenImage> get values => [dineIn, takeaway];
|
||||||
|
}
|
||||||
|
|
||||||
class $AssetsImagesGen {
|
class $AssetsImagesGen {
|
||||||
const $AssetsImagesGen();
|
const $AssetsImagesGen();
|
||||||
|
|
||||||
@ -97,6 +111,7 @@ class Assets {
|
|||||||
const Assets._();
|
const Assets._();
|
||||||
|
|
||||||
static const $AssetsAudioGen audio = $AssetsAudioGen();
|
static const $AssetsAudioGen audio = $AssetsAudioGen();
|
||||||
|
static const $AssetsIconsGen icons = $AssetsIconsGen();
|
||||||
static const $AssetsImagesGen images = $AssetsImagesGen();
|
static const $AssetsImagesGen images = $AssetsImagesGen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
lib/presentation/components/border/dashed_border.dart
Normal file
39
lib/presentation/components/border/dashed_border.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DashedDivider extends StatelessWidget {
|
||||||
|
final double height;
|
||||||
|
final double dashWidth;
|
||||||
|
final double dashSpacing;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
const DashedDivider({
|
||||||
|
super.key,
|
||||||
|
this.height = 1,
|
||||||
|
this.dashWidth = 5,
|
||||||
|
this.dashSpacing = 3,
|
||||||
|
this.color = Colors.grey,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: height,
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final boxWidth = constraints.constrainWidth();
|
||||||
|
final dashCount = (boxWidth / (dashWidth + dashSpacing)).floor();
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: List.generate(dashCount, (_) {
|
||||||
|
return SizedBox(
|
||||||
|
width: dashWidth,
|
||||||
|
height: height,
|
||||||
|
child: DecoratedBox(decoration: BoxDecoration(color: color)),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,3 +4,5 @@ import 'package:flutter_spinkit/flutter_spinkit.dart';
|
|||||||
import '../../../common/theme/theme.dart';
|
import '../../../common/theme/theme.dart';
|
||||||
|
|
||||||
part 'elevated_button.dart';
|
part 'elevated_button.dart';
|
||||||
|
part 'outline_button.dart';
|
||||||
|
part 'qty_button.dart';
|
||||||
|
|||||||
@ -6,7 +6,7 @@ class AppElevatedButton extends StatelessWidget {
|
|||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
required this.title,
|
required this.title,
|
||||||
this.width = double.infinity,
|
this.width = double.infinity,
|
||||||
this.height = 48.0,
|
this.height = 44.0,
|
||||||
this.isLoading = false,
|
this.isLoading = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ class AppElevatedButton extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
title,
|
title,
|
||||||
style: AppStyle.lg.copyWith(
|
style: AppStyle.md.copyWith(
|
||||||
color: AppColor.white,
|
color: AppColor.white,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
|
|||||||
58
lib/presentation/components/button/outline_button.dart
Normal file
58
lib/presentation/components/button/outline_button.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
part of 'button.dart';
|
||||||
|
|
||||||
|
class AppOutlineButton extends StatelessWidget {
|
||||||
|
const AppOutlineButton({
|
||||||
|
super.key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.title,
|
||||||
|
this.width = double.infinity,
|
||||||
|
this.height = 44.0,
|
||||||
|
this.isLoading = false,
|
||||||
|
this.borderColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Function()? onPressed;
|
||||||
|
final String title;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
final bool isLoading;
|
||||||
|
final Color? borderColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
side: BorderSide(color: borderColor ?? AppColor.primary),
|
||||||
|
),
|
||||||
|
child: isLoading
|
||||||
|
? Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SpinKitFadingCircle(color: AppColor.white, size: 24),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Loading',
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
color: AppColor.white,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
title,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
part of 'button.dart';
|
||||||
|
|
||||||
import '../../../common/theme/theme.dart';
|
|
||||||
|
|
||||||
class QtyButton extends StatelessWidget {
|
class QtyButton extends StatelessWidget {
|
||||||
const QtyButton({super.key});
|
const QtyButton({super.key});
|
||||||
|
|||||||
63
lib/presentation/components/card/service_card.dart
Normal file
63
lib/presentation/components/card/service_card.dart
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../common/data/service_data.dart';
|
||||||
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../image/image.dart';
|
||||||
|
import 'gradient_card.dart';
|
||||||
|
|
||||||
|
class ServiceCard extends StatelessWidget {
|
||||||
|
final Service service;
|
||||||
|
const ServiceCard({super.key, required this.service});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GradientCard(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadiusGeometry.circular(8),
|
||||||
|
child: Image.asset(
|
||||||
|
service.imagePath,
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
errorBuilder: (context, error, stackTrace) =>
|
||||||
|
ImagePlaceholder(width: 60, height: 60),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
service.name,
|
||||||
|
style: AppStyle.xl.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColor.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
service.description,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColor.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
'Ubah',
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
225
lib/presentation/pages/checkout/checkout_page.dart
Normal file
225
lib/presentation/pages/checkout/checkout_page.dart
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../common/data/service_data.dart';
|
||||||
|
import '../../../common/extension/extension.dart';
|
||||||
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../../../sample/product_sample_data.dart';
|
||||||
|
import '../../components/border/dashed_border.dart';
|
||||||
|
import '../../components/button/button.dart';
|
||||||
|
import '../../components/card/service_card.dart';
|
||||||
|
import 'widgets/checkout_item.dart';
|
||||||
|
import 'widgets/merchant.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class CheckoutPage extends StatelessWidget {
|
||||||
|
const CheckoutPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text('Checkout')),
|
||||||
|
bottomNavigationBar: Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding).copyWith(bottom: 24),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.black.withOpacity(0.1),
|
||||||
|
offset: Offset(2, 0),
|
||||||
|
blurRadius: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: AppElevatedButton(onPressed: () {}, title: 'Pesan Sekarang'),
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ServiceCard(service: services.first),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
CheckoutMerchant(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(thickness: 4, color: AppColor.borderLight),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_sectionTitle('Pesananmu'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
CheckoutItem(product: products.first),
|
||||||
|
CheckoutItem(product: products.first),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Ada Tambah lagi?',
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Kakmu bisa menambah menu lainnya, ya.',
|
||||||
|
style: AppStyle.md,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
AppOutlineButton(
|
||||||
|
width: 100,
|
||||||
|
onPressed: () {},
|
||||||
|
title: '+ Tambah',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(thickness: 4, color: AppColor.borderLight),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_sectionTitle('Voucher'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
color: AppColor.primary.withOpacity(0.1),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.confirmation_number,
|
||||||
|
color: AppColor.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Kamu bisa menggunakan voucher mu disini.',
|
||||||
|
style: AppStyle.md,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(Icons.chevron_right, color: AppColor.textSecondary),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(thickness: 4, color: AppColor.borderLight),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_sectionTitle('Metode Pembayaran'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
color: AppColor.primary.withOpacity(0.1),
|
||||||
|
),
|
||||||
|
child: Icon(Icons.wallet, color: AppColor.primary),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Pilih metode pembayaran disini.',
|
||||||
|
style: AppStyle.md,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(Icons.chevron_right, color: AppColor.textSecondary),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(thickness: 4, color: AppColor.borderLight),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_sectionTitle('Rincian Pembayaran'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Harga',
|
||||||
|
style: AppStyle.md.copyWith(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"40000".currencyFormatRp,
|
||||||
|
style: AppStyle.md.copyWith(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
|
child: DashedDivider(),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Total Pembayaran',
|
||||||
|
style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"40000".currencyFormatRp,
|
||||||
|
style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(thickness: 4, color: AppColor.borderLight),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(AppValue.padding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Kebijakan Pembatalan",
|
||||||
|
style: AppStyle.md.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Kamu tidak dapat melakukan pembatalan atau perubahan apapun pada pesanan setelah melakukan pembayaran.',
|
||||||
|
style: AppStyle.sm,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 40),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Text _sectionTitle(String title) {
|
||||||
|
return Text(
|
||||||
|
title,
|
||||||
|
style: AppStyle.xl.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
lib/presentation/pages/checkout/widgets/checkout_item.dart
Normal file
68
lib/presentation/pages/checkout/widgets/checkout_item.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../../sample/product_sample_data.dart';
|
||||||
|
import '../../../components/button/button.dart';
|
||||||
|
import '../../../components/image/image.dart';
|
||||||
|
|
||||||
|
class CheckoutItem extends StatelessWidget {
|
||||||
|
final Product product;
|
||||||
|
const CheckoutItem({super.key, required this.product});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(bottom: 16),
|
||||||
|
decoration: BoxDecoration(),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
AppNetworkImage(url: product.imageUrl, width: 60, height: 60),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
product.name,
|
||||||
|
style: AppStyle.md.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"1x ${product.price.currencyFormatRp}",
|
||||||
|
style: AppStyle.md,
|
||||||
|
),
|
||||||
|
Text("27000".currencyFormatRp, style: AppStyle.md),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Catatan',
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
QtyButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
lib/presentation/pages/checkout/widgets/merchant.dart
Normal file
44
lib/presentation/pages/checkout/widgets/merchant.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/constant/app_constant.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
|
||||||
|
class CheckoutMerchant extends StatelessWidget {
|
||||||
|
const CheckoutMerchant({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.surface,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
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(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(merchant.category, style: AppStyle.md.copyWith()),
|
||||||
|
Row(children: [SizedBox(width: 12)]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,9 +5,9 @@ import '../../../../../common/extension/extension.dart';
|
|||||||
import '../../../../../common/theme/theme.dart';
|
import '../../../../../common/theme/theme.dart';
|
||||||
import '../../../../../sample/product_sample_data.dart';
|
import '../../../../../sample/product_sample_data.dart';
|
||||||
import '../../../../components/button/button.dart';
|
import '../../../../components/button/button.dart';
|
||||||
import '../../../../components/button/qty_button.dart';
|
|
||||||
import '../../../../components/card/variant_card.dart';
|
import '../../../../components/card/variant_card.dart';
|
||||||
import '../../../../components/image/image.dart';
|
import '../../../../components/image/image.dart';
|
||||||
|
import '../../../../router/app_router.gr.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class MenuDetailPage extends StatefulWidget {
|
class MenuDetailPage extends StatefulWidget {
|
||||||
@ -68,7 +68,7 @@ class _MenuDetailPageState extends State<MenuDetailPage> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: AppElevatedButton(
|
child: AppElevatedButton(
|
||||||
onPressed: () {},
|
onPressed: () => context.router.push(CheckoutRoute()),
|
||||||
title: '+ Keranjang ${"27000".currencyFormatRp}',
|
title: '+ Keranjang ${"27000".currencyFormatRp}',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -78,5 +78,8 @@ class AppRouter extends RootStackRouter {
|
|||||||
// Menu
|
// Menu
|
||||||
AutoRoute(page: MenuRoute.page),
|
AutoRoute(page: MenuRoute.page),
|
||||||
AutoRoute(page: MenuDetailRoute.page),
|
AutoRoute(page: MenuDetailRoute.page),
|
||||||
|
|
||||||
|
// Checkout
|
||||||
|
AutoRoute(page: CheckoutRoute.page),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user