Aidra Driver 1.3.5+68
Aidra Driver - Your path to green energy
Loading...
Searching...
No Matches
weekly_collections_screen.dart
Go to the documentation of this file.
1import 'package:easy_localization/easy_localization.dart';
2import 'package:flutter/material.dart';
3import 'package:flutter_bloc/flutter_bloc.dart';
4import 'package:flutter_screenutil/flutter_screenutil.dart';
5import 'package:go_router/go_router.dart';
6// import 'package:easy_localization/easy_localization.dart';
7
8import '../../../../../core/router/routes.dart';
9import '../../../../../core/ui/widgets/custom_scaffold.dart';
10import '../../../../../core/ui/widgets/custom_text_form_field.dart';
11import '../../../../../core/ui/widgets/custom_card.dart';
12import '../../../../../core/ui/widgets/error_widget.dart';
13import '../../../../../core/ui/widgets/empty_content.dart';
14import '../../../../../core/ui/widgets/loading.dart';
15import '../../../../../core/ui/theme/color_palette.dart';
16import '../../../domain/entities/res/res_weekly_collection_entity.dart';
17import '../../bloc/weekly_collections_bloc/weekly_collections_bloc.dart';
18import '../../bloc/planning_bloc/routing_planning_bloc.dart';
19import '../../bloc/collections_to_schedule_bloc/collections_to_schedule_bloc.dart';
20import '../../../../auth/presentation/bloc/authentication_bloc/authentication_bloc.dart';
21import '../../../domain/entities/req/req_create_driver_collection_entity.dart';
22
23class WeeklyCollectionsScreen extends StatefulWidget {
24 const WeeklyCollectionsScreen({super.key});
25
26 @override
27 State<WeeklyCollectionsScreen> createState() =>
28 _WeeklyCollectionsScreenState();
29}
30
31class _WeeklyCollectionsScreenState extends State<WeeklyCollectionsScreen> {
32 final TextEditingController _searchController = TextEditingController();
33
34 @override
35 void initState() {
36 super.initState();
38
39 _searchController.addListener(() {
40 context.read<WeeklyCollectionsBloc>().add(
41 SearchWeeklyCollectionsEvent(query: _searchController.text),
42 );
43 });
44 }
45
47 final authState = context.read<AuthenticationBloc>().state;
48 if (authState is AuthenticationInitialState) {
49 context.read<AuthenticationBloc>().add(LoadSessionEvent());
50 } else if (authState is AuthenticatedState) {
51 _loadWeeklyCollections(authState);
52 }
53 }
54
55 void _loadWeeklyCollections(AuthenticatedState authState) {
56 final weekDates = _getCurrentWeekDates();
57 context.read<WeeklyCollectionsBloc>().add(
59 userId: authState.session.uid ?? 0,
60 startDate: weekDates['startDate']!,
61 endDate: weekDates['endDate']!,
62 ),
63 );
64 }
65
66 Map<String, String> _getCurrentWeekDates() {
67 final now = DateTime.now();
68
69 // // Find the most recent Saturday (start of week)
70 // int daysSinceLastSaturday = (now.weekday + 1) % 7;
71 // final startDate = now.subtract(Duration(days: daysSinceLastSaturday));
72
73 // // Thursday is 5 days after Saturday
74 // final endDate = startDate.add(Duration(days: 5));
75
76 return {
77 'startDate': _formatDate(now),
78 'endDate': _formatDate(now),
79 };
80 }
81
83 return '${date.day.toString().padLeft(2, '0')}/${date.month.toString().padLeft(2, '0')}/${date.year}';
84 }
85
86 @override
87 void dispose() {
88 _searchController.dispose();
89 super.dispose();
90 }
91
92 @override
93 Widget build(BuildContext context) {
94 return BlocBuilder<CollectionsToScheduleBloc, CollectionsToScheduleState>(
95 builder: (context, collectionsState) {
96 final isLoading = collectionsState is CollectionsToScheduleLoading;
97
98 return CustomScaffold(
99 title: 'scheduling.weekly_collections'.tr(),
101 isBackButtonEnabled: !isLoading,
102 body: MultiBlocListener(
103 listeners: [
104 BlocListener<AuthenticationBloc, AuthenticationState>(
105 listener: (context, state) {
106 if (state is AuthenticatedState) {
108 }
109 },
110 ),
111 BlocListener<CollectionsToScheduleBloc, CollectionsToScheduleState>(
112 listener: (context, state) {
113 if (state is CollectionsToScheduleLoaded) {
114 // Set the retrieved collections to the routing planning bloc
115 context.read<RoutingPlanningBloc>().add(
116 SetCollectionsToScheduleEvent(collections: state.collections),
117 );
118 // Navigate to end location chooser
119 context.push(Routes.endLocationChooserScreen.route);
120 } else if (state is CollectionsToScheduleError) {
121 ScaffoldMessenger.of(context).showSnackBar(
122 SnackBar(content: Text(state.failure.message)),
123 );
124 }
125 },
126 ),
127 ],
128 child: Column(
129 children: [
131 SizedBox(height: 16.h),
133 SizedBox(height: 16.h),
134 Expanded(child: _buildCollectionsList()),
136 ],
137 ),
138 ),
139 );
140 },
141 );
142 }
143
145 return Padding(
146 padding: EdgeInsets.all(16.w),
147 child: CustomTextFormField(
148 controller: _searchController,
149 hintText: 'scheduling.search_placeholder'.tr(),
150 suffixIcon: Icon(Icons.search),
151 keyboardType: TextInputType.text,
152 ),
153 );
154 }
155
157 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
158 builder: (context, state) {
159 if (state is! WeeklyCollectionsLoaded) return SizedBox.shrink();
160
161 return Padding(
162 padding: EdgeInsets.symmetric(horizontal: 16.w),
163 child: Row(
164 mainAxisAlignment: MainAxisAlignment.spaceBetween,
165 children: [
166 Text(
167 '${state.selectedCollections.length} ${'scheduling.selected_collections'.tr()}',
168 style: Theme.of(context).textTheme.bodyMedium,
169 ),
170 TextButton(
171 onPressed: () {
172 context
173 .read<WeeklyCollectionsBloc>()
174 .add(ClearSelectionEvent());
175 },
176 child: Text('scheduling.clear'.tr()),
177 ),
178 ],
179 ),
180 );
181 },
182 );
183 }
184
186 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
187 builder: (context, state) {
188 if (state is WeeklyCollectionsLoading) {
189 return Loading();
190 }
191
192 if (state is WeeklyCollectionsError) {
193 return CustomErrorWidget(
194 message: state.failure.message,
195 onReload: () {
196 _initializeData();
197 },
198 );
199 }
200
201 if (state is WeeklyCollectionsLoaded) {
202 if (state.filteredCollections.isEmpty) {
203 return EmptyContent(
204 text: state.searchQuery.isNotEmpty
205 ? "${'scheduling.no_collections_found_for'.tr()} ${state.searchQuery}"
206 : 'scheduling.no_collections_available'.tr(),
207 );
208 }
209
210 return ListView.builder(
211 padding: EdgeInsets.symmetric(horizontal: 16.w),
212 itemCount: state.filteredCollections.length,
213 itemBuilder: (context, index) {
214 final collection = state.filteredCollections[index];
215 final isSelected = state.selectedCollections.contains(collection);
216
217 return _buildCollectionCard(collection, isSelected);
218 },
219 );
220 }
221
222 return SizedBox.shrink();
223 },
224 );
225 }
226
228 return Padding(
229 padding: EdgeInsets.only(bottom: 5.h),
231 bgColor:
232 isSelected ? ColorPalette.lightGreen.withValues(alpha: 0.1) : null,
233 child: InkWell(
234 onTap: () {
235 context.read<WeeklyCollectionsBloc>().add(
237 );
238 },
239 borderRadius: BorderRadius.circular(10),
240 child: Padding(
241 padding: EdgeInsets.all(12.w),
242 child: Row(
243 children: [
244 Checkbox(
245 value: isSelected,
246 onChanged: (value) {
247 context.read<WeeklyCollectionsBloc>().add(
250 );
251 },
252 activeColor: ColorPalette.lightGreen,
253 ),
254 SizedBox(width: 12.w),
255 Expanded(
256 child: Column(
257 crossAxisAlignment: CrossAxisAlignment.start,
258 children: [
259 Text(
260 collection.supplierName ?? '',
261 style:
262 Theme.of(context).textTheme.titleMedium?.copyWith(
263 fontWeight: FontWeight.bold,
264 fontSize: 13.sp,
265 ),
266 ),
267 SizedBox(height: 4.h),
268 Text(
269 '${'scheduling.city'.tr()}: ${collection.city}',
270 style: Theme.of(context).textTheme.bodyMedium,
271 ),
272 SizedBox(height: 2.h),
274 '${'scheduling.reference'.tr()}: ${collection.internalCode}',
275 style: Theme.of(context).textTheme.bodySmall,
276 ),
277 ],
278 ),
279 ),
281 crossAxisAlignment: CrossAxisAlignment.end,
282 children: [
283 Container(
284 padding:
285 EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
286 decoration: BoxDecoration(
287 color: ColorPalette.tiffanyBlue.withValues(alpha: 0.1),
288 borderRadius: BorderRadius.circular(12),
289 ),
290 child: Text(
291 collection.type ?? '',
292 style: Theme.of(context).textTheme.bodySmall?.copyWith(
294 fontWeight: FontWeight.bold,
295 ),
296 ),
297 ),
298 ],
299 ),
300 ],
301 ),
302 ),
303 ),
304 ),
305 );
306 }
307
309 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
310 builder: (context, weeklyState) {
311 return BlocBuilder<CollectionsToScheduleBloc, CollectionsToScheduleState>(
312 builder: (context, collectionsState) {
313 final canContinue = weeklyState is WeeklyCollectionsLoaded &&
314 weeklyState.selectedCollections.isNotEmpty;
315
316 final isLoading = collectionsState is CollectionsToScheduleLoading;
317
318 // Hide the button completely when loading
319 if (isLoading) {
320 return SizedBox.shrink();
321 }
322
323 return Container(
324 width: double.infinity,
325 padding: EdgeInsets.all(16.w),
326 child: ElevatedButton(
327 onPressed: canContinue ? _onContinuePressed : null,
328 style: ElevatedButton.styleFrom(
329 backgroundColor: ColorPalette.lightGreen,
330 foregroundColor: Colors.white,
331 padding: EdgeInsets.symmetric(vertical: 16.h),
332 shape: RoundedRectangleBorder(
333 borderRadius: BorderRadius.circular(10),
334 ),
335 ),
336 child: Text(
337 'scheduling.continue'.tr(),
338 style: Theme.of(context).textTheme.titleMedium?.copyWith(
339 color: Colors.white,
340 fontWeight: FontWeight.bold,
341 ),
342 ),
343 ),
344 );
345 },
346 );
347 },
348 );
349 }
350
352 final weeklyState = context.read<WeeklyCollectionsBloc>().state;
353 final authState = context.read<AuthenticationBloc>().state;
354
355 if (weeklyState is WeeklyCollectionsLoaded && authState is AuthenticatedState) {
356 // Create collection points from selected collections
357 final collectionPoints = weeklyState.selectedCollections
358 .map((collection) => CollectionPointEntity(id: (collection.id)?.toInt() ?? 0))
359 .toList();
360
361 final user = UserEntity(id: (authState.session.uid)?.toInt() ?? 0);
362
364 collectionPoints: collectionPoints,
365 user: user,
366 );
367
368 // Get date range for retrieving collections to schedule
369 final weekDates = _getCurrentWeekDates();
370
371 // Trigger the create driver collection and fetch collections to schedule workflow
372 context.read<CollectionsToScheduleBloc>().add(
375 startDate: weekDates['startDate']!,
376 endDate: weekDates['endDate']!,
377 driverId: (authState.session.uid)?.toInt() ?? 0,
378 ),
379 );
380 }
381 }
382}
override void initState()
override void dispose()
class App extends StatefulWidget build(BuildContext context)
Definition app.dart:31
sealed class CheckInOutEvent extends Equatable userId
bool isLoading
static const lightGreen
static const tiffanyBlue
const WeeklyCollectionsScreen({super.key})
override State< WeeklyCollectionsScreen > createState()
sealed class CollectionsState extends Equatable collections
const CreateDriverCollectionEvent({ required this.request, required this.startDate, required this.endDate, required this.driverId, })
abstract class CollectionsToScheduleEvent extends Equatable request
final String startDate
final String endDate
const CollectionsToScheduleLoaded({required this.collections})
const CustomCard({ super.key, required this.child, this.padding, this.bgColor, })
final Color bgColor
final Widget child
final EdgeInsets padding
class Partner String
final TextEditingController _searchController
final Color color
Definition failures.dart:1
final String message
Definition failures.dart:0
final String date
final VoidCallback onPressed
const CollectionPointEntity({ required this.id, })
Routes
Definition routes.dart:30
const SetCollectionsToScheduleEvent({required this.collections})
final VoidCallback onTap
final String title
class UnloadingCollectionItem extends StatefulWidget isSelected
class SearchWeeklyCollectionsEvent extends WeeklyCollectionsEvent collection
const ToggleCollectionSelectionEvent({required this.collection})
const LoadWeeklyCollectionsEvent({ required this.userId, required this.startDate, required this.endDate, })
Widget _buildSelectionActions()
Widget _buildCollectionCard(ResWeeklyCollectionEntity collection, bool isSelected)
style Text( '${ 'scheduling.reference'.tr()}:${collection.internalCode}', style:Theme.of(context).textTheme.bodySmall,)
String _formatDate(DateTime date)
style Widget _buildContinueButton()
style SizedBox(height:2.h)
Widget _buildCollectionsList()
void _loadWeeklyCollections(AuthenticatedState authState)
Map< String, String > _getCurrentWeekDates()
Widget _buildSearchField()
void _onContinuePressed()
void _initializeData()
style Column(crossAxisAlignment:CrossAxisAlignment.end, children:[Container(padding:EdgeInsets.symmetric(horizontal:8.w, vertical:4.h), decoration:BoxDecoration(color:ColorPalette.tiffanyBlue.withValues(alpha:0.1), borderRadius:BorderRadius.circular(12),), child:Text(collection.type ?? '', style:Theme.of(context).textTheme.bodySmall?.copyWith(color:ColorPalette.tiffanyBlue, fontWeight:FontWeight.bold,),),),],)
const WeeklyCollectionsLoaded({ required this.allCollections, required this.filteredCollections, required this.selectedCollections, this.searchQuery='', })