feat
This commit is contained in:
parent
31bbcabf16
commit
c214fdaa8a
|
|
@ -1,12 +1,9 @@
|
||||||
import 'package:rijig_mobile/core/utils/exportimportview.dart';
|
import 'package:rijig_mobile/core/utils/exportimportview.dart';
|
||||||
import 'package:rijig_mobile/features/auth/presentation/screen/collector/clogin_screen.dart';
|
import 'package:rijig_mobile/features/home/presentation/screen/collector/pickup_history_screen.dart';
|
||||||
import 'package:rijig_mobile/features/auth/presentation/screen/collector/identity_validation_screen.dart';
|
|
||||||
import 'package:rijig_mobile/features/auth/presentation/screen/collector/welcome_collector_screen.dart';
|
|
||||||
|
|
||||||
final router = GoRouter(
|
final router = GoRouter(
|
||||||
routes: [
|
routes: [
|
||||||
// GoRoute(path: '/', builder: (context, state) => SplashScreen()),
|
GoRoute(path: '/', builder: (context, state) => SplashScreen()),
|
||||||
GoRoute(path: '/', builder: (context, state) => UploadKtpScreen()),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/onboarding',
|
path: '/onboarding',
|
||||||
builder: (context, state) => OnboardingPageScreen(),
|
builder: (context, state) => OnboardingPageScreen(),
|
||||||
|
|
@ -14,6 +11,9 @@ final router = GoRouter(
|
||||||
GoRoute(path: '/login', builder: (context, state) => LoginScreen()),
|
GoRoute(path: '/login', builder: (context, state) => LoginScreen()),
|
||||||
GoRoute(path: '/clogin', builder: (context, state) => CloginScreen()),
|
GoRoute(path: '/clogin', builder: (context, state) => CloginScreen()),
|
||||||
GoRoute(path: '/welcomec', builder: (context, state) => WelcomeCollectorScreen()),
|
GoRoute(path: '/welcomec', builder: (context, state) => WelcomeCollectorScreen()),
|
||||||
|
GoRoute(path: '/verifidentity', builder: (context, state) => UploadKtpScreen()),
|
||||||
|
GoRoute(path: '/berandapengepul', builder: (context, state) => ChomeCollectorScreen()),
|
||||||
|
GoRoute(path: '/cpickuphistory', builder: (context, state) => PickupHistoryScreen()),
|
||||||
|
|
||||||
// Rute untuk verifikasi OTP dengan ekstraksi data dari path
|
// Rute untuk verifikasi OTP dengan ekstraksi data dari path
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|
@ -23,6 +23,13 @@ final router = GoRouter(
|
||||||
return VerifOtpScreen(phoneNumber: phoneNumber);
|
return VerifOtpScreen(phoneNumber: phoneNumber);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/cverif-otp',
|
||||||
|
builder: (context, state) {
|
||||||
|
// dynamic phoneNumber = state.extra;
|
||||||
|
return CverifOtpScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
// GoRoute(path: '/setpin', builder: (context, state) => InputPinScreen()),
|
// GoRoute(path: '/setpin', builder: (context, state) => InputPinScreen()),
|
||||||
// GoRoute(path: '/verifpin', builder: (context, state) => VerifPinScreen()),
|
// GoRoute(path: '/verifpin', builder: (context, state) => VerifPinScreen()),
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,8 @@ export 'package:rijig_mobile/features/home/presentation/components/about_detail_
|
||||||
export 'package:rijig_mobile/features/home/presentation/components/article_content.dart';
|
export 'package:rijig_mobile/features/home/presentation/components/article_content.dart';
|
||||||
export 'package:rijig_mobile/features/pickup/presentation/screen/pickup_screen.dart';
|
export 'package:rijig_mobile/features/pickup/presentation/screen/pickup_screen.dart';
|
||||||
export 'package:rijig_mobile/features/pickup/presentation/screen/selectcollector_screen.dart';
|
export 'package:rijig_mobile/features/pickup/presentation/screen/selectcollector_screen.dart';
|
||||||
|
export 'package:rijig_mobile/features/auth/presentation/screen/collector/clogin_screen.dart';
|
||||||
|
export 'package:rijig_mobile/features/auth/presentation/screen/collector/identity_validation_screen.dart';
|
||||||
|
export 'package:rijig_mobile/features/auth/presentation/screen/collector/welcome_collector_screen.dart';
|
||||||
|
export 'package:rijig_mobile/features/home/presentation/screen/collector/chome_screen.dart';
|
||||||
|
export 'package:rijig_mobile/features/auth/presentation/screen/collector/cotp_screen.dart';
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,6 @@ class _CloginScreenState extends State<CloginScreen> {
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
CardButtonOne(
|
CardButtonOne(
|
||||||
textButton: "Kirim OTP",
|
textButton: "Kirim OTP",
|
||||||
// viewModel.isLoading
|
|
||||||
// ? 'Sending OTP...'
|
|
||||||
// : 'Send OTP',
|
|
||||||
fontSized: 16.sp,
|
fontSized: 16.sp,
|
||||||
colorText: whiteColor,
|
colorText: whiteColor,
|
||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
|
|
@ -68,20 +65,9 @@ class _CloginScreenState extends State<CloginScreen> {
|
||||||
horizontal: double.infinity,
|
horizontal: double.infinity,
|
||||||
vertical: 50,
|
vertical: 50,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// if (cPhoneController.text.isNotEmpty) {
|
router.go('/cverif-otp');
|
||||||
// debugPrint("send otp dipencet");
|
|
||||||
// await viewModel.loginOrRegister(
|
|
||||||
// cPhoneController.text,
|
|
||||||
// );
|
|
||||||
// if (viewModel.loginResponse != null) {
|
|
||||||
// router.go(
|
|
||||||
// "/verif-otp",
|
|
||||||
// extra: cPhoneController.text,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
// loadingTrue: viewModel.isLoading,
|
|
||||||
usingRow: false,
|
usingRow: false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -105,6 +91,5 @@ class _CloginScreenState extends State<CloginScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// return const Placeholder();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||||
|
import 'package:rijig_mobile/core/router.dart';
|
||||||
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
|
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||||
|
|
||||||
|
class CverifOtpScreen extends StatefulWidget {
|
||||||
|
const CverifOtpScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CverifOtpScreen> createState() => _CotpScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CotpScreenState extends State<CverifOtpScreen> {
|
||||||
|
final TextEditingController _cOtpController = TextEditingController();
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: PaddingCustom().paddingHorizontalVertical(15, 40),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text("OTP has been sent to 6287874527xxxx"),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
PinCodeTextField(
|
||||||
|
controller: _cOtpController,
|
||||||
|
appContext: context,
|
||||||
|
length: 4,
|
||||||
|
obscureText: false,
|
||||||
|
animationType: AnimationType.fade,
|
||||||
|
pinTheme: PinTheme(
|
||||||
|
shape: PinCodeFieldShape.box,
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
fieldHeight: 50,
|
||||||
|
fieldWidth: 50,
|
||||||
|
activeFillColor: whiteColor,
|
||||||
|
inactiveFillColor: whiteColor,
|
||||||
|
selectedFillColor: whiteColor,
|
||||||
|
activeColor: blackNavyColor,
|
||||||
|
inactiveColor: blackNavyColor,
|
||||||
|
selectedColor: primaryColor,
|
||||||
|
),
|
||||||
|
onChanged: (value) {},
|
||||||
|
onCompleted: (value) {},
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
|
||||||
|
CardButtonOne(
|
||||||
|
textButton: "lanjut",
|
||||||
|
|
||||||
|
fontSized: 16.sp,
|
||||||
|
colorText: whiteColor,
|
||||||
|
color: primaryColor,
|
||||||
|
borderRadius: 10,
|
||||||
|
horizontal: double.infinity,
|
||||||
|
vertical: 50,
|
||||||
|
onTap: () {
|
||||||
|
router.go("/verifidentity");
|
||||||
|
},
|
||||||
|
|
||||||
|
usingRow: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:rijig_mobile/core/router.dart';
|
||||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
import 'package:rijig_mobile/widget/buttoncard.dart';
|
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||||
|
|
||||||
|
|
@ -167,6 +168,7 @@ class _UploadKtpScreenState extends State<UploadKtpScreen> {
|
||||||
controller: controllers[key],
|
controller: controllers[key],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextButton(onPressed: ()=> router.go("/berandapengepul"), child: Text("ke home collector"))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class _WelcomeSeekJobScreenState extends State<WelcomeCollectorScreen> {
|
||||||
horizontal: double.infinity,
|
horizontal: double.infinity,
|
||||||
vertical: 50,
|
vertical: 50,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
router.go("/clogin");
|
router.push("/clogin");
|
||||||
},
|
},
|
||||||
usingRow: false,
|
usingRow: false,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ class LoginScreenState extends State<LoginScreen> {
|
||||||
SizedBox(height: mediaQuery.size.height * 0.2),
|
SizedBox(height: mediaQuery.size.height * 0.2),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
// Image.asset(
|
||||||
'assets/image/security.png',
|
// 'assets/image/security.png',
|
||||||
width: mediaQuery.size.width * 0.35,
|
// width: mediaQuery.size.width * 0.35,
|
||||||
),
|
// ),
|
||||||
FormFieldOne(
|
FormFieldOne(
|
||||||
controllers: phoneController,
|
controllers: phoneController,
|
||||||
hintText: 'Masukkan nomor whatsapp anda!',
|
hintText: 'Masukkan nomor whatsapp anda!',
|
||||||
|
|
@ -99,11 +99,16 @@ class LoginScreenState extends State<LoginScreen> {
|
||||||
children: [
|
children: [
|
||||||
Text("login sebagai:"),
|
Text("login sebagai:"),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => router.go('/welcomec'),
|
onPressed: () => router.push('/welcomec'),
|
||||||
child: Text("pengepul?"),
|
child: Text("pengepul?"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Gap(20),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => router.push('/navigasi'),
|
||||||
|
child: Text("skip login"),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
|
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||||
|
|
||||||
|
class CollectorRequestList extends StatelessWidget {
|
||||||
|
final List<Map<String, dynamic>> allRequests = List.generate(
|
||||||
|
5,
|
||||||
|
(index) => {
|
||||||
|
"name": "Nama ${index + 1}",
|
||||||
|
"phone": "62${81300000000 + index}",
|
||||||
|
"request_trash": [
|
||||||
|
{"trash_name": "Botol Plastik", "amoun_weight": 12 + index},
|
||||||
|
{"trash_name": "Kardus", "amoun_weight": 15 + index},
|
||||||
|
],
|
||||||
|
"address": "Desa Banyuwangi ${index + 1}",
|
||||||
|
"distance_from_you": 12.0 - index,
|
||||||
|
"requestedAt": "${9 + index}:${(index + 1) * 5}".padLeft(2, '0'),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final Map<String, dynamic> myRequest = {
|
||||||
|
"name": "Andi Wijaya",
|
||||||
|
"phone": "6281399991234",
|
||||||
|
"request_trash": [
|
||||||
|
{"trash_name": "Kertas", "amoun_weight": 8},
|
||||||
|
],
|
||||||
|
"address": "Desa Sumberagung",
|
||||||
|
"distance_from_you": 13.7,
|
||||||
|
"requestedAt": "10:15",
|
||||||
|
};
|
||||||
|
|
||||||
|
CollectorRequestList({super.key});
|
||||||
|
|
||||||
|
Widget _buildRequestCard(BuildContext context, Map<String, dynamic> data) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => _showRequestDetailDialog(context, data),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: whiteColor,
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(data['name'], style: Tulisan.subheading()),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text("Telp: ${data['phone']}", style: Tulisan.body(fontsize: 12)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
"Alamat: ${data['address']}",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
"Jarak: ${data['distance_from_you'].toStringAsFixed(1)} km",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
"Waktu Permintaan: ${data['requestedAt']}",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text("Detail Sampah:", style: Tulisan.body(fontsize: 13)),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
...List.generate((data['request_trash'] as List).length, (i) {
|
||||||
|
final trash = data['request_trash'][i];
|
||||||
|
return Text(
|
||||||
|
"• ${trash['trash_name']} - ${trash['amoun_weight']} kg",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showRequestDetailDialog(
|
||||||
|
BuildContext context,
|
||||||
|
Map<String, dynamic> data,
|
||||||
|
) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return Dialog(
|
||||||
|
backgroundColor: whiteColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(data['name'], style: Tulisan.subheading()),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
"Telp: ${data['phone']}",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
"Alamat: ${data['address']}",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
"Jarak: ${data['distance_from_you'].toStringAsFixed(1)} km",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
"Waktu Permintaan: ${data['requestedAt']}",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text("Detail Sampah:", style: Tulisan.body(fontsize: 13)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
...List.generate((data['request_trash'] as List).length, (i) {
|
||||||
|
final trash = data['request_trash'][i];
|
||||||
|
return Text(
|
||||||
|
"• ${trash['trash_name']} - ${trash['amoun_weight']} kg",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
CardButtonOne(
|
||||||
|
textButton: "Konfirmasi",
|
||||||
|
fontSized: 14,
|
||||||
|
colorText: whiteColor,
|
||||||
|
color: primaryColor,
|
||||||
|
borderRadius: 8,
|
||||||
|
horizontal: double.infinity,
|
||||||
|
vertical: 45,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text("Pickup dikonfirmasi")),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
usingRow: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TabBarView(
|
||||||
|
children: [
|
||||||
|
ListView.builder(
|
||||||
|
itemCount: allRequests.length,
|
||||||
|
itemBuilder:
|
||||||
|
(context, index) =>
|
||||||
|
_buildRequestCard(context, allRequests[index]),
|
||||||
|
),
|
||||||
|
ListView(children: [_buildRequestCard(context, myRequest)]),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:iconsax_flutter/iconsax_flutter.dart';
|
||||||
|
import 'package:rijig_mobile/core/router.dart';
|
||||||
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
|
import 'package:rijig_mobile/features/home/model/c_request_list_dummymodel.dart';
|
||||||
|
import 'package:rijig_mobile/widget/tabbar_custom.dart';
|
||||||
|
|
||||||
|
class ChomeCollectorScreen extends StatefulWidget {
|
||||||
|
const ChomeCollectorScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChomeCollectorScreen> createState() => _ChomeCollectorScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChomeCollectorScreenState extends State<ChomeCollectorScreen> {
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
backgroundColor: whiteColor,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: primaryColor,
|
||||||
|
title: Text('Request', style: Tulisan.subheading(color: whiteColor)),
|
||||||
|
centerTitle: true,
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(Icons.menu, color: whiteColor, size: 30),
|
||||||
|
onPressed: () {
|
||||||
|
_scaffoldKey.currentState?.openDrawer();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
bottom: PreferredSize(
|
||||||
|
preferredSize: const Size.fromHeight(70),
|
||||||
|
child: ClipRRect(
|
||||||
|
child: Container(
|
||||||
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: BoxDecoration(color: Colors.green.shade100),
|
||||||
|
child: TabBar(
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
indicator: BoxDecoration(
|
||||||
|
color: primaryColor,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: secondaryColor,
|
||||||
|
width: 2.6,
|
||||||
|
style: BorderStyle.solid,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
labelColor: whiteColor,
|
||||||
|
unselectedLabelColor: Colors.black54,
|
||||||
|
tabs: [
|
||||||
|
TabItem(title: 'All Request', count: 6),
|
||||||
|
TabItem(title: 'Request to You', count: 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
drawer: Drawer(
|
||||||
|
backgroundColor: whiteColor,
|
||||||
|
width: MediaQuery.of(context).size.width / 1.7,
|
||||||
|
child: ListView(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
DrawerHeader(
|
||||||
|
decoration: BoxDecoration(color: primaryColor),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const CircleAvatar(
|
||||||
|
radius: 28,
|
||||||
|
backgroundImage: AssetImage('assets/image/Go_Ride.png'),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Nama User',
|
||||||
|
style: Tulisan.body(color: Colors.white),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Status: Active',
|
||||||
|
style: Tulisan.body(
|
||||||
|
color: Colors.white70,
|
||||||
|
fontsize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Iconsax.user),
|
||||||
|
title: Text('Profil', style: Tulisan.customText(fontsize: 16)),
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Iconsax.document_1),
|
||||||
|
title: Text(
|
||||||
|
'Riwayat Pickup',
|
||||||
|
style: Tulisan.customText(fontsize: 16),
|
||||||
|
),
|
||||||
|
onTap: () => router.push('/cpickuphistory'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Iconsax.setting_2),
|
||||||
|
title: Text(
|
||||||
|
'Pengaturan',
|
||||||
|
style: Tulisan.customText(fontsize: 16),
|
||||||
|
),
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Iconsax.logout, color: redColor),
|
||||||
|
title: Text(
|
||||||
|
'Keluar',
|
||||||
|
style: Tulisan.customText(color: redColor, fontsize: 16),
|
||||||
|
),
|
||||||
|
onTap: () => router.go('/login'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: CollectorRequestList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
|
import 'package:rijig_mobile/widget/appbar.dart';
|
||||||
|
|
||||||
|
class PickupHistoryScreen extends StatelessWidget {
|
||||||
|
final List<Map<String, dynamic>> weeklyData = [
|
||||||
|
{"label": "Mon", "amount": 200000, "orders": 10},
|
||||||
|
{"label": "Tue", "amount": 0, "orders": 0},
|
||||||
|
{"label": "Wed", "amount": 100000, "orders": 7},
|
||||||
|
{"label": "Thu", "amount": 0, "orders": 0},
|
||||||
|
{"label": "Fri", "amount": 140000, "orders": 13},
|
||||||
|
{"label": "Sat", "amount": 50000, "orders": 5},
|
||||||
|
{"label": "Sun", "amount": 210000, "orders": 15},
|
||||||
|
];
|
||||||
|
|
||||||
|
PickupHistoryScreen({super.key});
|
||||||
|
|
||||||
|
Widget _dateRangeTab(String label, bool isActive) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 6),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isActive ? primaryColor : greyColor,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: isActive ? Colors.white : Colors.black87,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final totalIncome = weeklyData.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, d) => sum + (d['amount'] as int),
|
||||||
|
);
|
||||||
|
final totalOrders = weeklyData.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, d) => sum + (d['orders'] as int),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: CustomAppBar(judul: "Riwayat Pickup"),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Center(child: Text("Day", style: Tulisan.body())),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text("Week", style: Tulisan.body(color: redColor)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
children: [
|
||||||
|
_dateRangeTab("Oct\n5 - 11", false),
|
||||||
|
_dateRangeTab("Oct\n12 - 18", false),
|
||||||
|
_dateRangeTab("Oct\n19 - 25", false),
|
||||||
|
_dateRangeTab("Oct - Nov\n26 - 1", true),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
Center(
|
||||||
|
child: Text("Total Income", style: Tulisan.body(fontsize: 14)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Center(child: Text("Rp$totalIncome", style: Tulisan.heading())),
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
"$totalOrders Orders Completed",
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Text("Income Trend", style: Tulisan.subheading()),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: BarChart(
|
||||||
|
BarChartData(
|
||||||
|
alignment: BarChartAlignment.spaceAround,
|
||||||
|
maxY: 250000,
|
||||||
|
barTouchData: BarTouchData(enabled: true),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
getTitlesWidget: (value, _) {
|
||||||
|
final label = weeklyData[value.toInt()]["label"];
|
||||||
|
return Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(fontSize: 10),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leftTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 30,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderData: FlBorderData(show: false),
|
||||||
|
barGroups:
|
||||||
|
weeklyData
|
||||||
|
.asMap()
|
||||||
|
.map(
|
||||||
|
(index, data) => MapEntry(
|
||||||
|
index,
|
||||||
|
BarChartGroupData(
|
||||||
|
x: index,
|
||||||
|
barRods: [
|
||||||
|
BarChartRodData(
|
||||||
|
toY: data["amount"].toDouble(),
|
||||||
|
width: 16,
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
color: primaryColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.values
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||||
import 'package:rijig_mobile/widget/appbar.dart';
|
import 'package:rijig_mobile/widget/appbar.dart';
|
||||||
|
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||||
|
|
||||||
class Collector {
|
class Collector {
|
||||||
final String name;
|
final String name;
|
||||||
|
|
@ -44,6 +45,82 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
void _showCollectorDialog(Collector collector) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
radius: 30,
|
||||||
|
backgroundColor: greyAbsolutColor,
|
||||||
|
child: Icon(Icons.person, color: whiteColor, size: 30),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(collector.name, style: Tulisan.subheading()),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.star, color: Colors.amber, size: 18),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
collector.rating.toStringAsFixed(1),
|
||||||
|
style: Tulisan.body(fontsize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text("Alamat:", style: Tulisan.body(fontsize: 13)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(collector.address, style: Tulisan.body(fontsize: 13)),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
CardButtonOne(
|
||||||
|
textButton: "Pilih",
|
||||||
|
fontSized: 14,
|
||||||
|
colorText: whiteColor,
|
||||||
|
color: primaryColor,
|
||||||
|
borderRadius: 8,
|
||||||
|
horizontal: double.infinity,
|
||||||
|
vertical: 45,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
"${collector.name} dipilih sebagai pengepul.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
usingRow: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -57,54 +134,65 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
|
||||||
separatorBuilder: (_, __) => GapCustom().gapValue(10, true),
|
separatorBuilder: (_, __) => GapCustom().gapValue(10, true),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final collector = collectors[index];
|
final collector = collectors[index];
|
||||||
return Card(
|
return GestureDetector(
|
||||||
shadowColor: Colors.transparent,
|
onTap: () => _showCollectorDialog(collector),
|
||||||
color: whiteColor,
|
child: Card(
|
||||||
shape: RoundedRectangleBorder(
|
shadowColor: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(8),
|
color: whiteColor,
|
||||||
side: BorderSide(width: 1, color: greyColor),
|
shape: RoundedRectangleBorder(
|
||||||
),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Padding(
|
side: BorderSide(width: 1, color: greyColor),
|
||||||
padding: PaddingCustom().paddingAll(16),
|
),
|
||||||
child: Row(
|
child: Padding(
|
||||||
children: [
|
padding: PaddingCustom().paddingAll(16),
|
||||||
CircleAvatar(
|
child: Row(
|
||||||
radius: 28,
|
children: [
|
||||||
backgroundColor: greyAbsolutColor,
|
CircleAvatar(
|
||||||
child: Icon(Icons.person, color: whiteColor, size: 28),
|
radius: 28,
|
||||||
),
|
backgroundColor: greyAbsolutColor,
|
||||||
GapCustom().gapValue(16, false),
|
child: Icon(
|
||||||
Expanded(
|
Icons.person,
|
||||||
child: Column(
|
color: whiteColor,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
size: 28,
|
||||||
children: [
|
),
|
||||||
Text(
|
|
||||||
collector.name,
|
|
||||||
style: Tulisan.subheading(fontsize: 16),
|
|
||||||
),
|
|
||||||
GapCustom().gapValue(5, true),
|
|
||||||
Text(
|
|
||||||
collector.address,
|
|
||||||
style: TextStyle(
|
|
||||||
color: greyAbsolutColor,
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GapCustom().gapValue(5, true),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.star, color: Colors.amber, size: 18),
|
|
||||||
GapCustom().gapValue(5, false),
|
|
||||||
Text(
|
|
||||||
collector.rating.toStringAsFixed(1),
|
|
||||||
style: Tulisan.customText(fontsize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
GapCustom().gapValue(16, false),
|
||||||
],
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
collector.name,
|
||||||
|
style: Tulisan.subheading(fontsize: 16),
|
||||||
|
),
|
||||||
|
GapCustom().gapValue(5, true),
|
||||||
|
Text(
|
||||||
|
collector.address,
|
||||||
|
style: TextStyle(
|
||||||
|
color: greyAbsolutColor,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GapCustom().gapValue(5, true),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.star,
|
||||||
|
color: Colors.amber,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
GapCustom().gapValue(5, false),
|
||||||
|
Text(
|
||||||
|
collector.rating.toStringAsFixed(1),
|
||||||
|
style: Tulisan.customText(fontsize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
10
pubspec.lock
10
pubspec.lock
|
|
@ -233,6 +233,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
fl_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fl_chart
|
||||||
|
sha256: "577aeac8ca414c25333334d7c4bb246775234c0e44b38b10a82b559dd4d764e7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -991,4 +999,4 @@ packages:
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.2 <4.0.0"
|
dart: ">=3.7.2 <4.0.0"
|
||||||
flutter: ">=3.27.0"
|
flutter: ">=3.27.4"
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ dependencies:
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
custom_refresh_indicator: ^4.0.1
|
custom_refresh_indicator: ^4.0.1
|
||||||
device_info_plus: ^11.4.0
|
device_info_plus: ^11.4.0
|
||||||
|
fl_chart: ^1.0.0
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_carousel_widget: ^3.1.0
|
flutter_carousel_widget: ^3.1.0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue