Submit VisitUrl Added

This commit is contained in:
Vaibhav 2024-09-19 17:21:32 +05:30
parent 11b3b130d9
commit d077d06c07
6 changed files with 261 additions and 150 deletions

View File

@ -110,7 +110,7 @@ class _MyAppState extends State<MyApp> {
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
title: 'cheminova', title: 'Cheminova',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true), useMaterial3: true),

View File

@ -7,23 +7,50 @@ import '../services/api_urls.dart';
class VisitPdRdProvider with ChangeNotifier { class VisitPdRdProvider with ChangeNotifier {
final _apiClient = ApiClient(); final _apiClient = ApiClient();
bool _isLoading = false; bool isLoading = false;
void setLoading(bool loading) { void setLoading(bool loading) {
_isLoading = loading; isLoading = loading;
notifyListeners(); notifyListeners();
} }
Future<void> submitVisitPdRd(String id) async { Future<void> 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); setLoading(true);
try { 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'); debugPrint('Response: $response');
setLoading(false); setLoading(false);
if (response.statusCode == 200) { if (response.statusCode == 201) {
Navigator.push( Response response =
navigatorKey.currentContext!, await _apiClient.put(ApiUrls.updateTaskInventoryUrl + id);
MaterialPageRoute( debugPrint('Response: $response');
builder: (context) => const DataSubmitSuccessFullScreen())); setLoading(false);
if (response.statusCode == 200) {
Navigator.push(
navigatorKey.currentContext!,
MaterialPageRoute(
builder: (context) => const DataSubmitSuccessFullScreen()));
}
} }
} catch (e) { } catch (e) {
setLoading(false); setLoading(false);

View File

@ -225,6 +225,7 @@ class _DailyTasksScreenState extends State<DailyTasksScreen> {
builder: (context) => VisitDealersScreen( builder: (context) => VisitDealersScreen(
tradeName: tasksList.tradeName ?? '', tradeName: tasksList.tradeName ?? '',
id: tasksList.sId, id: tasksList.sId,
type: tasksList.addedFor,
))); )));
} }
}, },

View File

@ -4,7 +4,6 @@ import 'package:csc_picker/csc_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../constants/only_uppercase.dart'; import '../constants/only_uppercase.dart';
import '../widgets/common_elevated_button.dart'; import '../widgets/common_elevated_button.dart';
import '../widgets/common_text_form_field.dart'; import '../widgets/common_text_form_field.dart';

View File

