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';
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';
28 _WeeklyCollectionsScreenState();
31class _WeeklyCollectionsScreenState
extends State<WeeklyCollectionsScreen> {
40 context.read<WeeklyCollectionsBloc>().add(
47 final authState = context.read<AuthenticationBloc>().state;
48 if (authState is AuthenticationInitialState) {
49 context.read<AuthenticationBloc>().add(LoadSessionEvent());
50 }
else if (authState is AuthenticatedState) {
57 context.read<WeeklyCollectionsBloc>().add(
59 userId: authState.session.uid ?? 0,
67 final now = DateTime.now();
83 return '${date.day.toString().padLeft(2, '0
')}/${date.month.toString().padLeft(2, '0
')}/${date.year}';
93 Widget
build(BuildContext context) {
94 return BlocBuilder<CollectionsToScheduleBloc, CollectionsToScheduleState>(
95 builder: (context, collectionsState) {
96 final isLoading = collectionsState is CollectionsToScheduleLoading;
98 return CustomScaffold(
99 title:
'scheduling.weekly_collections'.tr(),
102 body: MultiBlocListener(
104 BlocListener<AuthenticationBloc, AuthenticationState>(
105 listener: (context, state) {
106 if (state is AuthenticatedState) {
111 BlocListener<CollectionsToScheduleBloc, CollectionsToScheduleState>(
112 listener: (context, state) {
115 context.read<RoutingPlanningBloc>().add(
119 context.push(
Routes.endLocationChooserScreen.route);
120 }
else if (state is CollectionsToScheduleError) {
121 ScaffoldMessenger.of(context).showSnackBar(
122 SnackBar(content:
Text(state.failure.message)),
147 child: CustomTextFormField(
149 hintText:
'scheduling.search_placeholder'.tr(),
150 suffixIcon: Icon(Icons.search),
151 keyboardType: TextInputType.text,
157 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
158 builder: (context, state) {
162 padding: EdgeInsets.symmetric(horizontal: 16.w),
164 mainAxisAlignment: MainAxisAlignment.spaceBetween,
167 '${state.selectedCollections.length} ${'scheduling.selected_collections
'.tr()}',
168 style: Theme.of(context).textTheme.bodyMedium,
173 .read<WeeklyCollectionsBloc>()
174 .add(ClearSelectionEvent());
186 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
187 builder: (context, state) {
188 if (state is WeeklyCollectionsLoading) {
192 if (state is WeeklyCollectionsError) {
193 return CustomErrorWidget(
194 message: state.failure.message,
202 if (state.filteredCollections.isEmpty) {
204 text: state.searchQuery.isNotEmpty
205 ?
"${'scheduling.no_collections_found_for'.tr()} ${state.searchQuery}"
206 :
'scheduling.no_collections_available'.tr(),
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);
217 return _buildCollectionCard(collection, isSelected);
229 padding: EdgeInsets.only(bottom: 5.h),
235 context.read<WeeklyCollectionsBloc>().add(
239 borderRadius: BorderRadius.circular(10),
247 context.read<WeeklyCollectionsBloc>().add(
257 crossAxisAlignment: CrossAxisAlignment.start,
262 Theme.of(context).textTheme.titleMedium?.copyWith(
263 fontWeight: FontWeight.bold,
269 '${'scheduling.city
'.tr()}: ${collection.city}',
270 style: Theme.of(context).textTheme.bodyMedium,
274 '${'scheduling.reference
'.tr()}: ${collection.internalCode}',
275 style: Theme.of(context).textTheme.bodySmall,
281 crossAxisAlignment: CrossAxisAlignment.end,
285 EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
286 decoration: BoxDecoration(
288 borderRadius: BorderRadius.circular(12),
292 style: Theme.of(context).textTheme.bodySmall?.copyWith(
294 fontWeight: FontWeight.bold,
309 return BlocBuilder<WeeklyCollectionsBloc, WeeklyCollectionsState>(
310 builder: (context, weeklyState) {
311 return BlocBuilder<CollectionsToScheduleBloc, CollectionsToScheduleState>(
312 builder: (context, collectionsState) {
314 weeklyState.selectedCollections.isNotEmpty;
316 final isLoading = collectionsState is CollectionsToScheduleLoading;
324 width:
double.infinity,
326 child: ElevatedButton(
328 style: ElevatedButton.styleFrom(
330 foregroundColor: Colors.white,
331 padding: EdgeInsets.symmetric(vertical: 16.h),
332 shape: RoundedRectangleBorder(
333 borderRadius: BorderRadius.circular(10),
337 'scheduling.continue'.tr(),
338 style: Theme.of(context).textTheme.titleMedium?.copyWith(
340 fontWeight: FontWeight.bold,
352 final weeklyState = context.read<WeeklyCollectionsBloc>().state;
353 final authState = context.read<AuthenticationBloc>().state;
357 final collectionPoints = weeklyState.selectedCollections
361 final user =
UserEntity(
id: (authState.session.uid)?.toInt() ?? 0);
364 collectionPoints: collectionPoints,
372 context.read<CollectionsToScheduleBloc>().add(
376 endDate: weekDates[
'endDate']!,
377 driverId: (authState.session.uid)?.toInt() ?? 0,
override void initState()
class App extends StatefulWidget build(BuildContext context)
sealed class CheckInOutEvent extends Equatable userId
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
const CollectionsToScheduleLoaded({required this.collections})
const CustomCard({ super.key, required this.child, this.padding, this.bgColor, })
final TextEditingController _searchController
const CollectionPointEntity({ required this.id, })
const SetCollectionsToScheduleEvent({required this.collections})
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()
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='', })