feat(api_service): Update try-catch funtion and handle exception
update(loading_animation): Update loading animation using Lottie
This commit is contained in:
anhtunz
2025-06-09 14:29:43 +07:00
parent 477646ab9d
commit 3a8fa3633c
44 changed files with 1659 additions and 1065 deletions

View File

@@ -9,6 +9,7 @@ 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/utils/date_time_utils.dart';
import '../feature/device_log/device_logs_model.dart';
import '../feature/devices/device_model.dart';
@@ -42,14 +43,12 @@ class DetailDeviceBloc extends BlocBase {
String thingID,
Completer<GoogleMapController> controller,
) async {
String body = await apiServices.getDeviceInfomation(thingID);
if (body != "") {
final data = jsonDecode(body);
Device device = Device.fromJson(data);
try {
Device device = await apiServices.getDeviceInformation(thingID);
sinkDeviceInfo.add(device);
if (device.areaPath != null) {
String fullLocation = await DeviceUtils.instance
.getFullDeviceLocation(context, device.areaPath!);
.getFullDeviceLocation(context, device.areaPath!, "");
log("Location: $fullLocation");
sinkDeviceLocation.add(fullLocation);
}
@@ -74,40 +73,46 @@ class DetailDeviceBloc extends BlocBase {
mapController
.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
}
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(context, e.toString());
}
}
void findLocation(BuildContext context, String areaPath) async {
String fullLocation =
await DeviceUtils.instance.getFullDeviceLocation(context, areaPath);
await DeviceUtils.instance.getFullDeviceLocation(context, areaPath, "");
sinkDeviceLocation.add(fullLocation);
}
void getNearerSensorValue(String thingID) 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());
Map<String, dynamic> params = {
'thing_id': thingID,
'from': from,
'to': now,
'limit': '100',
'n': '7',
};
final body = await apiServices.getLogsOfDevice(thingID, params);
if (body != "") {
final data = jsonDecode(body);
DeviceLog devicesListLog = DeviceLog.fromJson(data);
void getNearerSensorValue(BuildContext context,String thingID) async {
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{
} else {
sinkSensorTemps.add([]);
}
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
sinkSensorTemps.add([]);
}
}
}

View File

