diff --git a/lib/main.dart b/lib/main.dart index 6f42cbe..f4f6e6d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -110,7 +110,7 @@ class _MyAppState extends State { return MaterialApp( debugShowCheckedModeBanner: false, navigatorKey: navigatorKey, - title: 'cheminova', + title: 'Cheminova', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true), diff --git a/lib/provider/visit_pdrd_provider.dart b/lib/provider/visit_pdrd_provider.dart index f565a77..94caefc 100644 --- a/lib/provider/visit_pdrd_provider.dart +++ b/lib/provider/visit_pdrd_provider.dart @@ -7,27 +7,54 @@ import '../services/api_urls.dart'; class VisitPdRdProvider with ChangeNotifier { final _apiClient = ApiClient(); - bool _isLoading = false; + bool isLoading = false; + void setLoading(bool loading) { - _isLoading = loading; + isLoading = loading; notifyListeners(); } -Future submitVisitPdRd(String id) async { + Future submitVisitPdRd(String id, + {String? type, + + required String retailerName, + required String visitTime, + required String visitDate, + required String note, required String selectedPurpose, required String followUpActions, required String nextVisitDate + }) async { setLoading(true); + + try { - Response response = await _apiClient.put(ApiUrls.updateTaskInventoryUrl+id); + Response response = await _apiClient.post(ApiUrls.submitVisitUrl, data: { + "addedFor": type, // Could also be 'PrincipalDistributor' + "addedForId": id, // Example RetailDistributor/PrincipalDistributor ID + "tradename": retailerName, // Example trade name + "visitDate": visitDate, + "visitTime": visitTime, + "visitpurpose": selectedPurpose, + "meetingsummary":note, + "followup": followUpActions, + "nextvisitdate":nextVisitDate + + }); debugPrint('Response: $response'); setLoading(false); - if (response.statusCode == 200) { - Navigator.push( - navigatorKey.currentContext!, - MaterialPageRoute( - builder: (context) => const DataSubmitSuccessFullScreen())); + if (response.statusCode == 201) { + Response response = + await _apiClient.put(ApiUrls.updateTaskInventoryUrl + id); + debugPrint('Response: $response'); + setLoading(false); + if (response.statusCode == 200) { + Navigator.push( + navigatorKey.currentContext!, + MaterialPageRoute( + builder: (context) => const DataSubmitSuccessFullScreen())); + } } } catch (e) { setLoading(false); debugPrint("Error: $e"); } } -} \ No newline at end of file +} diff --git a/lib/screens/daily_tasks_screen.dart b/lib/screens/daily_tasks_screen.dart index 1aa6627..d4acd35 100644 --- a/lib/screens/daily_tasks_screen.dart +++ b/lib/screens/daily_tasks_screen.dart @@ -225,6 +225,7 @@ class _DailyTasksScreenState extends State { builder: (context) => VisitDealersScreen( tradeName: tasksList.tradeName ?? '', id: tasksList.sId, + type: tasksList.addedFor, ))); } }, diff --git a/lib/screens/retailer_details_screen.dart b/lib/screens/retailer_details_screen.dart index 73db517..72a54c1 100644 --- a/lib/screens/retailer_details_screen.dart +++ b/lib/screens/retailer_details_screen.dart @@ -4,7 +4,6 @@ import 'package:csc_picker/csc_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; - import '../constants/only_uppercase.dart'; import '../widgets/common_elevated_button.dart'; import '../widgets/common_text_form_field.dart'; diff --git a/lib/screens/visit_rd_pd_screen.dart b/lib/screens/visit_rd_pd_screen.dart index 26f4ce8..51a7ca6 100644 --- a/lib/screens/visit_rd_pd_screen.dart +++ b/lib/screens/visit_rd_pd_screen.dart @@ -12,7 +12,8 @@ import 'package:image_picker/image_picker.dart'; class VisitDealersScreen extends StatefulWidget { final String? tradeName; final String? id; - const VisitDealersScreen({super.key, required this.tradeName, this.id}); + final String? type; + const VisitDealersScreen({super.key, required this.tradeName, this.id, this.type}); @override State createState() => VisitDealersScreenState(); @@ -36,10 +37,62 @@ class VisitDealersScreenState extends State { String selectedPurpose = 'Sales'; List purposeOptions = ['Sales', 'Dues collection', 'Others']; - Future _pickImage() async { + Future _pickImage(ImageSource source) async { final ImagePicker picker = ImagePicker(); - await picker.pickImage(source: ImageSource.camera); - // Handle the picked image + final XFile? image = await picker.pickImage(source: source); + if (image != null) { + // Handle the picked image + // For example, you could update a state variable or send it to your provider + print('Image picked: ${image.path}'); + // You might want to update your UI to show the selected image + setState(() { + notesController.text = image.path; // Just for demonstration + }); + } + } + + void _showImageSourceActionSheet() { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SafeArea( + child: Wrap( + children: [ + ListTile( + leading: const Icon(Icons.camera_alt), + title: const Text('Take a photo'), + onTap: () { + Navigator.pop(context); + _pickImage(ImageSource.camera); + }, + ), + ListTile( + leading: const Icon(Icons.photo_library), + title: const Text('Choose from gallery'), + onTap: () { + Navigator.pop(context); + _pickImage(ImageSource.gallery); + }, + ), + ], + ), + ); + }, + ); + } + + Future _selectNextVisitDate() async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), + lastDate: DateTime.now().add(const Duration(days: 365)), + ); + if (picked != null) { + setState(() { + nextVisitDateController.text = DateFormat('dd/MM/yyyy').format(picked); + }); + } } @override @@ -55,147 +108,177 @@ class VisitDealersScreenState extends State { return ChangeNotifierProvider( create: (context) => _visitPdRdProvider, child: CommonBackground( - child: Scaffold( - backgroundColor: Colors.transparent, - appBar: CommonAppBar( - actions: [ - IconButton( - onPressed: () { - Navigator.pop(context); - }, - icon: Image.asset('assets/Back_attendance.png'), - padding: const EdgeInsets.only(right: 20), + child: Stack( + children: [ + Scaffold( + + backgroundColor: Colors.transparent, + appBar: CommonAppBar( + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Image.asset('assets/Back_attendance.png'), + padding: const EdgeInsets.only(right: 20), + ), + ], + title: Column( + children: [ + const Text('Visit Retailers', + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w400, + fontFamily: 'Anek')), + Text(widget.tradeName??'', + style: const TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w400, + fontFamily: 'Anek')), + ], + ), + backgroundColor: Colors.transparent, + elevation: 0, ), - ], - title: Column( - children: [ - const Text('Visit Retailers', - style: TextStyle( - fontSize: 20, - color: Colors.black, - fontWeight: FontWeight.w400, - fontFamily: 'Anek')), - Text(widget.tradeName??'', - style: const TextStyle( - fontSize: 20, - color: Colors.black, - fontWeight: FontWeight.w400, - fontFamily: 'Anek')), - ], - ), - backgroundColor: Colors.transparent, - elevation: 0, - ), - drawer: const CommonDrawer(), - body: SingleChildScrollView( - physics: const BouncingScrollPhysics(), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 16), - Container( - padding: - const EdgeInsets.all(20.0).copyWith(top: 30, bottom: 30), - margin: const EdgeInsets.symmetric(horizontal: 16.0), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.9), - borderRadius: BorderRadius.circular(26.0)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CommonTextFormField( - readOnly: true, - title: 'Select Retailer', - fillColor: Colors.white, - controller: retailerController), - const SizedBox(height: 15), - CommonTextFormField( - title: 'Visit date', - readOnly: true, - fillColor: Colors.white, - controller: dateController), - const SizedBox(height: 15), - CommonTextFormField( - title: 'Time', - readOnly: true, - fillColor: Colors.white, - controller: timeController), - const SizedBox(height: 15), - DropdownButtonFormField( - decoration: const InputDecoration( - labelText: 'Purpose of visit', - fillColor: Colors.white, - filled: true, - ), - value: selectedPurpose, - items: purposeOptions.map((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - onChanged: (String? newValue) { - setState(() { - selectedPurpose = newValue!; - }); - }, - ), - const SizedBox(height: 15), - CommonTextFormField( - title: 'Meeting Summary:', - fillColor: Colors.white, - maxLines: 3, - controller: meetingSummaryController), - const SizedBox(height: 15), - CommonTextFormField( - title: 'Follow-up Actions:', - fillColor: Colors.white, - maxLines: 3, - controller: followUpActionsController), - const SizedBox(height: 15), - CommonTextFormField( - title: 'Next visit date:', - readOnly: true, - fillColor: Colors.white, - controller: nextVisitDateController), - const SizedBox(height: 15), - Row( - children: [ - Expanded( - child: CommonTextFormField( - title: 'Attach Documents/Photos', - fillColor: Colors.white, - controller: notesController), + drawer: const CommonDrawer(), + body: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 16), + Container( + padding: + const EdgeInsets.all(20.0).copyWith(top: 30, bottom: 30), + margin: const EdgeInsets.symmetric(horizontal: 16.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.9), + borderRadius: BorderRadius.circular(26.0)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CommonTextFormField( + readOnly: true, + title: 'Select Retailer', + fillColor: Colors.white, + controller: retailerController), + const SizedBox(height: 15), + CommonTextFormField( + title: 'Visit date', + readOnly: true, + fillColor: Colors.white, + controller: dateController), + const SizedBox(height: 15), + CommonTextFormField( + title: 'Time', + readOnly: true, + fillColor: Colors.white, + controller: timeController), + const SizedBox(height: 15), + DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Purpose of visit', + fillColor: Colors.white, + filled: true, + ), + value: selectedPurpose, + items: purposeOptions.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + onChanged: (String? newValue) { + setState(() { + selectedPurpose = newValue!; + }); + }, + ), + const SizedBox(height: 15), + CommonTextFormField( + title: 'Meeting summary:', + fillColor: Colors.white, + maxLines: 3, + controller: meetingSummaryController), + const SizedBox(height: 15), + CommonTextFormField( + title: 'Follow-up Actions:', + fillColor: Colors.white, + maxLines: 3, + controller: followUpActionsController), + const SizedBox(height: 15), + GestureDetector( + onTap: _selectNextVisitDate, + child: AbsorbPointer( + child: CommonTextFormField( + title: 'Next visit date:', + readOnly: true, + fillColor: Colors.white, + controller: nextVisitDateController, + ), + ), + ), + const SizedBox(height: 15), + Row( + children: [ + Expanded( + child: CommonTextFormField( + title: 'Attach Documents/Photos', + fillColor: Colors.white, + controller: notesController), + ), + IconButton( + icon: const Icon(Icons.add_a_photo), + onPressed: _showImageSourceActionSheet, + ), + ], + ), + const SizedBox(height: 15), + Consumer(builder: (context, value, child) => Align( + alignment: Alignment.center, + child: CommonElevatedButton( + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'SUBMIT', + backgroundColor: const Color(0xff004791), + onPressed: () { + value.submitVisitPdRd(widget.id ?? '', type: widget.type, + retailerName: retailerController.text, + visitDate: dateController.text, + visitTime: timeController.text, + note: meetingSummaryController.text, + selectedPurpose: selectedPurpose, + followUpActions: followUpActionsController.text, + nextVisitDate: nextVisitDateController.text, + ); + }, + ), ), - IconButton( - icon: const Icon(Icons.camera_alt), - onPressed: _pickImage, ), ], ), - const SizedBox(height: 15), - Consumer(builder: (context, value, child) => Align( - alignment: Alignment.center, - child: CommonElevatedButton( - borderRadius: 30, - width: double.infinity, - height: kToolbarHeight - 10, - text: 'SUBMIT', - backgroundColor: const Color(0xff004791), - onPressed: () { - value.submitVisitPdRd(widget.id ?? ''); - }, - ), - ), - ), - ], - ), + ), + ], ), - ], + ), ), - ), + Consumer(builder: (context, value, child) { + if (value.isLoading) { + return Container( + color: Colors.black.withOpacity(0.5), + child: const Center( + child: CircularProgressIndicator(), + ), + ); + } + return const SizedBox.shrink(); + }), + ], ), ), ); diff --git a/lib/services/api_urls.dart b/lib/services/api_urls.dart index 97cc692..6f4904c 100644 --- a/lib/services/api_urls.dart +++ b/lib/services/api_urls.dart @@ -23,4 +23,5 @@ class ApiUrls { static const String getProductsManual = '${baseUrl}productmanual/getall'; static const String salesTaskUrl = '${baseUrl}product/getAll/user/'; static const String postSalesTaskUrl = '${baseUrl}sales/add-SC'; + static const String submitVisitUrl = '${baseUrl}visit'; }