@ -12,7 +12,8 @@ import 'package:image_picker/image_picker.dart';
class VisitDealersScreen extends StatefulWidget { class VisitDealersScreen extends StatefulWidget {
final String? tradeName; final String? tradeName;
final String? id; 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 @override
State<VisitDealersScreen> createState() => VisitDealersScreenState(); State<VisitDealersScreen> createState() => VisitDealersScreenState();
@ -36,10 +37,62 @@ class VisitDealersScreenState extends State<VisitDealersScreen> {
String selectedPurpose = 'Sales'; String selectedPurpose = 'Sales';
List<String> purposeOptions = ['Sales', 'Dues collection', 'Others']; List<String> purposeOptions = ['Sales', 'Dues collection', 'Others'];
Future<void> _pickImage() async { Future<void> _pickImage(ImageSource source) async {
final ImagePicker picker = ImagePicker(); final ImagePicker picker = ImagePicker();
await picker.pickImage(source: ImageSource.camera); final XFile? image = await picker.pickImage(source: source);
// Handle the picked image 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: <Widget>[
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<void> _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 @override
@ -55,147 +108,177 @@ class VisitDealersScreenState extends State<VisitDealersScreen> {
return ChangeNotifierProvider( return ChangeNotifierProvider(
create: (context) => _visitPdRdProvider, create: (context) => _visitPdRdProvider,
child: CommonBackground( child: CommonBackground(
child: Scaffold( child: Stack(
backgroundColor: Colors.transparent, children: [
appBar: CommonAppBar( Scaffold(
actions: [
IconButton( backgroundColor: Colors.transparent,
onPressed: () { appBar: CommonAppBar(
Navigator.pop(context); actions: [
}, IconButton(
icon: Image.asset('assets/Back_attendance.png'), onPressed: () {
padding: const EdgeInsets.only(right: 20), 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,
), ),
], drawer: const CommonDrawer(),
title: Column( body: SingleChildScrollView(
children: [ physics: const BouncingScrollPhysics(),
const Text('Visit Retailers', child: Column(
style: TextStyle( mainAxisAlignment: MainAxisAlignment.center,
fontSize: 20, crossAxisAlignment: CrossAxisAlignment.center,
color: Colors.black, children: <Widget>[
fontWeight: FontWeight.w400, const SizedBox(height: 16),
fontFamily: 'Anek')), Container(
Text(widget.tradeName??'', padding:
style: const TextStyle( const EdgeInsets.all(20.0).copyWith(top: 30, bottom: 30),
fontSize: 20, margin: const EdgeInsets.symmetric(horizontal: 16.0),
color: Colors.black, decoration: BoxDecoration(
fontWeight: FontWeight.w400, border: Border.all(color: Colors.white),
fontFamily: 'Anek')), color: const Color(0xffB4D1E5).withOpacity(0.9),
], borderRadius: BorderRadius.circular(26.0)),
), child: Column(
backgroundColor: Colors.transparent, crossAxisAlignment: CrossAxisAlignment.start,
elevation: 0, children: <Widget>[
), CommonTextFormField(
drawer: const CommonDrawer(), readOnly: true,
body: SingleChildScrollView( title: 'Select Retailer',
physics: const BouncingScrollPhysics(), fillColor: Colors.white,
child: Column( controller: retailerController),
mainAxisAlignment: MainAxisAlignment.center, const SizedBox(height: 15),
crossAxisAlignment: CrossAxisAlignment.center, CommonTextFormField(
children: <Widget>[ title: 'Visit date',
const SizedBox(height: 16), readOnly: true,
Container( fillColor: Colors.white,
padding: controller: dateController),
const EdgeInsets.all(20.0).copyWith(top: 30, bottom: 30), const SizedBox(height: 15),
margin: const EdgeInsets.symmetric(horizontal: 16.0), CommonTextFormField(
decoration: BoxDecoration( title: 'Time',
border: Border.all(color: Colors.white), readOnly: true,
color: const Color(0xffB4D1E5).withOpacity(0.9), fillColor: Colors.white,
borderRadius: BorderRadius.circular(26.0)), controller: timeController),
child: Column( const SizedBox(height: 15),
crossAxisAlignment: CrossAxisAlignment.start, DropdownButtonFormField<String>(
children: <Widget>[ decoration: const InputDecoration(
CommonTextFormField( labelText: 'Purpose of visit',
readOnly: true, fillColor: Colors.white,
title: 'Select Retailer', filled: true,
fillColor: Colors.white, ),
controller: retailerController), value: selectedPurpose,
const SizedBox(height: 15), items: purposeOptions.map((String value) {
CommonTextFormField( return DropdownMenuItem<String>(
title: 'Visit date', value: value,
readOnly: true, child: Text(value),
fillColor: Colors.white, );
controller: dateController), }).toList(),
const SizedBox(height: 15), onChanged: (String? newValue) {
CommonTextFormField( setState(() {
title: 'Time', selectedPurpose = newValue!;
readOnly: true, });
fillColor: Colors.white, },
controller: timeController), ),
const SizedBox(height: 15), const SizedBox(height: 15),
DropdownButtonFormField<String>( CommonTextFormField(
decoration: const InputDecoration( title: 'Meeting summary:',
labelText: 'Purpose of visit', fillColor: Colors.white,
fillColor: Colors.white, maxLines: 3,
filled: true, controller: meetingSummaryController),
), const SizedBox(height: 15),
value: selectedPurpose, CommonTextFormField(
items: purposeOptions.map((String value) { title: 'Follow-up Actions:',
return DropdownMenuItem<String>( fillColor: Colors.white,
value: value, maxLines: 3,
child: Text(value), controller: followUpActionsController),
); const SizedBox(height: 15),
}).toList(), GestureDetector(
onChanged: (String? newValue) { onTap: _selectNextVisitDate,
setState(() { child: AbsorbPointer(
selectedPurpose = newValue!; child: CommonTextFormField(
}); title: 'Next visit date:',
}, readOnly: true,
), fillColor: Colors.white,
const SizedBox(height: 15), controller: nextVisitDateController,
CommonTextFormField( ),
title: 'Meeting Summary:', ),
fillColor: Colors.white, ),
maxLines: 3, const SizedBox(height: 15),
controller: meetingSummaryController), Row(
const SizedBox(height: 15), children: [
CommonTextFormField( Expanded(
title: 'Follow-up Actions:', child: CommonTextFormField(
fillColor: Colors.white, title: 'Attach Documents/Photos',
maxLines: 3, fillColor: Colors.white,
controller: followUpActionsController), controller: notesController),
const SizedBox(height: 15), ),
CommonTextFormField( IconButton(
title: 'Next visit date:', icon: const Icon(Icons.add_a_photo),
readOnly: true, onPressed: _showImageSourceActionSheet,
fillColor: Colors.white, ),
controller: nextVisitDateController), ],
const SizedBox(height: 15), ),
Row( const SizedBox(height: 15),
children: [ Consumer<VisitPdRdProvider>(builder: (context, value, child) => Align(
Expanded( alignment: Alignment.center,
child: CommonTextFormField( child: CommonElevatedButton(
title: 'Attach Documents/Photos', borderRadius: 30,
fillColor: Colors.white, width: double.infinity,
controller: notesController), 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<VisitPdRdProvider>(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<VisitPdRdProvider>(builder: (context, value, child) {
if (value.isLoading) {
return Container(
color: Colors.black.withOpacity(0.5),
child: const Center(
child: CircularProgressIndicator(),
),
);
}
return const SizedBox.shrink();
}),
],
), ),
), ),
); );

View File

@ -23,4 +23,5 @@ class ApiUrls {
static const String getProductsManual = '${baseUrl}productmanual/getall'; static const String getProductsManual = '${baseUrl}productmanual/getall';
static const String salesTaskUrl = '${baseUrl}product/getAll/user/'; static const String salesTaskUrl = '${baseUrl}product/getAll/user/';
static const String postSalesTaskUrl = '${baseUrl}sales/add-SC'; static const String postSalesTaskUrl = '${baseUrl}sales/add-SC';
static const String submitVisitUrl = '${baseUrl}visit';
} }