@@ -1,10 +1,13 @@
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';
@@ -35,40 +38,41 @@ class DeviceLogsBloc extends BlocBase {
@override
void dispose() {}
void getAllDevices() async {
String body = await apiServices.getOwnerDevices();
if (body != "") {
final data = jsonDecode(body);
List<dynamic> items = data['items'];
List<Device> originalDevices = Device.fromJsonDynamicList(items);
void getAllDevices(BuildContext context) async {
try {
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(
BuildContext context,
int offset,
String thingID,
DateTime fromDate,
List<SensorLogs> sensors,
) async {
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"
};
final body = await apiServices.getLogsOfDevice(thingID, params);
if (body != "") {
final data = jsonDecode(body);
DeviceLog devicesListLog = DeviceLog.fromJson(data);
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);
@@ -81,6 +85,9 @@ class DeviceLogsBloc extends BlocBase {
sinkmessage.add(ApplicationConstants.NO_DATA);
}
sinkSensors.add(sensors);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(context, e.toString());
}
}
}

View File

@@ -9,6 +9,7 @@ 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';
@@ -75,151 +76,210 @@ class DeviceUpdateBloc extends BlocBase {
// deviceInfo.done;
}
Future<void> getAllProvinces() async {
Future<void> getAllProvinces(BuildContext context) async {
List<DropdownMenuItem<Province>> provincesData = [];
provincesData.clear();
sinkListProvinces.add(provincesData);
final body = await apiServices.getAllProvinces();
final data = jsonDecode(body);
List<dynamic> items = data["items"];
final provinces = Province.fromJsonDynamicList(items);
for (var province in provinces) {
provincesData.add(
DropdownMenuItem(value: province, child: Text(province.fullName!)));
try {
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());
}
sinkListProvinces.add(provincesData);
}
Future<void> getAllDistricts(String provinceID) async {
Future<void> getAllDistricts(BuildContext context, String provinceID) async {
List<DropdownMenuItem<District>> districtsData = [];
districtsData.clear();
sinkListDistricts.add(districtsData);
final body = await apiServices.getAllDistricts(provinceID);
final data = jsonDecode(body);
List<dynamic> items = data["items"];
final districts = District.fromJsonDynamicList(items);
for (var district in districts) {
districtsData.add(
DropdownMenuItem(value: district, child: Text(district.fullName!)));
try {
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());
}
sinkListDistricts.add(districtsData);
}
Future<void> getAllWards(String districtID) async {
Future<void> getAllWards(BuildContext context, String districtID) async {
List<DropdownMenuItem<Ward>> wardsData = [];
wardsData.clear();
sinkListWards.add(wardsData);
final body = await apiServices.getAllWards(districtID);
final data = jsonDecode(body);
List<dynamic> items = data["items"];
final wards = Ward.fromJsonDynamicList(items);
for (var ward in wards) {
wardsData.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
try {
final wards = await apiServices.getAllWards(districtID);
for (var ward in wards) {
wardsData.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
}
sinkListWards.add(wardsData);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
}
sinkListWards.add(wardsData);
}
Future<void> getDeviceInfomation(
Future<void> getDeviceInformation(
BuildContext context,
String thingID,
List<DropdownMenuItem<District>> districtsData,
List<DropdownMenuItem<Ward>> wardsData,
TextEditingController deviceNameController,
TextEditingController latitudeController,
TextEditingController longitudeController) async {
String body = await apiServices.getDeviceInfomation(thingID);
final data = jsonDecode(body);
Device device = Device.fromJson(data);
sinkDeviceInfo.add(device);
deviceNameController.text = device.name ?? "";
latitudeController.text = device.settings!.latitude ?? "";
longitudeController.text = device.settings!.longitude ?? "";
if (device.areaPath != "") {
List<String> areaPath = device.areaPath!.split('_');
String provinceCode = areaPath[0];
String districtCode = areaPath[1];
String wardCode = areaPath[2];
getAllDistricts(provinceCode);
getAllWards(districtCode);
final provinceResponse = await apiServices.getProvinceByID(provinceCode);
final provincesData = jsonDecode(provinceResponse);
Province province = Province.fromJson(provincesData['data']);
final districtResponse = await apiServices.getDistrictByID(districtCode);
final districtData = jsonDecode(districtResponse);
District district = District.fromJson(districtData['data']);
final wardResponse = await apiServices.getWardByID(wardCode);
final wardData = jsonDecode(wardResponse);
Ward ward = Ward.fromJson(wardData['data']);
Map<String, String> provinceData = {
"name": province.fullName!,
"code": province.code!
};
sinkProvinceData.add(provinceData);
Map<String, String> districData = {
"name": district.fullName!,
"code": district.code!,
};
sinkDistrictData.add(districData);
Map<String, String> wardMap = {
"name": ward.fullName!,
"code": ward.code!,
};
sinkWardData.add(wardMap);
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) {
print("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(String name) async {
final response = await apiServices.getProvincesByName(name);
final data = jsonDecode(response);
if (data != null &&
data.containsKey('items') &&
data['items'] != null &&
data['items'].isNotEmpty) {
List<dynamic> items = data['items'];
List<Province> provinces = Province.fromJsonDynamicList(items);
Future<Province> getProvinceByName(BuildContext context, String name) async {
try {
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");
}
return Province(name: "null");
}
Future<District> getDistrictByName(String name, String provinceCode) async {
final response = await apiServices.getDistrictsByName(name);
if (response != "") {
final data = jsonDecode(response);
List<dynamic> items = data['items'];
if (items.isNotEmpty) {
List<District> districts = District.fromJsonDynamicList(items);
if (districts.isNotEmpty) {
for (var district in districts) {
if (district.provinceCode == provinceCode) {
return district;
}
}
}
Future<District> getDistrictByName(
BuildContext context, String name, String provinceCode) async {
try {
final districts = await apiServices.getDistrictsByName(name);
return districts.firstWhere(
(district) => district.provinceCode == provinceCode,
orElse: () => District(name: "null"),
);
} catch (e) {
if (context.mounted) {
showErrorTopSnackBarCustom(context, e.toString());
}
return District(name: "null");
}
return District(name: "null");
}
Future<Ward> getWardByName(String name, String districtCode) async {
final response = await apiServices.getWarsdByName(name);
final data = jsonDecode(response);
if (data != null && data['items'] != null) {
List<dynamic> items = data['items'];
if (items.isNotEmpty) {
List<Ward> wards = Ward.fromJsonDynamicList(items);
if (wards.isNotEmpty) {
for (var ward in wards) {
if (ward.districtCode == districtCode) {
return ward;
}
}
}
Future<Ward> getWardByName(
BuildContext context, String name, String districtCode) async {
try {
final wards = await apiServices.getWardsByName(name);
return wards.firstWhere(
(ward) => ward.districtCode == districtCode,
orElse: () => Ward(name: "null"),
);
} catch (e) {
if (context.mounted) {
showErrorTopSnackBarCustom(context, e.toString());
}
return Ward(name: "null");
}
return Ward(name: "null");
}
Future<void> updateDevice(
@@ -232,24 +292,31 @@ class DeviceUpdateBloc extends BlocBase {
String districtCode,
String wardCode,
) async {
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,
);
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());
}
}
}

View File

@@ -1,11 +1,14 @@
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';
class DevicesManagerBloc extends BlocBase {
@@ -73,31 +76,27 @@ class DevicesManagerBloc extends BlocBase {
// }
// }
void getDeviceByState(int state) async {
sinkTagStates.add([state]);
void getDeviceByState(BuildContext context,int state) async {
try {
sinkTagStates.add([state]);
Map<String, List<Device>> deviceByState = {
ApplicationConstants.OFFLINE_STATE: [],
ApplicationConstants.NORMAL_STATE: [],
ApplicationConstants.WARNING_STATE: [],
ApplicationConstants.INPROGRESS_STATE: [],
ApplicationConstants.ERROR_STATE: [],
};
Map<String, List<Device>> deviceByState = {
ApplicationConstants.OFFLINE_STATE: [],
ApplicationConstants.NORMAL_STATE: [],
ApplicationConstants.WARNING_STATE: [],
ApplicationConstants.INPROGRESS_STATE: [],
ApplicationConstants.ERROR_STATE: [],
};
List<Device> devices = [];
String body;
List<Device> devices = [];
List<Device> originalDevices = [];
if (state != -2) {
originalDevices =
await apiServices.getOwnerDeviceByState({"state": state.toString()});
} else {
originalDevices = await apiServices.getOwnerDevices();
}
if (state != -2) {
body =
await apiServices.getOwnerDeviceByState({"state": state.toString()});
} else {
body = await apiServices.getOwnerDevices();
}
if (body.isNotEmpty) {
final data = jsonDecode(body);
List<dynamic> items = data['items'];
List<Device> originalDevices = Device.fromJsonDynamicList(items);
List<Device> publicDevices = [];
for(var device in originalDevices){
@@ -116,9 +115,14 @@ class DevicesManagerBloc extends BlocBase {
}
sinkDeviceByState.add(deviceByState);
}
sinkAllDevices.add(devices);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
}
sinkAllDevices.add(devices);
}
String _getStateKey(int state) {

View File

@@ -8,6 +8,7 @@ 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';
@@ -29,77 +30,114 @@ class DetailGroupBloc extends BlocBase {
@override
void dispose() {}
Future<void> getGroupDetail(String groupID) async {
final body = await apiServices.getGroupDetail(groupID);
final data = jsonDecode(body);
List<DeviceOfGroup> warningDevices = [];
if (data != null) {
GroupDetail group = GroupDetail.fromJson(data);
sinkDetailGroup.add(group);
if (group.devices != null) {
for (var device in group.devices!) {
if (device.state == 1) {
warningDevices.add(device);
Future<void> getGroupDetail(BuildContext context,String groupID) async {
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);
}
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 {
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!");
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 {
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");
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 {
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");
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 {
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_leave_group_success,
appLocalization(context).notification_leave_group_failed);
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 {
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,
);
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() async {
Future<List<Device>> getOwnerDevices(BuildContext context) async {
List<Device> allDevices = [];
String body = await apiServices.getOwnerDevices();
if (body != "") {
final data = jsonDecode(body);
List<dynamic> items = data['items'];
allDevices = Device.fromJsonDynamicList(items);
try {
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 allDevices;
}
Future<void> addDeviceToGroup(
@@ -107,12 +145,18 @@ class DetailGroupBloc extends BlocBase {
Map<String, dynamic> body = {
"thing_id": thingID,
};
int statusCode = await apiServices.addDeviceToGroup(groupID, body);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_add_device_success,
appLocalization(context).notification_add_device_failed,
);
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());
}
}
}

View File

@@ -10,6 +10,7 @@ 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';
@@ -38,46 +39,27 @@ class InterFamilyBloc extends BlocBase {
void getAllGroup(String role) async {
List<Group> groups = [];
sinkCurrentGroups.add(groups);
try {
groups = await apiServices.getAllGroups();
groups = sortGroupByName(groups);
final body = await apiServices.getAllGroups();
List<Group> currentGroups = groups.where(
(group) {
bool isPublic = group.visibility == "PUBLIC";
if (role == ApplicationConstants.OWNER_GROUP) {
return group.isOwner == true && isPublic;
}
if (role == ApplicationConstants.PARTICIPANT_GROUP) {
return group.isOwner == null && isPublic;
}
return false;
},
).toList();
if (body.isNotEmpty) {
try {
final data = jsonDecode(body);
if (data is Map && data.containsKey("items") && data["items"] is List) {
List<dynamic> items = data["items"];
groups = Group.fromJsonDynamicList(items);
groups = sortGroupByName(groups);
List<Group> currentGroups = groups.where(
(group) {
bool isPublic = group.visibility == "PUBLIC";
if (role == ApplicationConstants.OWNER_GROUP) {
return group.isOwner == true && isPublic;
}
if (role == ApplicationConstants.PARTICIPANT_GROUP) {
return group.isOwner == null && isPublic;
}
return false;
},
).toList();
sinkCurrentGroups.add(currentGroups);
} else {
log("No items found in API response or empty JSON object");
sinkCurrentGroups.add([]);
}
} catch (e) {
// Xử lý lỗi khi jsonDecode thất bại
log("Error decoding JSON: $e");
sinkCurrentGroups.add([]);
}
} else {
log("Get groups from API failed: Empty response");
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");
@@ -85,46 +67,70 @@ class InterFamilyBloc extends BlocBase {
Future<void> createGroup(
BuildContext context, String name, String description) async {
APIServices apiServices = APIServices();
Map<String, dynamic> body = {"name": name, "description": description};
int? statusCode = await apiServices.createGroup(body);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_add_group_success,
appLocalization(context).notification_add_group_failed);
try {
Map<String, dynamic> body = {"name": name, "description": description};
int? statusCode = await apiServices.createGroup(body);
showSnackBarResponseByStatusCode(
context,
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> changeGroupInfomation(BuildContext context, String groupID,
Future<void> changeGroupInformation(BuildContext context, String groupID,
String name, String description) async {
Map<String, dynamic> body = {"name": name, "description": description};
int statusCode = await apiServices.updateGroup(body, groupID);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_update_group_success,
appLocalization(context).notification_update_group_failed);
try {
Map<String, dynamic> body = {"name": name, "description": description};
int statusCode = await apiServices.updateGroup(body, groupID);
showSnackBarResponseByStatusCode(
context,
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 {
Map<String, dynamic> body = {
"group_id": groupID,
};
int statusCode = await apiServices.joinGroup(groupID, body);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_join_request_group_success,
appLocalization(context).notification_join_request_group_failed);
try {
Map<String, dynamic> body = {
"group_id": groupID,
};
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 {
int statusCode = await apiServices.deleteGroup(groupID);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context).notification_delete_group_success,
appLocalization(context).notification_delete_group_failed);
try {
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) {

View File

@@ -12,6 +12,7 @@ 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();
@@ -42,10 +43,16 @@ class MainBloc extends BlocBase {
@override
void dispose() {}
void getUserProfile() async {
String data = await apiServices.getUserDetail();
User user = User.fromJson(jsonDecode(data));
sinkUserProfile.add(user);
void getUserProfile(BuildContext context) async {
try {
User user = await apiServices.getUserDetail();
sinkUserProfile.add(user);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
}
}
getFCMTokenAndPresentations() async {

View File

@@ -1,10 +1,15 @@
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:sfm_app/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 {
// Settings Screen
APIServices apiServices = APIServices();
final userProfile = StreamController<User>.broadcast();
StreamSink<User> get sinkUserProfile => userProfile.sink;
Stream<User> get streamUserProfile => userProfile.stream;
@@ -18,6 +23,17 @@ class SettingsBloc extends BlocBase {
isChangeProfileInfomation.stream;
void getUserProfile(BuildContext context) async {
try {
User user = await apiServices.getUserDetail();
sinkUserProfile.add(user);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
}
}
@override
void dispose() {