Update
Logging data Try-catch function
This commit is contained in:
@@ -4,7 +4,6 @@ import '../product/base/bloc/base_bloc.dart';
|
||||
import '../feature/bell/bell_model.dart';
|
||||
|
||||
class BellBloc extends BlocBase {
|
||||
|
||||
final bellItems = StreamController<List<BellItems>>.broadcast();
|
||||
StreamSink<List<BellItems>> get sinkBellItems => bellItems.sink;
|
||||
Stream<List<BellItems>> get streamBellItems => bellItems.stream;
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:sfm_app/product/services/api_services.dart';
|
||||
import 'package:sfm_app/product/utils/device_utils.dart';
|
||||
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
import '../product/utils/date_time_utils.dart';
|
||||
import '../feature/device_log/device_logs_model.dart';
|
||||
import '../feature/devices/device_model.dart';
|
||||
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/utils/device_utils.dart';
|
||||
|
||||
class DetailDeviceBloc extends BlocBase {
|
||||
APIServices apiServices = APIServices();
|
||||
@@ -43,7 +40,7 @@ class DetailDeviceBloc extends BlocBase {
|
||||
String thingID,
|
||||
Completer<GoogleMapController> controller,
|
||||
) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Device device = await apiServices.getDeviceInformation(thingID);
|
||||
sinkDeviceInfo.add(device);
|
||||
if (device.areaPath != null) {
|
||||
@@ -73,10 +70,41 @@ class DetailDeviceBloc extends BlocBase {
|
||||
mapController
|
||||
.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// Device device = await apiServices.getDeviceInformation(thingID);
|
||||
// sinkDeviceInfo.add(device);
|
||||
// if (device.areaPath != null) {
|
||||
// String fullLocation = await DeviceUtils.instance
|
||||
// .getFullDeviceLocation(context, device.areaPath!, "");
|
||||
// log("Location: $fullLocation");
|
||||
// sinkDeviceLocation.add(fullLocation);
|
||||
// }
|
||||
// Map<String, dynamic> sensorMap = {};
|
||||
// if (device.status!.sensors != null) {
|
||||
// sensorMap = DeviceUtils.instance
|
||||
// .getDeviceSensors(context, device.status!.sensors!);
|
||||
// } else {
|
||||
// sensorMap = DeviceUtils.instance.getDeviceSensors(context, []);
|
||||
// }
|
||||
// sinkDeviceSensor.add(sensorMap);
|
||||
// if (device.settings!.latitude! != "" &&
|
||||
// device.settings!.longitude! != "") {
|
||||
// final CameraPosition cameraPosition = CameraPosition(
|
||||
// target: LatLng(
|
||||
// double.parse(device.settings!.latitude!),
|
||||
// double.parse(device.settings!.longitude!),
|
||||
// ),
|
||||
// zoom: 13,
|
||||
// );
|
||||
// final GoogleMapController mapController = await controller.future;
|
||||
// mapController
|
||||
// .animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
|
||||
// }
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
void findLocation(BuildContext context, String areaPath) async {
|
||||
@@ -85,12 +113,13 @@ class DetailDeviceBloc extends BlocBase {
|
||||
sinkDeviceLocation.add(fullLocation);
|
||||
}
|
||||
|
||||
void getNearerSensorValue(BuildContext context,String thingID) async {
|
||||
try {
|
||||
void getNearerSensorValue(BuildContext context, String thingID) async {
|
||||
apiServices.execute(context, () async {
|
||||
List<SensorLogs> sensorTemps = [];
|
||||
DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
|
||||
String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
|
||||
String now = DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||
String now =
|
||||
DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||
Map<String, dynamic> params = {
|
||||
'thing_id': thingID,
|
||||
'from': from,
|
||||
@@ -98,7 +127,8 @@ class DetailDeviceBloc extends BlocBase {
|
||||
'limit': '100',
|
||||
'n': '7',
|
||||
};
|
||||
DeviceLog devicesListLog = await apiServices.getLogsOfDevice(thingID, params);
|
||||
DeviceLog devicesListLog =
|
||||
await apiServices.getLogsOfDevice(thingID, params);
|
||||
if (devicesListLog.sensors!.isNotEmpty) {
|
||||
for (var sensor in devicesListLog.sensors!) {
|
||||
sensorTemps.add(sensor);
|
||||
@@ -108,11 +138,35 @@ class DetailDeviceBloc extends BlocBase {
|
||||
} else {
|
||||
sinkSensorTemps.add([]);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
sinkSensorTemps.add([]);
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// List<SensorLogs> sensorTemps = [];
|
||||
// DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
|
||||
// String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
|
||||
// String now =
|
||||
// DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||
// Map<String, dynamic> params = {
|
||||
// 'thing_id': thingID,
|
||||
// 'from': from,
|
||||
// 'to': now,
|
||||
// 'limit': '100',
|
||||
// 'n': '7',
|
||||
// };
|
||||
// DeviceLog devicesListLog =
|
||||
// await apiServices.getLogsOfDevice(thingID, params);
|
||||
// if (devicesListLog.sensors!.isNotEmpty) {
|
||||
// for (var sensor in devicesListLog.sensors!) {
|
||||
// sensorTemps.add(sensor);
|
||||
// }
|
||||
// sensorTemps = sensorTemps.reversed.toList();
|
||||
// sinkSensorTemps.add(sensorTemps);
|
||||
// } else {
|
||||
// sinkSensorTemps.add([]);
|
||||
// }
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// sinkSensorTemps.add([]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../feature/devices/device_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/constant/app/app_constants.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/utils/date_time_utils.dart';
|
||||
|
||||
import '../product/utils/device_utils.dart';
|
||||
@@ -39,15 +36,12 @@ class DeviceLogsBloc extends BlocBase {
|
||||
void dispose() {}
|
||||
|
||||
void getAllDevices(BuildContext context) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
List<Device> originalDevices = await apiServices.getOwnerDevices();
|
||||
List<Device> devices =
|
||||
DeviceUtils.instance.sortDeviceByState(originalDevices);
|
||||
sinkAllDevices.add(devices);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void getDeviceLogByThingID(
|
||||
@@ -57,7 +51,7 @@ class DeviceLogsBloc extends BlocBase {
|
||||
DateTime fromDate,
|
||||
List<SensorLogs> sensors,
|
||||
) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
sinkmessage.add(ApplicationConstants.LOADING);
|
||||
String fromDateString =
|
||||
DateTimeUtils.instance.formatDateTimeToString(fromDate);
|
||||
@@ -85,9 +79,38 @@ class DeviceLogsBloc extends BlocBase {
|
||||
sinkmessage.add(ApplicationConstants.NO_DATA);
|
||||
}
|
||||
sinkSensors.add(sensors);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// sinkmessage.add(ApplicationConstants.LOADING);
|
||||
// String fromDateString =
|
||||
// DateTimeUtils.instance.formatDateTimeToString(fromDate);
|
||||
// String now =
|
||||
// DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||
// Map<String, dynamic> params = {
|
||||
// 'thing_id': thingID,
|
||||
// 'from': fromDateString,
|
||||
// 'to': now,
|
||||
// 'limit': '30',
|
||||
// "offset": offset.toString(),
|
||||
// "asc": "true"
|
||||
// };
|
||||
// DeviceLog devicesListLog =
|
||||
// await apiServices.getLogsOfDevice(thingID, params);
|
||||
// if (devicesListLog.sensors!.isEmpty) {
|
||||
// bool hasMore = false;
|
||||
// sinkHasMore.add(hasMore);
|
||||
// }
|
||||
// if (devicesListLog.sensors!.isNotEmpty) {
|
||||
// for (var sensor in devicesListLog.sensors!) {
|
||||
// sensors.add(sensor);
|
||||
// }
|
||||
// } else {
|
||||
// sinkmessage.add(ApplicationConstants.NO_DATA);
|
||||
// }
|
||||
// sinkSensors.add(sensors);
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class DeviceNotificationSettingsBloc extends BlocBase {
|
||||
StreamSink<String> get sinkMessageChange => messageChange.sink;
|
||||
Stream<String> get streaMmessageChange => messageChange.stream;
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../product/services/api_services.dart';
|
||||
import '../product/services/language_services.dart';
|
||||
import '../product/shared/model/ward_model.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/utils/response_status_utils.dart';
|
||||
|
||||
import '../product/shared/model/district_model.dart';
|
||||
import '../product/shared/model/province_model.dart';
|
||||
import '../feature/devices/device_model.dart';
|
||||
@@ -80,56 +80,42 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
List<DropdownMenuItem<Province>> provincesData = [];
|
||||
provincesData.clear();
|
||||
sinkListProvinces.add(provincesData);
|
||||
try {
|
||||
List<Province> provinces = await apiServices.getAllProvinces();
|
||||
await apiServices.execute(context, () async {
|
||||
List<Province> provinces = await apiServices.getAllProvinces();
|
||||
for (var province in provinces) {
|
||||
provincesData.add(
|
||||
DropdownMenuItem(value: province, child: Text(province.fullName!)));
|
||||
}
|
||||
sinkListProvinces.add(provincesData);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getAllDistricts(BuildContext context, String provinceID) async {
|
||||
List<DropdownMenuItem<District>> districtsData = [];
|
||||
districtsData.clear();
|
||||
sinkListDistricts.add(districtsData);
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
final districts = await apiServices.getAllDistricts(provinceID);
|
||||
for (var district in districts) {
|
||||
districtsData.add(
|
||||
DropdownMenuItem(value: district, child: Text(district.fullName!)));
|
||||
}
|
||||
sinkListDistricts.add(districtsData);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getAllWards(BuildContext context, String districtID) async {
|
||||
List<DropdownMenuItem<Ward>> wardsData = [];
|
||||
wardsData.clear();
|
||||
sinkListWards.add(wardsData);
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
final wards = await apiServices.getAllWards(districtID);
|
||||
for (var ward in wards) {
|
||||
wardsData.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
|
||||
wardsData
|
||||
.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
|
||||
}
|
||||
sinkListWards.add(wardsData);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getDeviceInformation(
|
||||
@@ -138,7 +124,7 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
TextEditingController deviceNameController,
|
||||
TextEditingController latitudeController,
|
||||
TextEditingController longitudeController) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Device device = await apiServices.getDeviceInformation(thingID);
|
||||
sinkDeviceInfo.add(device);
|
||||
deviceNameController.text = device.name ?? "";
|
||||
@@ -155,23 +141,24 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
String wardCode = areaPath[2];
|
||||
|
||||
// Kiểm tra các mã có hợp lệ không (không rỗng)
|
||||
if (provinceCode.isNotEmpty && districtCode.isNotEmpty && wardCode.isNotEmpty) {
|
||||
if (provinceCode.isNotEmpty &&
|
||||
districtCode.isNotEmpty &&
|
||||
wardCode.isNotEmpty) {
|
||||
try {
|
||||
// Lấy danh sách districts và wards
|
||||
await getAllDistricts(context,provinceCode);
|
||||
await getAllWards(context,districtCode);
|
||||
await getAllDistricts(context, provinceCode);
|
||||
await getAllWards(context, districtCode);
|
||||
|
||||
// Xử lý Province
|
||||
try {
|
||||
Province province = await apiServices.getProvinceByID(provinceCode);
|
||||
Map<String, String> provinceData = {
|
||||
"name": province.fullName ?? "Unknown Province",
|
||||
"code": province.code ?? provinceCode
|
||||
};
|
||||
sinkProvinceData.add(provinceData);
|
||||
|
||||
Province province =
|
||||
await apiServices.getProvinceByID(provinceCode);
|
||||
Map<String, String> provinceData = {
|
||||
"name": province.fullName ?? "Unknown Province",
|
||||
"code": province.code ?? provinceCode
|
||||
};
|
||||
sinkProvinceData.add(provinceData);
|
||||
} catch (e) {
|
||||
|
||||
// Thêm dữ liệu mặc định khi lỗi
|
||||
Map<String, String> provinceData = {
|
||||
"name": "Error Loading Province",
|
||||
@@ -179,20 +166,20 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
};
|
||||
sinkProvinceData.add(provinceData);
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
|
||||
// Xử lý District
|
||||
try {
|
||||
District district = await apiServices.getDistrictByID(districtCode);
|
||||
Map<String, String> districData = {
|
||||
"name": district.fullName ?? "Unknown District",
|
||||
"code": district.code ?? districtCode,
|
||||
};
|
||||
sinkDistrictData.add(districData);
|
||||
District district =
|
||||
await apiServices.getDistrictByID(districtCode);
|
||||
Map<String, String> districData = {
|
||||
"name": district.fullName ?? "Unknown District",
|
||||
"code": district.code ?? districtCode,
|
||||
};
|
||||
sinkDistrictData.add(districData);
|
||||
} catch (e) {
|
||||
print("Lỗi khi lấy thông tin district ($districtCode): $e");
|
||||
log("Lỗi khi lấy thông tin district ($districtCode): $e");
|
||||
Map<String, String> districData = {
|
||||
"name": "Error Loading District",
|
||||
"code": districtCode,
|
||||
@@ -202,84 +189,168 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
|
||||
// Xử lý Ward
|
||||
try {
|
||||
Ward ward = await apiServices.getWardByID(wardCode);
|
||||
Map<String, String> wardMap = {
|
||||
"name": ward.fullName ?? "Unknown Ward",
|
||||
"code": ward.code ?? wardCode,
|
||||
};
|
||||
sinkWardData.add(wardMap);
|
||||
Ward ward = await apiServices.getWardByID(wardCode);
|
||||
Map<String, String> wardMap = {
|
||||
"name": ward.fullName ?? "Unknown Ward",
|
||||
"code": ward.code ?? wardCode,
|
||||
};
|
||||
sinkWardData.add(wardMap);
|
||||
} catch (e) {
|
||||
print("Lỗi khi lấy thông tin ward ($wardCode): $e");
|
||||
log("Lỗi khi lấy thông tin ward ($wardCode): $e");
|
||||
Map<String, String> wardMap = {
|
||||
"name": "Error Loading Ward",
|
||||
"code": wardCode,
|
||||
};
|
||||
sinkWardData.add(wardMap);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
print("Lỗi khi gọi getAllDistricts hoặc getAllWards: $e");
|
||||
log("Lỗi khi gọi getAllDistricts hoặc getAllWards: $e");
|
||||
}
|
||||
} else {
|
||||
await getAllProvinces(context);
|
||||
print("Một hoặc nhiều mã địa phương trống: Province: $provinceCode, District: $districtCode, Ward: $wardCode");
|
||||
log("Một hoặc nhiều mã địa phương trống: Province: $provinceCode, District: $districtCode, Ward: $wardCode");
|
||||
}
|
||||
} else {
|
||||
showNoIconTopSnackBar(context,"AreaPath không đủ thông tin: ${device.areaPath}",Colors.orangeAccent, Colors.white);
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
"AreaPath không đủ thông tin: ${device.areaPath}",
|
||||
Colors.orangeAccent,
|
||||
Colors.white);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showNoIconTopSnackBar(context,"Lỗi trong getDeviceInfomation: $e",Colors.orangeAccent, Colors.white);
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// Device device = await apiServices.getDeviceInformation(thingID);
|
||||
// sinkDeviceInfo.add(device);
|
||||
// deviceNameController.text = device.name ?? "";
|
||||
// latitudeController.text = device.settings!.latitude ?? "";
|
||||
// longitudeController.text = device.settings!.longitude ?? "";
|
||||
|
||||
// if (device.areaPath != null && device.areaPath!.isNotEmpty) {
|
||||
// List<String> areaPath = device.areaPath!.split('_');
|
||||
|
||||
// // Kiểm tra độ dài của areaPath
|
||||
// if (areaPath.length >= 3) {
|
||||
// String provinceCode = areaPath[0];
|
||||
// String districtCode = areaPath[1];
|
||||
// String wardCode = areaPath[2];
|
||||
|
||||
// // Kiểm tra các mã có hợp lệ không (không rỗng)
|
||||
// if (provinceCode.isNotEmpty &&
|
||||
// districtCode.isNotEmpty &&
|
||||
// wardCode.isNotEmpty) {
|
||||
// try {
|
||||
// // Lấy danh sách districts và wards
|
||||
// await getAllDistricts(context, provinceCode);
|
||||
// await getAllWards(context, districtCode);
|
||||
|
||||
// // Xử lý Province
|
||||
// try {
|
||||
// Province province =
|
||||
// await apiServices.getProvinceByID(provinceCode);
|
||||
// Map<String, String> provinceData = {
|
||||
// "name": province.fullName ?? "Unknown Province",
|
||||
// "code": province.code ?? provinceCode
|
||||
// };
|
||||
// sinkProvinceData.add(provinceData);
|
||||
// } catch (e) {
|
||||
// // Thêm dữ liệu mặc định khi lỗi
|
||||
// Map<String, String> provinceData = {
|
||||
// "name": "Error Loading Province",
|
||||
// "code": provinceCode
|
||||
// };
|
||||
// sinkProvinceData.add(provinceData);
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
|
||||
// // Xử lý District
|
||||
// try {
|
||||
// District district =
|
||||
// await apiServices.getDistrictByID(districtCode);
|
||||
// Map<String, String> districData = {
|
||||
// "name": district.fullName ?? "Unknown District",
|
||||
// "code": district.code ?? districtCode,
|
||||
// };
|
||||
// sinkDistrictData.add(districData);
|
||||
// } catch (e) {
|
||||
// log("Lỗi khi lấy thông tin district ($districtCode): $e");
|
||||
// Map<String, String> districData = {
|
||||
// "name": "Error Loading District",
|
||||
// "code": districtCode,
|
||||
// };
|
||||
// sinkDistrictData.add(districData);
|
||||
// }
|
||||
|
||||
// // Xử lý Ward
|
||||
// try {
|
||||
// Ward ward = await apiServices.getWardByID(wardCode);
|
||||
// Map<String, String> wardMap = {
|
||||
// "name": ward.fullName ?? "Unknown Ward",
|
||||
// "code": ward.code ?? wardCode,
|
||||
// };
|
||||
// sinkWardData.add(wardMap);
|
||||
// } catch (e) {
|
||||
// print("Lỗi khi lấy thông tin ward ($wardCode): $e");
|
||||
// Map<String, String> wardMap = {
|
||||
// "name": "Error Loading Ward",
|
||||
// "code": wardCode,
|
||||
// };
|
||||
// sinkWardData.add(wardMap);
|
||||
// }
|
||||
// } catch (e) {
|
||||
// print("Lỗi khi gọi getAllDistricts hoặc getAllWards: $e");
|
||||
// }
|
||||
// } else {
|
||||
// await getAllProvinces(context);
|
||||
// print(
|
||||
// "Một hoặc nhiều mã địa phương trống: Province: $provinceCode, District: $districtCode, Ward: $wardCode");
|
||||
// }
|
||||
// } else {
|
||||
// showNoIconTopSnackBar(
|
||||
// context,
|
||||
// "AreaPath không đủ thông tin: ${device.areaPath}",
|
||||
// Colors.orangeAccent,
|
||||
// Colors.white);
|
||||
// }
|
||||
// }
|
||||
// } catch (e) {
|
||||
// showNoIconTopSnackBar(context, "Lỗi trong getDeviceInfomation: $e",
|
||||
// Colors.orangeAccent, Colors.white);
|
||||
// }
|
||||
}
|
||||
|
||||
Future<Province> getProvinceByName(BuildContext context, String name) async {
|
||||
try {
|
||||
return await apiServices.execute(context, () async {
|
||||
List<Province> provinces = await apiServices.getProvincesByName(name);
|
||||
if (provinces.isNotEmpty) {
|
||||
return provinces[0];
|
||||
} else {
|
||||
return Province(name: "null");
|
||||
}
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
return Province(name: "null");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Future<District> getDistrictByName(
|
||||
BuildContext context, String name, String provinceCode) async {
|
||||
try {
|
||||
return apiServices.execute(context, () async {
|
||||
final districts = await apiServices.getDistrictsByName(name);
|
||||
return districts.firstWhere(
|
||||
(district) => district.provinceCode == provinceCode,
|
||||
(district) => district.provinceCode == provinceCode,
|
||||
orElse: () => District(name: "null"),
|
||||
);
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
return District(name: "null");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<Ward> getWardByName(
|
||||
BuildContext context, String name, String districtCode) async {
|
||||
try {
|
||||
return apiServices.execute(context, () async {
|
||||
final wards = await apiServices.getWardsByName(name);
|
||||
return wards.firstWhere(
|
||||
(ward) => ward.districtCode == districtCode,
|
||||
(ward) => ward.districtCode == districtCode,
|
||||
orElse: () => Ward(name: "null"),
|
||||
);
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
return Ward(name: "null");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateDevice(
|
||||
@@ -292,10 +363,10 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
String districtCode,
|
||||
String wardCode,
|
||||
) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
DateTime dateTime = DateTime.now();
|
||||
String formattedDateTime =
|
||||
DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||
DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||
Map<String, dynamic> body = {
|
||||
"name": name,
|
||||
"area_province": provinceCode,
|
||||
@@ -312,11 +383,30 @@ class DeviceUpdateBloc extends BlocBase {
|
||||
appLocalization(context).notification_update_device_success,
|
||||
appLocalization(context).notification_update_device_failed,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
// try {
|
||||
// DateTime dateTime = DateTime.now();
|
||||
// String formattedDateTime =
|
||||
// DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||
// Map<String, dynamic> body = {
|
||||
// "name": name,
|
||||
// "area_province": provinceCode,
|
||||
// "area_district": districtCode,
|
||||
// "area_ward": wardCode,
|
||||
// "latitude": latitude,
|
||||
// "longitude": longitude,
|
||||
// "note": "User updated device infomation at $formattedDateTime",
|
||||
// };
|
||||
// int statusCode = await apiServices.updateOwnerDevice(thingID, body);
|
||||
// showSnackBarResponseByStatusCodeNoIcon(
|
||||
// context,
|
||||
// statusCode,
|
||||
// appLocalization(context).notification_update_device_success,
|
||||
// appLocalization(context).notification_update_device_failed,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../feature/devices/device_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/constant/app/app_constants.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/utils/device_utils.dart';
|
||||
|
||||
@@ -76,7 +73,7 @@ class DevicesManagerBloc extends BlocBase {
|
||||
// }
|
||||
// }
|
||||
|
||||
void getDeviceByState(BuildContext context,int state) async {
|
||||
void getDeviceByState(BuildContext context, int state) async {
|
||||
try {
|
||||
sinkTagStates.add([state]);
|
||||
|
||||
@@ -91,16 +88,16 @@ class DevicesManagerBloc extends BlocBase {
|
||||
List<Device> devices = [];
|
||||
List<Device> originalDevices = [];
|
||||
if (state != -2) {
|
||||
originalDevices =
|
||||
await apiServices.getOwnerDeviceByState({"state": state.toString()});
|
||||
originalDevices = await apiServices
|
||||
.getOwnerDeviceByState({"state": state.toString()});
|
||||
} else {
|
||||
originalDevices = await apiServices.getOwnerDevices();
|
||||
}
|
||||
|
||||
List<Device> publicDevices = [];
|
||||
|
||||
for(var device in originalDevices){
|
||||
if(device.visibility == "PUBLIC"){
|
||||
for (var device in originalDevices) {
|
||||
if (device.visibility == "PUBLIC") {
|
||||
publicDevices.add(device);
|
||||
}
|
||||
}
|
||||
@@ -119,10 +116,8 @@ class DevicesManagerBloc extends BlocBase {
|
||||
sinkAllDevices.add(devices);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String _getStateKey(int state) {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../feature/devices/device_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
import '../product/services/language_services.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/utils/response_status_utils.dart';
|
||||
|
||||
import '../feature/inter_family/group_detail/group_detail_model.dart';
|
||||
|
||||
class DetailGroupBloc extends BlocBase {
|
||||
@@ -30,86 +27,117 @@ class DetailGroupBloc extends BlocBase {
|
||||
@override
|
||||
void dispose() {}
|
||||
|
||||
Future<void> getGroupDetail(BuildContext context,String groupID) async {
|
||||
try {
|
||||
Future<void> getGroupDetail(BuildContext context, String groupID) async {
|
||||
await apiServices.execute(context, () async {
|
||||
List<DeviceOfGroup> warningDevices = [];
|
||||
GroupDetail group = await apiServices.getGroupDetail(groupID);
|
||||
sinkDetailGroup.add(group);
|
||||
if (group.devices != null) {
|
||||
for (var device in group.devices!) {
|
||||
if (device.state == 1) {
|
||||
warningDevices.add(device);
|
||||
}
|
||||
GroupDetail group = await apiServices.getGroupDetail(groupID);
|
||||
sinkDetailGroup.add(group);
|
||||
if (group.devices != null) {
|
||||
for (var device in group.devices!) {
|
||||
if (device.state == 1) {
|
||||
warningDevices.add(device);
|
||||
}
|
||||
sinkWarningDevice.add(warningDevices);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
sinkWarningDevice.add(warningDevices);
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// List<DeviceOfGroup> warningDevices = [];
|
||||
// GroupDetail group = await apiServices.getGroupDetail(groupID);
|
||||
// sinkDetailGroup.add(group);
|
||||
// if (group.devices != null) {
|
||||
// for (var device in group.devices!) {
|
||||
// if (device.state == 1) {
|
||||
// warningDevices.add(device);
|
||||
// }
|
||||
// }
|
||||
// sinkWarningDevice.add(warningDevices);
|
||||
// }
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> approveUserToGroup(BuildContext context, String groupID,
|
||||
String userID, String userName) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Map<String, dynamic> body = {"group_id": groupID, "user_id": userID};
|
||||
int statusCode = await apiServices.approveGroup(body);
|
||||
showSnackBarResponseByStatusCode(context, statusCode,
|
||||
"Đã duyệt $userName vào nhóm!", "Duyệt $userName thất bại!");
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// Map<String, dynamic> body = {"group_id": groupID, "user_id": userID};
|
||||
// int statusCode = await apiServices.approveGroup(body);
|
||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
||||
// "Đã duyệt $userName vào nhóm!", "Duyệt $userName thất bại!");
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> deleteOrUnapproveUser(BuildContext context, String groupID,
|
||||
String userID, String userName) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||
showSnackBarResponseByStatusCode(context, statusCode,
|
||||
"Đã xóa người dùng $userName", "Xóa người dùng $userName thất bại");
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
||||
// "Đã xóa người dùng $userName", "Xóa người dùng $userName thất bại");
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> deleteDevice(BuildContext context, String groupID,
|
||||
String thingID, String deviceName) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.deleteDeviceInGroup(groupID, thingID);
|
||||
showSnackBarResponseByStatusCode(context, statusCode,
|
||||
"Đã xóa thiết bị $deviceName", "Xóa thiết bị $deviceName thất bại");
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// int statusCode = await apiServices.deleteDeviceInGroup(groupID, thingID);
|
||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
||||
// "Đã xóa thiết bị $deviceName", "Xóa thiết bị $deviceName thất bại");
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> leaveGroup(
|
||||
BuildContext context, String groupID, String userID) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_leave_group_success,
|
||||
appLocalization(context).notification_leave_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||
// showSnackBarResponseByStatusCode(
|
||||
// context,
|
||||
// statusCode,
|
||||
// appLocalization(context).notification_leave_group_success,
|
||||
// appLocalization(context).notification_leave_group_failed);
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> updateDeviceNameInGroup(
|
||||
BuildContext context, String thingID, String newAlias) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Map<String, dynamic> body = {"thing_id": thingID, "alias": newAlias};
|
||||
int statusCode = await apiServices.updateDeviceAlias(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -118,26 +146,29 @@ class DetailGroupBloc extends BlocBase {
|
||||
appLocalization(context).notification_update_device_success,
|
||||
appLocalization(context).notification_update_device_failed,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// Map<String, dynamic> body = {"thing_id": thingID, "alias": newAlias};
|
||||
// int statusCode = await apiServices.updateDeviceAlias(body);
|
||||
// showSnackBarResponseByStatusCode(
|
||||
// context,
|
||||
// statusCode,
|
||||
// appLocalization(context).notification_update_device_success,
|
||||
// appLocalization(context).notification_update_device_failed,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
Future<List<Device>> getOwnerDevices(BuildContext context) async {
|
||||
List<Device> allDevices = [];
|
||||
try {
|
||||
Future<List<Device>> getOwnerDevices(BuildContext context) {
|
||||
return apiServices.execute(context, () async {
|
||||
final originalDevices = await apiServices.getOwnerDevices();
|
||||
allDevices = originalDevices.where((device) => device.visibility == "PUBLIC").toList();
|
||||
|
||||
return allDevices;
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
return allDevices;
|
||||
}
|
||||
return originalDevices
|
||||
.where((device) => device.visibility == "PUBLIC")
|
||||
.toList();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> addDeviceToGroup(
|
||||
@@ -145,7 +176,7 @@ class DetailGroupBloc extends BlocBase {
|
||||
Map<String, dynamic> body = {
|
||||
"thing_id": thingID,
|
||||
};
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.addDeviceToGroup(groupID, body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
@@ -153,10 +184,18 @@ class DetailGroupBloc extends BlocBase {
|
||||
appLocalization(context).notification_add_device_success,
|
||||
appLocalization(context).notification_add_device_failed,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// int statusCode = await apiServices.addDeviceToGroup(groupID, body);
|
||||
// showSnackBarResponseByStatusCode(
|
||||
// context,
|
||||
// statusCode,
|
||||
// appLocalization(context).notification_add_device_success,
|
||||
// appLocalization(context).notification_add_device_failed,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,19 @@ import '../feature/home/device_alias_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
|
||||
class HomeBloc extends BlocBase {
|
||||
|
||||
final allDevicesAliasMap = StreamController<Map<String,List<DeviceWithAlias>>>.broadcast();
|
||||
StreamSink<Map<String,List<DeviceWithAlias>>> get sinkAllDevicesAliasMap =>
|
||||
final allDevicesAliasMap =
|
||||
StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
||||
StreamSink<Map<String, List<DeviceWithAlias>>> get sinkAllDevicesAliasMap =>
|
||||
allDevicesAliasMap.sink;
|
||||
Stream<Map<String,List<DeviceWithAlias>>> get streamAllDevicesAliasMap =>
|
||||
Stream<Map<String, List<DeviceWithAlias>>> get streamAllDevicesAliasMap =>
|
||||
allDevicesAliasMap.stream;
|
||||
|
||||
final allDevicesAliasJoinedMap = StreamController<Map<String,List<DeviceWithAlias>>>.broadcast();
|
||||
StreamSink<Map<String,List<DeviceWithAlias>>> get sinkAllDevicesAliasJoinedMap =>
|
||||
allDevicesAliasJoinedMap.sink;
|
||||
Stream<Map<String,List<DeviceWithAlias>>> get streamAllDevicesAliasJoinedMap =>
|
||||
allDevicesAliasJoinedMap.stream;
|
||||
final allDevicesAliasJoinedMap =
|
||||
StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
||||
StreamSink<Map<String, List<DeviceWithAlias>>>
|
||||
get sinkAllDevicesAliasJoinedMap => allDevicesAliasJoinedMap.sink;
|
||||
Stream<Map<String, List<DeviceWithAlias>>>
|
||||
get streamAllDevicesAliasJoinedMap => allDevicesAliasJoinedMap.stream;
|
||||
|
||||
final countNotification = StreamController<int>.broadcast();
|
||||
StreamSink<int> get sinkCountNotification => countNotification.sink;
|
||||
@@ -26,13 +27,19 @@ class HomeBloc extends BlocBase {
|
||||
StreamSink<bool?> get sinkHasJoinedDevice => hasJoinedDevice.sink;
|
||||
Stream<bool?> get streamHasJoinedDevice => hasJoinedDevice.stream;
|
||||
|
||||
final ownerDevicesStatus =
|
||||
final ownerDevicesStatus =
|
||||
StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
||||
StreamSink<Map<String, List<DeviceWithAlias>>>
|
||||
get sinkOwnerDevicesStatus => ownerDevicesStatus.sink;
|
||||
StreamSink<Map<String, List<DeviceWithAlias>>> get sinkOwnerDevicesStatus =>
|
||||
ownerDevicesStatus.sink;
|
||||
Stream<Map<String, List<DeviceWithAlias>>> get streamOwnerDevicesStatus =>
|
||||
ownerDevicesStatus.stream;
|
||||
|
||||
@override
|
||||
void dispose() {}
|
||||
void dispose() {
|
||||
allDevicesAliasMap.close();
|
||||
allDevicesAliasJoinedMap.close();
|
||||
countNotification.close();
|
||||
hasJoinedDevice.close();
|
||||
ownerDevicesStatus.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../product/constant/app/app_constants.dart';
|
||||
|
||||
import '../product/constant/app/app_constants.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/services/language_services.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../product/utils/response_status_utils.dart';
|
||||
import '../feature/inter_family/groups/groups_model.dart';
|
||||
|
||||
@@ -36,10 +33,10 @@ class InterFamilyBloc extends BlocBase {
|
||||
@override
|
||||
void dispose() {}
|
||||
|
||||
void getAllGroup(String role) async {
|
||||
void getAllGroup(BuildContext context, String role) async {
|
||||
List<Group> groups = [];
|
||||
sinkCurrentGroups.add(groups);
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
groups = await apiServices.getAllGroups();
|
||||
groups = sortGroupByName(groups);
|
||||
|
||||
@@ -55,19 +52,13 @@ class InterFamilyBloc extends BlocBase {
|
||||
return false;
|
||||
},
|
||||
).toList();
|
||||
|
||||
sinkCurrentGroups.add(currentGroups);
|
||||
} catch (e) {
|
||||
// Xử lý lỗi khi jsonDecode thất bại
|
||||
log("Error decoding JSON: $e");
|
||||
sinkCurrentGroups.add([]);
|
||||
}
|
||||
log("Inter Family Role: $role");
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> createGroup(
|
||||
BuildContext context, String name, String description) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Map<String, dynamic> body = {"name": name, "description": description};
|
||||
int? statusCode = await apiServices.createGroup(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -75,17 +66,12 @@ class InterFamilyBloc extends BlocBase {
|
||||
statusCode,
|
||||
appLocalization(context).notification_add_group_success,
|
||||
appLocalization(context).notification_add_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> changeGroupInformation(BuildContext context, String groupID,
|
||||
String name, String description) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
Map<String, dynamic> body = {"name": name, "description": description};
|
||||
int statusCode = await apiServices.updateGroup(body, groupID);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -93,44 +79,32 @@ class InterFamilyBloc extends BlocBase {
|
||||
statusCode,
|
||||
appLocalization(context).notification_update_group_success,
|
||||
appLocalization(context).notification_update_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> joinGroup(BuildContext context, String groupID) async {
|
||||
try {
|
||||
Map<String, dynamic> body = {
|
||||
"group_id": groupID,
|
||||
};
|
||||
Map<String, dynamic> body = {
|
||||
"group_id": groupID,
|
||||
};
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.joinGroup(groupID, body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_join_request_group_success,
|
||||
appLocalization(context).notification_join_request_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> deleteGroup(BuildContext context, String groupID) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.deleteGroup(groupID);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_group_success,
|
||||
appLocalization(context).notification_delete_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
List<Group> sortGroupByName(List<Group> groups) {
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import 'dart:async';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
|
||||
class LoginBloc extends BlocBase{
|
||||
|
||||
final loginRequest = StreamController<Map<String,dynamic>>.broadcast();
|
||||
StreamSink<Map<String,dynamic>> get sinkLoginRequest => loginRequest.sink;
|
||||
Stream<Map<String,dynamic>> get streamLoginRequest => loginRequest.stream;
|
||||
|
||||
class LoginBloc extends BlocBase {
|
||||
final loginRequest = StreamController<Map<String, dynamic>>.broadcast();
|
||||
StreamSink<Map<String, dynamic>> get sinkLoginRequest => loginRequest.sink;
|
||||
Stream<Map<String, dynamic>> get streamLoginRequest => loginRequest.stream;
|
||||
|
||||
final isShowPassword = StreamController<bool>.broadcast();
|
||||
StreamSink<bool> get sinkIsShowPassword => isShowPassword.sink;
|
||||
Stream<bool> get streamIsShowPassword => isShowPassword.stream;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
}
|
||||
|
||||
}
|
||||
void dispose() {}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sfm_app/product/cache/local_manager.dart';
|
||||
import 'package:sfm_app/product/constant/app/api_path_constant.dart';
|
||||
import 'package:sfm_app/product/constant/enums/local_keys_enums.dart';
|
||||
import 'package:sfm_app/product/network/network_manager.dart';
|
||||
|
||||
import '../product/cache/local_manager.dart';
|
||||
import '../product/constant/app/api_path_constant.dart';
|
||||
import '../product/constant/enums/local_keys_enums.dart';
|
||||
import '../product/network/network_manager.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/services/api_services.dart';
|
||||
import '../feature/bell/bell_model.dart';
|
||||
import '../feature/settings/profile/profile_model.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
|
||||
class MainBloc extends BlocBase {
|
||||
APIServices apiServices = APIServices();
|
||||
@@ -44,19 +42,13 @@ class MainBloc extends BlocBase {
|
||||
void dispose() {}
|
||||
|
||||
void getUserProfile(BuildContext context) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
User user = await apiServices.getUserDetail();
|
||||
sinkUserProfile.add(user);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
getFCMTokenAndPresentations() async {
|
||||
|
||||
String? firebaseAppToken = await FirebaseMessaging.instance.getToken();
|
||||
|
||||
if (firebaseAppToken != null) {
|
||||
@@ -67,14 +59,11 @@ class MainBloc extends BlocBase {
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> sendNotificationToken(String token) async{
|
||||
Future<int> sendNotificationToken(String token) async {
|
||||
String uid = await getUID();
|
||||
Map<String,dynamic> body = {
|
||||
"user_id": uid,
|
||||
"app_token": token
|
||||
};
|
||||
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
||||
Map<String, dynamic> body = {"user_id": uid, "app_token": token};
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.updateDataInServer(APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
|
||||
import '../product/services/map_services.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
import '../feature/devices/device_model.dart';
|
||||
@@ -75,6 +75,4 @@ class MapBloc extends BlocBase {
|
||||
context, "Không tìm thấy đường", Colors.orange, Colors.white);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:sfm_app/product/services/api_services.dart';
|
||||
|
||||
import '../product/services/api_services.dart';
|
||||
import '../feature/settings/profile/profile_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
import '../product/shared/shared_snack_bar.dart';
|
||||
|
||||
class SettingsBloc extends BlocBase {
|
||||
class SettingsBloc extends BlocBase {
|
||||
// Settings Screen
|
||||
APIServices apiServices = APIServices();
|
||||
final userProfile = StreamController<User>.broadcast();
|
||||
StreamSink<User> get sinkUserProfile => userProfile.sink;
|
||||
Stream<User> get streamUserProfile => userProfile.stream;
|
||||
|
||||
|
||||
// Profile Screen
|
||||
final isChangeProfileInfomation = StreamController<bool>.broadcast();
|
||||
StreamSink<bool> get sinkIsChangeProfileInfomation =>
|
||||
@@ -22,20 +19,13 @@ class SettingsBloc extends BlocBase {
|
||||
Stream<bool> get streamIsChangeProfileInfomation =>
|
||||
isChangeProfileInfomation.stream;
|
||||
|
||||
|
||||
void getUserProfile(BuildContext context) async {
|
||||
try {
|
||||
void getUserProfile(BuildContext context) async {
|
||||
await apiServices.execute(context, () async {
|
||||
User user = await apiServices.getUserDetail();
|
||||
sinkUserProfile.add(user);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
}
|
||||
void dispose() {}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sfm_app/product/shared/shared_snack_bar.dart';
|
||||
import '../../product/extension/context_extension.dart';
|
||||
|
||||
import '../../product/services/language_services.dart';
|
||||
import '../../bloc/bell_bloc.dart';
|
||||
import '../../product/base/bloc/base_bloc.dart';
|
||||
@@ -77,7 +76,8 @@ class _BellScreenState extends State<BellScreen> {
|
||||
if (index < bellSnapshot.data!.length) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
readNotification(bellSnapshot.data![index].id!);
|
||||
readNotification(
|
||||
bellSnapshot.data![index].id!);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -163,24 +163,18 @@ class _BellScreenState extends State<BellScreen> {
|
||||
getBellNotification(offset);
|
||||
}
|
||||
|
||||
void readNotification(String id) async{
|
||||
try {
|
||||
void readNotification(String id) async {
|
||||
await apiServices.execute(context, () async {
|
||||
List<String> read = [];
|
||||
read.add(id);
|
||||
await apiServices
|
||||
.updateStatusOfNotification(read);
|
||||
await apiServices.updateStatusOfNotification(read);
|
||||
read.clear();
|
||||
} catch (e) {
|
||||
if (mounted){
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> getBellNotification(int offset) async {
|
||||
try {
|
||||
apiServices.execute(context, () async {
|
||||
bell = await apiServices.getBellNotifications(
|
||||
offset.toString(), (offset + 20).toString());
|
||||
if (bell.items!.isEmpty) {
|
||||
@@ -193,10 +187,7 @@ class _BellScreenState extends State<BellScreen> {
|
||||
}
|
||||
bellBloc.bellItems.add(items);
|
||||
check = false;
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String timeAgo(BuildContext context, DateTime dateTime) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sfm_app/bloc/devices_manager_bloc.dart';
|
||||
import 'package:sfm_app/product/shared/shared_snack_bar.dart';
|
||||
|
||||
import '../../bloc/devices_manager_bloc.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import '../../product/utils/response_status_utils.dart';
|
||||
import '../../product/constant/enums/role_enums.dart';
|
||||
import '../../product/services/api_services.dart';
|
||||
@@ -11,7 +12,8 @@ import '../../product/constant/icon/icon_constants.dart';
|
||||
import '../../product/extension/context_extension.dart';
|
||||
import '../../product/services/language_services.dart';
|
||||
|
||||
addNewDevice(BuildContext context, String role, DevicesManagerBloc deviceManagerBloc) async {
|
||||
addNewDevice(BuildContext context, String role,
|
||||
DevicesManagerBloc deviceManagerBloc) async {
|
||||
TextEditingController extIDController = TextEditingController(text: "");
|
||||
TextEditingController deviceNameController = TextEditingController(text: "");
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -77,7 +79,8 @@ addNewDevice(BuildContext context, String role, DevicesManagerBloc deviceManager
|
||||
Colors.white);
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
} else {
|
||||
addDevices(context, role, extID, deviceName, deviceManagerBloc);
|
||||
addDevices(
|
||||
context, role, extID, deviceName, deviceManagerBloc);
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
}
|
||||
},
|
||||
@@ -90,12 +93,12 @@ addNewDevice(BuildContext context, String role, DevicesManagerBloc deviceManager
|
||||
);
|
||||
}
|
||||
|
||||
void addDevices(
|
||||
BuildContext context, String role, String extID, String deviceName, DevicesManagerBloc deviceManagerBloc) async {
|
||||
void addDevices(BuildContext context, String role, String extID,
|
||||
String deviceName, DevicesManagerBloc deviceManagerBloc) async {
|
||||
APIServices apiServices = APIServices();
|
||||
Map<String, dynamic> body = {};
|
||||
if (role == RoleEnums.ADMIN.name) {
|
||||
try {
|
||||
await apiServices.execute(context,() async {
|
||||
body = {"ext_id": extID, "name": deviceName};
|
||||
int statusCode = await apiServices.createDeviceByAdmin(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -103,15 +106,10 @@ void addDevices(
|
||||
statusCode,
|
||||
appLocalization(context).notification_create_device_success,
|
||||
appLocalization(context).notification_create_device_failed);
|
||||
deviceManagerBloc.getDeviceByState(context,-2);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
deviceManagerBloc.getDeviceByState(context, -2);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
await apiServices.execute(context,() async {
|
||||
body = {"ext_id": extID};
|
||||
int statusCode = await apiServices.registerDevice(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -119,12 +117,7 @@ void addDevices(
|
||||
statusCode,
|
||||
appLocalization(context).notification_add_device_success,
|
||||
appLocalization(context).notification_device_not_exist);
|
||||
deviceManagerBloc.getDeviceByState(context,-2);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
deviceManagerBloc.getDeviceByState(context, -2);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import '../../bloc/devices_manager_bloc.dart';
|
||||
import '../../product/constant/enums/role_enums.dart';
|
||||
import '../../product/services/api_services.dart';
|
||||
import '../../product/services/language_services.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import '../../product/utils/response_status_utils.dart';
|
||||
|
||||
handleDeleteDevice(BuildContext context, DevicesManagerBloc devicesManagerBloc,
|
||||
@@ -48,27 +47,24 @@ deleteOrUnregisterDevice(BuildContext context, DevicesManagerBloc devicesBloc,
|
||||
Map<String, dynamic> body = {
|
||||
"ext_id": extID,
|
||||
};
|
||||
int statusCode = await apiServices.unregisterDevice(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_device_success,
|
||||
appLocalization(context).notification_delete_device_failed);
|
||||
devicesBloc.getDeviceByState(context,-2);
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.unregisterDevice(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_device_success,
|
||||
appLocalization(context).notification_delete_device_failed);
|
||||
devicesBloc.getDeviceByState(context, -2);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.deleteDeviceByAdmin(extID);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_device_success,
|
||||
appLocalization(context).notification_delete_device_failed);
|
||||
devicesBloc.getDeviceByState(context,-2);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
devicesBloc.getDeviceByState(context, -2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart';
|
||||
|
||||
import '../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import '../../product/utils/app_logger_utils.dart';
|
||||
import 'shared/alert_card.dart';
|
||||
import 'shared/warning_card.dart';
|
||||
import '../../product/utils/device_utils.dart';
|
||||
@@ -19,8 +18,8 @@ import '../../bloc/home_bloc.dart';
|
||||
import '../../product/base/bloc/base_bloc.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
||||
const HomeScreen({super.key, required this.persistentTabController});
|
||||
final PersistentTabController persistentTabController;
|
||||
@override
|
||||
State<HomeScreen> createState() => _HomeScreenState();
|
||||
}
|
||||
@@ -29,7 +28,6 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
late HomeBloc homeBloc;
|
||||
APIServices apiServices = APIServices();
|
||||
Map<String, List<DeviceWithAlias>> allDevicesAliasMap = {};
|
||||
Map<String, List<DeviceWithAlias>> allDevicesAliasJoinedMap = {};
|
||||
List<DeviceWithAlias> devices = [];
|
||||
bool isFunctionCall = false;
|
||||
Timer? getAllDevicesTimer;
|
||||
@@ -41,6 +39,8 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
homeBloc = BlocProvider.of(context);
|
||||
getAllDevicesTimer?.cancel();
|
||||
AppLoggerUtils.debug("Init State HomeScreen");
|
||||
getOwnerAndJoinedDevices();
|
||||
const duration = Duration(seconds: 10);
|
||||
getAllDevicesTimer =
|
||||
@@ -50,6 +50,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
@override
|
||||
void dispose() {
|
||||
getAllDevicesTimer?.cancel();
|
||||
homeBloc.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -198,107 +199,23 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
StreamBuilder<bool?>(
|
||||
stream: homeBloc.streamHasJoinedDevice,
|
||||
initialData: null,
|
||||
builder: (context, hasJoinedDeviceSnapshot) {
|
||||
return StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||
stream: homeBloc.streamAllDevicesAliasMap,
|
||||
builder: (context, allDevicesAliasMapSnapshot) {
|
||||
return StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||
stream: homeBloc.streamAllDevicesAliasJoinedMap,
|
||||
builder: (context, allDevicesAliasJoinedMapSnapshot) {
|
||||
if (hasJoinedDeviceSnapshot.data == null) {
|
||||
return const SharedComponentLoadingAnimation();
|
||||
} else {
|
||||
final data = allDevicesAliasMapSnapshot.data!;
|
||||
final dataJoined =
|
||||
allDevicesAliasJoinedMapSnapshot.data!;
|
||||
if (hasJoinedDeviceSnapshot.data == false) {
|
||||
if (!allDevicesAliasMapSnapshot.hasData ||
|
||||
allDevicesAliasMapSnapshot.data == null) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return OverviewCard(
|
||||
isOwner: true,
|
||||
total: data['all']?.length ?? 0,
|
||||
active: data['online']?.length ?? 0,
|
||||
inactive: data['offline']?.length ?? 0,
|
||||
warning: data['warn']?.length ?? 0,
|
||||
unused: data['not-use']?.length ?? 0,
|
||||
showUnused: false,
|
||||
);
|
||||
} else {
|
||||
return DefaultTabController(
|
||||
length: 2,
|
||||
child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TabBar(
|
||||
tabs: [
|
||||
Tab(
|
||||
text: appLocalization(context)
|
||||
.over_view_owner_devices),
|
||||
Tab(
|
||||
text: appLocalization(context)
|
||||
.over_view_joined_devices),
|
||||
],
|
||||
labelColor: Colors.blue,
|
||||
unselectedLabelColor: Colors.grey,
|
||||
indicatorColor: Colors.blue,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: context.dynamicHeight(0.5),
|
||||
minHeight: context.dynamicHeight(0.3),
|
||||
),
|
||||
child: TabBarView(
|
||||
children: [
|
||||
OverviewCard(
|
||||
isOwner: true,
|
||||
total: data['all']?.length ?? 0,
|
||||
active: data['online']?.length ?? 0,
|
||||
inactive:
|
||||
data['offline']?.length ?? 0,
|
||||
warning: data['warn']?.length ?? 0,
|
||||
unused:
|
||||
data['not-use']?.length ?? 0,
|
||||
showUnused: false,
|
||||
),
|
||||
OverviewCard(
|
||||
isOwner: false,
|
||||
total:
|
||||
dataJoined['all']?.length ?? 0,
|
||||
active:
|
||||
dataJoined['online']?.length ??
|
||||
0,
|
||||
inactive:
|
||||
dataJoined['offline']?.length ??
|
||||
0,
|
||||
warning:
|
||||
dataJoined['warn']?.length ?? 0,
|
||||
unused:
|
||||
dataJoined['not-use']?.length ??
|
||||
0,
|
||||
showUnused: false,
|
||||
showActive: false,
|
||||
showInactive: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||
stream: homeBloc.streamAllDevicesAliasMap,
|
||||
builder: (context, allDevicesAliasMapSnapshot) {
|
||||
if(allDevicesAliasMapSnapshot.data == null){
|
||||
return const SharedComponentLoadingAnimation();
|
||||
}else{
|
||||
final data = allDevicesAliasMapSnapshot.data!;
|
||||
return OverviewCard(
|
||||
isOwner: true,
|
||||
total: data['all']?.length ?? 0,
|
||||
active: data['online']?.length ?? 0,
|
||||
inactive: data['offline']?.length ?? 0,
|
||||
warning: data['warn']?.length ?? 0,
|
||||
unused: data['not-use']?.length ?? 0,
|
||||
showUnused: false,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -309,8 +226,8 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
}
|
||||
|
||||
void getOwnerAndJoinedDevices() async {
|
||||
try {
|
||||
devices = await apiServices.getDashBoardDevices();
|
||||
await apiServices.execute(context, () async {
|
||||
devices = await apiServices.getDashBoardDevices().handleApiError();
|
||||
List<DeviceWithAlias> publicDevices = [];
|
||||
for (var device in devices) {
|
||||
if (device.visibility == "PUBLIC") {
|
||||
@@ -320,10 +237,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
getOwnerDeviceState(publicDevices);
|
||||
checkSettingDevice(publicDevices);
|
||||
getDeviceStatusAliasMap(publicDevices);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void getOwnerDeviceState(List<DeviceWithAlias> allDevices) async {
|
||||
@@ -335,7 +249,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
|
||||
int count = 0;
|
||||
for (var device in allDevices) {
|
||||
if (device.isOwner != true) continue;
|
||||
// if (device.isOwner != true) continue;
|
||||
|
||||
if (!mounted) return;
|
||||
Map<String, dynamic> sensorMap = DeviceUtils.instance
|
||||
@@ -368,55 +282,34 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
|
||||
void getDeviceStatusAliasMap(List<DeviceWithAlias> devices) {
|
||||
allDevicesAliasMap.clear();
|
||||
allDevicesAliasJoinedMap.clear();
|
||||
bool check = false;
|
||||
for (var key in ['all', 'online', 'offline', 'warning', 'not-use']) {
|
||||
allDevicesAliasMap[key] = [];
|
||||
allDevicesAliasJoinedMap[key] = [];
|
||||
}
|
||||
|
||||
for (DeviceWithAlias device in devices) {
|
||||
if (device.isOwner == true) {
|
||||
allDevicesAliasMap['all']!.add(device);
|
||||
if (device.state == 0 || device.state == 1) {
|
||||
allDevicesAliasMap['online']!.add(device);
|
||||
}
|
||||
if (device.state == -1) {
|
||||
allDevicesAliasMap['offline']!.add(device);
|
||||
}
|
||||
if (device.state == 1) {
|
||||
allDevicesAliasMap['warning']!.add(device);
|
||||
}
|
||||
if (device.state == -2) {
|
||||
allDevicesAliasMap['not-use']!.add(device);
|
||||
}
|
||||
} else {
|
||||
check = true;
|
||||
allDevicesAliasJoinedMap['all']!.add(device);
|
||||
if (device.state == 0 || device.state == 1) {
|
||||
allDevicesAliasJoinedMap['online']!.add(device);
|
||||
}
|
||||
if (device.state == -1) {
|
||||
allDevicesAliasJoinedMap['offline']!.add(device);
|
||||
}
|
||||
if (device.state == 1) {
|
||||
allDevicesAliasJoinedMap['warning']!.add(device);
|
||||
}
|
||||
if (device.state == -2) {
|
||||
allDevicesAliasJoinedMap['not-use']!.add(device);
|
||||
}
|
||||
allDevicesAliasMap['all']!.add(device);
|
||||
if (device.state == 0 || device.state == 1) {
|
||||
allDevicesAliasMap['online']!.add(device);
|
||||
}
|
||||
if (device.state == -1) {
|
||||
allDevicesAliasMap['offline']!.add(device);
|
||||
}
|
||||
if (device.state == 1) {
|
||||
allDevicesAliasMap['warning']!.add(device);
|
||||
}
|
||||
if (device.state == -2) {
|
||||
allDevicesAliasMap['not-use']!.add(device);
|
||||
}
|
||||
|
||||
}
|
||||
homeBloc.sinkHasJoinedDevice.add(check);
|
||||
homeBloc.sinkAllDevicesAliasMap.add(allDevicesAliasMap);
|
||||
homeBloc.sinkAllDevicesAliasJoinedMap.add(allDevicesAliasJoinedMap);
|
||||
}
|
||||
|
||||
void checkSettingDevice(List<DeviceWithAlias> devices) async {
|
||||
try {
|
||||
if (isFunctionCall) {
|
||||
log("Ham check setting da duoc goi");
|
||||
} else {
|
||||
if (isFunctionCall) {
|
||||
log("Ham check setting da duoc goi");
|
||||
} else {
|
||||
await apiServices.execute(context, () async {
|
||||
List<DeviceNotificationSettings> list =
|
||||
await apiServices.getAllSettingsNotificationOfDevices();
|
||||
// log("List: $list");
|
||||
@@ -425,24 +318,16 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
for (var device in devices) {
|
||||
if (!thingIdsInList.contains(device.thingId)) {
|
||||
log("Device with Thing ID ${device.thingId} is not in the notification settings list.");
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
await apiServices.setupDeviceNotification(
|
||||
device.thingId!, device.name!);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
log("All devices are in the notification settings list.");
|
||||
}
|
||||
}
|
||||
}
|
||||
isFunctionCall = true;
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
});
|
||||
}
|
||||
isFunctionCall = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:sfm_app/feature/home/device_alias_model.dart';
|
||||
import '../../../product/shared/shared_rocket_container.dart';
|
||||
import '../../../product/constant/enums/app_route_enums.dart';
|
||||
import '../../../product/constant/image/image_constants.dart';
|
||||
import '../../../product/extension/context_extension.dart';
|
||||
@@ -11,16 +11,16 @@ import '../../../product/services/language_services.dart';
|
||||
import '../../../product/utils/device_utils.dart';
|
||||
|
||||
import '../../../product/constant/icon/icon_constants.dart';
|
||||
import '../device_alias_model.dart';
|
||||
|
||||
Future<Widget> notificationCard(BuildContext context, String notiticationType,
|
||||
Future<Widget> notificationCard(BuildContext context, String notificationType,
|
||||
String notificationTitle, DeviceWithAlias device) async {
|
||||
String location = "";
|
||||
if (device.areaPath != "") {
|
||||
location = await DeviceUtils.instance
|
||||
.getFullDeviceLocation(context, device.areaPath!,"");
|
||||
.getFullDeviceLocation(context, device.areaPath!, "");
|
||||
}
|
||||
String path = "";
|
||||
// DateTime time = DateTime.now();
|
||||
String time = "";
|
||||
for (var sensor in device.status!.sensors!) {
|
||||
if (sensor.name! == "7") {
|
||||
@@ -29,7 +29,7 @@ Future<Widget> notificationCard(BuildContext context, String notiticationType,
|
||||
time = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||
}
|
||||
}
|
||||
if (notiticationType == "lowBattery") {
|
||||
if (notificationType == "lowBattery") {
|
||||
path = ImageConstants.instance.getImage("low_battery");
|
||||
}
|
||||
return Card(
|
||||
@@ -117,24 +117,57 @@ Future<Widget> notificationCard(BuildContext context, String notiticationType,
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: OutlinedButton(
|
||||
style: const ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll(Colors.blueAccent),
|
||||
),
|
||||
onPressed: () {
|
||||
context.pushNamed(AppRoutes.DEVICE_DETAIL.name,
|
||||
pathParameters: {'thingID': device.thingId!});
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context).detail_message,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
device.isOwner!
|
||||
? Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: OutlinedButton(
|
||||
style: const ButtonStyle(
|
||||
backgroundColor:
|
||||
WidgetStatePropertyAll(Colors.blueAccent),
|
||||
),
|
||||
onPressed: () {
|
||||
context.pushNamed(AppRoutes.DEVICE_DETAIL.name,
|
||||
pathParameters: {'thingID': device.thingId!});
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context).detail_message,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ClipPath(
|
||||
clipper: SharedRocketContainer(),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(context.lowValue),
|
||||
height: context.mediumValue,
|
||||
width: context.dynamicWidth(0.22),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green[300],
|
||||
),
|
||||
child: Text(
|
||||
appLocalization(context).interfamily_page_name,
|
||||
),
|
||||
),
|
||||
),
|
||||
OutlinedButton(
|
||||
style: const ButtonStyle(
|
||||
backgroundColor:
|
||||
WidgetStatePropertyAll(Colors.blueAccent),
|
||||
),
|
||||
onPressed: () {
|
||||
context.pushNamed(AppRoutes.DEVICE_DETAIL.name,
|
||||
pathParameters: {'thingID': device.thingId!});
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context).detail_message,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:maps_launcher/maps_launcher.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
|
||||
import '../../../product/shared/shared_rocket_container.dart';
|
||||
import '../device_alias_model.dart';
|
||||
import '../../../product/constant/icon/icon_constants.dart';
|
||||
import '../../../product/constant/image/image_constants.dart';
|
||||
@@ -18,10 +20,10 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
||||
Color backgroundColor = Colors.blue;
|
||||
Color textColor = Colors.white;
|
||||
String message = "";
|
||||
String fullLocation = "";
|
||||
String fullLocation = "";
|
||||
if (device.areaPath != "") {
|
||||
fullLocation = await DeviceUtils.instance
|
||||
.getFullDeviceLocation(context, device.areaPath!,"");
|
||||
.getFullDeviceLocation(context, device.areaPath!, "");
|
||||
}
|
||||
String time = "";
|
||||
for (var sensor in device.status!.sensors!) {
|
||||
@@ -187,84 +189,185 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
||||
),
|
||||
),
|
||||
SizedBox(width: context.mediumValue),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
WidgetStatePropertyAll(backgroundColor)),
|
||||
onPressed: () async {
|
||||
if (message ==
|
||||
appLocalization(context).button_fake_fire_message) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(Icons.warning),
|
||||
iconColor: Colors.red,
|
||||
title: Text(appLocalization(context)
|
||||
.confirm_fake_fire_message),
|
||||
content: Text(appLocalization(context)
|
||||
.confirm_fake_fire_body),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
int statusCode = await apiServices
|
||||
.confirmFakeFireByUser(device.thingId!);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
device.isOwner!
|
||||
? Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
WidgetStatePropertyAll(backgroundColor)),
|
||||
onPressed: () async {
|
||||
if (message ==
|
||||
appLocalization(context)
|
||||
.button_fake_fire_message) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(Icons.warning),
|
||||
iconColor: Colors.red,
|
||||
title: Text(appLocalization(context)
|
||||
.confirm_fake_fire_message),
|
||||
content: Text(appLocalization(context)
|
||||
.confirm_fake_fire_body),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await apiServices.execute(context,
|
||||
() async {
|
||||
int statusCode = await apiServices
|
||||
.confirmFakeFireByUser(
|
||||
device.thingId!);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_failed,
|
||||
Colors.red,
|
||||
Colors.red);
|
||||
}
|
||||
});
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_failed,
|
||||
Colors.red,
|
||||
Colors.red);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context)
|
||||
.confirm_fake_fire_sure_message,
|
||||
style:
|
||||
const TextStyle(color: Colors.red)),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(appLocalization(context)
|
||||
.cancel_button_content),
|
||||
),
|
||||
],
|
||||
.confirm_fake_fire_sure_message,
|
||||
style: const TextStyle(
|
||||
color: Colors.red)),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(appLocalization(context)
|
||||
.cancel_button_content),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.let_PCCC_handle_message,
|
||||
Colors.orange,
|
||||
Colors.white);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
message,
|
||||
style: TextStyle(color: textColor),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).let_PCCC_handle_message,
|
||||
Colors.orange,
|
||||
Colors.white);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
message,
|
||||
style: TextStyle(color: textColor),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ClipPath(
|
||||
clipper: SharedRocketContainer(),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(context.lowValue),
|
||||
height: context.mediumValue,
|
||||
width: context.dynamicWidth(0.22),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green[300],
|
||||
),
|
||||
child: Text(
|
||||
appLocalization(context).interfamily_page_name,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll(
|
||||
backgroundColor)),
|
||||
onPressed: () async {
|
||||
if (message ==
|
||||
appLocalization(context)
|
||||
.button_fake_fire_message) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(Icons.warning),
|
||||
iconColor: Colors.red,
|
||||
title: Text(appLocalization(context)
|
||||
.confirm_fake_fire_message),
|
||||
content: Text(appLocalization(context)
|
||||
.confirm_fake_fire_body),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await apiServices.execute(context,
|
||||
() async {
|
||||
int statusCode =
|
||||
await apiServices
|
||||
.confirmFakeFireByUser(
|
||||
device.thingId!);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.notification_confirm_fake_fire_failed,
|
||||
Colors.red,
|
||||
Colors.red);
|
||||
}
|
||||
});
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context)
|
||||
.confirm_fake_fire_sure_message,
|
||||
style: const TextStyle(
|
||||
color: Colors.red)),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(appLocalization(context)
|
||||
.cancel_button_content),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context)
|
||||
.let_PCCC_handle_message,
|
||||
Colors.orange,
|
||||
Colors.white);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
message,
|
||||
style: TextStyle(color: textColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../bloc/group_detail_bloc.dart';
|
||||
import '../../../product/shared/shared_loading_animation.dart';
|
||||
import '../../../product/shared/shared_snack_bar.dart';
|
||||
import 'group_detail_model.dart';
|
||||
import '../../../product/base/bloc/base_bloc.dart';
|
||||
import '../../../product/constant/app/app_constants.dart';
|
||||
@@ -325,7 +324,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
Future.delayed(context.lowDuration).then(
|
||||
(value) => Navigator.pop(context),
|
||||
);
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices
|
||||
.deleteGroup(widget.group);
|
||||
showSnackBarResponseByStatusCode(
|
||||
@@ -335,11 +334,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
.notification_delete_group_success,
|
||||
appLocalization(context)
|
||||
.notification_delete_group_failed);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context)
|
||||
|
||||
@@ -39,7 +39,7 @@ class _GroupsScreenState extends State<GroupsScreen> {
|
||||
const duration = Duration(seconds: 5);
|
||||
getAllGroupsTimer = Timer.periodic(
|
||||
duration,
|
||||
(Timer t) => interFamilyBloc.getAllGroup(widget.role),
|
||||
(Timer t) => interFamilyBloc.getAllGroup(context, widget.role),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class _GroupsScreenState extends State<GroupsScreen> {
|
||||
stream: interFamilyBloc.streamCurrentGroups,
|
||||
builder: (context, groupsSnapshot) {
|
||||
if (groupsSnapshot.data == null) {
|
||||
interFamilyBloc.getAllGroup(widget.role);
|
||||
interFamilyBloc.getAllGroup(context,widget.role);
|
||||
return const SharedLoadingAnimation();
|
||||
} else if (groupsSnapshot.data!.isEmpty) {
|
||||
return Center(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
|
||||
import '../../../bloc/inter_family_bloc.dart';
|
||||
import '../../../product/constant/icon/icon_constants.dart';
|
||||
import '../../../product/extension/context_extension.dart';
|
||||
import '../../../product/services/language_services.dart';
|
||||
|
||||
import 'groups_model.dart';
|
||||
|
||||
shareGroup(BuildContext context, Group group) {
|
||||
@@ -80,7 +80,8 @@ showActionDialog(
|
||||
if (dialogTitle == appLocalization(context).delete_group_title) {
|
||||
Navigator.of(dialogContext).pop();
|
||||
await interFamilyBloc.deleteGroup(context, group.id!);
|
||||
interFamilyBloc.getAllGroup(role);
|
||||
// ignore: use_build_context_synchronously
|
||||
interFamilyBloc.getAllGroup(context,role);
|
||||
} else {}
|
||||
},
|
||||
child: Text(
|
||||
|
||||
@@ -122,7 +122,7 @@ createOrJoinGroupDialog(
|
||||
try {
|
||||
await interFamilyBloc.createGroup(
|
||||
context, groupName, description);
|
||||
interFamilyBloc.getAllGroup(role);
|
||||
interFamilyBloc.getAllGroup(context, role);
|
||||
Navigator.of(dialogContext).pop();
|
||||
} catch (e) {
|
||||
// log("Lỗi khi tạo nhóm: $e");
|
||||
@@ -133,7 +133,7 @@ createOrJoinGroupDialog(
|
||||
try {
|
||||
await interFamilyBloc.changeGroupInformation(
|
||||
context, groupID, groupName, description);
|
||||
interFamilyBloc.getAllGroup(role);
|
||||
interFamilyBloc.getAllGroup(context, role);
|
||||
Navigator.of(dialogContext).pop();
|
||||
} catch (e) {
|
||||
// log("Lỗi khi sửa nhóm: $e");
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -10,16 +8,14 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart';
|
||||
import 'package:sfm_app/product/shared/shared_snack_bar.dart';
|
||||
import 'package:sfm_app/product/utils/permission_handler.dart';
|
||||
|
||||
import '../../product/utils/permission_handler.dart';
|
||||
import '../../product/permission/notification_permission.dart';
|
||||
import '../../product/services/notification_services.dart';
|
||||
import '../settings/profile/profile_model.dart';
|
||||
import '../../product/extension/context_extension.dart';
|
||||
import '../../bloc/home_bloc.dart';
|
||||
import '../../product/constant/app/app_constants.dart';
|
||||
import '../../product/constant/enums/app_route_enums.dart';
|
||||
import '../../product/permission/location_permission.dart';
|
||||
import '../../product/services/theme_services.dart';
|
||||
import '../../bloc/devices_manager_bloc.dart';
|
||||
import '../devices/devices_manager_screen.dart';
|
||||
@@ -47,8 +43,6 @@ class MainScreen extends StatefulWidget {
|
||||
State<MainScreen> createState() => _MainScreenState();
|
||||
}
|
||||
|
||||
PersistentTabController controller = PersistentTabController(initialIndex: 0);
|
||||
|
||||
// @pragma('vm:entry-point')
|
||||
// Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
// log("Full background message payload: ${message.toMap()}");
|
||||
@@ -59,8 +53,8 @@ PersistentTabController controller = PersistentTabController(initialIndex: 0);
|
||||
// log("Background message handled: ${message.data['title']}");
|
||||
// }
|
||||
|
||||
|
||||
class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
PersistentTabController controller = PersistentTabController(initialIndex: 0);
|
||||
APIServices apiServices = APIServices();
|
||||
// final NotificationServices notificationServices = NotificationServices();
|
||||
late MainBloc mainBloc;
|
||||
@@ -112,17 +106,19 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||
RemoteNotification? notification = message.notification;
|
||||
AndroidNotification? android = message.notification?.android;
|
||||
if (notification != null && android != null ) {
|
||||
if (notification != null && android != null) {
|
||||
const AndroidNotificationDetails androidPlatformChannelSpecifics =
|
||||
AndroidNotificationDetails(
|
||||
'your channel id', 'your channel name',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
ticker: 'ticker');
|
||||
AndroidNotificationDetails('your channel id', 'your channel name',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
ticker: 'ticker');
|
||||
const NotificationDetails platformChannelSpecifics =
|
||||
NotificationDetails(android: androidPlatformChannelSpecifics);
|
||||
NotificationDetails(android: androidPlatformChannelSpecifics);
|
||||
flutterLocalNotificationsPlugin.show(
|
||||
notification.hashCode, notification.title, notification.body, platformChannelSpecifics,
|
||||
notification.hashCode,
|
||||
notification.title,
|
||||
notification.body,
|
||||
platformChannelSpecifics,
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -151,7 +147,6 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
}
|
||||
|
||||
|
||||
List<PersistentBottomNavBarItem> _navBarsItems() {
|
||||
return [
|
||||
PersistentBottomNavBarItem(
|
||||
@@ -200,7 +195,9 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
List<Widget> _buildScreens() {
|
||||
return [
|
||||
BlocProvider(
|
||||
child: const HomeScreen(),
|
||||
child: HomeScreen(
|
||||
persistentTabController: controller,
|
||||
),
|
||||
blocBuilder: () => HomeBloc(),
|
||||
),
|
||||
BlocProvider(
|
||||
@@ -238,7 +235,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
SizedBox(
|
||||
width: context.lowValue,
|
||||
),
|
||||
Flexible( child: Text(userSnapshot.data?.name ?? ""))
|
||||
Flexible(child: Text(userSnapshot.data?.name ?? ""))
|
||||
],
|
||||
);
|
||||
}),
|
||||
@@ -404,12 +401,10 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
Future<void> getBellNotification() async {
|
||||
try{
|
||||
await apiServices.execute(context, () async {
|
||||
bell = await apiServices.getBellNotifications("0", "20");
|
||||
mainBloc.bellBloc.add(bell);
|
||||
}catch(e){
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool checkStatus(List<BellItems> bells) {
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:google_maps_cluster_manager_2/google_maps_cluster_manager_2.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart'
|
||||
hide ClusterManager, Cluster;
|
||||
import 'package:sfm_app/feature/devices/device_model.dart';
|
||||
import 'package:sfm_app/bloc/map_bloc.dart';
|
||||
import 'package:sfm_app/feature/map/widget/on_tap_marker_widget.dart';
|
||||
import 'package:sfm_app/product/base/bloc/base_bloc.dart';
|
||||
import 'package:sfm_app/product/constant/icon/icon_constants.dart';
|
||||
import 'package:sfm_app/product/permission/location_permission.dart';
|
||||
import 'package:sfm_app/product/services/api_services.dart';
|
||||
import 'package:sfm_app/product/utils/permission_handler.dart';
|
||||
|
||||
import '../../bloc/map_bloc.dart';
|
||||
import '../../product/base/bloc/base_bloc.dart';
|
||||
import '../../product/constant/enums/app_theme_enums.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import '../../product/constant/icon/icon_constants.dart';
|
||||
import '../../product/services/api_services.dart';
|
||||
import '../../product/utils/permission_handler.dart';
|
||||
import '../devices/device_model.dart';
|
||||
import 'widget/on_tap_marker_widget.dart';
|
||||
|
||||
class MapScreen extends StatefulWidget {
|
||||
const MapScreen({super.key});
|
||||
@@ -39,7 +36,7 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
APIServices apiServices = APIServices();
|
||||
final streamController = StreamController<GoogleMapController>.broadcast();
|
||||
List<Device> devices = [];
|
||||
Completer<GoogleMapController> _controller = Completer();
|
||||
final Completer<GoogleMapController> _controller = Completer();
|
||||
List<String> imageAssets = [
|
||||
IconConstants.instance.getIcon("normal_icon"),
|
||||
IconConstants.instance.getIcon("offline_icon"),
|
||||
@@ -121,7 +118,8 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
clusterManager.updateMap();
|
||||
},
|
||||
polylines: {
|
||||
if (polylinesSnapshot.data != null && polylinesSnapshot.data!.isNotEmpty) ... [
|
||||
if (polylinesSnapshot.data != null &&
|
||||
polylinesSnapshot.data!.isNotEmpty) ...[
|
||||
Polyline(
|
||||
polylineId: const PolylineId('router'),
|
||||
points: polylinesSnapshot.data!,
|
||||
@@ -189,7 +187,8 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
position: cluster.location,
|
||||
onTap: () async {
|
||||
LocationPermission permission = await checkAndRequestPermission();
|
||||
if (permission == LocationPermission.whileInUse || permission == LocationPermission.always) {
|
||||
if (permission == LocationPermission.whileInUse ||
|
||||
permission == LocationPermission.always) {
|
||||
Position position = await Geolocator.getCurrentPosition();
|
||||
onTapMarker(
|
||||
// ignore: use_build_context_synchronously
|
||||
@@ -277,23 +276,12 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
void getAllMarkers() async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
devices.clear();
|
||||
final devicesList = await apiServices.getOwnerDevices();
|
||||
for (var device in devicesList) {
|
||||
devices.add(device);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Future<bool> checkLocationPermission(context) async {
|
||||
// bool check = await LocationPermissionRequest.instance
|
||||
// .checkLocationPermission(context);
|
||||
// return check;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../product/shared/shared_snack_bar.dart';
|
||||
import '../../../bloc/device_notification_settings_bloc.dart';
|
||||
import 'device_notification_settings_model.dart';
|
||||
@@ -111,15 +111,12 @@ class _DeviceNotificationSettingsScreenState
|
||||
}
|
||||
|
||||
void getNotificationSetting() async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
deviceNotifications =
|
||||
await apiServices.getAllSettingsNotificationOfDevices();
|
||||
deviceNotificationSettingsBloc.sinkListNotifications
|
||||
.add(deviceNotifications);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget listNotificationSetting(
|
||||
@@ -293,13 +290,14 @@ class _DeviceNotificationSettingsScreenState
|
||||
|
||||
void updateDeviceNotification(String thingID, Map<String, int> notifiSettings,
|
||||
bool isDataChange) async {
|
||||
try {
|
||||
await apiServices.execute(context, () async {
|
||||
int statusCode = await apiServices.updateDeviceNotificationSettings(
|
||||
thingID, notifiSettings);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).notification_update_device_settings_success,
|
||||
appLocalization(context)
|
||||
.notification_update_device_settings_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
@@ -311,11 +309,6 @@ class _DeviceNotificationSettingsScreenState
|
||||
}
|
||||
isDataChange = false;
|
||||
deviceNotificationSettingsBloc.sinkIsDataChange.add(isDataChange);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../product/shared/shared_snack_bar.dart';
|
||||
import '../../../product/constant/icon/icon_constants.dart';
|
||||
import '../../../product/services/api_services.dart';
|
||||
@@ -8,7 +9,6 @@ import '../../../bloc/settings_bloc.dart';
|
||||
import '../../../product/shared/shared_input_decoration.dart';
|
||||
import '../../../product/extension/context_extension.dart';
|
||||
import '../../../product/services/language_services.dart';
|
||||
|
||||
import 'profile_model.dart';
|
||||
|
||||
changeUserInfomation(
|
||||
@@ -38,7 +38,7 @@ changeUserInfomation(
|
||||
? IconButton(
|
||||
onPressed: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
try {
|
||||
await apiServices.execute(context,() async {
|
||||
formKey.currentState!.save();
|
||||
String latitude = user.latitude ?? "";
|
||||
String longitude = user.longitude ?? "";
|
||||
@@ -51,7 +51,7 @@ changeUserInfomation(
|
||||
"longitude": longitude
|
||||
};
|
||||
int statusCode =
|
||||
await apiServices.updateUserProfile(body);
|
||||
await apiServices.updateUserProfile(body);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
modalBottomSheetContext,
|
||||
@@ -69,11 +69,42 @@ changeUserInfomation(
|
||||
}
|
||||
settingsBloc.getUserProfile(context);
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// formKey.currentState!.save();
|
||||
// String latitude = user.latitude ?? "";
|
||||
// String longitude = user.longitude ?? "";
|
||||
// Map<String, dynamic> body = {
|
||||
// "name": username,
|
||||
// "email": email,
|
||||
// "phone": tel,
|
||||
// "address": address,
|
||||
// "latitude": latitude,
|
||||
// "longitude": longitude
|
||||
// };
|
||||
// int statusCode =
|
||||
// await apiServices.updateUserProfile(body);
|
||||
// if (statusCode == 200) {
|
||||
// showNoIconTopSnackBar(
|
||||
// modalBottomSheetContext,
|
||||
// appLocalization(context)
|
||||
// .notification_update_profile_success,
|
||||
// Colors.green,
|
||||
// Colors.white);
|
||||
// } else {
|
||||
// showNoIconTopSnackBar(
|
||||
// modalBottomSheetContext,
|
||||
// appLocalization(context)
|
||||
// .notification_update_profile_failed,
|
||||
// Colors.redAccent,
|
||||
// Colors.white);
|
||||
// }
|
||||
// settingsBloc.getUserProfile(context);
|
||||
// Navigator.pop(modalBottomSheetContext);
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(context, e.toString());
|
||||
// }
|
||||
}
|
||||
},
|
||||
icon:
|
||||
@@ -212,7 +243,7 @@ changeUserInfomation(
|
||||
child: TextButton(
|
||||
onPressed: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
try {
|
||||
await apiServices.execute(context,() async {
|
||||
formKey.currentState!.save();
|
||||
String latitude = user.latitude ?? "";
|
||||
String longitude = user.longitude ?? "";
|
||||
@@ -224,8 +255,8 @@ changeUserInfomation(
|
||||
"latitude": latitude,
|
||||
"longitude": longitude
|
||||
};
|
||||
int statusCode =
|
||||
await apiServices.updateUserProfile(body);
|
||||
int statusCode = await apiServices
|
||||
.updateUserProfile(body);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
modalBottomSheetContext,
|
||||
@@ -243,11 +274,7 @@ changeUserInfomation(
|
||||
}
|
||||
settingsBloc.getUserProfile(context);
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
style: const ButtonStyle(
|
||||
@@ -296,15 +323,15 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
isChangeSnapshot.data ?? isChange
|
||||
? IconButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
if (formKey.currentState!.validate()) {
|
||||
if (formKey.currentState!.validate()) {
|
||||
await apiServices.execute(context,() async {
|
||||
formKey.currentState!.save();
|
||||
Map<String, dynamic> body = {
|
||||
"password_old": oldPass,
|
||||
"password_new": newPass,
|
||||
};
|
||||
int statusCode =
|
||||
await apiServices.updateUserPassword(body);
|
||||
await apiServices.updateUserPassword(body);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
modalBottomSheetContext,
|
||||
@@ -321,11 +348,7 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
Colors.white);
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
});
|
||||
}
|
||||
},
|
||||
icon:
|
||||
@@ -410,15 +433,15 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
? Center(
|
||||
child: TextButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await apiServices.execute(context,() async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
formKey.currentState!.save();
|
||||
Map<String, dynamic> body = {
|
||||
"password_old": oldPass,
|
||||
"password_new": newPass,
|
||||
};
|
||||
int statusCode =
|
||||
await apiServices.updateUserPassword(body);
|
||||
int statusCode = await apiServices
|
||||
.updateUserPassword(body);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
modalBottomSheetContext,
|
||||
@@ -436,11 +459,38 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
});
|
||||
// try {
|
||||
// if (formKey.currentState!.validate()) {
|
||||
// formKey.currentState!.save();
|
||||
// Map<String, dynamic> body = {
|
||||
// "password_old": oldPass,
|
||||
// "password_new": newPass,
|
||||
// };
|
||||
// int statusCode = await apiServices
|
||||
// .updateUserPassword(body);
|
||||
// if (statusCode == 200) {
|
||||
// showNoIconTopSnackBar(
|
||||
// modalBottomSheetContext,
|
||||
// appLocalization(context)
|
||||
// .notification_update_password_success,
|
||||
// Colors.green,
|
||||
// Colors.white);
|
||||
// } else {
|
||||
// showNoIconTopSnackBar(
|
||||
// modalBottomSheetContext,
|
||||
// appLocalization(context)
|
||||
// .notification_update_password_failed,
|
||||
// Colors.redAccent,
|
||||
// Colors.white);
|
||||
// }
|
||||
// Navigator.pop(modalBottomSheetContext);
|
||||
// }
|
||||
// } catch (e) {
|
||||
// if (!context.mounted) return;
|
||||
// showErrorTopSnackBarCustom(
|
||||
// context, e.toString());
|
||||
// }
|
||||
},
|
||||
style: const ButtonStyle(
|
||||
backgroundColor:
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../product/constant/app/app_constants.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import 'profile/profile_screen.dart';
|
||||
import '../../product/constant/icon/icon_constants.dart';
|
||||
import '../../product/extension/context_extension.dart';
|
||||
@@ -29,7 +27,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
settingsBloc = BlocProvider.of(context);
|
||||
// getUserProfile();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -41,7 +38,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
),
|
||||
body: StreamBuilder<User>(
|
||||
stream: settingsBloc.streamUserProfile,
|
||||
// initialData: user,
|
||||
builder: (context, userSnapshot) {
|
||||
if (userSnapshot.data == null) {
|
||||
settingsBloc.getUserProfile(context);
|
||||
@@ -139,17 +135,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
// void getUserProfile() async {
|
||||
// try {
|
||||
// user = await apiServices.getUserDetail();
|
||||
// settingsBloc.sinkUserProfile.add(user);
|
||||
// } catch (e) {
|
||||
// if (!mounted) return;
|
||||
// showErrorTopSnackBarCustom(
|
||||
// context, e.toString());
|
||||
// }
|
||||
// }
|
||||
|
||||
String getAvatarContent(String username) {
|
||||
String name = "";
|
||||
if (username.isNotEmpty) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sfm_app/product/utils/app_logger_utils.dart';
|
||||
import 'package:sfm_app/product/utils/responsive_text_utils.dart';
|
||||
|
||||
import '../theme/app_theme_light.dart';
|
||||
@@ -169,3 +170,15 @@ extension TextStyleExtention on BuildContext {
|
||||
TextStyle get headlineLargeTextStyle =>
|
||||
Theme.of(this).textTheme.headlineLarge!;
|
||||
}
|
||||
|
||||
|
||||
extension FutureExtension<T> on Future<T> {
|
||||
Future<T> handleApiError() async {
|
||||
try {
|
||||
return await this;
|
||||
} catch (e) {
|
||||
AppLoggerUtils.error(e.toString());
|
||||
return Future.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import '../utils/app_logger_utils.dart';
|
||||
|
||||
import '../constant/status_code/status_code_constants.dart';
|
||||
|
||||
import '../cache/local_manager.dart';
|
||||
@@ -39,7 +41,8 @@ class NetworkManager {
|
||||
Future<String> getDataFromServer(String path) async {
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET url: $url");
|
||||
AppLoggerUtils.info("GET url: $url");
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.get(url, headers: headers).timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
@@ -53,7 +56,8 @@ class NetworkManager {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
// AppLoggerUtils.error(message)
|
||||
// log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
@@ -73,7 +77,8 @@ class NetworkManager {
|
||||
String path, Map<String, dynamic> params) async {
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
||||
AppLoggerUtils.info("GET Params url: $url");
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.get(url, headers: headers).timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
@@ -90,16 +95,16 @@ class NetworkManager {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.get(url, headers: headers);
|
||||
if (response.statusCode == StatusCodeConstants.CREATED ||
|
||||
response.statusCode == StatusCodeConstants.OK) {
|
||||
return response.body;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
// final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
||||
// final headers = await getHeaders();
|
||||
// final response = await http.get(url, headers: headers);
|
||||
// if (response.statusCode == StatusCodeConstants.CREATED ||
|
||||
// response.statusCode == StatusCodeConstants.OK) {
|
||||
// return response.body;
|
||||
// } else {
|
||||
// return "";
|
||||
// }
|
||||
}
|
||||
|
||||
/// Creates new data on the server using a POST request.
|
||||
@@ -109,7 +114,8 @@ class NetworkManager {
|
||||
Future<int> createDataInServer(String path, Map<String, dynamic> body) async {
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] POST url: $url");
|
||||
AppLoggerUtils.info("POST url: $url");
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] POST url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http
|
||||
.post(url, headers: headers, body: jsonEncode(body))
|
||||
@@ -137,7 +143,8 @@ class NetworkManager {
|
||||
Future<int> updateDataInServer(String path, Map<String, dynamic> body) async {
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] PUT url: $url");
|
||||
AppLoggerUtils.info("PUT url: $url");
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] PUT url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response =
|
||||
await http.put(url, headers: headers, body: jsonEncode(body)).timeout(
|
||||
@@ -166,7 +173,8 @@ class NetworkManager {
|
||||
Future<int> deleteDataInServer(String path) async {
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
||||
AppLoggerUtils.info("DELETE url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.delete(url, headers: headers).timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
|
||||
@@ -5,7 +5,8 @@ import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:sfm_app/product/shared/model/province_model.dart';
|
||||
import '../shared/model/province_model.dart';
|
||||
import '../utils/app_logger_utils.dart';
|
||||
import '../../feature/device_log/device_logs_model.dart';
|
||||
import '../../feature/devices/device_model.dart';
|
||||
import '../../feature/home/device_alias_model.dart';
|
||||
@@ -26,6 +27,8 @@ import '../constant/enums/local_keys_enums.dart';
|
||||
import '../network/network_manager.dart';
|
||||
|
||||
class APIServices {
|
||||
|
||||
|
||||
Map<String, String> headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
@@ -52,12 +55,10 @@ class APIServices {
|
||||
return headers;
|
||||
}
|
||||
|
||||
Future<T> executeApiCall<T>(
|
||||
Future<dynamic> Function() apiCall, {
|
||||
T Function(dynamic)? parser,
|
||||
String errorMessage = 'Lỗi khi gọi API',
|
||||
T Function(int)? statusCodeHandler, // Thêm handler cho statusCode
|
||||
}) async {
|
||||
Future<T> executeApiCall<T>(Future<dynamic> Function() apiCall,
|
||||
{T Function(dynamic)? parser,
|
||||
String errorMessage = 'Lỗi khi gọi API',
|
||||
T Function(int)? statusCodeHandler}) async {
|
||||
try {
|
||||
final response = await apiCall().timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
@@ -81,11 +82,38 @@ class APIServices {
|
||||
throw Exception('Dữ liệu trả về rỗng');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
// log('Lỗi API: $e, StackTrace: $stackTrace');
|
||||
AppLoggerUtils.error("Lỗi gọi API", e, stackTrace);
|
||||
throw Exception('$errorMessage: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Most Used Function
|
||||
// Future<T> execute<T>(Future<T> Function() apiCall) async {
|
||||
// try {
|
||||
// return await apiCall();
|
||||
// } catch (e) {
|
||||
|
||||
// AppLoggerUtils.error(e.toString());
|
||||
// return Future.error(e);
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<T> execute<T>(
|
||||
BuildContext context,
|
||||
Future<T> Function() apiCall, {
|
||||
bool checkMounted = true,
|
||||
}) async {
|
||||
try {
|
||||
return await apiCall();
|
||||
} catch (e) {
|
||||
if (checkMounted && !context.mounted) {
|
||||
return Future.error('Widget not mounted');
|
||||
}
|
||||
showErrorTopSnackBarCustom(context, "Lỗi hệ thống");
|
||||
return Future.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> login(String path, Map<String, dynamic> loginRequest) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
final headers = await getHeaders();
|
||||
@@ -229,7 +257,8 @@ class APIServices {
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> updateDeviceNotificationSettings(String thingID, Map<String, int> data) async {
|
||||
Future<int> updateDeviceNotificationSettings(
|
||||
String thingID, Map<String, int> data) async {
|
||||
Map<String, dynamic> body = {"thing_id": thingID, "notifi_settings": data};
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
@@ -279,7 +308,7 @@ class APIServices {
|
||||
.getDataFromServer(APIPathConstants.PROVINCES_PATH),
|
||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}');
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
Future<List<Province>> getProvincesByName(String name) async {
|
||||
@@ -290,7 +319,7 @@ class APIServices {
|
||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}/$name',
|
||||
);
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
Future<Province> getProvinceByID(String provinceID) async {
|
||||
|
||||
26
lib/product/shared/shared_rocket_container.dart
Normal file
26
lib/product/shared/shared_rocket_container.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SharedRocketContainer extends CustomClipper<Path> {
|
||||
@override
|
||||
Path getClip(Size size) {
|
||||
final double width = size.width;
|
||||
final double height = size.height;
|
||||
|
||||
const double pointyWidth = 20.0;
|
||||
|
||||
Path path = Path();
|
||||
path.moveTo(0, 0);
|
||||
path.lineTo(width - pointyWidth, 0);
|
||||
path.lineTo(width, height / 2);
|
||||
path.lineTo(width - pointyWidth, height);
|
||||
path.lineTo(0, height);
|
||||
path.close();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Path> oldClipper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ class AppThemeDark extends AppTheme {
|
||||
|
||||
@override
|
||||
ThemeData get theme => FlexThemeData.dark(
|
||||
scaffoldBackground: Colors.black,
|
||||
useMaterial3: true,
|
||||
scheme: FlexScheme.flutterDash,
|
||||
subThemesData: const FlexSubThemesData(
|
||||
|
||||
@@ -13,6 +13,7 @@ class AppThemeLight extends AppTheme {
|
||||
|
||||
@override
|
||||
ThemeData get theme => FlexThemeData.light(
|
||||
scaffoldBackground: Colors.white,
|
||||
useMaterial3: true,
|
||||
scheme: FlexScheme.flutterDash,
|
||||
bottomAppBarElevation: 20.0,
|
||||
|
||||
39
lib/product/utils/app_logger_utils.dart
Normal file
39
lib/product/utils/app_logger_utils.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
class AppLoggerUtils{
|
||||
static final Logger _logger = Logger(
|
||||
printer: PrettyPrinter(
|
||||
methodCount: 2,
|
||||
errorMethodCount: 8,
|
||||
lineLength: 120,
|
||||
colors: true,
|
||||
printEmojis: true,
|
||||
dateTimeFormat: (DateTime dateTime) {
|
||||
// Tùy chỉnh định dạng thời gian
|
||||
return '[${DateTime.now().toLocal().toString().split(' ')[1]}]';
|
||||
},
|
||||
// dateTimeFormat: DateTimeFormat.dateAndTime
|
||||
),
|
||||
level: Level.debug, // Cấp độ log tối thiểu (có thể thay đổi trong môi trường production)
|
||||
);
|
||||
|
||||
static void debug(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||
_logger.d(message);
|
||||
}
|
||||
|
||||
static void info(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||
_logger.i(message);
|
||||
}
|
||||
|
||||
static void warning(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||
_logger.w(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
static void error(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||
_logger.e(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
static void trace(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||
_logger.t(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class DeviceUtils {
|
||||
String provinceID = parts[0];
|
||||
String districtID = parts[1];
|
||||
String wardID = parts[2];
|
||||
|
||||
|
||||
Province province = await apiServices.getProvinceByID(provinceID);
|
||||
District district = await apiServices.getDistrictByID(districtID);
|
||||
Ward ward = await apiServices.getWardByID(wardID);
|
||||
|
||||
Reference in New Issue
Block a user