This commit is contained in:
pahmiudahgede 2025-05-23 11:15:25 +07:00
parent 31bbcabf16
commit c214fdaa8a
13 changed files with 723 additions and 76 deletions

View File

@ -1,12 +1,9 @@
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/auth/presentation/screen/collector/identity_validation_screen.dart';
import 'package:rijig_mobile/features/auth/presentation/screen/collector/welcome_collector_screen.dart';
import 'package:rijig_mobile/features/home/presentation/screen/collector/pickup_history_screen.dart';
final router = GoRouter(
routes: [
// GoRoute(path: '/', builder: (context, state) => SplashScreen()),
GoRoute(path: '/', builder: (context, state) => UploadKtpScreen()),
GoRoute(path: '/', builder: (context, state) => SplashScreen()),
GoRoute(
path: '/onboarding',
builder: (context, state) => OnboardingPageScreen(),
@ -14,6 +11,9 @@ final router = GoRouter(
GoRoute(path: '/login', builder: (context, state) => LoginScreen()),
GoRoute(path: '/clogin', builder: (context, state) => CloginScreen()),
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
GoRoute(
@ -23,6 +23,13 @@ final router = GoRouter(
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: '/verifpin', builder: (context, state) => VerifPinScreen()),

View File

@ -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/pickup/presentation/screen/pickup_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';

View File

@ -58,9 +58,6 @@ class _CloginScreenState extends State<CloginScreen> {
SizedBox(height: 20),
CardButtonOne(
textButton: "Kirim OTP",
// viewModel.isLoading
// ? 'Sending OTP...'
// : 'Send OTP',
fontSized: 16.sp,
colorText: whiteColor,
color: primaryColor,
@ -68,20 +65,9 @@ class _CloginScreenState extends State<CloginScreen> {
horizontal: double.infinity,
vertical: 50,
onTap: () {
// if (cPhoneController.text.isNotEmpty) {
// debugPrint("send otp dipencet");
// await viewModel.loginOrRegister(
// cPhoneController.text,
// );
// if (viewModel.loginResponse != null) {
// router.go(
// "/verif-otp",
// extra: cPhoneController.text,
// );
// }
// }
router.go('/cverif-otp');
},
// loadingTrue: viewModel.isLoading,
usingRow: false,
),
],
@ -105,6 +91,5 @@ class _CloginScreenState extends State<CloginScreen> {
),
),
);
// return const Placeholder();
}
}

View File

@ -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,
),
],
),
),
),
),
);
}
}

View File

@ -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/image.dart' as img;
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/widget/buttoncard.dart';
@ -167,6 +168,7 @@ class _UploadKtpScreenState extends State<UploadKtpScreen> {
controller: controllers[key],
),
),
TextButton(onPressed: ()=> router.go("/berandapengepul"), child: Text("ke home collector"))
],
),
),

View File

@ -59,7 +59,7 @@ class _WelcomeSeekJobScreenState extends State<WelcomeCollectorScreen> {
horizontal: double.infinity,
vertical: 50,
onTap: () {
router.go("/clogin");
router.push("/clogin");
},
usingRow: false,
),

View File

@ -43,10 +43,10 @@ class LoginScreenState extends State<LoginScreen> {
SizedBox(height: mediaQuery.size.height * 0.2),
Column(
children: [
Image.asset(
'assets/image/security.png',
width: mediaQuery.size.width * 0.35,
),
// Image.asset(
// 'assets/image/security.png',
// width: mediaQuery.size.width * 0.35,
// ),
FormFieldOne(
controllers: phoneController,
hintText: 'Masukkan nomor whatsapp anda!',
@ -99,11 +99,16 @@ class LoginScreenState extends State<LoginScreen> {
children: [
Text("login sebagai:"),
TextButton(
onPressed: () => router.go('/welcomec'),
onPressed: () => router.push('/welcomec'),
child: Text("pengepul?"),
),
],
),
Gap(20),
TextButton(
onPressed: () => router.push('/navigasi'),
child: Text("skip login"),
),
],
),
],

View File

@ -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)]),
],
);
}
}

View File

@ -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(),
),
);
}
}

View File

@ -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(),
),
),
),
),
],
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'dart:math';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/widget/appbar.dart';
import 'package:rijig_mobile/widget/buttoncard.dart';
class Collector {
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
Widget build(BuildContext context) {
return Scaffold(
@ -57,54 +134,65 @@ class _SelectCollectorScreenState extends State<SelectCollectorScreen> {
separatorBuilder: (_, __) => GapCustom().gapValue(10, true),
itemBuilder: (context, index) {
final collector = collectors[index];
return Card(
shadowColor: Colors.transparent,
color: whiteColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(width: 1, color: greyColor),
),
child: Padding(
padding: PaddingCustom().paddingAll(16),
child: Row(
children: [
CircleAvatar(
radius: 28,
backgroundColor: greyAbsolutColor,
child: Icon(Icons.person, color: whiteColor, size: 28),
),
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),
),
],
),
],
return GestureDetector(
onTap: () => _showCollectorDialog(collector),
child: Card(
shadowColor: Colors.transparent,
color: whiteColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(width: 1, color: greyColor),
),
child: Padding(
padding: PaddingCustom().paddingAll(16),
child: Row(
children: [
CircleAvatar(
radius: 28,
backgroundColor: greyAbsolutColor,
child: Icon(
Icons.person,
color: whiteColor,
size: 28,
),
),
),
],
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),
),
],
),
],
),
),
],
),
),
),
);

View File

@ -233,6 +233,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct main"
description: flutter
@ -991,4 +999,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.7.2 <4.0.0"
flutter: ">=3.27.0"
flutter: ">=3.27.4"

View File

@ -15,6 +15,7 @@ dependencies:
cupertino_icons: ^1.0.8
custom_refresh_indicator: ^4.0.1
device_info_plus: ^11.4.0
fl_chart: ^1.0.0
flutter:
sdk: flutter
flutter_carousel_widget: ^3.1.0