Bug fixes
This commit is contained in:
parent
7d424edc11
commit
bced613c1d
@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:cheminova/constants/constant.dart';
|
import 'package:cheminova/constants/constant.dart';
|
||||||
import 'package:cheminova/provider/add_sales_provider.dart';
|
import 'package:cheminova/provider/add_sales_provider.dart';
|
||||||
import 'package:cheminova/provider/collect_kyc_provider.dart';
|
import 'package:cheminova/provider/collect_kyc_provider.dart';
|
||||||
|
import 'package:cheminova/provider/notification_provider.dart';
|
||||||
import 'package:cheminova/provider/pd_rd_provider.dart';
|
import 'package:cheminova/provider/pd_rd_provider.dart';
|
||||||
import 'package:cheminova/provider/product_manual_provider.dart';
|
import 'package:cheminova/provider/product_manual_provider.dart';
|
||||||
import 'package:cheminova/provider/product_provider.dart';
|
import 'package:cheminova/provider/product_provider.dart';
|
||||||
@ -109,6 +110,7 @@ Future<void> main() async {
|
|||||||
ChangeNotifierProvider(create: (_) => TaskProvider()),
|
ChangeNotifierProvider(create: (_) => TaskProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => ProductManualProvider()),
|
ChangeNotifierProvider(create: (_) => ProductManualProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => AddSalesProvider()),
|
ChangeNotifierProvider(create: (_) => AddSalesProvider()),
|
||||||
|
ChangeNotifierProvider(create: (_) => NotificationProvider()),
|
||||||
],
|
],
|
||||||
child: const MyApp(),
|
child: const MyApp(),
|
||||||
),
|
),
|
||||||
|
19
lib/models/announcement_model.dart
Normal file
19
lib/models/announcement_model.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class AnnouncementModel {
|
||||||
|
String id;
|
||||||
|
String message;
|
||||||
|
String date;
|
||||||
|
|
||||||
|
AnnouncementModel({
|
||||||
|
required this.id,
|
||||||
|
required this.message,
|
||||||
|
required this.date,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory AnnouncementModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return AnnouncementModel(
|
||||||
|
id: json['_id'],
|
||||||
|
message: json['message'],
|
||||||
|
date: json['createdAt'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -65,7 +65,7 @@ class ShippingAddress {
|
|||||||
postalCode: json['postalCode'] ?? '',
|
postalCode: json['postalCode'] ?? '',
|
||||||
country: json['country'] ?? '',
|
country: json['country'] ?? '',
|
||||||
panNumber: json['panNumber'] ?? '',
|
panNumber: json['panNumber'] ?? '',
|
||||||
tradeName: json['tradeName'] ?? '',
|
tradeName: json['tradeName'] ?? 'XYZ',
|
||||||
gstNumber: json['gstNumber'] ?? '',
|
gstNumber: json['gstNumber'] ?? '',
|
||||||
isDefault: json['isDefault'] ?? false,
|
isDefault: json['isDefault'] ?? false,
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,6 @@ import 'package:cheminova/services/secure__storage_service.dart';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
class LoginProvider extends ChangeNotifier {
|
class LoginProvider extends ChangeNotifier {
|
||||||
final _storageService = SecureStorageService();
|
final _storageService = SecureStorageService();
|
||||||
|
|
||||||
@ -29,7 +28,8 @@ class LoginProvider extends ChangeNotifier {
|
|||||||
'email': emailController.text.trim(),
|
'email': emailController.text.trim(),
|
||||||
'password': passwordController.text.trim()
|
'password': passwordController.text.trim()
|
||||||
});
|
});
|
||||||
setLoading(false);
|
|
||||||
|
// Handle successful response
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
await _storageService.write(
|
await _storageService.write(
|
||||||
key: 'access_token', value: response.data['token']);
|
key: 'access_token', value: response.data['token']);
|
||||||
@ -37,12 +37,25 @@ class LoginProvider extends ChangeNotifier {
|
|||||||
print('fcmToken: $fcmToken');
|
print('fcmToken: $fcmToken');
|
||||||
await _apiClient.post(ApiUrls.fcmUrl, data: {'fcmToken': fcmToken});
|
await _apiClient.post(ApiUrls.fcmUrl, data: {'fcmToken': fcmToken});
|
||||||
return (true, response.data['message'].toString());
|
return (true, response.data['message'].toString());
|
||||||
} else {
|
|
||||||
return (false, response.data['message'].toString());
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
|
// Handle other status codes
|
||||||
|
setLoading(false);
|
||||||
|
return (false, response.data['message'].toString());
|
||||||
|
} catch (e) {
|
||||||
|
// Handle DioError specifically
|
||||||
|
if (e is DioException) {
|
||||||
|
setLoading(false);
|
||||||
|
if (e.response != null && e.response!.statusCode == 400) {
|
||||||
|
return (false, e.response!.data['message'].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
// Return a more informative error message if there's an exception
|
||||||
|
return (false, 'Something went wrong: ${e.toString()}');
|
||||||
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return (false, 'Something want wrong');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:cheminova/models/announcement_model.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -13,10 +14,12 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
final _apiClient = ApiClient();
|
final _apiClient = ApiClient();
|
||||||
List<Notifications> notificationList = [];
|
List<Notifications> notificationList = [];
|
||||||
|
List<AnnouncementModel> _announcementList = [];
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
|
List<AnnouncementModel> get announcementList => _announcementList;
|
||||||
|
|
||||||
void setLoading(bool loading) {
|
void setLoading(bool loading) {
|
||||||
_isLoading = loading;
|
_isLoading = loading;
|
||||||
@ -37,4 +40,21 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getAnnouncement() async {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
Response response = await _apiClient.get(ApiUrls.announcements);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
_announcementList = (response.data as List)
|
||||||
|
.map((e) => AnnouncementModel.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
93
lib/screens/announcement_screen.dart
Normal file
93
lib/screens/announcement_screen.dart
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import 'package:cheminova/provider/notification_provider.dart';
|
||||||
|
import 'package:cheminova/utils/string_extension.dart';
|
||||||
|
import 'package:cheminova/widgets/common_app_bar.dart';
|
||||||
|
import 'package:cheminova/widgets/common_background.dart';
|
||||||
|
import 'package:cheminova/widgets/common_drawer.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class AnnouncementScreen extends StatefulWidget {
|
||||||
|
const AnnouncementScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AnnouncementScreen> createState() => _AnnouncementScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnnouncementScreenState extends State<AnnouncementScreen> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
context.read<NotificationProvider>().getAnnouncement();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final notificationProvider = context.watch<NotificationProvider>();
|
||||||
|
return 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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
title: const Text('Announcement',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontFamily: 'Anek')),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
elevation: 0,
|
||||||
|
),
|
||||||
|
drawer: const CommonDrawer(),
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
ListView.builder(
|
||||||
|
itemCount: notificationProvider.announcementList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
bottom: 10,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
|
child: ListTile(
|
||||||
|
title: const Text('Message:'),
|
||||||
|
subtitle: Text(
|
||||||
|
'${notificationProvider.announcementList[index].message.capitalize()}\nDate: ${DateFormat("dd/MM/yyyy").format(
|
||||||
|
DateTime.parse(notificationProvider
|
||||||
|
.announcementList[index].date),
|
||||||
|
)}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
if (notificationProvider.isLoading)
|
||||||
|
Container(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withOpacity(0.2),
|
||||||
|
),
|
||||||
|
child: const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -394,15 +394,12 @@ class _AssignTasksScreenState extends State<AssignTasksScreen> {
|
|||||||
.map((PdRdResponseModel distributor) {
|
.map((PdRdResponseModel distributor) {
|
||||||
return DropdownMenuItem<PdRdResponseModel>(
|
return DropdownMenuItem<PdRdResponseModel>(
|
||||||
value: distributor,
|
value: distributor,
|
||||||
child: Text(
|
child: Text(((selectedDistributorType ==
|
||||||
(selectedDistributorType ==
|
'PrincipalDistributor')
|
||||||
'PrincipalDistributor'
|
|
||||||
? distributor
|
? distributor
|
||||||
.shippingAddress!.tradeName
|
.shippingAddress!.tradeName
|
||||||
.capitalize()
|
: distributor.kyc!.tradeName)
|
||||||
: distributor.kyc!.tradeName
|
|
||||||
.capitalize()),
|
.capitalize()),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
@ -123,6 +123,7 @@ class _ChangePasswordPageState extends State<ChangePasswordPage> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
controller: _oldPasswordController,
|
controller: _oldPasswordController,
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your password';
|
return 'Please enter your password';
|
||||||
@ -133,6 +134,7 @@ class _ChangePasswordPageState extends State<ChangePasswordPage> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
controller: _newPasswordController,
|
controller: _newPasswordController,
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your password';
|
return 'Please enter your password';
|
||||||
@ -143,6 +145,7 @@ class _ChangePasswordPageState extends State<ChangePasswordPage> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
controller: _confirmPasswordController,
|
controller: _confirmPasswordController,
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your password';
|
return 'Please enter your password';
|
||||||
|
@ -141,6 +141,8 @@ class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
title: ' Enter Your Email ID',
|
title: ' Enter Your Email ID',
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your email id';
|
return 'Please enter your email id';
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:cheminova/notification_service.dart';
|
import 'package:cheminova/notification_service.dart';
|
||||||
import 'package:cheminova/provider/user_provider.dart';
|
import 'package:cheminova/provider/user_provider.dart';
|
||||||
|
import 'package:cheminova/screens/announcement_screen.dart';
|
||||||
import 'package:cheminova/screens/visit_rd_pd_screen.dart';
|
import 'package:cheminova/screens/visit_rd_pd_screen.dart';
|
||||||
import 'package:cheminova/screens/assign_task_dash_board_screen.dart';
|
import 'package:cheminova/screens/assign_task_dash_board_screen.dart';
|
||||||
import 'package:cheminova/screens/calendar_screen.dart';
|
import 'package:cheminova/screens/calendar_screen.dart';
|
||||||
@ -188,10 +189,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Row(
|
_buildCustomCard('Rejected Applications',
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: _buildCustomCard('Rejected Applications',
|
|
||||||
'Re-upload Rejected Documents', onTap: () {
|
'Re-upload Rejected Documents', onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
@ -200,9 +198,15 @@ class _HomePageState extends State<HomePage> {
|
|||||||
const RejectedApplicationScreen(),
|
const RejectedApplicationScreen(),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
),
|
const SizedBox(height: 5),
|
||||||
],
|
_buildCustomCard('Announcements', 'Announcements for you',
|
||||||
),
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const AnnouncementScreen(),
|
||||||
|
));
|
||||||
|
}),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -87,6 +87,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
Consumer<LoginProvider>(
|
Consumer<LoginProvider>(
|
||||||
builder: (context, value, child) =>
|
builder: (context, value, child) =>
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
controller: value.emailController,
|
controller: value.emailController,
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
@ -99,12 +100,14 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
title: 'Username'),
|
title: 'Email'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Consumer<LoginProvider>(
|
Consumer<LoginProvider>(
|
||||||
builder: (context, value, child) =>
|
builder: (context, value, child) =>
|
||||||
CommonTextFormField(
|
CommonTextFormField(
|
||||||
|
textCapitalization: TextCapitalization.none,
|
||||||
|
obscureText: true,
|
||||||
controller: value.passwordController,
|
controller: value.passwordController,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
@ -112,7 +115,9 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
title: 'Password')),
|
title: 'Password',
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
|
@ -178,11 +178,11 @@ class _SelectDistributerScreenState extends State<SelectDistributerScreen> {
|
|||||||
return DropdownMenuItem<PdRdResponseModel>(
|
return DropdownMenuItem<PdRdResponseModel>(
|
||||||
value: distributor,
|
value: distributor,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedDistributorType ==
|
((selectedDistributorType ==
|
||||||
'PrincipalDistributor'
|
'Principal Distributor')
|
||||||
? distributor.shippingAddress!.tradeName
|
? distributor.shippingAddress!.tradeName
|
||||||
.capitalize()
|
: distributor.kyc!.tradeName)
|
||||||
: distributor.kyc!.tradeName.capitalize(),
|
.capitalize(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
@ -24,4 +24,5 @@ class ApiUrls {
|
|||||||
static const String postSalesTaskUrl = '${baseUrl}sales/add-TM';
|
static const String postSalesTaskUrl = '${baseUrl}sales/add-TM';
|
||||||
static const String visitRdPd = '$baseUrl/visit';
|
static const String visitRdPd = '$baseUrl/visit';
|
||||||
static const String allTaskByDate = '${baseUrl}task/alltask';
|
static const String allTaskByDate = '${baseUrl}task/alltask';
|
||||||
|
static const String announcements = '${baseUrl}announcement/TMs';
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
extension StringExtension on String {
|
extension StringExtension on String {
|
||||||
String capitalize() {
|
String capitalize() {
|
||||||
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
|
if (isEmpty) return this;
|
||||||
|
return "${this[0].toUpperCase()}${substring(1)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class CommonDrawer extends StatelessWidget {
|
|||||||
leading: const Icon(Icons.home),
|
leading: const Icon(Icons.home),
|
||||||
title: const Text('Home'),
|
title: const Text('Home'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const HomePage()),
|
MaterialPageRoute(builder: (context) => const HomePage()),
|
||||||
);
|
);
|
||||||
|
@ -48,8 +48,8 @@ class CommonTextFormField extends StatelessWidget {
|
|||||||
controller: controller,
|
controller: controller,
|
||||||
textCapitalization: textCapitalization,
|
textCapitalization: textCapitalization,
|
||||||
readOnly: readOnly ?? false,
|
readOnly: readOnly ?? false,
|
||||||
maxLines: maxLines,
|
// maxLines: maxLines,
|
||||||
maxLength: maxLength,
|
// maxLength: maxLength,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
onTapOutside: (event) => FocusScope.of(context).unfocus(),
|
onTapOutside: (event) => FocusScope.of(context).unfocus(),
|
||||||
validator: validator,
|
validator: validator,
|
||||||
|
Loading…
Reference in New Issue
Block a user