impl: trying to excecute UI idea
This commit is contained in:
parent
f4259a785e
commit
42cd53752b
|
@ -3,6 +3,8 @@ import 'package:rijig_mobile/core/utils/exportimportview.dart';
|
|||
final router = GoRouter(
|
||||
routes: [
|
||||
GoRoute(path: '/', builder: (context, state) => SplashScreen()),
|
||||
GoRoute(path: '/trashview', builder: (context, state) => TestRequestPickScreen()),
|
||||
GoRoute(path: '/ordersumary', builder: (context, state) => OrderSummaryScreen()),
|
||||
GoRoute(
|
||||
path: '/cmapview',
|
||||
builder: (context, state) => CollectorRouteMapScreen(),
|
||||
|
|
|
@ -24,3 +24,9 @@ export 'package:rijig_mobile/features/auth/presentation/screen/collector/cotp_sc
|
|||
export 'package:rijig_mobile/features/auth/presentation/screen/collector/clogin_screen.dart';
|
||||
export 'package:rijig_mobile/features/home/presentation/screen/collector/pickup_history_screen.dart';
|
||||
export 'package:rijig_mobile/features/pickup/presentation/screen/pickup_map_screen.dart';
|
||||
|
||||
|
||||
|
||||
// remmovable
|
||||
export 'package:rijig_mobile/features/home/presentation/components/cart_test_screen.dart';
|
||||
export 'package:rijig_mobile/features/home/presentation/components/trash_testview.dart';
|
|
@ -0,0 +1,609 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
class OrderSummaryScreen extends StatefulWidget {
|
||||
const OrderSummaryScreen({super.key});
|
||||
|
||||
@override
|
||||
State<OrderSummaryScreen> createState() => _OrderSummaryScreenState();
|
||||
}
|
||||
|
||||
class _OrderSummaryScreenState extends State<OrderSummaryScreen> {
|
||||
// List untuk menyimpan item yang dipilih
|
||||
List<Map<String, dynamic>> selectedItems = [
|
||||
{
|
||||
'name': 'Plastik',
|
||||
'price': 1000,
|
||||
'quantity': 1.0,
|
||||
'icon': Icons.local_drink,
|
||||
'backgroundColor': Colors.blue.shade100,
|
||||
'iconColor': Colors.blue,
|
||||
},
|
||||
{
|
||||
'name': 'Kertas Campur',
|
||||
'price': 700,
|
||||
'quantity': 2.5,
|
||||
'icon': Icons.description,
|
||||
'backgroundColor': Colors.orange.shade100,
|
||||
'iconColor': Colors.orange,
|
||||
},
|
||||
];
|
||||
|
||||
void _removeItem(int index) {
|
||||
setState(() {
|
||||
selectedItems.removeAt(index);
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Item berhasil dihapus'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _incrementQuantity(int index) {
|
||||
setState(() {
|
||||
selectedItems[index]['quantity'] += 2.5;
|
||||
});
|
||||
}
|
||||
|
||||
void _decrementQuantity(int index) {
|
||||
setState(() {
|
||||
if (selectedItems[index]['quantity'] > 0) {
|
||||
selectedItems[index]['quantity'] =
|
||||
(selectedItems[index]['quantity'] - 2.5).clamp(0.0, double.infinity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _showQuantityDialog(int index) {
|
||||
TextEditingController controller = TextEditingController(
|
||||
text: selectedItems[index]['quantity'].toString()
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Input Jumlah ${selectedItems[index]['name']}'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Jumlah (kg)',
|
||||
border: OutlineInputBorder(),
|
||||
suffixText: 'kg',
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Batal'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
double? newQuantity = double.tryParse(controller.text);
|
||||
if (newQuantity != null && newQuantity >= 0) {
|
||||
setState(() {
|
||||
selectedItems[index]['quantity'] = newQuantity;
|
||||
});
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Masukkan angka yang valid')),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text('Simpan'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
double get totalWeight {
|
||||
return selectedItems.fold(0.0, (sum, item) => sum + item['quantity']);
|
||||
}
|
||||
|
||||
int get estimatedEarnings {
|
||||
return selectedItems.fold<int>(0, (sum, item) =>
|
||||
sum + ((item['price'] as int) * (item['quantity'] as double)).round().toInt());
|
||||
}
|
||||
|
||||
int get applicationFee {
|
||||
return 550;
|
||||
}
|
||||
|
||||
int get estimatedIncome {
|
||||
return estimatedEarnings - applicationFee;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade50,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: Colors.black),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Text(
|
||||
'Detail Pesanan',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header Jenis Sampah
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha:0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.delete_outline,
|
||||
color: Colors.orange,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
'Jenis Sampah',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigate back to selection screen
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.add, color: Colors.blue, size: 16),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'Tambah',
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
|
||||
// List Items dengan Slidable
|
||||
...selectedItems.asMap().entries.map((entry) {
|
||||
int index = entry.key;
|
||||
Map<String, dynamic> item = entry.value;
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12),
|
||||
child: Slidable(
|
||||
key: ValueKey(item['name']),
|
||||
endActionPane: ActionPane(
|
||||
motion: ScrollMotion(),
|
||||
children: [
|
||||
SlidableAction(
|
||||
onPressed: (context) => _removeItem(index),
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.white,
|
||||
icon: Icons.delete,
|
||||
label: 'Hapus',
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade50,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: Colors.grey.shade200),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Icon
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: item['backgroundColor'],
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Icon(
|
||||
item['icon'],
|
||||
color: item['iconColor'],
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
|
||||
// Item info
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item['name'],
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'Rp ${item['price']}/kg',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
// Delete icon placeholder (always there for consistent height)
|
||||
SizedBox(
|
||||
height: 16,
|
||||
child: Icon(
|
||||
Icons.delete_outline,
|
||||
color: Colors.red,
|
||||
size: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Quantity controls
|
||||
Row(
|
||||
children: [
|
||||
// Decrease button
|
||||
GestureDetector(
|
||||
onTap: () => _decrementQuantity(index),
|
||||
child: Container(
|
||||
width: 28,
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.remove,
|
||||
color: Colors.grey.shade600,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
|
||||
// Quantity display (clickable)
|
||||
GestureDetector(
|
||||
onTap: () => _showQuantityDialog(index),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
),
|
||||
child: Text(
|
||||
'${item['quantity'].toString().replaceAll('.0', '')} kg',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
|
||||
// Increase button
|
||||
GestureDetector(
|
||||
onTap: () => _incrementQuantity(index),
|
||||
child: Container(
|
||||
width: 28,
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
// Total Weight
|
||||
Container(
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.scale,
|
||||
color: Colors.grey.shade700,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
'Berat total',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'${totalWeight.toString().replaceAll('.0', '')} kg',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 20),
|
||||
|
||||
// Perkiraan Pendapatan
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha:0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.folder,
|
||||
color: Colors.orange,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
'Perkiraan Pendapatan',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
|
||||
// Estimasi pembayaran
|
||||
_buildIncomeRow(
|
||||
'Estimasi pembayaran',
|
||||
estimatedEarnings,
|
||||
Colors.orange,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
|
||||
// Biaya jasa aplikasi
|
||||
_buildIncomeRow(
|
||||
'Biaya jasa aplikasi',
|
||||
applicationFee,
|
||||
Colors.orange,
|
||||
showInfo: true,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
|
||||
// Estimasi pendapatan
|
||||
_buildIncomeRow(
|
||||
'Estimasi pendapatan',
|
||||
estimatedIncome,
|
||||
Colors.orange,
|
||||
isBold: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Bottom Continue Button
|
||||
Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha:0.2),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, -2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: selectedItems.isNotEmpty ? () {
|
||||
// Handle continue action
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Lanjut ke proses selanjutnya'),
|
||||
),
|
||||
);
|
||||
} : null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: selectedItems.isNotEmpty ? Colors.blue : Colors.grey,
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Lanjut',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIncomeRow(String title, int amount, Color color, {bool showInfo = false, bool isBold = false}) {
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.currency_exchange,
|
||||
color: Colors.white,
|
||||
size: 12,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: isBold ? FontWeight.w600 : FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
if (showInfo) ...[
|
||||
SizedBox(width: 4),
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
color: Colors.blue,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
amount.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: isBold ? FontWeight.w600 : FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,501 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:rijig_mobile/core/router.dart';
|
||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||
|
||||
class TestRequestPickScreen extends StatefulWidget {
|
||||
const TestRequestPickScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TestRequestPickScreen> createState() => _TestRequestPickScreenState();
|
||||
}
|
||||
|
||||
class _TestRequestPickScreenState extends State<TestRequestPickScreen> {
|
||||
// Map untuk menyimpan quantity setiap item
|
||||
Map<String, double> quantities = {
|
||||
'Plastik': 1.0,
|
||||
'Kertas Campur': 1.0,
|
||||
'Kaca': 0.0,
|
||||
'Minyak Jelantah': 0.0,
|
||||
'Kaleng Alumunium': 0.0,
|
||||
};
|
||||
|
||||
// Map untuk menyimpan harga per kg
|
||||
Map<String, int> prices = {
|
||||
'Plastik': 1000,
|
||||
'Kertas Campur': 700,
|
||||
'Kaca': 300,
|
||||
'Minyak Jelantah': 2500,
|
||||
'Kaleng Alumunium': 3500,
|
||||
};
|
||||
|
||||
// Map untuk menyimpan icon data
|
||||
Map<String, IconData> icons = {
|
||||
'Plastik': Icons.local_drink,
|
||||
'Kertas Campur': Icons.description,
|
||||
'Kaca': Icons.wine_bar,
|
||||
'Minyak Jelantah': Icons.opacity,
|
||||
'Kaleng Alumunium': Icons.recycling,
|
||||
};
|
||||
|
||||
// Map untuk menyimpan warna background
|
||||
Map<String, Color> backgroundColors = {
|
||||
'Plastik': Colors.blue.shade100,
|
||||
'Kertas Campur': Colors.orange.shade100,
|
||||
'Kaca': Colors.red.shade100,
|
||||
'Minyak Jelantah': Colors.orange.shade200,
|
||||
'Kaleng Alumunium': Colors.green.shade100,
|
||||
};
|
||||
|
||||
// Map untuk menyimpan warna icon
|
||||
Map<String, Color> iconColors = {
|
||||
'Plastik': Colors.blue,
|
||||
'Kertas Campur': Colors.orange,
|
||||
'Kaca': Colors.red,
|
||||
'Minyak Jelantah': Colors.orange.shade700,
|
||||
'Kaleng Alumunium': Colors.green,
|
||||
};
|
||||
|
||||
void _resetQuantity(String itemName) {
|
||||
setState(() {
|
||||
quantities[itemName] = 0.0;
|
||||
});
|
||||
}
|
||||
|
||||
void _incrementQuantity(String itemName) {
|
||||
setState(() {
|
||||
quantities[itemName] = (quantities[itemName]! + 2.5);
|
||||
});
|
||||
}
|
||||
|
||||
void _decrementQuantity(String itemName) {
|
||||
setState(() {
|
||||
if (quantities[itemName]! > 0) {
|
||||
quantities[itemName] = (quantities[itemName]! - 2.5).clamp(
|
||||
0.0,
|
||||
double.infinity,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _showQuantityDialog(String itemName) {
|
||||
TextEditingController controller = TextEditingController(
|
||||
text: quantities[itemName]!.toString(),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Input Jumlah $itemName'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Jumlah (kg)',
|
||||
border: OutlineInputBorder(),
|
||||
suffixText: 'kg',
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Batal'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
double? newQuantity = double.tryParse(controller.text);
|
||||
if (newQuantity != null && newQuantity >= 0) {
|
||||
setState(() {
|
||||
quantities[itemName] = newQuantity;
|
||||
});
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Masukkan angka yang valid')),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text('Simpan'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
double get totalWeight {
|
||||
return quantities.values.fold(0.0, (sum, quantity) => sum + quantity);
|
||||
}
|
||||
|
||||
int get totalPrice {
|
||||
int total = 0;
|
||||
quantities.forEach((item, quantity) {
|
||||
total += (prices[item]! * quantity).round();
|
||||
});
|
||||
return total;
|
||||
}
|
||||
|
||||
int get totalItems {
|
||||
return quantities.values.where((quantity) => quantity > 0).length;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade50,
|
||||
appBar: AppBar(
|
||||
backgroundColor: whiteColor,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: Colors.black),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(Icons.location_on, color: Colors.grey),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'Purbalingga',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
child: Text('Ganti', style: TextStyle(color: Colors.blue)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// Header
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(16),
|
||||
color: whiteColor,
|
||||
child: Text(
|
||||
'Pilih Sampah',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// List Items
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.all(16),
|
||||
itemCount: quantities.keys.length,
|
||||
itemBuilder: (context, index) {
|
||||
String itemName = quantities.keys.elementAt(index);
|
||||
double quantity = quantities[itemName]!;
|
||||
int price = prices[itemName]!;
|
||||
|
||||
return Container(
|
||||
margin: EdgeInsets.only(bottom: 12),
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: whiteColor,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha: 0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Icon
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColors[itemName],
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
),
|
||||
child: Icon(
|
||||
icons[itemName],
|
||||
color: iconColors[itemName],
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
|
||||
// Item info
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
itemName,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
'Rp $price/kg',
|
||||
style: TextStyle(
|
||||
color: whiteColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Show delete icon when quantity > 0 (below price)
|
||||
SizedBox(height: 4),
|
||||
SizedBox(
|
||||
height: 24, // Fixed height untuk consistency
|
||||
child:
|
||||
quantity > 0
|
||||
? GestureDetector(
|
||||
onTap: () => _resetQuantity(itemName),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.shade50,
|
||||
borderRadius: BorderRadius.circular(
|
||||
4,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.delete_outline,
|
||||
color: Colors.red,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox(), // Empty space when no quantity
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Quantity controls or Add button
|
||||
quantity > 0
|
||||
? Row(
|
||||
children: [
|
||||
// Decrease button
|
||||
GestureDetector(
|
||||
onTap: () => _decrementQuantity(itemName),
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.shade50,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.remove,
|
||||
color: Colors.red,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
|
||||
// Quantity display (clickable)
|
||||
GestureDetector(
|
||||
onTap: () => _showQuantityDialog(itemName),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.grey.shade300,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'${quantity.toString().replaceAll('.0', '')} kg',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
|
||||
// Increase button
|
||||
GestureDetector(
|
||||
onTap: () => _incrementQuantity(itemName),
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.blue,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
// Add button when quantity is 0
|
||||
GestureDetector(
|
||||
onTap: () => _incrementQuantity(itemName),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'Tambah',
|
||||
style: TextStyle(
|
||||
color: whiteColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// Bottom summary
|
||||
Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: whiteColor,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha: 0.2),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, -2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'$totalItems jenis ${totalWeight.toString().replaceAll('.0', '')} kg',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'Est. ',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'Rp ${totalPrice.toString()}',
|
||||
style: TextStyle(
|
||||
color: whiteColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
'Minimum total berat 3kg',
|
||||
style: TextStyle(fontSize: 12, color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
ElevatedButton(
|
||||
onPressed:
|
||||
totalWeight >= 3
|
||||
? () {
|
||||
// Handle continue action
|
||||
router.push('/ordersumary');
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text('Lanjut ke proses selanjutnya'),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
: null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
totalWeight >= 3 ? Colors.blue : Colors.grey,
|
||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Lanjut',
|
||||
style: TextStyle(
|
||||
color: whiteColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -71,10 +71,14 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Icon(
|
||||
IconButton(onPressed: ()=>router.push('/trashview'), icon: Icon(
|
||||
Iconsax.notification_copy,
|
||||
color: primaryColor,
|
||||
),
|
||||
),),
|
||||
// Icon(
|
||||
// Iconsax.notification_copy,
|
||||
// color: primaryColor,
|
||||
// ),
|
||||
Gap(10),
|
||||
Icon(Iconsax.message_copy, color: primaryColor),
|
||||
],
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:rijig_mobile/core/router.dart';
|
||||
import 'dart:math';
|
||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||
import 'package:rijig_mobile/widget/appbar.dart';
|
||||
|
@ -66,17 +68,17 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
|
|||
backgroundColor: greyAbsolutColor,
|
||||
child: Icon(Icons.person, color: whiteColor, size: 30),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Gap(12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(collector.name, style: Tulisan.subheading()),
|
||||
const SizedBox(height: 4),
|
||||
Gap(4),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.star, color: Colors.amber, size: 18),
|
||||
const SizedBox(width: 4),
|
||||
Gap(4),
|
||||
Text(
|
||||
collector.rating.toStringAsFixed(1),
|
||||
style: Tulisan.body(fontsize: 12),
|
||||
|
@ -88,11 +90,11 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Gap(16),
|
||||
Text("Alamat:", style: Tulisan.body(fontsize: 13)),
|
||||
const SizedBox(height: 6),
|
||||
Gap(6),
|
||||
Text(collector.address, style: Tulisan.body(fontsize: 13)),
|
||||
const SizedBox(height: 24),
|
||||
Gap(24),
|
||||
CardButtonOne(
|
||||
textButton: "Pilih",
|
||||
fontSized: 14,
|
||||
|
@ -102,7 +104,7 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
|
|||
horizontal: double.infinity,
|
||||
vertical: 45,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
router.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
behavior: SnackBarBehavior.floating,
|
||||
|
|
|
@ -374,6 +374,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_slidable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_slidable
|
||||
sha256: ab7dbb16f783307c9d7762ede2593ce32c220ba2ba0fd540a3db8e9a3acba71a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -26,6 +26,7 @@ dependencies:
|
|||
flutter_map: ^8.1.1
|
||||
flutter_screenutil: ^5.9.3
|
||||
flutter_secure_storage: ^9.2.4
|
||||
flutter_slidable: ^4.0.0
|
||||
flutter_svg: ^2.1.0
|
||||
gap: ^3.0.1
|
||||
geolocator: ^14.0.0
|
||||
|
|
Loading…
Reference in New Issue