INFRA: Set Up Project.
This commit is contained in:
95
lib/service/cart_provider.dart
Normal file
95
lib/service/cart_provider.dart
Normal file
@@ -0,0 +1,95 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'package:customer/constant/constant.dart';
|
||||
import 'package:customer/models/cart_product_model.dart';
|
||||
import 'package:customer/themes/custom_dialog_box.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'database_helper.dart';
|
||||
|
||||
class CartProvider with ChangeNotifier {
|
||||
final _cartStreamController = StreamController<List<CartProductModel>>.broadcast();
|
||||
List<CartProductModel> _cartItems = [];
|
||||
|
||||
Stream<List<CartProductModel>> get cartStream => _cartStreamController.stream;
|
||||
|
||||
CartProvider() {
|
||||
_initCart();
|
||||
}
|
||||
|
||||
Future<void> _initCart() async {
|
||||
_cartItems = await DatabaseHelper.instance.fetchCartProducts();
|
||||
_cartStreamController.sink.add(_cartItems);
|
||||
}
|
||||
|
||||
Future<void> addToCart(BuildContext context, CartProductModel product, int quantity) async {
|
||||
_cartItems = await DatabaseHelper.instance.fetchCartProducts();
|
||||
if ((_cartItems.where((item) => item.id == product.id)).isNotEmpty) {
|
||||
var index = _cartItems.indexWhere((item) => item.id == product.id);
|
||||
_cartItems[index].quantity = quantity;
|
||||
if (product.extras != null || product.extras!.isNotEmpty) {
|
||||
_cartItems[index].extras = product.extras;
|
||||
_cartItems[index].extrasPrice = product.extrasPrice;
|
||||
} else {
|
||||
_cartItems[index].extras = [];
|
||||
_cartItems[index].extrasPrice = "0";
|
||||
}
|
||||
await DatabaseHelper.instance.updateCartProduct(_cartItems[index]);
|
||||
} else {
|
||||
if (_cartItems.isEmpty || _cartItems.where((item) => item.vendorID == product.vendorID).isNotEmpty) {
|
||||
product.quantity = quantity;
|
||||
_cartItems.add(product);
|
||||
cartItem.add(product);
|
||||
await DatabaseHelper.instance.insertCartProduct(product);
|
||||
log("===> insert");
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CustomDialogBox(
|
||||
title: "Alert".tr,
|
||||
descriptions: "Your cart already contains items from another restaurant. Would you like to replace them with items from this restaurant instead?".tr,
|
||||
positiveString: "Add".tr,
|
||||
negativeString: "Cancel".tr,
|
||||
positiveClick: () async {
|
||||
cartItem.clear();
|
||||
_cartItems.clear();
|
||||
DatabaseHelper.instance.deleteAllCartProducts();
|
||||
addToCart(context, product, quantity);
|
||||
Get.back();
|
||||
},
|
||||
negativeClick: () {
|
||||
Get.back();
|
||||
},
|
||||
img: null,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
_initCart();
|
||||
}
|
||||
|
||||
Future<void> removeFromCart(CartProductModel product, int quantity) async {
|
||||
_cartItems = await DatabaseHelper.instance.fetchCartProducts();
|
||||
var index = _cartItems.indexWhere((item) => item.id == product.id);
|
||||
if (index >= 0) {
|
||||
_cartItems[index].quantity = quantity;
|
||||
if (_cartItems[index].quantity == 0) {
|
||||
await DatabaseHelper.instance.deleteCartProduct(product.id!);
|
||||
_cartItems.removeAt(index);
|
||||
cartItem.removeAt(index);
|
||||
} else {
|
||||
await DatabaseHelper.instance.updateCartProduct(_cartItems[index]);
|
||||
}
|
||||
}
|
||||
_initCart();
|
||||
}
|
||||
|
||||
Future<void> clearDatabase() async {
|
||||
_cartItems.clear();
|
||||
cartItem.clear();
|
||||
_cartStreamController.sink.add(_cartItems);
|
||||
}
|
||||
}
|
||||
106
lib/service/database_helper.dart
Normal file
106
lib/service/database_helper.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'package:customer/constant/constant.dart';
|
||||
import 'package:customer/models/cart_product_model.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
class DatabaseHelper {
|
||||
static final DatabaseHelper instance = DatabaseHelper._init();
|
||||
static Database? _database;
|
||||
|
||||
DatabaseHelper._init();
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDB('cart.db');
|
||||
return _database!;
|
||||
}
|
||||
|
||||
Future<Database> _initDB(String filePath) async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = join(dbPath, filePath);
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 1,
|
||||
onCreate: _createDB,
|
||||
);
|
||||
}
|
||||
|
||||
Future _createDB(Database db, int version) async {
|
||||
// const idType = 'TEXT PRIMARY KEY';
|
||||
const textType = 'TEXT NOT NULL';
|
||||
const intType = 'INTEGER NOT NULL';
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE cart_products (
|
||||
id $textType,
|
||||
category_id $textType,
|
||||
name $textType,
|
||||
photo $textType,
|
||||
price $textType,
|
||||
discountPrice $textType,
|
||||
vendorID $textType,
|
||||
quantity $intType,
|
||||
extras_price $textType,
|
||||
extras $textType,
|
||||
variant_info $textType NULL
|
||||
)
|
||||
''');
|
||||
print('Table cart_products created'); // Debugging
|
||||
}
|
||||
|
||||
Future<void> insertCartProduct(CartProductModel product) async {
|
||||
log(product.toJson().toString());
|
||||
final db = await instance.database;
|
||||
await db.insert(
|
||||
'cart_products',
|
||||
product.toJson()
|
||||
..['variant_info'] = jsonEncode(product.variantInfo)
|
||||
..['extras'] = jsonEncode(product.extras),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<CartProductModel>> fetchCartProducts() async {
|
||||
final db = await instance.database;
|
||||
final maps = await db.query('cart_products');
|
||||
return List.generate(maps.length, (i) {
|
||||
return CartProductModel.fromJson(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateCartProduct(CartProductModel product) async {
|
||||
log(product.toJson().toString());
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
'cart_products',
|
||||
product.toJson()
|
||||
..['variant_info'] = jsonEncode(product.variantInfo)
|
||||
..['extras'] = jsonEncode(product.extras),
|
||||
where: 'id = ?',
|
||||
whereArgs: [product.id],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteCartProduct(String id) async {
|
||||
final db = await instance.database;
|
||||
await db.delete(
|
||||
'cart_products',
|
||||
where: 'id = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
}
|
||||
|
||||
Future close() async {
|
||||
final db = await instance.database;
|
||||
db.close();
|
||||
}
|
||||
|
||||
Future<void> deleteAllCartProducts() async {
|
||||
final db = await database;
|
||||
cartItem.clear();
|
||||
await db.delete('cart_products');
|
||||
}
|
||||
}
|
||||
3678
lib/service/fire_store_utils.dart
Normal file
3678
lib/service/fire_store_utils.dart
Normal file
File diff suppressed because it is too large
Load Diff
20
lib/service/localization_service.dart
Normal file
20
lib/service/localization_service.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../lang/app_en.dart';
|
||||
|
||||
class LocalizationService extends Translations {
|
||||
// Default locale
|
||||
static const locale = Locale('en', 'US');
|
||||
|
||||
static final locales = [const Locale('en')];
|
||||
|
||||
// Keys and their translations
|
||||
// Translations are separated maps in `lang` file
|
||||
@override
|
||||
Map<String, Map<String, String>> get keys => {'en_US': enUS};
|
||||
|
||||
// Gets locale from language, and updates the locale
|
||||
void changeLocale(String lang) {
|
||||
Get.updateLocale(Locale(lang));
|
||||
}
|
||||
}
|
||||
109
lib/service/notification_service.dart
Normal file
109
lib/service/notification_service.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
Future<void> firebaseMessageBackgroundHandle(RemoteMessage message) async {
|
||||
log("BackGround Message :: ${message.messageId}");
|
||||
}
|
||||
|
||||
class NotificationService {
|
||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
Future<void> initInfo() async {
|
||||
await FirebaseMessaging.instance
|
||||
.setForegroundNotificationPresentationOptions(
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
);
|
||||
var request = await FirebaseMessaging.instance.requestPermission(
|
||||
alert: true,
|
||||
announcement: false,
|
||||
badge: true,
|
||||
carPlay: false,
|
||||
criticalAlert: false,
|
||||
provisional: false,
|
||||
sound: true,
|
||||
);
|
||||
|
||||
if (request.authorizationStatus == AuthorizationStatus.authorized ||
|
||||
request.authorizationStatus == AuthorizationStatus.provisional) {
|
||||
const AndroidInitializationSettings initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||
var iosInitializationSettings = const DarwinInitializationSettings();
|
||||
final InitializationSettings initializationSettings =
|
||||
InitializationSettings(
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: iosInitializationSettings);
|
||||
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
||||
onDidReceiveNotificationResponse: (payload) {});
|
||||
setupInteractedMessage();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setupInteractedMessage() async {
|
||||
RemoteMessage? initialMessage =
|
||||
await FirebaseMessaging.instance.getInitialMessage();
|
||||
if (initialMessage != null) {
|
||||
FirebaseMessaging.onBackgroundMessage(
|
||||
(message) => firebaseMessageBackgroundHandle(message));
|
||||
}
|
||||
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||
log("::::::::::::onMessage:::::::::::::::::");
|
||||
if (message.notification != null) {
|
||||
log(message.notification.toString());
|
||||
display(message);
|
||||
}
|
||||
});
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
||||
log("::::::::::::onMessageOpenedApp:::::::::::::::::");
|
||||
if (message.notification != null) {
|
||||
log(message.notification.toString());
|
||||
}
|
||||
});
|
||||
log("::::::::::::Permission authorized:::::::::::::::::");
|
||||
await FirebaseMessaging.instance.subscribeToTopic("customer");
|
||||
}
|
||||
|
||||
static Future<String?>? getToken() async {
|
||||
String? token = await FirebaseMessaging.instance.getToken();
|
||||
return token;
|
||||
}
|
||||
|
||||
void display(RemoteMessage message) async {
|
||||
log('Got a message whilst in the foreground!');
|
||||
log('Message data: ${message.notification!.body.toString()}');
|
||||
try {
|
||||
AndroidNotificationChannel channel = const AndroidNotificationChannel(
|
||||
'0',
|
||||
'goRide-customer',
|
||||
description: 'Show QuickLAI Notification',
|
||||
importance: Importance.max,
|
||||
);
|
||||
AndroidNotificationDetails notificationDetails =
|
||||
AndroidNotificationDetails(channel.id, channel.name,
|
||||
channelDescription: 'your channel Description',
|
||||
importance: Importance.high,
|
||||
priority: Priority.high,
|
||||
ticker: 'ticker');
|
||||
const DarwinNotificationDetails darwinNotificationDetails =
|
||||
DarwinNotificationDetails(
|
||||
presentAlert: true, presentBadge: true, presentSound: true);
|
||||
NotificationDetails notificationDetailsBoth = NotificationDetails(
|
||||
android: notificationDetails, iOS: darwinNotificationDetails);
|
||||
await FlutterLocalNotificationsPlugin().show(
|
||||
0,
|
||||
message.notification!.title,
|
||||
message.notification!.body,
|
||||
notificationDetailsBoth,
|
||||
payload: jsonEncode(message.data),
|
||||
);
|
||||
} on Exception catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
108
lib/service/send_notification.dart
Normal file
108
lib/service/send_notification.dart
Normal file
@@ -0,0 +1,108 @@
|
||||
import 'dart:convert';
|
||||
import 'package:customer/constant/constant.dart';
|
||||
import 'package:customer/models/notification_model.dart';
|
||||
import 'package:customer/service/fire_store_utils.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:googleapis_auth/auth_io.dart';
|
||||
|
||||
class SendNotification {
|
||||
static final _scopes = ['https://www.googleapis.com/auth/firebase.messaging'];
|
||||
|
||||
static Future getCharacters() {
|
||||
return http.get(Uri.parse(Constant.jsonNotificationFileURL.toString()));
|
||||
}
|
||||
|
||||
static Future<String> getAccessToken() async {
|
||||
Map<String, dynamic> jsonData = {};
|
||||
|
||||
await getCharacters().then((response) {
|
||||
jsonData = json.decode(response.body);
|
||||
});
|
||||
final serviceAccountCredentials = ServiceAccountCredentials.fromJson(jsonData);
|
||||
final client = await clientViaServiceAccount(serviceAccountCredentials, _scopes);
|
||||
return client.credentials.accessToken.data;
|
||||
}
|
||||
|
||||
static Future<bool> sendFcmMessage(String type, String token, Map<String, dynamic>? payload) async {
|
||||
print(type);
|
||||
try {
|
||||
final String accessToken = await getAccessToken();
|
||||
debugPrint("accessToken=======>");
|
||||
debugPrint(accessToken);
|
||||
NotificationModel? notificationModel = await FireStoreUtils.getNotificationContent(type);
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('https://fcm.googleapis.com/v1/projects/${Constant.senderId}/messages:send'),
|
||||
headers: <String, String>{'Content-Type': 'application/json', 'Authorization': 'Bearer $accessToken'},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
'message': {
|
||||
'token': token,
|
||||
'notification': {'body': notificationModel?.message ?? '', 'title': notificationModel?.subject ?? ''},
|
||||
'data': payload,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
debugPrint("Notification=======>");
|
||||
debugPrint(response.statusCode.toString());
|
||||
debugPrint(response.body);
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> sendOneNotification({required String token, required String title, required String body, required Map<String, dynamic> payload}) async {
|
||||
try {
|
||||
final String accessToken = await getAccessToken();
|
||||
debugPrint("accessToken=======>");
|
||||
debugPrint(accessToken);
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('https://fcm.googleapis.com/v1/projects/${Constant.senderId}/messages:send'),
|
||||
headers: <String, String>{'Content-Type': 'application/json', 'Authorization': 'Bearer $accessToken'},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
'message': {
|
||||
'token': token,
|
||||
'notification': {'body': body, 'title': title},
|
||||
'data': payload,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
debugPrint("Notification=======>");
|
||||
debugPrint(response.statusCode.toString());
|
||||
debugPrint(response.body);
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> sendChatFcmMessage(String title, String message, String token, Map<String, dynamic>? payload) async {
|
||||
try {
|
||||
final String accessToken = await getAccessToken();
|
||||
final response = await http.post(
|
||||
Uri.parse('https://fcm.googleapis.com/v1/projects/${Constant.senderId}/messages:send'),
|
||||
headers: <String, String>{'Content-Type': 'application/json', 'Authorization': 'Bearer $accessToken'},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
'message': {
|
||||
'token': token,
|
||||
'notification': {'body': message, 'title': title},
|
||||
'data': payload,
|
||||
},
|
||||
}),
|
||||
);
|
||||
debugPrint("Notification=======>");
|
||||
debugPrint(response.statusCode.toString());
|
||||
debugPrint(response.body);
|
||||
return true;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user