Aidra Connect 10.0.2+16
Aidra Connect Mobile Application
Loading...
Searching...
No Matches
edit_collection_request_view.dart
Go to the documentation of this file.
1import 'dart:ui';
2
3import 'package:connect/core/localization/app_localizations.dart';
4import 'package:connect/core/ui/widgets/custom_scaffold.dart';
5import 'package:connect/features/collections/domain/entities/update_collection_req_entity.dart';
6import 'package:flutter/cupertino.dart';
7import 'package:flutter/services.dart';
8
9import '../../../../../../../../authentication/presentation/logic/authentication_bloc/authentication_bloc.dart';
10import '/core/ui/theme/color_palette.dart';
11import '/core/ui/widgets/custom_action_slider.dart';
12import '/core/ui/widgets/custom_snackbar.dart';
13import '/core/ui/widgets/custom_text_form_field.dart';
14import '/features/collections/domain/entities/collection_entity.dart';
15import '/features/collections/presentation/logic/collection_requests_history_bloc/collection_requests_history_bloc.dart';
16import '/features/collections/presentation/logic/update_collection_cubit/update_collection_cubit.dart';
17import '/features/collections/presentation/screens/transaction_history_screen/widgets/expected_date_field.dart';
18import '/features/collections/presentation/screens/transaction_history_screen/widgets/time_ranges_field.dart';
19import 'package:flutter/material.dart';
20import 'package:flutter_bloc/flutter_bloc.dart';
21import 'package:flutter_screenutil/flutter_screenutil.dart';
22import 'package:go_router/go_router.dart';
23
24class EditCollectionRequestsScreen extends StatefulWidget {
26 super.key,
27 required this.collection,
28 });
29
31
32 @override
33 State<EditCollectionRequestsScreen> createState() =>
34 _EditCollectionRequestsScreenState();
35}
36
37class _EditCollectionRequestsScreenState
38 extends State<EditCollectionRequestsScreen>
39 with SingleTickerProviderStateMixin {
40 final _formKey = GlobalKey<FormState>();
41 final _volumeController = TextEditingController();
42 final _instructioncontroller = TextEditingController();
43 late AnimationController _controller;
44 late Animation<double> _scaleAnimation;
45
47 DateTime? _expectedDate;
49
50 @override
51 void initState() {
52 setState(() {
53 if (widget.collection.orderLines?.first.productQty != null) {
55 widget.collection.orderLines!.first.productQty!.toString();
56 }
57 _selectedTimeRange = widget.collection.proposedTime;
58 _expectedDate = widget.collection.dateOrder;
59 _instructioncontroller.text = widget.collection.instruction ?? '';
60 _collectionType = widget.collection.collectionRequest ?? 'manual';
61 });
62 _controller = AnimationController(
63 duration: const Duration(milliseconds: 800),
64 vsync: this,
65 );
66 _scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
67 CurvedAnimation(parent: _controller, curve: Curves.easeOutBack),
68 );
69 _controller.forward();
70
71 super.initState();
72 }
73
75 if (_formKey.currentState!.validate()) {
76 final authenticationState = context.read<AuthenticationBloc>().state;
77 if (authenticationState is AuthenticatedState) {
78 String partnerId = authenticationState.session.partnerId!;
79
80 int uid = authenticationState.session.uid!;
81
82 final updatedCollection = UpdateCollectionReqEntity(
83 id: widget.collection.id ?? 0,
84 collectionRequest: _collectionType,
85 instruction: _instructioncontroller.text,
86 dateOrder: _expectedDate,
87 proposedTimeId: _selectedTimeRange?.id?.toInt(),
88 quantity: num.parse(_volumeController.text),
89 partnerId: int.parse(partnerId),
90 userId: uid,
91 );
92 context
93 .read<UpdateCollectionCubit>()
94 .updateCollectionRequest(entity: updatedCollection);
95 }
96 }
97 }
98
99 @override
100 Widget build(BuildContext context) {
101 return BlocConsumer<UpdateCollectionCubit, UpdateCollectionState>(
102 listener: (context, state) {
103 if (state is CollectionUpdatedState) {
104 context.pop();
106 context,
108 AppLocalizations.of(context)
109 .translate('Your collection has been successfully updated'));
110
111 final authenticationState = context.read<AuthenticationBloc>().state;
112 if (authenticationState is AuthenticatedState) {
113 String? partnerId = authenticationState.session.partnerId;
114 context.read<CollectionRequestsHistoryBloc>().add(
116 );
117 }
118 }
119 if (state is CollectionUpdateFailureState) {
121 context,
123 AppLocalizations.of(context)
124 .translate('Error while updating your collection, try again'),
125 );
126 }
127 },
128 builder: (context, state) {
129 return CustomScaffold(
130 title: AppLocalizations.of(context).translate('Update collection'),
131 body: SafeArea(
132 child: Padding(
133 padding: EdgeInsets.symmetric(horizontal: 10.sp, vertical: 15.sp),
134 child: state is UpdatingCollectionState
135 ? Center(
136 child: CircularProgressIndicator(),
137 )
138 : ScaleTransition(
139 scale: _scaleAnimation,
140 child: ClipRRect(
141 borderRadius: BorderRadius.circular(20),
142 child: BackdropFilter(
143 filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
144 child: Container(
145 padding: EdgeInsets.all(15.sp),
146 decoration: BoxDecoration(
147 color: Theme.of(context).colorScheme.surface,
148 borderRadius: BorderRadius.circular(20),
149 ),
150 child: SingleChildScrollView(
151 child: Form(
152 key: _formKey,
153 child: Column(
154 children: [
156 SizedBox(height: 15.sp),
158 ],
159 ),
160 ),
161 ),
162 ),
163 ),
164 ),
165 ),
166 ),
167 ),
168 );
169 // if (state is UpdatingCollectionState) {
170 // return Center(
171 // child: CircularProgressIndicator(),
172 // );
173 // } else {
174 // return ScaleTransition(
175 // scale: _scaleAnimation,
176 // child: ClipRRect(
177 // borderRadius: BorderRadius.circular(20),
178 // child: BackdropFilter(
179 // filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
180 // child: Container(
181 // padding: EdgeInsets.all(15.sp),
182 // decoration: BoxDecoration(
183 // color: Theme.of(context).colorScheme.surface,
184 // borderRadius: BorderRadius.circular(20),
185 // ),
186 // child: SingleChildScrollView(
187 // child: Form(
188 // key: _formKey,
189 // child: Column(
190 // children: [
191 // _buildAnimatedInputs(),
192 // SizedBox(height: 15.sp),
193 // _buildSubmitButton(),
194 // ],
195 // ),
196 // ),
197 // ),
198 // ),
199 // ),
200 // ),
201 // );
202 // }
203 },
204 );
205 }
206
208 return Column(
209 children: [
211 icon: CupertinoIcons.calendar,
212 title: AppLocalizations.of(context).translate('When'),
213 child: Row(
214 children: [
215 Expanded(child: _buildDateField(context)),
216 SizedBox(width: 15.sp),
217 Expanded(child: _buildTimeField(context)),
218 ],
219 ),
220 ),
221 SizedBox(height: 15.sp),
223 icon: CupertinoIcons.cube_box,
224 title: AppLocalizations.of(context).translate('How Much in Kg'),
226 ),
227 SizedBox(height: 15.sp),
229 icon: CupertinoIcons.text_quote,
230 title: AppLocalizations.of(context).translate('Any Instructions'),
232 ),
233 ],
234 );
235 }
236
238 required IconData icon,
239 required String title,
240 required Widget child,
241 }) {
242 return Column(
243 crossAxisAlignment: CrossAxisAlignment.start,
244 children: [
245 Row(
246 children: [
247 Icon(icon, color: Theme.of(context).colorScheme.primary),
248 SizedBox(width: 10.sp),
249 Text(
250 title,
251 style: Theme.of(context).textTheme.titleMedium?.copyWith(
252 fontWeight: FontWeight.w600,
253 ),
254 ),
255 ],
256 ),
257 Divider(height: 20.sp),
258 child,
259 SizedBox(height: 10.sp),
260 ],
261 );
262 }
263
265 return CustomSliderV2(
266 action: (action) => _onUpdateCollection(),
267 text: AppLocalizations.of(context)
268 .translate('Update collection')
269 .toUpperCase(),
270 );
271 }
272
273 Widget _buildDateField(BuildContext context) {
274 return Column(
275 crossAxisAlignment: CrossAxisAlignment.start,
276 children: [
277 Text(
278 AppLocalizations.of(context).translate('Collection Date'),
279 style: Theme.of(context).textTheme.bodySmall?.copyWith(
280 color: Theme.of(context).hintColor,
281 ),
282 ),
283 SizedBox(height: 8.sp),
284 Container(
285 decoration: BoxDecoration(
286 color: Theme.of(context).colorScheme.surface,
287 borderRadius: BorderRadius.circular(10),
288 border: Border.all(
289 color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
290 width: 0.5,
291 ),
292 ),
293 child: ExpectedDateField(
294 isEditingField: true,
295 expectedDate: _expectedDate ?? DateTime.now(),
296 onDatePicked: (newDate) {
297 setState(() => _expectedDate = newDate);
298 },
299 ),
300 ),
301 ],
302 );
303 }
304
305 Widget _buildTimeField(BuildContext context) {
306 return Column(
307 crossAxisAlignment: CrossAxisAlignment.start,
308 children: [
309 Text(
310 AppLocalizations.of(context).translate('Time Range'),
311 style: Theme.of(context).textTheme.bodySmall?.copyWith(
312 color: Theme.of(context).hintColor,
313 ),
314 ),
315 SizedBox(height: 8.sp),
316 Container(
317 decoration: BoxDecoration(
318 color: Theme.of(context).colorScheme.surface,
319 borderRadius: BorderRadius.circular(10),
320 border: Border.all(
321 color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
322 width: 0.5,
323 ),
324 ),
327 onPickTimeRange: (time) {
328 setState(() => _selectedTimeRange = time);
329 },
330 ),
331 ),
332 ],
333 );
334 }
335
337 return CustomTextFormField(
338 hintText: AppLocalizations.of(context).translate('Enter Quantity'),
339 controller: _volumeController,
340 inputType: TextInputType.number,
341 inputFormatters: [
342 FilteringTextInputFormatter.digitsOnly,
343 LengthLimitingTextInputFormatter(
344 5,
345 ),
346 ],
347 validator: (value) {
348 if (value == null || value.isEmpty) {
349 return AppLocalizations.of(context).translate('Quantity is required');
350 }
351 final int? number = int.tryParse(value);
352 if (number == null) {
353 return AppLocalizations.of(context).translate('Enter a valid number');
354 }
355 if (number > 10000) {
356 return AppLocalizations.of(context)
357 .translate('Maximum allowed quantity is 10,000');
358 }
359 return null;
360 },
361 );
362 }
363
365 return Column(
366 crossAxisAlignment: CrossAxisAlignment.start,
367 children: [
368 CustomTextFormField(
369 hintText: AppLocalizations.of(context)
370 .translate('Enter any special instructions'),
371 maxLines: 4,
372 controller: _instructioncontroller,
373 ),
374 ],
375 );
376 }
377}
378
379class AutoManualSwitcher extends StatefulWidget {
380 final ValueChanged<bool> onToggle;
381 final bool initialValue;
382
384 super.key,
385 required this.onToggle,
386 required this.initialValue,
387 });
388
389 @override
390 AutoManualSwitcherState createState() => AutoManualSwitcherState();
391}
392
393class AutoManualSwitcherState extends State<AutoManualSwitcher> {
394 late bool isAuto;
395
396 @override
397 void initState() {
398 super.initState();
399 isAuto = widget.initialValue;
400 }
401
402 void toggleMode() {
403 setState(() {
404 isAuto = !isAuto;
405 });
406 widget.onToggle(isAuto);
407 }
408
409 @override
410 Widget build(BuildContext context) {
411 return GestureDetector(
413 child: Container(
414 padding: EdgeInsets.symmetric(vertical: 15.sp, horizontal: 30.sp),
415 decoration: BoxDecoration(
416 borderRadius: BorderRadius.circular(10),
417 gradient: LinearGradient(
418 colors: isAuto
419 ? [
420 Theme.of(context).scaffoldBackgroundColor,
421 Theme.of(context).colorScheme.surface,
422 ]
423 : [
424 Theme.of(context).colorScheme.surface,
425 Theme.of(context).scaffoldBackgroundColor,
426 ],
427 ),
428 ),
429 child: Row(
430 mainAxisAlignment: MainAxisAlignment.spaceAround,
431 children: [
432 AnimatedOpacity(
433 opacity: isAuto ? 1.0 : 0.5,
434 duration: const Duration(milliseconds: 300),
435 child: Text(
436 AppLocalizations.of(context).translate('auto'),
437 style: Theme.of(context).textTheme.bodySmall?.copyWith(
439 ? Theme.of(context).colorScheme.primary
440 : Theme.of(context).colorScheme.onSurface,
441 fontWeight: isAuto ? FontWeight.bold : FontWeight.normal,
442 ),
443 ),
444 ),
445 const SizedBox(width: 20),
446 AnimatedOpacity(
447 opacity: isAuto ? 0.5 : 1.0,
448 duration: const Duration(milliseconds: 300),
449 child: Text(
450 AppLocalizations.of(context).translate('manual'),
451 style: Theme.of(context).textTheme.bodySmall?.copyWith(
453 ? Theme.of(context).colorScheme.onSurface
454 : Theme.of(context).colorScheme.primary,
455 fontWeight: isAuto ? FontWeight.normal : FontWeight.bold,
456 ),
457 ),
458 ),
459 ],
460 ),
461 ),
462 );
463 }
464}
465
466class EditCard extends StatelessWidget {
467 const EditCard({
468 super.key,
469 required this.child,
470 required this.title,
471 });
472
473 final Widget child;
474 final String title;
475
476 @override
477 Widget build(BuildContext context) {
478 return Column(
479 crossAxisAlignment: CrossAxisAlignment.center,
480 children: [
481 Row(
482 children: [
483 SizedBox(
484 width: 20.sp,
485 child: Divider(
486 height: 0.0,
487 thickness: 0.5,
488 color: Theme.of(context).hintColor,
489 ),
490 ),
491 SizedBox(width: 10.sp),
492 Text(
493 title,
494 style: Theme.of(context).textTheme.bodySmall?.copyWith(
495 color: Theme.of(context).hintColor,
496 ),
497 ),
498 SizedBox(width: 10.sp),
499 Expanded(
500 child: Divider(
501 height: 0.0,
502 thickness: 0.5,
503 color: Theme.of(context).hintColor,
504 ),
505 ),
506 ],
507 ),
508 SizedBox(height: 12.sp),
509 child,
510 ],
511 );
512 }
513}
AppLocalizations(this.locale)
class CalenderTransactionsSummaryVeiw extends StatefulWidget collection
String translate(String key)
static AppLocalizations of(BuildContext context)
static const lightGreen
static const red
static display(final BuildContext context, final Color color, final String message,)
override AutoManualSwitcherState createState()
const AutoManualSwitcher({ super.key, required this.onToggle, required this.initialValue, })
override State< EditCollectionRequestsScreen > createState()
const EditCollectionRequestsScreen({ super.key, required this.collection, })
final ValueChanged< bool > onToggle
final CollectionEntity collection
const EditCard({ super.key, required this.child, required this.title, })
final String title
final Widget child
override Widget build(BuildContext context)
ProposedTimeEntity({ required this.id, required this.name, })
final num partnerId
const LoadOnGoingCollectionRequestsEvent({required this.partnerId})
ProposedTimeEntity _selectedTimeRange
Widget _buildAnimatedInputs()
final _instructioncontroller
Widget _buildInputCard({ required IconData icon, required String title, required Widget child, })
DateTime _expectedDate
Widget _buildTimeField(BuildContext context)
late Animation< double > _scaleAnimation
Widget _buildDateField(BuildContext context)
Widget _buildInstructionsField()
Widget _buildQuantityField()
Widget _buildSubmitButton()
final Widget child
final EdgeInsets padding
override void initState()
class AutoManualSwitcher extends StatefulWidget isAuto
final VoidCallback onTap
final Color color
Definition failures.dart:1
override Widget build(BuildContext context)
final double value
final int uid
final ProposedTimeEntity selectedTimeRange
const TimeRangeField({ super.key, required this.selectedTimeRange, required this.onPickTimeRange, })
final String title
const CollectionUpdateFailureState({ required this.failure, })