Aidra Connect 10.0.2+16
Aidra Connect Mobile Application
Loading...
Searching...
No Matches
create_new_collection_view.dart
Go to the documentation of this file.
1import 'package:connect/core/localization/app_localizations.dart';
2import 'package:flutter/services.dart';
3
4import '/core/ui/theme/color_palette.dart';
5import '/core/ui/widgets/custom_action_slider.dart';
6import '/core/ui/widgets/custom_snackbar.dart';
7import '/core/ui/widgets/custom_text_form_field.dart';
8import '/features/authentication/presentation/logic/authentication_bloc/authentication_bloc.dart';
9import '/features/collections/domain/entities/collection_entity.dart';
10import '/features/collections/domain/entities/create_collection_req_entity.dart';
11import '/features/collections/presentation/logic/collection_requests_history_bloc/collection_requests_history_bloc.dart';
12import '/features/collections/presentation/logic/create_collection_cubit/create_collection_cubit.dart';
13import '/features/collections/presentation/screens/transaction_history_screen/widgets/expected_date_field.dart';
14import '/features/collections/presentation/screens/transaction_history_screen/widgets/time_ranges_field.dart';
15import 'package:flutter/material.dart';
16import 'package:flutter_bloc/flutter_bloc.dart';
17import 'package:flutter_screenutil/flutter_screenutil.dart';
18import 'package:flutter/cupertino.dart';
19
20import 'dart:ui';
21
22class CreateNewCollectionView extends StatefulWidget {
23 const CreateNewCollectionView({super.key});
24
25 @override
26 State<CreateNewCollectionView> createState() =>
27 _CreateNewCollectionViewState();
28}
29
30class _CreateNewCollectionViewState extends State<CreateNewCollectionView>
31 with SingleTickerProviderStateMixin {
32 late AnimationController _controller;
33 late Animation<double> _scaleAnimation;
34
35 @override
36 void initState() {
37 super.initState();
38 _controller = AnimationController(
39 duration: const Duration(milliseconds: 800),
40 vsync: this,
41 );
42 _scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
43 CurvedAnimation(parent: _controller, curve: Curves.easeOutBack),
44 );
45 _controller.forward();
46 }
47
48 @override
49 void dispose() {
50 _controller.dispose();
51 super.dispose();
52 }
53
54 @override
55 Widget build(BuildContext context) {
56 return BlocConsumer<CreateCollectionCubit, CreateCollectionState>(
57 listener: (context, state) {
58 if (state is CollectionCreatedState) {
60 context,
62 AppLocalizations.of(context)
63 .translate('Your collection has been successfully created'),
64 );
65 final authenticationState = context.read<AuthenticationBloc>().state;
66 if (authenticationState is AuthenticatedState) {
67 String? partnerId = authenticationState.session.partnerId;
68 if (partnerId != null) {
69 context.read<CollectionRequestsHistoryBloc>().add(
72 ),
73 );
74 }
75 }
76 }
79 context,
81 AppLocalizations.of(context)
82 .translate('Error while creating your collection, try again'),
83 );
84 }
85 },
86 builder: (context, state) {
87 return ScaleTransition(
88 scale: _scaleAnimation,
89 child: ClipRRect(
90 borderRadius: BorderRadius.circular(20),
91 child: BackdropFilter(
92 filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
93 child: Container(
94 margin: EdgeInsets.all(15.sp),
95 padding: EdgeInsets.all(20.sp),
96 decoration: BoxDecoration(
97 color: Theme.of(context).colorScheme.surface.withOpacity(0.8),
98 borderRadius: BorderRadius.circular(20),
99 ),
100 child: SingleChildScrollView(
101 child: Form(
102 key: _formKey,
103 child: Column(
104 children: [
106 SizedBox(height: 15.sp),
108 ],
109 ),
110 ),
111 ),
112 ),
113 ),
114 ),
115 );
116 },
117 );
118 }
119
121 return Column(
122 children: [
124 icon: CupertinoIcons.calendar,
125 title: AppLocalizations.of(context).translate('When'),
126 child: Row(
127 children: [
128 Expanded(child: _buildDateField(context)),
129 SizedBox(width: 15.sp),
130 Expanded(child: _buildTimeField(context)),
131 ],
132 ),
133 ),
134 SizedBox(height: 15.sp),
136 icon: CupertinoIcons.cube_box,
137 title: AppLocalizations.of(context).translate('How Much in Kg'),
139 ),
140 SizedBox(height: 15.sp),
142 icon: CupertinoIcons.text_quote,
143 title: AppLocalizations.of(context).translate('Any Instructions'),
145 ),
146 ],
147 );
148 }
149
151 required IconData icon,
152 required String title,
153 required Widget child,
154 }) {
155 return Column(
156 crossAxisAlignment: CrossAxisAlignment.start,
157 children: [
158 Row(
159 children: [
160 Icon(icon, color: Theme.of(context).colorScheme.primary),
161 SizedBox(width: 10.sp),
162 Text(
163 title,
164 style: Theme.of(context).textTheme.titleMedium?.copyWith(
165 fontWeight: FontWeight.w600,
166 ),
167 ),
168 ],
169 ),
170 Divider(height: 20.sp),
171 child,
172 SizedBox(height: 10.sp),
173 ],
174 );
175 }
176
178 return CustomSliderV2(
179 action: (action) => _onCreateNewCollection(),
180 text: AppLocalizations.of(context).translate('SCHEDULE COLLECTION'),
181 );
182 }
183
184 DateTime? _expectedDate = DateTime.now().add(Duration(days: 2));
186 final _formKey = GlobalKey<FormState>();
187 final _volumeController = TextEditingController();
188 final _instructioncontroller = TextEditingController();
189
191 final authenticationState = context.read<AuthenticationBloc>().state;
192 if (authenticationState is AuthenticatedState) {
193 String partnerId = authenticationState.session.partnerId!;
194
195 if (_selectedTimeRange != null &&
196 _expectedDate != null &&
197 _formKey.currentState!.validate()) {
198 final newCollection = CreateCollectionRequestEntity(
199 collectionRequest: AppLocalizations.of(context).translate('manual'),
200 dateOrder: _expectedDate,
201 orderLines: [
204 productQty: num.parse(_volumeController.text),
205 )
206 ],
208 proposedTime: _selectedTimeRange,
209 userId: authenticationState.session.uid,
210 instruction: _instructioncontroller.text,
211 );
212
213 context
214 .read<CreateCollectionCubit>()
215 .createCollection(entity: newCollection);
216 } else {
218 context,
220 AppLocalizations.of(context)
221 .translate('Please select both time range and date to continue'),
222 );
223 }
224 }
225 }
226
227 Widget _buildDateField(BuildContext context) {
228 return Column(
229 crossAxisAlignment: CrossAxisAlignment.start,
230 children: [
231 Text(
232 AppLocalizations.of(context).translate('Collection Date'),
233 style: Theme.of(context).textTheme.bodySmall?.copyWith(
234 color: Theme.of(context).hintColor,
235 ),
236 ),
237 SizedBox(height: 8.sp),
238 Container(
239 decoration: BoxDecoration(
240 color: Theme.of(context).colorScheme.surface,
241 borderRadius: BorderRadius.circular(10),
242 border: Border.all(
243 color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
244 width: 0.5,
245 ),
246 ),
247 child: ExpectedDateField(
248 isEditingField: false,
249 expectedDate:
250 _expectedDate ?? DateTime.now().add(Duration(days: 2)),
251 onDatePicked: (newDate) {
252 setState(() => _expectedDate = newDate);
253 },
254 ),
255 ),
256 ],
257 );
258 }
259
260 Widget _buildTimeField(BuildContext context) {
261 return Column(
262 crossAxisAlignment: CrossAxisAlignment.start,
263 children: [
264 Text(
265 AppLocalizations.of(context).translate('Time Range'),
266 style: Theme.of(context).textTheme.bodySmall?.copyWith(
267 color: Theme.of(context).hintColor,
268 ),
269 ),
270 SizedBox(height: 8.sp),
271 Container(
272 decoration: BoxDecoration(
273 color: Theme.of(context).colorScheme.surface,
274 borderRadius: BorderRadius.circular(10),
275 border: Border.all(
276 color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
277 width: 0.5,
278 ),
279 ),
282 onPickTimeRange: (time) {
283 setState(() => _selectedTimeRange = time);
284 },
285 ),
286 ),
287 ],
288 );
289 }
290
292 return CustomTextFormField(
293 hintText: AppLocalizations.of(context).translate('Enter Quantity'),
294 controller: _volumeController,
295 inputType: TextInputType.number,
296 inputFormatters: [
297 FilteringTextInputFormatter.digitsOnly,
298 LengthLimitingTextInputFormatter(
299 5,
300 ),
301 ],
302 validator: (value) {
303 if (value == null || value.isEmpty) {
304 return AppLocalizations.of(context).translate('Quantity is required');
305 }
306 final int? number = int.tryParse(value);
307 if (number == null) {
308 return AppLocalizations.of(context).translate('Enter a valid number');
309 }
310 if (number > 10000) {
311 return AppLocalizations.of(context)
312 .translate('Maximum allowed quantity is 10,000');
313 }
314 return null;
315 },
316 );
317 }
318
320 return Column(
321 crossAxisAlignment: CrossAxisAlignment.start,
322 children: [
323 CustomTextFormField(
324 hintText: AppLocalizations.of(context)
325 .translate('Enter any special instructions'),
326 maxLines: 4,
327 controller: _instructioncontroller,
328 ),
329 ],
330 );
331 }
332}
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,)
const CreateNewCollectionView({super.key})
override State< CreateNewCollectionView > createState()
final num productQty
ProposedTimeEntity({ required this.id, required this.name, })
final num partnerId
const LoadOnGoingCollectionRequestsEvent({required this.partnerId})
const RequestOrderLineEntity({ required this.partnerId, required this.productQty, })
const CollectionCreattionFailureState({required this.failure})
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()
override void dispose()
final Widget child
final EdgeInsets padding
override void initState()
final Color color
Definition failures.dart:1
override Widget build(BuildContext context)
final double value
final ProposedTimeEntity selectedTimeRange
const TimeRangeField({ super.key, required this.selectedTimeRange, required this.onPickTimeRange, })
final String title