1)Push notification added
This commit is contained in:
parent
e40371ad6a
commit
410c8903ae
@ -19,6 +19,10 @@ pluginManagement {
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.3.0" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id "com.google.gms.google-services" version "4.3.15" apply false
|
||||
id "com.google.firebase.crashlytics" version "2.8.1" apply false
|
||||
// END: FlutterFire Configuration
|
||||
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
|
||||
}
|
||||
|
||||
|
36
lib/controller/notification_api_service.dart
Normal file
36
lib/controller/notification_api_service.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:cheminova/models/notification_model.dart';
|
||||
import 'package:cheminova/utils/api_urls.dart';
|
||||
|
||||
import '../utils/common_api_service.dart';
|
||||
|
||||
class NotificationApiService {
|
||||
Future<List<NotificationModel>?> getNotification(String token) async {
|
||||
try {
|
||||
String url =ApiUrls.getNotificationUrl; // Base URL to fetch product manuals
|
||||
|
||||
final response = await commonApiService<List<NotificationModel>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
additionalHeaders: { // Pass the token here
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
fromJson: (json) {
|
||||
if (json['notifications'] != null) {
|
||||
// Map the list of product manuals from the response
|
||||
final List<NotificationModel> notification = (json['notifications'] as List)
|
||||
.map((manualJson) => NotificationModel.fromJson(manualJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
return notification;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
|
||||
print(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
50
lib/controller/notification_controller.dart
Normal file
50
lib/controller/notification_controller.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:cheminova/controller/notification_api_service.dart';
|
||||
import 'package:cheminova/controller/product_mannual_service.dart';
|
||||
import 'package:cheminova/models/notification_model.dart';
|
||||
import 'package:cheminova/notification_service.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/product_mannual_model.dart'; // Your model import
|
||||
// Your service import
|
||||
|
||||
class NotificationController extends GetxController {
|
||||
|
||||
var notificationList = <NotificationModel>[].obs;
|
||||
|
||||
// Service to fetch data
|
||||
final NotificationApiService notificationApiService = NotificationApiService();
|
||||
|
||||
// Loading state
|
||||
var isLoading = false.obs;
|
||||
|
||||
// Method to fetch product manuals from the service
|
||||
void fetchNotificationApiService() async {
|
||||
try {
|
||||
// Set loading to true
|
||||
isLoading.value = true;
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
var manuals = await notificationApiService.getNotification(token!);
|
||||
|
||||
// If data is returned, update the list
|
||||
if (manuals != null) {
|
||||
notificationList .value = manuals;
|
||||
} else {
|
||||
notificationList.value = []; // If no data, set an empty list
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle error here, for example logging or showing an error message
|
||||
print("Error fetching product manuals: $e");
|
||||
} finally {
|
||||
// Set loading to false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// Fetch product manuals when the controller is initialized
|
||||
fetchNotificationApiService();
|
||||
super.onInit();
|
||||
}
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
|
||||
|
||||
import 'package:cheminova/utils/api_urls.dart';
|
||||
|
||||
import '../models/product_mannual_model.dart';
|
||||
import '../utils/common_api_service.dart'; // Replace with your actual common API service import
|
||||
|
||||
class ProductMannualService {
|
||||
Future<List<ProductManualModel>?> getProductManuals(String token) async {
|
||||
try {
|
||||
String url = "/api/productmanual/getall"; // Base URL to fetch product manuals
|
||||
String url = ApiUrls.getProductManualUrl; // Base URL to fetch product manuals
|
||||
|
||||
final response = await commonApiService<List<ProductManualModel>>(
|
||||
method: "GET",
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'package:cheminova/utils/api_urls.dart';
|
||||
|
||||
import '../models/product_model1.dart';
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
@ -7,7 +9,7 @@ class ProductService {
|
||||
try {
|
||||
String url;
|
||||
if (category != null && category.isNotEmpty) {
|
||||
url = "/api/product/getAll/user?page=$page&category=$category";
|
||||
url = "ApiUrls.getProductUrl?page=$page&category=$category";
|
||||
} else {
|
||||
url = "/api/product/getAll/user?page=$page"; // URL without category filter
|
||||
}
|
||||
@ -39,7 +41,7 @@ class ProductService {
|
||||
try {
|
||||
final response = await commonApiService<List<Map<String, dynamic>>>(
|
||||
method: "GET",
|
||||
url: "/api/category/getCategories",
|
||||
url: ApiUrls.getCategoryUrl,
|
||||
fromJson: (json) {
|
||||
if (json['categories'] != null) {
|
||||
final List<Map<String, dynamic>> category = (json['categories'] as List)
|
||||
|
@ -1,8 +1,23 @@
|
||||
import 'package:cheminova/screens/splash_screen.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
|
||||
import 'firebase_options.dart';
|
||||
|
||||
var box;
|
||||
void main()async{
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
|
||||
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
await Hive.initFlutter();
|
||||
await Hive.openBox('cartBox');
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
|
67
lib/models/notification_model.dart
Normal file
67
lib/models/notification_model.dart
Normal file
@ -0,0 +1,67 @@
|
||||
class NotificationModel {
|
||||
String? id;
|
||||
String? title;
|
||||
String? msg;
|
||||
String? addedFor;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
int? v;
|
||||
|
||||
NotificationModel({
|
||||
this.id,
|
||||
this.title,
|
||||
this.msg,
|
||||
this.addedFor,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.v,
|
||||
});
|
||||
|
||||
factory NotificationModel.fromJson(Map<String, dynamic> json) {
|
||||
return NotificationModel(
|
||||
id: json['_id'],
|
||||
title: json['title'],
|
||||
msg: json['msg'],
|
||||
addedFor: json['added_for'],
|
||||
createdAt: json['createdAt'],
|
||||
updatedAt: json['updatedAt'],
|
||||
v: json['__v'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'title': title,
|
||||
'msg': msg,
|
||||
'added_for': addedFor,
|
||||
'createdAt': createdAt,
|
||||
'updatedAt': updatedAt,
|
||||
'__v': v,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationResponse {
|
||||
String? returnMessage;
|
||||
List<NotificationModel>? notifications;
|
||||
|
||||
NotificationResponse({this.returnMessage, this.notifications});
|
||||
|
||||
factory NotificationResponse.fromJson(Map<String, dynamic> json) {
|
||||
return NotificationResponse(
|
||||
returnMessage: json['return_message'],
|
||||
notifications: json['notifications'] != null
|
||||
? List<NotificationModel>.from(json['notifications']
|
||||
.map((notification) => NotificationModel.fromJson(notification)))
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'return_message': returnMessage,
|
||||
'notifications': notifications?.map((notification) => notification.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
165
lib/notification_service.dart
Normal file
165
lib/notification_service.dart
Normal file
@ -0,0 +1,165 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
class NotificationServices {
|
||||
//initialising firebase message plugin
|
||||
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
||||
|
||||
//initialising firebase message plugin
|
||||
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
//function to initialise flutter local notification plugin to show notifications for android when app is active
|
||||
void initLocalNotifications(
|
||||
BuildContext context, RemoteMessage message) async {
|
||||
var androidInitializationSettings =
|
||||
const AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||
var iosInitializationSettings = const DarwinInitializationSettings();
|
||||
|
||||
var initializationSetting = InitializationSettings(
|
||||
android: androidInitializationSettings, iOS: iosInitializationSettings);
|
||||
|
||||
await _flutterLocalNotificationsPlugin.initialize(initializationSetting,
|
||||
onDidReceiveNotificationResponse: (payload) {
|
||||
// handle interaction when app is active for android
|
||||
handleMessage(context, message);
|
||||
});
|
||||
}
|
||||
|
||||
void firebaseInit(BuildContext context) {
|
||||
FirebaseMessaging.onMessage.listen((message) {
|
||||
RemoteNotification? notification = message.notification;
|
||||
AndroidNotification? android = message.notification!.android;
|
||||
|
||||
if (kDebugMode) {
|
||||
print("notifications title:${notification!.title}");
|
||||
print("notifications body:${notification.body}");
|
||||
print('count:${android!.count}');
|
||||
print('data:${message.data.toString()}');
|
||||
}
|
||||
|
||||
if (Platform.isIOS) {
|
||||
forgroundMessage();
|
||||
}
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
initLocalNotifications(context, message);
|
||||
showNotification(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void requestNotificationPermission() async {
|
||||
NotificationSettings settings = await messaging.requestPermission(
|
||||
alert: true,
|
||||
announcement: true,
|
||||
badge: true,
|
||||
carPlay: true,
|
||||
criticalAlert: true,
|
||||
provisional: true,
|
||||
sound: true,
|
||||
);
|
||||
|
||||
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
|
||||
if (kDebugMode) {
|
||||
print('user granted permission');
|
||||
}
|
||||
} else if (settings.authorizationStatus ==
|
||||
AuthorizationStatus.provisional) {
|
||||
if (kDebugMode) {
|
||||
print('user granted provisional permission');
|
||||
}
|
||||
} else {
|
||||
//appsetting.AppSettings.openNotificationSettings();
|
||||
if (kDebugMode) {
|
||||
print('user denied permission');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function to show visible notification when app is active
|
||||
Future<void> showNotification(RemoteMessage message) async {
|
||||
AndroidNotificationChannel channel = AndroidNotificationChannel(
|
||||
message.notification!.android!.channelId.toString(),
|
||||
message.notification!.android!.channelId.toString(),
|
||||
importance: Importance.max,
|
||||
showBadge: true,
|
||||
playSound: true,
|
||||
sound: const RawResourceAndroidNotificationSound('jetsons_doorbell'));
|
||||
|
||||
AndroidNotificationDetails androidNotificationDetails =
|
||||
AndroidNotificationDetails(
|
||||
channel.id.toString(), channel.name.toString(),
|
||||
channelDescription: 'your channel description',
|
||||
importance: Importance.high,
|
||||
priority: Priority.high,
|
||||
playSound: true,
|
||||
ticker: 'ticker',
|
||||
sound: channel.sound
|
||||
// sound: RawResourceAndroidNotificationSound('jetsons_doorbell')
|
||||
// icon: largeIconPath
|
||||
);
|
||||
|
||||
const DarwinNotificationDetails darwinNotificationDetails =
|
||||
DarwinNotificationDetails(
|
||||
presentAlert: true, presentBadge: true, presentSound: true);
|
||||
|
||||
NotificationDetails notificationDetails = NotificationDetails(
|
||||
android: androidNotificationDetails, iOS: darwinNotificationDetails);
|
||||
|
||||
Future.delayed(Duration.zero, () {
|
||||
_flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
message.notification!.title.toString(),
|
||||
message.notification!.body.toString(),
|
||||
notificationDetails,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
//function to get device token on which we will send the notifications
|
||||
Future<String> getDeviceToken() async {
|
||||
String? token = await messaging.getToken();
|
||||
return token!;
|
||||
}
|
||||
|
||||
void isTokenRefresh() async {
|
||||
messaging.onTokenRefresh.listen((event) {
|
||||
event.toString();
|
||||
if (kDebugMode) {
|
||||
print('refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//handle tap on notification when app is in background or terminated
|
||||
Future<void> setupInteractMessage(BuildContext context) async {
|
||||
// when app is terminated
|
||||
RemoteMessage? initialMessage =
|
||||
await FirebaseMessaging.instance.getInitialMessage();
|
||||
|
||||
if (initialMessage != null) {
|
||||
handleMessage(context, initialMessage);
|
||||
}
|
||||
|
||||
//when app ins background
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((event) {
|
||||
handleMessage(context, event);
|
||||
});
|
||||
}
|
||||
|
||||
void handleMessage(BuildContext context, RemoteMessage message) {}
|
||||
|
||||
Future forgroundMessage() async {
|
||||
await FirebaseMessaging.instance
|
||||
.setForegroundNotificationPresentationOptions(
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
import 'package:cheminova/controller/home_controller.dart';
|
||||
import 'package:cheminova/screens/inventory/inventory_management_screen.dart';
|
||||
import 'package:cheminova/screens/kyc/kyc_screen.dart';
|
||||
import 'package:cheminova/screens/notification/notification_screen.dart';
|
||||
import 'package:cheminova/screens/order/order_tracking_screen.dart';
|
||||
import 'package:cheminova/screens/order_management/order_management_screen.dart';
|
||||
import 'package:cheminova/screens/product/product_catalog_screen.dart';
|
||||
import 'package:cheminova/screens/product/product_mannual.dart';
|
||||
import 'package:cheminova/screens/report/order_history_report_screen.dart';
|
||||
import 'package:cheminova/screens/report/reporting_analytics_screen.dart';
|
||||
import 'package:cheminova/screens/retail/retail_distributer_on_boarding_screen.dart';
|
||||
@ -13,6 +16,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'kyc/kyc_retailer_info_screen.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
||||
@ -46,8 +51,23 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
title: const Text(
|
||||
"Welcome",
|
||||
),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Action for notification icon tap
|
||||
Get.to(() => NotificationScreen());
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 16.0), // Add padding to align with the AppBar edges
|
||||
child: const Icon(
|
||||
Icons.notifications, // Notification icon
|
||||
color: Colors.white, // Icon color (customize as needed)
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
@ -59,6 +79,8 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 15.0,),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
@ -112,6 +134,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
() => const ReportingAnalyticsScreen(),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@ -131,9 +154,32 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
HomeCard(
|
||||
title: 'Product Mannual',
|
||||
onTap: () => Get.to(
|
||||
() => const ProductsManualScreen(),
|
||||
),
|
||||
),
|
||||
HomeCard(
|
||||
title: 'Kyc',
|
||||
onTap: () => Get.to(
|
||||
() => KycRetailerInfoScreen(),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -67,7 +67,7 @@ class _InventoryManagementScreenState extends State<InventoryManagementScreen> {
|
||||
"Inventory Management",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
131
lib/screens/notification/notification_screen.dart
Normal file
131
lib/screens/notification/notification_screen.dart
Normal file
@ -0,0 +1,131 @@
|
||||
import 'package:cheminova/controller/notification_controller.dart';
|
||||
import 'package:cheminova/models/notification_model.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../widgets/comman_background.dart';
|
||||
import '../../widgets/common_appbar.dart';
|
||||
|
||||
class NotificationScreen extends StatelessWidget {
|
||||
NotificationScreen({super.key});
|
||||
|
||||
// Initialize the controller
|
||||
final NotificationController notificationController = Get.put(NotificationController());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Fetch notifications when the screen is first built
|
||||
notificationController.fetchNotificationApiService();
|
||||
|
||||
return CommonBackground(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: CommonAppBar(
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: SvgPicture.asset('assets/svg/back_arrow.svg'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
),
|
||||
],
|
||||
title: const Text('Notification',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontFamily: 'Anek')),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
),
|
||||
drawer: MyDrawer(),
|
||||
body: Obx(() {
|
||||
// Show a loading indicator while data is being fetched
|
||||
if (notificationController.isLoading.value) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (notificationController.notificationList.isEmpty) {
|
||||
// Handle empty state
|
||||
return const Center(child: Text("No notifications available"));
|
||||
} else {
|
||||
// Show the notification list once data is fetched
|
||||
return MyListView(notificationList: notificationController.notificationList);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyListView extends StatelessWidget {
|
||||
final List<NotificationModel> notificationList;
|
||||
|
||||
const MyListView({super.key, required this.notificationList});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Group notifications by date
|
||||
Map<String, List<NotificationModel>> groupedNotifications = {};
|
||||
|
||||
for (var notification in notificationList) {
|
||||
// Ensure that 'notifications' is not null
|
||||
if (notification != null) {
|
||||
String date = DateFormat("dd MMM yyyy")
|
||||
.format(DateTime.parse(notification.createdAt ?? ''));
|
||||
if (!groupedNotifications.containsKey(date)) {
|
||||
groupedNotifications[date] = [];
|
||||
}
|
||||
groupedNotifications[date]!.add(notification);
|
||||
}
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
itemCount: groupedNotifications.length,
|
||||
itemBuilder: (context, index) {
|
||||
String date = groupedNotifications.keys.elementAt(index);
|
||||
List<NotificationModel> notificationsForDate = groupedNotifications[date]!;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Display the date once
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
date,
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
// Display notifications for the date
|
||||
...notificationsForDate.map(
|
||||
(notification) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: ExpansionTile(
|
||||
collapsedBackgroundColor: Colors.white,
|
||||
backgroundColor: Colors.white,
|
||||
trailing: const SizedBox.shrink(),
|
||||
title: Text(
|
||||
notification.title ?? 'No title',
|
||||
style: const TextStyle(
|
||||
fontSize: 17, fontWeight: FontWeight.w500),
|
||||
),
|
||||
subtitle: Text(notification.msg ?? 'No message'),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -204,7 +204,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
],
|
||||
title: const Text("Checkout"),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -80,7 +80,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
"Order Confirmation",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -61,7 +61,7 @@ class _OrderDetailScreenState extends State<OrderDetailScreen> {
|
||||
"Order Detail",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -56,7 +56,7 @@ class _OrderTrackingScreenState extends State<OrderTrackingScreen> {
|
||||
"Order Tracking",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -48,7 +48,7 @@ class _ShipmentTrackingScreenState extends State<ShipmentTrackingScreen> {
|
||||
"Shipment Tracking",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -87,7 +87,7 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
],
|
||||
title: const Text("Order Management"),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -90,7 +90,7 @@ class _CartScreenState extends State<CartScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -175,7 +175,7 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -64,7 +64,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
"Product Detail",
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
drawer: MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
@ -46,6 +46,7 @@ class _ProductsManualScreenState extends State<ProductsManualScreen> {
|
||||
return AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
title: Center(child: Text("Product Manual")),
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Padding(
|
||||
|
@ -50,6 +50,7 @@ Future<BodyType?> commonApiService<BodyType>({
|
||||
if (method == "POST") {
|
||||
response = await dio.post("$baseUrl$url",
|
||||
data: isformData ? formData : body, options: options);
|
||||
|
||||
} else if (method == "PUT") {
|
||||
response = await dio.put("$baseUrl$url",
|
||||
data: isformData ? formData : body, options: options);
|
||||
@ -69,13 +70,14 @@ Future<BodyType?> commonApiService<BodyType>({
|
||||
prefs.setString('token', response.data['token']);
|
||||
}
|
||||
|
||||
if (url == "/api/territorymanager/my-profile") {
|
||||
return fromJson(response.data['myData']);
|
||||
}
|
||||
// if (url == "/api/territorymanager/my-profile") {
|
||||
// return fromJson(response.data['myData']);
|
||||
// }
|
||||
|
||||
return fromJson(response.data);
|
||||
} on DioException catch (e) {
|
||||
print("dio exception $url ${e.response?.data}}");
|
||||
|
||||
print("dio exception details: ${e.message} ${e.response?.statusCode}");
|
||||
String errorMessage = "An error occurred";
|
||||
|
||||
|
37
lib/utils/secure__storage_service.dart
Normal file
37
lib/utils/secure__storage_service.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
class SecureStorageService {
|
||||
// Create a private constructor
|
||||
SecureStorageService._privateConstructor();
|
||||
|
||||
// The single instance of the class
|
||||
static final SecureStorageService _instance = SecureStorageService._privateConstructor();
|
||||
|
||||
// The single instance of FlutterSecureStorage
|
||||
final FlutterSecureStorage _storage = const FlutterSecureStorage();
|
||||
|
||||
// Factory constructor to return the same instance
|
||||
factory SecureStorageService() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
// Method to write data to secure storage
|
||||
Future<void> write({required String key, required String value}) async {
|
||||
await _storage.write(key: key, value: value);
|
||||
}
|
||||
|
||||
// Method to read data from secure storage
|
||||
Future<String?> read({required String key}) async {
|
||||
return await _storage.read(key: key);
|
||||
}
|
||||
|
||||
// Method to delete data from secure storage
|
||||
Future<void> delete({required String key}) async {
|
||||
await _storage.delete(key: key);
|
||||
}
|
||||
|
||||
// Method to clear all data from secure storage
|
||||
Future<void> clear() async {
|
||||
await _storage.deleteAll();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class CommonAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Widget title;
|
||||
@ -14,7 +15,9 @@ class CommonAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
leading: Builder(builder: (context) {
|
||||
return IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(Icons.menu),
|
||||
icon: SvgPicture.asset(
|
||||
'assets/svg/menu.svg',
|
||||
),
|
||||
color: Colors.white);
|
||||
}),
|
||||
backgroundColor: Colors.transparent,
|
||||
|
Loading…
Reference in New Issue
Block a user