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(
debugShowCheckedModeBanner: false,
navigatorKey: navigatorKey,
title: 'cheminova',
title: 'Cheminova',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true),

View File

@ -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<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);
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");
}
}
}
}

View File

@ -225,6 +225,7 @@ class _DailyTasksScreenState extends State<DailyTasksScreen> {
builder: (context) => VisitDealersScreen(
tradeName: tasksList.tradeName ?? '',
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/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';

View File

@ -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<VisitDealersScreen> createState() => VisitDealersScreenState();
@ -36,10 +37,62 @@ class VisitDealersScreenState extends State<VisitDealersScreen> {
String selectedPurpose = 'Sales';
List<String> purposeOptions = ['Sales', 'Dues collection', 'Others'];
Future<void> _pickImage() async {
Future<void> _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: <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
@ -55,147 +108,177 @@ class VisitDealersScreenState extends State<VisitDealersScreen> {
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: <Widget>[
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: <Widget>[
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<String>(
decoration: const InputDecoration(
labelText: 'Purpose of visit',
fillColor: Colors.white,
filled: true,
),
value: selectedPurpose,
items: purposeOptions.map((String value) {
return DropdownMenuItem<String>(
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: <Widget>[
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: <Widget>[
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<String>(
decoration: const InputDecoration(
labelText: 'Purpose of visit',
fillColor: Colors.white,
filled: true,
),
value: selectedPurpose,
items: purposeOptions.map((String value) {
return DropdownMenuItem<String>(
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<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 ?? '', 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 salesTaskUrl = '${baseUrl}product/getAll/user/';
static const String postSalesTaskUrl = '${baseUrl}sales/add-SC';
static const String submitVisitUrl = '${baseUrl}visit';
}