update
feat(api_service): Update try-catch funtion and handle exception update(loading_animation): Update loading animation using Lottie
This commit is contained in:
@@ -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([]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
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';
|
||||
import '../../product/services/api_services.dart';
|
||||
import '../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import 'bell_model.dart';
|
||||
|
||||
class BellScreen extends StatefulWidget {
|
||||
@@ -56,11 +59,7 @@ class _BellScreenState extends State<BellScreen> {
|
||||
initialData: items,
|
||||
builder: (context, bellSnapshot) {
|
||||
return check
|
||||
? Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: context.highValue,
|
||||
),
|
||||
)
|
||||
? const SharedLoadingAnimation()
|
||||
: bellSnapshot.data?.isEmpty ?? true
|
||||
? Center(
|
||||
child: Text(
|
||||
@@ -78,16 +77,7 @@ class _BellScreenState extends State<BellScreen> {
|
||||
if (index < bellSnapshot.data!.length) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
List<String> read = [];
|
||||
read.add(bellSnapshot.data![index].id!);
|
||||
int code = await apiServices
|
||||
.updateStatusOfNotification(read);
|
||||
if (code == 200) {
|
||||
read.clear();
|
||||
} else {
|
||||
read.clear();
|
||||
}
|
||||
refresh();
|
||||
readNotification(bellSnapshot.data![index].id!);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -143,7 +133,7 @@ class _BellScreenState extends State<BellScreen> {
|
||||
builder: (context, hasMoreSnapshot) {
|
||||
return Center(
|
||||
child: hasMoreSnapshot.data ?? hasMore
|
||||
? const CircularProgressIndicator()
|
||||
? const SharedComponentLoadingAnimation()
|
||||
: Text(
|
||||
appLocalization(context)
|
||||
.bell_read_all,
|
||||
@@ -173,20 +163,40 @@ class _BellScreenState extends State<BellScreen> {
|
||||
getBellNotification(offset);
|
||||
}
|
||||
|
||||
Future<void> getBellNotification(int offset) async {
|
||||
bell = await apiServices.getBellNotifications(
|
||||
offset.toString(), (offset + 20).toString());
|
||||
|
||||
if (bell.items!.isEmpty) {
|
||||
hasMore = false;
|
||||
bellBloc.sinkHasMore.add(hasMore);
|
||||
} else {
|
||||
for (var item in bell.items!) {
|
||||
items.add(item);
|
||||
void readNotification(String id) async{
|
||||
try {
|
||||
List<String> read = [];
|
||||
read.add(id);
|
||||
await apiServices
|
||||
.updateStatusOfNotification(read);
|
||||
read.clear();
|
||||
} catch (e) {
|
||||
if (mounted){
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
}
|
||||
bellBloc.bellItems.add(items);
|
||||
check = false;
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> getBellNotification(int offset) async {
|
||||
try {
|
||||
bell = await apiServices.getBellNotifications(
|
||||
offset.toString(), (offset + 20).toString());
|
||||
if (bell.items!.isEmpty) {
|
||||
hasMore = false;
|
||||
bellBloc.sinkHasMore.add(hasMore);
|
||||
} else {
|
||||
for (var item in bell.items!) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
bellBloc.bellItems.add(items);
|
||||
check = false;
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
String timeAgo(BuildContext context, DateTime dateTime) {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import 'widgets/tag_widget.dart';
|
||||
import '../devices/device_model.dart';
|
||||
import '../../bloc/device_logs_bloc.dart';
|
||||
@@ -42,7 +44,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
||||
() {
|
||||
if (controller.position.maxScrollExtent == controller.offset) {
|
||||
offset += 30;
|
||||
deviceLogsBloc.getDeviceLogByThingID(
|
||||
deviceLogsBloc.getDeviceLogByThingID(context,
|
||||
offset, thingID, dateTime!, sensors);
|
||||
}
|
||||
},
|
||||
@@ -64,10 +66,8 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
||||
stream: deviceLogsBloc.streamAllDevices,
|
||||
builder: (context, allDevicesSnapshot) {
|
||||
if (allDevicesSnapshot.data == null) {
|
||||
deviceLogsBloc.getAllDevices();
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
deviceLogsBloc.getAllDevices(context);
|
||||
return const SharedLoadingAnimation();
|
||||
} else {
|
||||
return StreamBuilder<List<SensorLogs>>(
|
||||
stream: deviceLogsBloc.streamSensors,
|
||||
@@ -188,6 +188,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
||||
);
|
||||
} else {
|
||||
deviceLogsBloc.getDeviceLogByThingID(
|
||||
context,
|
||||
offset,
|
||||
thingID,
|
||||
dateTime!,
|
||||
@@ -246,7 +247,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
||||
return Center(
|
||||
child: hasMoreSnapshot.data ??
|
||||
hasMore
|
||||
? const CircularProgressIndicator()
|
||||
? const SharedComponentLoadingAnimation()
|
||||
: Text(
|
||||
appLocalization(context)
|
||||
.main_no_data),
|
||||
@@ -310,7 +311,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
||||
deviceLogsBloc.sensors.add(sensors);
|
||||
hasMore = true;
|
||||
deviceLogsBloc.sinkHasMore.add(hasMore);
|
||||
deviceLogsBloc.getDeviceLogByThingID(offset, thingID, dateTime!, sensors);
|
||||
deviceLogsBloc.getDeviceLogByThingID(context,offset, thingID, dateTime!, sensors);
|
||||
}
|
||||
|
||||
Widget leadingList(SensorLogs sensor) {
|
||||
|
||||
@@ -95,23 +95,36 @@ void addDevices(
|
||||
APIServices apiServices = APIServices();
|
||||
Map<String, dynamic> body = {};
|
||||
if (role == RoleEnums.ADMIN.name) {
|
||||
body = {"ext_id": extID, "name": deviceName};
|
||||
int statusCode = await apiServices.createDeviceByAdmin(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_create_device_success,
|
||||
appLocalization(context).notification_create_device_failed);
|
||||
deviceManagerBloc.getDeviceByState(-2);
|
||||
try {
|
||||
body = {"ext_id": extID, "name": deviceName};
|
||||
int statusCode = await apiServices.createDeviceByAdmin(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
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());
|
||||
}
|
||||
|
||||
} else {
|
||||
body = {"ext_id": extID};
|
||||
int statusCode = await apiServices.registerDevice(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_add_device_success,
|
||||
appLocalization(context).notification_device_not_exist);
|
||||
deviceManagerBloc.getDeviceByState(-2);
|
||||
try {
|
||||
body = {"ext_id": extID};
|
||||
int statusCode = await apiServices.registerDevice(body);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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,
|
||||
@@ -53,14 +54,21 @@ deleteOrUnregisterDevice(BuildContext context, DevicesManagerBloc devicesBloc,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_device_success,
|
||||
appLocalization(context).notification_delete_device_failed);
|
||||
devicesBloc.getDeviceByState(-2);
|
||||
devicesBloc.getDeviceByState(context,-2);
|
||||
} else {
|
||||
int statusCode = await apiServices.deleteDeviceByAdmin(extID);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context).notification_delete_device_success,
|
||||
appLocalization(context).notification_delete_device_failed);
|
||||
devicesBloc.getDeviceByState(-2);
|
||||
try {
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:sfm_app/product/shared/shared_component_loading_animation.dart';
|
||||
import 'package:simple_ripple_animation/simple_ripple_animation.dart';
|
||||
|
||||
import '../../../product/constant/image/image_constants.dart';
|
||||
import '../../../product/shared/shared_line_chart.dart';
|
||||
import '../../../product/shared/shared_curve.dart';
|
||||
import '../../../product/shared/shared_loading_animation.dart';
|
||||
import '../../device_log/device_logs_model.dart';
|
||||
import '../device_model.dart';
|
||||
import '../../../product/base/bloc/base_bloc.dart';
|
||||
@@ -92,8 +94,11 @@ class _DetailDeviceScreenState extends State<DetailDeviceScreen> {
|
||||
widget.thingID,
|
||||
controller,
|
||||
);
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: Text(appLocalization(context).no_data_message),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return StreamBuilder<Map<String, dynamic>>(
|
||||
@@ -125,28 +130,6 @@ class _DetailDeviceScreenState extends State<DetailDeviceScreen> {
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
// Center(
|
||||
// child: Container(
|
||||
// height: 50,
|
||||
// width: 400,
|
||||
// // color: Colors.blueAccent,
|
||||
// alignment: Alignment.centerRight,
|
||||
// margin: const EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// const SizedBox(),
|
||||
// Text(
|
||||
// deviceSnapshot.data?.name ?? "",
|
||||
// style: const TextStyle(
|
||||
// fontSize: 25,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -541,12 +524,10 @@ class _DetailDeviceScreenState extends State<DetailDeviceScreen> {
|
||||
builder: (context, sensorTempsSnapshot) {
|
||||
if (sensorTempsSnapshot.data == null) {
|
||||
detailDeviceBloc
|
||||
.getNearerSensorValue(widget.thingID);
|
||||
.getNearerSensorValue(context,widget.thingID);
|
||||
return const AspectRatio(
|
||||
aspectRatio: 3,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
child: SharedComponentLoadingAnimation(),
|
||||
);
|
||||
} else if (sensorTempsSnapshot.data!.isEmpty) {
|
||||
return Center(
|
||||
@@ -657,12 +638,7 @@ class _DetailDeviceScreenState extends State<DetailDeviceScreen> {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
return const SharedLoadingAnimation();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:search_choices/search_choices.dart';
|
||||
|
||||
import '../../../product/shared/shared_loading_animation.dart';
|
||||
import '../device_model.dart';
|
||||
import '../../../bloc/device_update_bloc.dart';
|
||||
import 'map_dialog.dart';
|
||||
@@ -47,7 +48,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
deviceUpdateBloc = BlocProvider.of(context);
|
||||
deviceUpdateBloc.getAllProvinces();
|
||||
deviceUpdateBloc.getAllProvinces(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -72,16 +73,16 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
||||
initialData: device,
|
||||
builder: (context, deviceInfoSnapshot) {
|
||||
if (deviceInfoSnapshot.data!.thingId == null) {
|
||||
deviceUpdateBloc.getDeviceInfomation(
|
||||
deviceUpdateBloc.getDeviceInformation(
|
||||
context,
|
||||
widget.thingID,
|
||||
districtsData,
|
||||
wardsData,
|
||||
// provincesData,
|
||||
// districtsData,
|
||||
// wardsData,
|
||||
deviceNameController,
|
||||
deviceLatitudeController,
|
||||
deviceLongitudeController);
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return const SharedLoadingAnimation();
|
||||
} else {
|
||||
return StreamBuilder<bool>(
|
||||
stream: deviceUpdateBloc.streamIsChanged,
|
||||
@@ -245,7 +246,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
||||
.sinkProvinceData
|
||||
.add(provinceData);
|
||||
deviceUpdateBloc
|
||||
.getAllDistricts(
|
||||
.getAllDistricts(context,
|
||||
value.code);
|
||||
selectedDistrict = "";
|
||||
districtData['name'] =
|
||||
@@ -318,7 +319,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
||||
.sinkDistrictData
|
||||
.add(districtData);
|
||||
deviceUpdateBloc
|
||||
.getAllWards(value.code);
|
||||
.getAllWards(context,value.code);
|
||||
selectedWard = "";
|
||||
wardData['name'] =
|
||||
selectedWard!;
|
||||
|
||||
@@ -64,7 +64,7 @@ showMapDialog(
|
||||
String latitude = mapDialogLatitudeController.text;
|
||||
String longitude = mapDialogLongitudeController.text;
|
||||
log("Finish -- Latitude: $latitude, longitude: $longitude --");
|
||||
getDataFromApi(latitude, longitude, deviceUpdateBloc);
|
||||
getDataFromApi(context,latitude, longitude, deviceUpdateBloc);
|
||||
latitudeController.text =
|
||||
mapDialogLatitudeController.text;
|
||||
longitudeController.text =
|
||||
@@ -184,7 +184,7 @@ addMarker(
|
||||
updateCameraPosition(position, 14, mapController);
|
||||
}
|
||||
|
||||
void getDataFromApi(String latitude, String longitude,
|
||||
void getDataFromApi(BuildContext context,String latitude, String longitude,
|
||||
DeviceUpdateBloc deviceUpdateBloc) async {
|
||||
String path =
|
||||
"maps/api/geocode/json?latlng=$latitude,$longitude&language=vi&result_type=political&key=${ApplicationConstants.MAP_KEY}";
|
||||
@@ -215,7 +215,7 @@ void getDataFromApi(String latitude, String longitude,
|
||||
log("$key: $value");
|
||||
});
|
||||
|
||||
await _processLocations(locations, deviceUpdateBloc);
|
||||
await _processLocations(context,locations, deviceUpdateBloc);
|
||||
}
|
||||
|
||||
Map<String, String> _extractLocationComponents(
|
||||
@@ -241,31 +241,31 @@ Map<String, String> _extractLocationComponents(
|
||||
return locations;
|
||||
}
|
||||
|
||||
Future<void> _processLocations(
|
||||
Future<void> _processLocations(BuildContext context,
|
||||
Map<String, String> locations, DeviceUpdateBloc deviceUpdateBloc) async {
|
||||
String provinceNameFromAPI = locations['provincekey'] ?? "";
|
||||
String districtNameFromAPI = locations['districtkey'] ?? "";
|
||||
String wardNameFromAPI = locations['wardkey'] ?? "";
|
||||
|
||||
final province =
|
||||
await deviceUpdateBloc.getProvinceByName(provinceNameFromAPI);
|
||||
await deviceUpdateBloc.getProvinceByName(context,provinceNameFromAPI);
|
||||
if (province.name != "null") {
|
||||
log("Province: ${province.fullName}, ProvinceCode: ${province.code}");
|
||||
deviceUpdateBloc.sinkProvinceData
|
||||
.add({"code": province.code!, "name": province.fullName!});
|
||||
deviceUpdateBloc.getAllProvinces();
|
||||
deviceUpdateBloc.getAllProvinces(context);
|
||||
|
||||
final district = await deviceUpdateBloc.getDistrictByName(
|
||||
final district = await deviceUpdateBloc.getDistrictByName(context,
|
||||
districtNameFromAPI, province.code!);
|
||||
log("Districtname: ${district.fullName}, districtCode: ${district.code}");
|
||||
deviceUpdateBloc.getAllDistricts(province.code!);
|
||||
deviceUpdateBloc.getAllDistricts(context,province.code!);
|
||||
if (district.name != "null") {
|
||||
deviceUpdateBloc.sinkDistrictData
|
||||
.add({"code": district.code!, "name": district.fullName!});
|
||||
final ward =
|
||||
await deviceUpdateBloc.getWardByName(wardNameFromAPI, district.code!);
|
||||
await deviceUpdateBloc.getWardByName(context,wardNameFromAPI, district.code!);
|
||||
log("Wardname: ${ward.fullName}, WardCode: ${ward.code}");
|
||||
deviceUpdateBloc.getAllWards(district.code!);
|
||||
deviceUpdateBloc.getAllWards(context,district.code!);
|
||||
if (ward.name != "null") {
|
||||
log("Xac dinh duoc het thong tin tu toa do");
|
||||
deviceUpdateBloc.sinkWardData
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:data_table_2/data_table_2.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import 'add_new_device_widget.dart';
|
||||
import 'delete_device_widget.dart';
|
||||
import 'device_model.dart';
|
||||
@@ -41,7 +43,7 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
||||
const duration = Duration(seconds: 10);
|
||||
getAllDevicesTimer = Timer.periodic(
|
||||
duration,
|
||||
(Timer t) => devicesManagerBloc.getDeviceByState(tagIndex),
|
||||
(Timer t) => devicesManagerBloc.getDeviceByState(context,tagIndex),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,8 +70,8 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
||||
builder: (context, allDeviceSnapshot) {
|
||||
if(allDeviceSnapshot.data == null){
|
||||
devicesManagerBloc
|
||||
.getDeviceByState(tagSnapshot.data?[0] ?? -2);
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
.getDeviceByState(context,tagSnapshot.data?[0] ?? -2);
|
||||
return const SharedLoadingAnimation();
|
||||
}
|
||||
if (allDeviceSnapshot.data!.isEmpty) {
|
||||
return Center(
|
||||
@@ -219,10 +221,9 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
||||
stream: devicesManagerBloc.streamDeviceByState,
|
||||
builder: (context, devicesByStateSnapshot) {
|
||||
if (devicesByStateSnapshot.data == null) {
|
||||
devicesManagerBloc.getDeviceByState(
|
||||
devicesManagerBloc.getDeviceByState(context,
|
||||
tagSnapshot.data?[0] ?? -2);
|
||||
return const Center(
|
||||
child: CircularProgressIndicator());
|
||||
return const SharedComponentLoadingAnimation();
|
||||
} else {
|
||||
return SharedPieChart(
|
||||
deviceByState:
|
||||
@@ -392,7 +393,7 @@ class TagState extends StatelessWidget {
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
devicesManagerBloc.getDeviceByState(-2);
|
||||
devicesManagerBloc.getDeviceByState(context,-2);
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
|
||||
@@ -3,6 +3,9 @@ import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../product/shared/shared_loading_animation.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
import 'shared/alert_card.dart';
|
||||
import 'shared/warning_card.dart';
|
||||
import '../../product/utils/device_utils.dart';
|
||||
@@ -206,7 +209,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
stream: homeBloc.streamAllDevicesAliasJoinedMap,
|
||||
builder: (context, allDevicesAliasJoinedMapSnapshot) {
|
||||
if (hasJoinedDeviceSnapshot.data == null) {
|
||||
return const CircularProgressIndicator();
|
||||
return const SharedComponentLoadingAnimation();
|
||||
} else {
|
||||
final data = allDevicesAliasMapSnapshot.data!;
|
||||
final dataJoined =
|
||||
@@ -219,54 +222,71 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
}
|
||||
|
||||
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);
|
||||
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),
|
||||
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,
|
||||
),
|
||||
SizedBox(
|
||||
height: context.dynamicHeight(0.6),
|
||||
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),
|
||||
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,),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -289,19 +309,21 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
}
|
||||
|
||||
void getOwnerAndJoinedDevices() async {
|
||||
String response = await apiServices.getDashBoardDevices();
|
||||
final data = jsonDecode(response);
|
||||
List<dynamic> result = data["items"];
|
||||
devices = DeviceWithAlias.fromJsonDynamicList(result);
|
||||
List<DeviceWithAlias> publicDevices = [];
|
||||
for (var device in devices) {
|
||||
if (device.visibility == "PUBLIC") {
|
||||
publicDevices.add(device);
|
||||
try {
|
||||
devices = await apiServices.getDashBoardDevices();
|
||||
List<DeviceWithAlias> publicDevices = [];
|
||||
for (var device in devices) {
|
||||
if (device.visibility == "PUBLIC") {
|
||||
publicDevices.add(device);
|
||||
}
|
||||
}
|
||||
getOwnerDeviceState(publicDevices);
|
||||
checkSettingDevice(publicDevices);
|
||||
getDeviceStatusAliasMap(publicDevices);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
getOwnerDeviceState(publicDevices);
|
||||
checkSettingDevice(publicDevices);
|
||||
getDeviceStatusAliasMap(publicDevices);
|
||||
}
|
||||
|
||||
void getOwnerDeviceState(List<DeviceWithAlias> allDevices) async {
|
||||
@@ -391,33 +413,36 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
}
|
||||
|
||||
void checkSettingDevice(List<DeviceWithAlias> devices) async {
|
||||
if (isFunctionCall) {
|
||||
log("Ham check setting da duoc goi");
|
||||
} else {
|
||||
String? response =
|
||||
await apiServices.getAllSettingsNotificationOfDevices();
|
||||
if (response != "") {
|
||||
final data = jsonDecode(response);
|
||||
final result = data['data'];
|
||||
// log("Data ${DeviceNotificationSettings.mapFromJson(jsonDecode(data)).values.toList()}");
|
||||
try {
|
||||
if (isFunctionCall) {
|
||||
log("Ham check setting da duoc goi");
|
||||
} else {
|
||||
List<DeviceNotificationSettings> list =
|
||||
DeviceNotificationSettings.mapFromJson(result).values.toList();
|
||||
await apiServices.getAllSettingsNotificationOfDevices();
|
||||
// log("List: $list");
|
||||
Set<String> thingIdsInList =
|
||||
list.map((device) => device.thingId!).toSet();
|
||||
for (var device in devices) {
|
||||
if (!thingIdsInList.contains(device.thingId)) {
|
||||
log("Device with Thing ID ${device.thingId} is not in the notification settings list.");
|
||||
await apiServices.setupDeviceNotification(
|
||||
device.thingId!, device.name!);
|
||||
try {
|
||||
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.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("apiServices: getAllSettingsNotificationofDevices error!");
|
||||
}
|
||||
isFunctionCall = true;
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
isFunctionCall = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Future<Widget> notificationCard(BuildContext context, String notiticationType,
|
||||
String location = "";
|
||||
if (device.areaPath != "") {
|
||||
location = await DeviceUtils.instance
|
||||
.getFullDeviceLocation(context, device.areaPath!);
|
||||
.getFullDeviceLocation(context, device.areaPath!,"");
|
||||
}
|
||||
String path = "";
|
||||
// DateTime time = DateTime.now();
|
||||
|
||||
@@ -3,69 +3,97 @@ import 'status_card.dart';
|
||||
import '../../../product/extension/context_extension.dart';
|
||||
import '../../../product/services/language_services.dart';
|
||||
|
||||
class OverviewCard extends StatelessWidget {
|
||||
class OverviewCard extends StatefulWidget {
|
||||
final bool isOwner;
|
||||
final int total;
|
||||
final int active;
|
||||
final int inactive;
|
||||
final int warning;
|
||||
final int unused;
|
||||
final bool showTotal;
|
||||
final bool showActive;
|
||||
final bool showInactive;
|
||||
final bool showWarning;
|
||||
final bool showUnused;
|
||||
|
||||
const OverviewCard(
|
||||
{super.key,
|
||||
required this.isOwner,
|
||||
required this.total,
|
||||
required this.active,
|
||||
required this.inactive,
|
||||
required this.warning,
|
||||
required this.unused});
|
||||
const OverviewCard({
|
||||
super.key,
|
||||
required this.isOwner,
|
||||
required this.total,
|
||||
required this.active,
|
||||
required this.inactive,
|
||||
required this.warning,
|
||||
required this.unused,
|
||||
this.showTotal = true,
|
||||
this.showActive = true,
|
||||
this.showInactive = true,
|
||||
this.showWarning = true,
|
||||
this.showUnused = true,
|
||||
});
|
||||
|
||||
@override
|
||||
State<OverviewCard> createState() => _OverviewCardState();
|
||||
}
|
||||
|
||||
class _OverviewCardState extends State<OverviewCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
elevation: 8,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: context.paddingNormal,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
isOwner
|
||||
? appLocalization(context).overview_message
|
||||
: appLocalization(context).interfamily_page_name,
|
||||
style: context.h2,
|
||||
),
|
||||
SizedBox(height: context.normalValue),
|
||||
Column(
|
||||
return FittedBox(
|
||||
alignment: Alignment.topCenter,
|
||||
child: SizedBox(
|
||||
width: context.width,
|
||||
child: Card(
|
||||
// elevation: 8,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: context.paddingNormal,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
StatusCard(
|
||||
label: appLocalization(context).total_nof_devices_message,
|
||||
count: total,
|
||||
color: Colors.blue,
|
||||
Text(
|
||||
widget.isOwner
|
||||
? appLocalization(context).overview_message
|
||||
: appLocalization(context).interfamily_page_name,
|
||||
style: context.h2,
|
||||
),
|
||||
StatusCard(
|
||||
label: appLocalization(context).active_devices_message,
|
||||
count: active,
|
||||
color: Colors.green,
|
||||
),
|
||||
StatusCard(
|
||||
label: appLocalization(context).inactive_devices_message,
|
||||
count: inactive,
|
||||
color: Colors.grey,
|
||||
),
|
||||
StatusCard(
|
||||
label: appLocalization(context).warning_devices_message,
|
||||
count: warning,
|
||||
color: Colors.orange,
|
||||
),
|
||||
StatusCard(
|
||||
label: appLocalization(context).unused_devices_message,
|
||||
count: unused,
|
||||
color: Colors.yellow,
|
||||
SizedBox(height: context.normalValue),
|
||||
Column(
|
||||
children: [
|
||||
if (widget.showTotal)
|
||||
StatusCard(
|
||||
label: appLocalization(context).total_nof_devices_message,
|
||||
count: widget.total,
|
||||
color: Colors.blue,
|
||||
),
|
||||
if (widget.showActive)
|
||||
StatusCard(
|
||||
label: appLocalization(context).active_devices_message,
|
||||
count: widget.active,
|
||||
color: Colors.green,
|
||||
),
|
||||
if (widget.showInactive)
|
||||
StatusCard(
|
||||
label: appLocalization(context).inactive_devices_message,
|
||||
count: widget.inactive,
|
||||
color: Colors.grey,
|
||||
),
|
||||
if (widget.showWarning)
|
||||
StatusCard(
|
||||
label: appLocalization(context).warning_devices_message,
|
||||
count: widget.warning,
|
||||
color: Colors.orange,
|
||||
),
|
||||
if (widget.showUnused)
|
||||
StatusCard(
|
||||
label: appLocalization(context).unused_devices_message,
|
||||
count: widget.unused,
|
||||
color: Colors.yellow,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
||||
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!) {
|
||||
@@ -209,22 +209,28 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () 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);
|
||||
try {
|
||||
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);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'group_detail_model.dart';
|
||||
|
||||
addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
||||
String groupID, List<DeviceOfGroup> devices) async {
|
||||
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices();
|
||||
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices(context);
|
||||
List<String> selectedItems = [];
|
||||
List<String> selectedDevices = [];
|
||||
if (devices.isNotEmpty) {
|
||||
@@ -131,7 +131,7 @@ addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
||||
for (var device in selectedItems) {
|
||||
await detailGroupBloc.addDeviceToGroup(
|
||||
context, groupID, device);
|
||||
await detailGroupBloc.getGroupDetail(groupID);
|
||||
await detailGroupBloc.getGroupDetail(context,groupID);
|
||||
}
|
||||
|
||||
Navigator.of(dialogContext).pop();
|
||||
|
||||
@@ -4,6 +4,8 @@ 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';
|
||||
@@ -35,15 +37,13 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
const duration = Duration(seconds: 10);
|
||||
getGroupDetailTimer = Timer.periodic(
|
||||
duration,
|
||||
(Timer t) => detailGroupBloc.getGroupDetail(widget.group),
|
||||
(Timer t) => detailGroupBloc.getGroupDetail(context, widget.group),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
getGroupDetailTimer?.cancel();
|
||||
// Thieeus hamf
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -53,10 +53,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
stream: detailGroupBloc.streamDetailGroup,
|
||||
builder: (context, detailGroupSnapshot) {
|
||||
if (detailGroupSnapshot.data?.id == null) {
|
||||
detailGroupBloc.getGroupDetail(widget.group);
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
detailGroupBloc.getGroupDetail(context, widget.group);
|
||||
return const SharedLoadingAnimation();
|
||||
} else {
|
||||
return Scaffold(
|
||||
key: scaffoldKey,
|
||||
@@ -142,8 +140,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
widget.group,
|
||||
user.id!,
|
||||
user.name!);
|
||||
detailGroupBloc
|
||||
.getGroupDetail(widget.group);
|
||||
detailGroupBloc.getGroupDetail(
|
||||
context, widget.group);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.check,
|
||||
@@ -160,8 +158,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
widget.group,
|
||||
user.id!,
|
||||
user.name!);
|
||||
await detailGroupBloc
|
||||
.getGroupDetail(widget.group);
|
||||
await detailGroupBloc.getGroupDetail(
|
||||
context, widget.group);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.close,
|
||||
@@ -207,8 +205,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
widget.group,
|
||||
user.id!,
|
||||
user.name!);
|
||||
await detailGroupBloc
|
||||
.getGroupDetail(widget.group);
|
||||
await detailGroupBloc.getGroupDetail(
|
||||
context, widget.group);
|
||||
},
|
||||
value: 2,
|
||||
child: Text(appLocalization(context)
|
||||
@@ -241,7 +239,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
? PopupMenuButton(
|
||||
icon: IconConstants.instance
|
||||
.getMaterialIcon(Icons.more_horiz),
|
||||
itemBuilder: (contex) => [
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
@@ -327,15 +325,21 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
Future.delayed(context.lowDuration).then(
|
||||
(value) => Navigator.pop(context),
|
||||
);
|
||||
int statusCode = await apiServices
|
||||
.deleteGroup(widget.group);
|
||||
showSnackBarResponseByStatusCode(
|
||||
context,
|
||||
statusCode,
|
||||
appLocalization(context)
|
||||
.notification_delete_group_success,
|
||||
appLocalization(context)
|
||||
.notification_delete_group_failed);
|
||||
try {
|
||||
int statusCode = await apiServices
|
||||
.deleteGroup(widget.group);
|
||||
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());
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
appLocalization(context)
|
||||
@@ -463,7 +467,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
DeviceUtils.instance.checkStateDevice(
|
||||
context, devices[index].state!),
|
||||
style: TextStyle(
|
||||
color: DeviceUtils.instance.getTableRowColor(context,
|
||||
color: DeviceUtils.instance.getTableRowColor(
|
||||
context,
|
||||
devices[index].state!,
|
||||
),
|
||||
),
|
||||
@@ -525,7 +530,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
||||
String alias = aliasController.text;
|
||||
await detailGroupBloc.updateDeviceNameInGroup(
|
||||
context, device.thingId!, alias);
|
||||
await detailGroupBloc.getGroupDetail(widget.group);
|
||||
await detailGroupBloc.getGroupDetail(context, widget.group);
|
||||
},
|
||||
child: Text(appLocalization(context).confirm_button_content)),
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../product/constant/enums/app_route_enums.dart';
|
||||
import '../../../product/shared/shared_component_loading_animation.dart';
|
||||
import '../../../product/shared/shared_loading_animation.dart';
|
||||
import 'groups_model.dart';
|
||||
import '../../../bloc/inter_family_bloc.dart';
|
||||
import '../inter_family_widget.dart';
|
||||
@@ -54,64 +56,76 @@ class _GroupsScreenState extends State<GroupsScreen> {
|
||||
return StreamBuilder<List<Group>>(
|
||||
stream: interFamilyBloc.streamCurrentGroups,
|
||||
builder: (context, groupsSnapshot) {
|
||||
if(groupsSnapshot.data == null){
|
||||
if (groupsSnapshot.data == null) {
|
||||
interFamilyBloc.getAllGroup(widget.role);
|
||||
return const Center(child: CircularProgressIndicator(),);
|
||||
}else if(groupsSnapshot.data!.isEmpty){
|
||||
return Center(child: Text(appLocalization(context).dont_have_group),);
|
||||
}else {
|
||||
return const SharedLoadingAnimation();
|
||||
} else if (groupsSnapshot.data!.isEmpty) {
|
||||
return Center(
|
||||
child: Text(appLocalization(context).dont_have_group),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
body: groupsSnapshot.data?.isEmpty ?? true
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
? const SharedComponentLoadingAnimation()
|
||||
: ListView.builder(
|
||||
itemCount: groupsSnapshot.data!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
context.pushNamed(AppRoutes.GROUP_DETAIL.name,
|
||||
pathParameters: {"groupId": groupsSnapshot.data![index].id!},
|
||||
extra: widget.role);
|
||||
},
|
||||
leading: IconConstants.instance.getMaterialIcon(Icons.diversity_2),
|
||||
title: Text(
|
||||
groupsSnapshot.data![index].name ?? '',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
itemCount: groupsSnapshot.data!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
context.pushNamed(AppRoutes.GROUP_DETAIL.name,
|
||||
pathParameters: {
|
||||
"groupId": groupsSnapshot.data![index].id!
|
||||
},
|
||||
extra: widget.role);
|
||||
},
|
||||
leading: IconConstants.instance
|
||||
.getMaterialIcon(Icons.diversity_2),
|
||||
title: Text(
|
||||
groupsSnapshot.data![index].name ?? '',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(
|
||||
groupsSnapshot.data![index].description ?? ""),
|
||||
trailing:
|
||||
widget.role == ApplicationConstants.OWNER_GROUP
|
||||
? PopupMenuButton(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(8.0),
|
||||
bottomRight: Radius.circular(8.0),
|
||||
topLeft: Radius.circular(8.0),
|
||||
topRight: Radius.circular(8.0),
|
||||
),
|
||||
),
|
||||
itemBuilder: (ctx) => [
|
||||
_buildPopupMenuItem(
|
||||
groupsSnapshot.data![index],
|
||||
context,
|
||||
appLocalization(context)
|
||||
.share_group_title,
|
||||
Icons.share,
|
||||
4),
|
||||
_buildPopupMenuItem(
|
||||
groupsSnapshot.data![index],
|
||||
context,
|
||||
appLocalization(context)
|
||||
.change_group_infomation_title,
|
||||
Icons.settings_backup_restore,
|
||||
2),
|
||||
_buildPopupMenuItem(
|
||||
groupsSnapshot.data![index],
|
||||
context,
|
||||
appLocalization(context)
|
||||
.delete_group_title,
|
||||
Icons.delete_forever_rounded,
|
||||
3),
|
||||
],
|
||||
icon: const Icon(Icons.more_horiz),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
subtitle: Text(groupsSnapshot.data![index].description ?? ""),
|
||||
trailing: widget.role == ApplicationConstants.OWNER_GROUP
|
||||
? PopupMenuButton(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(8.0),
|
||||
bottomRight: Radius.circular(8.0),
|
||||
topLeft: Radius.circular(8.0),
|
||||
topRight: Radius.circular(8.0),
|
||||
),
|
||||
),
|
||||
itemBuilder: (ctx) => [
|
||||
_buildPopupMenuItem(groupsSnapshot.data![index], context,
|
||||
appLocalization(context).share_group_title, Icons.share, 4),
|
||||
_buildPopupMenuItem(
|
||||
groupsSnapshot.data![index],
|
||||
context,
|
||||
appLocalization(context).change_group_infomation_title,
|
||||
Icons.settings_backup_restore,
|
||||
2),
|
||||
_buildPopupMenuItem(
|
||||
groupsSnapshot.data![index],
|
||||
context,
|
||||
appLocalization(context).delete_group_title,
|
||||
Icons.delete_forever_rounded,
|
||||
3),
|
||||
],
|
||||
icon: const Icon(Icons.more_horiz),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -121,15 +135,16 @@ class _GroupsScreenState extends State<GroupsScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
PopupMenuItem _buildPopupMenuItem(
|
||||
Group group, BuildContext context, String title, IconData iconData, int position) {
|
||||
PopupMenuItem _buildPopupMenuItem(Group group, BuildContext context,
|
||||
String title, IconData iconData, int position) {
|
||||
return PopupMenuItem(
|
||||
onTap: () {
|
||||
if (title == appLocalization(context).share_group_title) {
|
||||
Future.delayed(context.lowDuration, () {
|
||||
shareGroup(context, group);
|
||||
});
|
||||
} else if (title == appLocalization(context).change_group_infomation_title) {
|
||||
} else if (title ==
|
||||
appLocalization(context).change_group_infomation_title) {
|
||||
Future.delayed(context.lowDuration, () {
|
||||
createOrJoinGroupDialog(
|
||||
context,
|
||||
|
||||
@@ -131,7 +131,7 @@ createOrJoinGroupDialog(
|
||||
appLocalization(context)
|
||||
.change_group_infomation_content) {
|
||||
try {
|
||||
await interFamilyBloc.changeGroupInfomation(
|
||||
await interFamilyBloc.changeGroupInformation(
|
||||
context, groupID, groupName, description);
|
||||
interFamilyBloc.getAllGroup(role);
|
||||
Navigator.of(dialogContext).pop();
|
||||
|
||||
@@ -10,6 +10,7 @@ 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/permission/notification_permission.dart';
|
||||
import '../../product/services/notification_services.dart';
|
||||
@@ -100,7 +101,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
initialCheck();
|
||||
getBellNotification();
|
||||
mainBloc.getUserProfile();
|
||||
mainBloc.getUserProfile(context);
|
||||
|
||||
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
|
||||
log("New FCM Token: $newToken");
|
||||
@@ -412,8 +413,12 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
Future<void> getBellNotification() async {
|
||||
bell = await apiServices.getBellNotifications("0", "20");
|
||||
mainBloc.bellBloc.add(bell);
|
||||
try{
|
||||
bell = await apiServices.getBellNotifications("0", "20");
|
||||
mainBloc.bellBloc.add(bell);
|
||||
}catch(e){
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
bool checkStatus(List<BellItems> bells) {
|
||||
|
||||
@@ -17,6 +17,7 @@ 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 '../../product/constant/enums/app_theme_enums.dart';
|
||||
import '../../product/shared/shared_snack_bar.dart';
|
||||
|
||||
class MapScreen extends StatefulWidget {
|
||||
const MapScreen({super.key});
|
||||
@@ -73,11 +74,11 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
checkThemeTimer?.cancel();
|
||||
getMarker?.cancel();
|
||||
_controller = Completer();
|
||||
streamController.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void onMapCreated(GoogleMapController controller) {
|
||||
@@ -273,18 +274,18 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
void getAllMarkers() async {
|
||||
String response = await apiServices.getOwnerDevices();
|
||||
if (response != "") {
|
||||
final data = jsonDecode(response);
|
||||
List<dynamic> result = data['items'];
|
||||
if (result.isNotEmpty) {
|
||||
devices.clear();
|
||||
final devicesList = Device.fromJsonDynamicList(result);
|
||||
for (var device in devicesList) {
|
||||
devices.add(device);
|
||||
}
|
||||
} else {}
|
||||
try {
|
||||
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 {
|
||||
|
||||
@@ -79,7 +79,7 @@ onTapMarker(
|
||||
destination,
|
||||
);
|
||||
String deviceLocations = await DeviceUtils.instance
|
||||
.getFullDeviceLocation(context, device.areaPath!);
|
||||
.getFullDeviceLocation(context, device.areaPath!,device.name);
|
||||
String yourLocation =
|
||||
appLocalization(context).map_your_location;
|
||||
showDirections(
|
||||
@@ -88,7 +88,6 @@ onTapMarker(
|
||||
otherMarkers,
|
||||
mapBloc,
|
||||
yourLocation,
|
||||
|
||||
deviceLocations,
|
||||
double.parse(device.settings!.latitude!),
|
||||
double.parse(device.settings!.longitude!),
|
||||
|
||||
@@ -111,14 +111,15 @@ class _DeviceNotificationSettingsScreenState
|
||||
}
|
||||
|
||||
void getNotificationSetting() async {
|
||||
String? response = await apiServices.getAllSettingsNotificationOfDevices();
|
||||
final data = jsonDecode(response);
|
||||
final result = data['data'];
|
||||
// log("Data ${DeviceNotificationSettings.mapFromJson(jsonDecode(data)).values.toList()}");
|
||||
deviceNotifications =
|
||||
DeviceNotificationSettings.mapFromJson(result).values.toList();
|
||||
deviceNotificationSettingsBloc.sinkListNotifications
|
||||
.add(deviceNotifications);
|
||||
try {
|
||||
deviceNotifications =
|
||||
await apiServices.getAllSettingsNotificationOfDevices();
|
||||
deviceNotificationSettingsBloc.sinkListNotifications
|
||||
.add(deviceNotifications);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showErrorTopSnackBarCustom(context, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Widget listNotificationSetting(
|
||||
@@ -292,22 +293,29 @@ class _DeviceNotificationSettingsScreenState
|
||||
|
||||
void updateDeviceNotification(String thingID, Map<String, int> notifiSettings,
|
||||
bool isDataChange) async {
|
||||
int statusCode = await apiServices.updateDeviceNotificationSettings(
|
||||
thingID, notifiSettings);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).notification_update_device_settings_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).notification_update_device_settings_failed,
|
||||
Colors.red,
|
||||
Colors.white);
|
||||
try {
|
||||
int statusCode = await apiServices.updateDeviceNotificationSettings(
|
||||
thingID, notifiSettings);
|
||||
if (statusCode == 200) {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).notification_update_device_settings_success,
|
||||
Colors.green,
|
||||
Colors.white);
|
||||
} else {
|
||||
showNoIconTopSnackBar(
|
||||
context,
|
||||
appLocalization(context).notification_update_device_settings_failed,
|
||||
Colors.red,
|
||||
Colors.white);
|
||||
}
|
||||
isDataChange = false;
|
||||
deviceNotificationSettingsBloc.sinkIsDataChange.add(isDataChange);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
isDataChange = false;
|
||||
deviceNotificationSettingsBloc.sinkIsDataChange.add(isDataChange);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,35 +38,42 @@ changeUserInfomation(
|
||||
? IconButton(
|
||||
onPressed: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
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);
|
||||
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());
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
}
|
||||
},
|
||||
icon:
|
||||
@@ -205,35 +212,42 @@ changeUserInfomation(
|
||||
child: TextButton(
|
||||
onPressed: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
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);
|
||||
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());
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
}
|
||||
},
|
||||
style: const ButtonStyle(
|
||||
@@ -282,30 +296,36 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
isChangeSnapshot.data ?? isChange
|
||||
? IconButton(
|
||||
onPressed: () async {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
},
|
||||
icon:
|
||||
@@ -390,30 +410,36 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
||||
? Center(
|
||||
child: TextButton(
|
||||
onPressed: () async {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
Navigator.pop(modalBottomSheetContext);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorTopSnackBarCustom(
|
||||
context, e.toString());
|
||||
}
|
||||
},
|
||||
style: const ButtonStyle(
|
||||
|
||||
@@ -3,6 +3,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';
|
||||
@@ -27,7 +29,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
settingsBloc = BlocProvider.of(context);
|
||||
getUserProfile();
|
||||
// getUserProfile();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -38,76 +40,75 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
centerTitle: true,
|
||||
),
|
||||
body: StreamBuilder<User>(
|
||||
stream: settingsBloc.streamUserProfile,
|
||||
initialData: user,
|
||||
builder: (context, userSnapshot) {
|
||||
return userSnapshot.data?.id == "" || user.id == ""
|
||||
? Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: context.highValue,
|
||||
stream: settingsBloc.streamUserProfile,
|
||||
// initialData: user,
|
||||
builder: (context, userSnapshot) {
|
||||
if (userSnapshot.data == null) {
|
||||
settingsBloc.getUserProfile(context);
|
||||
return const SharedLoadingAnimation();
|
||||
} else {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: Theme.of(context).focusColor,
|
||||
radius: 70,
|
||||
child: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).highlightColor,
|
||||
radius: 60,
|
||||
child: CircleAvatar(
|
||||
radius: 50,
|
||||
child: Text(
|
||||
getAvatarContent(userSnapshot.data?.username ?? ""),
|
||||
style: context.dynamicResponsiveSize(36),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: Theme.of(context).focusColor,
|
||||
radius: 70,
|
||||
child: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).highlightColor,
|
||||
radius: 60,
|
||||
child: CircleAvatar(
|
||||
radius: 50,
|
||||
child: Text(
|
||||
getAvatarContent(
|
||||
userSnapshot.data?.username ?? ""),
|
||||
style: context.dynamicResponsiveSize(36),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
userSnapshot.data?.name ?? "User Name",
|
||||
style: context.h2,
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [Text(userSnapshot.data?.email ?? "Email")],
|
||||
),
|
||||
SizedBox(height: context.mediumValue),
|
||||
cardContent(
|
||||
Icons.account_circle_rounded,
|
||||
appLocalization(context).profile_change_info,
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.lock_outline,
|
||||
appLocalization(context).profile_change_pass,
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.settings_outlined,
|
||||
appLocalization(context).profile_setting,
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.logout_outlined,
|
||||
appLocalization(context).log_out,
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
userSnapshot.data?.name ?? "User Name",
|
||||
style: context.h2,
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [Text(userSnapshot.data?.email ?? "Email")],
|
||||
),
|
||||
SizedBox(height: context.mediumValue),
|
||||
cardContent(
|
||||
Icons.account_circle_rounded,
|
||||
appLocalization(context).profile_change_info,
|
||||
userSnapshot.data ?? user),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.lock_outline,
|
||||
appLocalization(context).profile_change_pass,
|
||||
userSnapshot.data ?? user),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.settings_outlined,
|
||||
appLocalization(context).profile_setting,
|
||||
userSnapshot.data ?? user),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.logout_outlined,
|
||||
appLocalization(context).log_out,
|
||||
userSnapshot.data ?? user),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
cardContent(IconData icon, String content) {
|
||||
cardContent(IconData icon, String content, User user) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
if (icon == Icons.account_circle_rounded) {
|
||||
@@ -138,11 +139,16 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
void getUserProfile() async {
|
||||
String data = await apiServices.getUserDetail();
|
||||
user = User.fromJson(jsonDecode(data));
|
||||
settingsBloc.sinkUserProfile.add(user);
|
||||
}
|
||||
// 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 = "";
|
||||
|
||||
@@ -25,4 +25,5 @@ class ApplicationConstants {
|
||||
static const PARTICIPANT_GROUP = "participant";
|
||||
static const NO_DATA = "no_data";
|
||||
static const LOADING = "loading";
|
||||
static int CALL_API_TIMEOUT = 15;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
@@ -12,6 +13,7 @@ class NetworkManager {
|
||||
NetworkManager._init();
|
||||
static NetworkManager? _instance;
|
||||
static NetworkManager? get instance => _instance ??= NetworkManager._init();
|
||||
|
||||
|
||||
Future<Map<String, String>> getHeaders() async {
|
||||
String? token =
|
||||
@@ -35,15 +37,24 @@ class NetworkManager {
|
||||
/// [String] if the request is successful (status code 200), or an empty
|
||||
/// string if the request fails
|
||||
Future<String> getDataFromServer(String path) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.get(url, headers: headers);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.body;
|
||||
} else {
|
||||
return "";
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
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),
|
||||
onTimeout: () =>
|
||||
throw TimeoutException('Yêu cầu GET hết thời gian'),
|
||||
);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.body;
|
||||
} else {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +71,25 @@ class NetworkManager {
|
||||
/// Returns a [Future<String>] containing the server response body.
|
||||
Future<String> getDataFromServerWithParams(
|
||||
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");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.get(url, headers: headers).timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
onTimeout: () =>
|
||||
throw TimeoutException('Yêu cầu GET+PARAM hết thời gian'),
|
||||
);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.body;
|
||||
} else {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
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();
|
||||
@@ -77,12 +107,27 @@ class NetworkManager {
|
||||
/// [path] is the endpoint for the request, and [body] contains the data
|
||||
/// to be sent. Returns the HTTP status code of the response.
|
||||
Future<int> createDataInServer(String path, Map<String, dynamic> body) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
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));
|
||||
return response.statusCode;
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
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))
|
||||
.timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
onTimeout: () =>
|
||||
throw TimeoutException('Yêu cầu POST hết thời gian'),
|
||||
);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.statusCode;
|
||||
} else {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates existing data on the server using a PUT request.
|
||||
@@ -90,12 +135,26 @@ class NetworkManager {
|
||||
/// [path] is the endpoint for the request, and [body] contains the data
|
||||
/// to be updated. Returns the HTTP status code of the response.
|
||||
Future<int> updateDataInServer(String path, Map<String, dynamic> body) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
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));
|
||||
return response.statusCode;
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
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(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
onTimeout: () =>
|
||||
throw TimeoutException('Yêu cầu PUT hết thời gian'),
|
||||
);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.statusCode;
|
||||
} else {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes data from the server using a DELETE request.
|
||||
@@ -105,10 +164,24 @@ class NetworkManager {
|
||||
/// A status code of 200 indicates success, while other codes indicate
|
||||
/// failure or an error.
|
||||
Future<int> deleteDataInServer(String path) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.delete(url, headers: headers);
|
||||
return response.statusCode;
|
||||
try {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
||||
final headers = await getHeaders();
|
||||
final response = await http.delete(url, headers: headers).timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
onTimeout: () =>
|
||||
throw TimeoutException('Yêu cầu DELETE hết thời gian'),
|
||||
);
|
||||
if (response.statusCode == StatusCodeConstants.OK ||
|
||||
response.statusCode == StatusCodeConstants.CREATED) {
|
||||
return response.statusCode;
|
||||
} else {
|
||||
throw Exception('Lỗi server: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
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 '../../feature/device_log/device_logs_model.dart';
|
||||
import '../../feature/devices/device_model.dart';
|
||||
import '../../feature/home/device_alias_model.dart';
|
||||
import '../../feature/inter_family/group_detail/group_detail_model.dart';
|
||||
import '../../feature/inter_family/groups/groups_model.dart';
|
||||
import '../../feature/settings/device_notification_settings/device_notification_settings_model.dart';
|
||||
import '../../feature/settings/profile/profile_model.dart';
|
||||
import '../constant/app/api_path_constant.dart';
|
||||
import '../shared/model/district_model.dart';
|
||||
import '../shared/model/ward_model.dart';
|
||||
import '../shared/shared_snack_bar.dart';
|
||||
import '../constant/enums/app_route_enums.dart';
|
||||
import 'language_services.dart';
|
||||
@@ -41,6 +52,40 @@ 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 {
|
||||
try {
|
||||
final response = await apiCall().timeout(
|
||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
||||
onTimeout: () => throw TimeoutException('Yêu cầu hết thời gian'),
|
||||
);
|
||||
|
||||
if (statusCodeHandler != null && response is int) {
|
||||
return statusCodeHandler(response);
|
||||
}
|
||||
|
||||
if (response is String && response != "") {
|
||||
if (parser != null) {
|
||||
try {
|
||||
return parser(jsonDecode(response));
|
||||
} catch (e) {
|
||||
throw Exception('Lỗi parsing dữ liệu: $e');
|
||||
}
|
||||
}
|
||||
return response as T;
|
||||
} else {
|
||||
throw Exception('Dữ liệu trả về rỗng');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
// log('Lỗi API: $e, StackTrace: $stackTrace');
|
||||
throw Exception('$errorMessage: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> login(String path, Map<String, dynamic> loginRequest) async {
|
||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||
final headers = await getHeaders();
|
||||
@@ -49,14 +94,11 @@ class APIServices {
|
||||
return response.body;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -122,67 +164,88 @@ class APIServices {
|
||||
return language;
|
||||
}
|
||||
|
||||
Future<Bell> getBellNotifications(String offset, String pagesize) async {
|
||||
Bell bell = Bell();
|
||||
final params = {"offset": offset, "page_size": pagesize};
|
||||
final data = await NetworkManager.instance!.getDataFromServerWithParams(
|
||||
APIPathConstants.BELL_NOTIFICATIONS_PATH, params);
|
||||
if (data != "") {
|
||||
bell = Bell.fromJson(jsonDecode(data));
|
||||
return bell;
|
||||
} else {
|
||||
return bell;
|
||||
}
|
||||
Future<Bell> getBellNotifications(String offset, String pageSize) async {
|
||||
final params = {"offset": offset, "page_size": pageSize};
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.getDataFromServerWithParams(
|
||||
APIPathConstants.BELL_NOTIFICATIONS_PATH, params),
|
||||
parser: (json) => Bell.fromJson(json),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.BELL_NOTIFICATIONS_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> updateStatusOfNotification(List<String> notificationID) async {
|
||||
Map<String, dynamic> body = {
|
||||
"event_ids": notificationID,
|
||||
};
|
||||
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.BELL_UPDATE_READ_NOTIFICATIONS_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.BELL_UPDATE_READ_NOTIFICATIONS_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.BELL_NOTIFICATIONS_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getUserDetail() async {
|
||||
Future<User> getUserDetail() async {
|
||||
String uid = await getUID();
|
||||
String? response = await NetworkManager.instance!
|
||||
.getDataFromServer('${APIPathConstants.USER_PATH}/$uid');
|
||||
return response;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer('${APIPathConstants.USER_PATH}/$uid'),
|
||||
parser: (json) => User.fromJson(json),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.USER_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> updateUserProfile(Map<String, dynamic> body) async {
|
||||
String uid = await getUID();
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.updateDataInServer("${APIPathConstants.USER_PROFILE_PATH}/$uid", body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.USER_PROFILE_PATH}/$uid", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.USER_PROFILE_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> updateUserPassword(Map<String, dynamic> body) async {
|
||||
String uid = await getUID();
|
||||
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.USER_PATH}/$uid/password", body);
|
||||
return statusCode;
|
||||
// int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
// "${APIPathConstants.USER_PATH}/$uid/password", body);
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.USER_PATH}/$uid/password", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.USER_PATH}');
|
||||
}
|
||||
|
||||
Future<String> getAllSettingsNotificationOfDevices() async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DEVICE_NOTIFICATION_SETTINGS);
|
||||
return data;
|
||||
Future<List<DeviceNotificationSettings>>
|
||||
getAllSettingsNotificationOfDevices() async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DEVICE_NOTIFICATION_SETTINGS),
|
||||
parser: (json) =>
|
||||
DeviceNotificationSettings.mapFromJson(json['data']).values.toList(),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}',
|
||||
);
|
||||
}
|
||||
|
||||
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};
|
||||
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
||||
}
|
||||
|
||||
Future<String> getDashBoardDevices() async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DASHBOARD_DEVICES);
|
||||
return data;
|
||||
Future<List<DeviceWithAlias>> getDashBoardDevices() async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DASHBOARD_DEVICES),
|
||||
parser: (json) => DeviceWithAlias.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DASHBOARD_DEVICES}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> setupDeviceNotification(String thingID, String deviceName) async {
|
||||
@@ -202,68 +265,105 @@ class APIServices {
|
||||
"104": 1,
|
||||
}
|
||||
};
|
||||
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
||||
}
|
||||
|
||||
Future<String> getAllProvinces() async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.PROVINCES_PATH);
|
||||
return data;
|
||||
Future<List<Province>> getAllProvinces() async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.PROVINCES_PATH),
|
||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}');
|
||||
;
|
||||
}
|
||||
|
||||
Future<String> getProvincesByName(String name) async {
|
||||
Future<List<Province>> getProvincesByName(String name) async {
|
||||
final params = {'name': name};
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.PROVINCES_PATH, params);
|
||||
return data;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.PROVINCES_PATH, params),
|
||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}/$name',
|
||||
);
|
||||
;
|
||||
}
|
||||
|
||||
Future<String> getProvinceByID(String provinceID) async {
|
||||
String data = await NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.PROVINCES_PATH}/$provinceID");
|
||||
return data;
|
||||
Future<Province> getProvinceByID(String provinceID) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.PROVINCES_PATH}/$provinceID"),
|
||||
parser: (json) => Province.fromJson(json['data']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}/$provinceID}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getAllDistricts(String provinceID) async {
|
||||
Future<List<District>> getAllDistricts(String provinceID) async {
|
||||
final params = {"parent": provinceID};
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params);
|
||||
return data;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params),
|
||||
parser: (json) => District.fromJsonDynamicList(json['items']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH} by parentCode $provinceID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getDistrictsByName(String districtName) async {
|
||||
Future<List<District>> getDistrictsByName(String districtName) async {
|
||||
final params = {"name": districtName};
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params);
|
||||
return data;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params),
|
||||
parser: (json) => District.fromJsonDynamicList(json['items']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH} by name $districtName',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getDistrictByID(String districtID) async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.DISTRICTS_PATH}/$districtID");
|
||||
return data;
|
||||
Future<District> getDistrictByID(String districtID) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.DISTRICTS_PATH}/$districtID"),
|
||||
parser: (json) => District.fromJson(json['data']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH}/$districtID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getAllWards(String districtID) async {
|
||||
Future<List<Ward>> getAllWards(String districtID) async {
|
||||
final params = {'parent': districtID};
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params);
|
||||
return data;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params),
|
||||
parser: (json) => Ward.fromJsonDynamicList(json['items']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.WARDS_PATH} by parent $districtID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getWarsdByName(String wardName) async {
|
||||
Future<List<Ward>> getWardsByName(String wardName) async {
|
||||
final params = {"name": wardName};
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params);
|
||||
return data;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params),
|
||||
parser: (json) => Ward.fromJsonDynamicList(json['items']),
|
||||
errorMessage:
|
||||
'Lỗi khi GET /${APIPathConstants.WARDS_PATH} by name $wardName',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getWardByID(String wardID) async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.WARDS_PATH}/$wardID");
|
||||
return data;
|
||||
Future<Ward> getWardByID(String wardID) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.WARDS_PATH}/$wardID"),
|
||||
parser: (json) => Ward.fromJson(json['data']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.WARDS_PATH}/$wardID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> confirmFakeFireByUser(String thingID) async {
|
||||
@@ -271,131 +371,187 @@ class APIServices {
|
||||
"state": 3,
|
||||
"note": "Người dùng xác nhận cháy giả!"
|
||||
};
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.updateDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID", body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.DEVICE_PATH}/$thingID", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.DEVICE_PATH}/$thingID');
|
||||
}
|
||||
|
||||
Future<String> getOwnerDevices() async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DEVICE_PATH);
|
||||
return data;
|
||||
Future<List<Device>> getOwnerDevices() async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.DEVICE_PATH),
|
||||
parser: (json) => Device.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getOwnerDeviceByState(Map<String, dynamic> params) async {
|
||||
String? data = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DEVICE_PATH, params);
|
||||
return data;
|
||||
Future<List<Device>> getOwnerDeviceByState(
|
||||
Map<String, dynamic> params) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DEVICE_PATH, params),
|
||||
parser: (json) => Device.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> createDeviceByAdmin(Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.DEVICE_PATH}');
|
||||
}
|
||||
|
||||
Future<int> registerDevice(Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_REGISTER_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_REGISTER_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.DEVICE_REGISTER_PATH}');
|
||||
}
|
||||
|
||||
Future<int> deleteDeviceByAdmin(String thingID) async {
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.deleteDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID");
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.deleteDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID"),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi DELETE /${APIPathConstants.DEVICE_PATH}/$thingID');
|
||||
}
|
||||
|
||||
Future<int> unregisterDevice(Map<String, dynamic> body) async {
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_UNREGISTER_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.DEVICE_UNREGISTER_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi DELETE /${APIPathConstants.DEVICE_UNREGISTER_PATH} by USER');
|
||||
}
|
||||
|
||||
Future<String> getDeviceInfomation(String thingID) async {
|
||||
String? response = await NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.DEVICE_PATH}/$thingID");
|
||||
return response;
|
||||
Future<Device> getDeviceInformation(String thingID) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.DEVICE_PATH}/$thingID"),
|
||||
parser: (json) => Device.fromJson(json),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}/$thingID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getAllGroups() async {
|
||||
String? body = await NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.ALL_GROUPS_PATH);
|
||||
return body;
|
||||
Future<List<Group>> getAllGroups() async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer(APIPathConstants.ALL_GROUPS_PATH),
|
||||
parser: (json) => Group.fromJsonDynamicList(json['items']),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.USER_PATH}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> createGroup(Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.GROUPS_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.GROUPS_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.GROUPS_PATH}');
|
||||
}
|
||||
|
||||
Future<int> updateGroup(Map<String, dynamic> body, String groupID) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.updateDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID", body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.GROUPS_PATH}/$groupID');
|
||||
}
|
||||
|
||||
Future<int> joinGroup(String groupID, Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.JOIN_GROUP_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.JOIN_GROUP_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.JOIN_GROUP_PATH}');
|
||||
}
|
||||
|
||||
Future<int> deleteGroup(String groupID) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.deleteDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID");
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.deleteDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID"),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID');
|
||||
}
|
||||
|
||||
Future<String> getGroupDetail(String groupID) async {
|
||||
String? body = await NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.GROUPS_PATH}/$groupID");
|
||||
return body;
|
||||
Future<GroupDetail> getGroupDetail(String groupID) async {
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.getDataFromServer("${APIPathConstants.GROUPS_PATH}/$groupID"),
|
||||
parser: (json) => GroupDetail.fromJson(json),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.GROUPS_PATH}/$groupID',
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> approveGroup(Map<String, dynamic> body) async {
|
||||
int statusCode = await NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.APPROVE_GROUP_PATH, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!
|
||||
.createDataInServer(APIPathConstants.APPROVE_GROUP_PATH, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.APPROVE_GROUP_PATH}');
|
||||
}
|
||||
|
||||
Future<int> deleteUserInGroup(String groupID, String userID) async {
|
||||
int? statusCode = await NetworkManager.instance!.deleteDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID");
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.deleteDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID"),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID');
|
||||
}
|
||||
|
||||
Future<int> deleteDeviceInGroup(String groupID, String thingID) async {
|
||||
int? statusCode = await NetworkManager.instance!.deleteDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID");
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.deleteDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID"),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID');
|
||||
}
|
||||
|
||||
Future<int> updateDeviceAlias(Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
||||
}
|
||||
|
||||
Future<int> addDeviceToGroup(
|
||||
String groupID, Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!.createDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/things", body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.createDataInServer(
|
||||
"${APIPathConstants.GROUPS_PATH}/$groupID/things", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage:
|
||||
'Lỗi khi PUT /${APIPathConstants.GROUPS_PATH}/$groupID/things');
|
||||
}
|
||||
|
||||
Future<int> updateOwnerDevice(
|
||||
String thingID, Map<String, dynamic> body) async {
|
||||
int? statusCode = await NetworkManager.instance!
|
||||
.updateDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID", body);
|
||||
return statusCode;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.updateDataInServer(
|
||||
"${APIPathConstants.DEVICE_PATH}/$thingID", body),
|
||||
statusCodeHandler: (statusCode) => statusCode,
|
||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.DEVICE_PATH}/$thingID');
|
||||
}
|
||||
|
||||
Future<String> getLogsOfDevice(
|
||||
Future<DeviceLog> getLogsOfDevice(
|
||||
String thingID, Map<String, dynamic> params) async {
|
||||
String? body = await NetworkManager.instance!
|
||||
.getDataFromServerWithParams(APIPathConstants.DEVICE_LOGS_PATH, params);
|
||||
return body;
|
||||
return executeApiCall(
|
||||
() => NetworkManager.instance!.getDataFromServerWithParams(
|
||||
APIPathConstants.DEVICE_LOGS_PATH, params),
|
||||
parser: (json) => DeviceLog.fromJson(json),
|
||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_LOGS_PATH}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
23
lib/product/shared/shared_component_loading_animation.dart
Normal file
23
lib/product/shared/shared_component_loading_animation.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
class SharedComponentLoadingAnimation extends StatefulWidget {
|
||||
const SharedComponentLoadingAnimation({super.key});
|
||||
|
||||
@override
|
||||
State<SharedComponentLoadingAnimation> createState() => _SharedComponentLoadingAnimationState();
|
||||
}
|
||||
|
||||
class _SharedComponentLoadingAnimationState extends State<SharedComponentLoadingAnimation> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: LottieBuilder.asset(
|
||||
'assets/animations/component_loading.json',
|
||||
width: 80,
|
||||
height: 80,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
23
lib/product/shared/shared_loading_animation.dart
Normal file
23
lib/product/shared/shared_loading_animation.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
class SharedLoadingAnimation extends StatefulWidget {
|
||||
const SharedLoadingAnimation({super.key});
|
||||
|
||||
@override
|
||||
State<SharedLoadingAnimation> createState() => _SharedLoadingAnimationState();
|
||||
}
|
||||
|
||||
class _SharedLoadingAnimationState extends State<SharedLoadingAnimation> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: LottieBuilder.asset(
|
||||
'assets/animations/loading.json',
|
||||
width: 100,
|
||||
height: 100,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -182,23 +182,23 @@ class _SharedPieChartState extends State<SharedPieChart> {
|
||||
switch (originalIndex) {
|
||||
case 0: // OFFLINE_STATE
|
||||
log("Touched Index device state = -1");
|
||||
widget.devicesManagerBloc.getDeviceByState(-1);
|
||||
widget.devicesManagerBloc.getDeviceByState(context,-1);
|
||||
break;
|
||||
case 1: // NORMAL_STATE
|
||||
log("Touched Index Get device state = 0");
|
||||
widget.devicesManagerBloc.getDeviceByState(0);
|
||||
widget.devicesManagerBloc.getDeviceByState(context,0);
|
||||
break;
|
||||
case 2: // WARNING_STATE
|
||||
log("Touched Index Get device state = 1");
|
||||
widget.devicesManagerBloc.getDeviceByState(1);
|
||||
widget.devicesManagerBloc.getDeviceByState(context,1);
|
||||
break;
|
||||
case 3: // INPROGRESS_STATE
|
||||
log("Touched Index Get device state = 2");
|
||||
widget.devicesManagerBloc.getDeviceByState(2);
|
||||
widget.devicesManagerBloc.getDeviceByState(context,2);
|
||||
break;
|
||||
case 4: // ERROR_STATE
|
||||
log("Touched Index Get device state = 3");
|
||||
widget.devicesManagerBloc.getDeviceByState(3);
|
||||
widget.devicesManagerBloc.getDeviceByState(context,3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,30 +93,34 @@ class DeviceUtils {
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
Future<String> getFullDeviceLocation(
|
||||
BuildContext context, String areaPath) async {
|
||||
if (areaPath != "") {
|
||||
BuildContext context, String areaPath, String? deviceName) async {
|
||||
if (areaPath.isNotEmpty) {
|
||||
List<String> parts = areaPath.split('_');
|
||||
|
||||
if (parts.length < 3 || parts[0].isEmpty || parts[1].isEmpty || parts[2].isEmpty) {
|
||||
if (deviceName != null && deviceName.isNotEmpty) {
|
||||
return deviceName;
|
||||
} else {
|
||||
return appLocalization(context).no_data_message;
|
||||
}
|
||||
}
|
||||
|
||||
String provinceID = parts[0];
|
||||
String districtID = parts[1];
|
||||
String wardID = parts[2];
|
||||
|
||||
String provinceBody = await apiServices.getProvinceByID(provinceID);
|
||||
final provinceItem = jsonDecode(provinceBody);
|
||||
Province province = Province.fromJson(provinceItem['data']);
|
||||
String districtBody = await apiServices.getDistrictByID(districtID);
|
||||
final districtItem = jsonDecode(districtBody);
|
||||
District district = District.fromJson(districtItem['data']);
|
||||
String wardBody = await apiServices.getWardByID(wardID);
|
||||
final wardItem = jsonDecode(wardBody);
|
||||
Ward ward = Ward.fromJson(wardItem['data']);
|
||||
|
||||
Province province = await apiServices.getProvinceByID(provinceID);
|
||||
District district = await apiServices.getDistrictByID(districtID);
|
||||
Ward ward = await apiServices.getWardByID(wardID);
|
||||
return "${ward.fullName}, ${district.fullName}, ${province.fullName}";
|
||||
}
|
||||
|
||||
return appLocalization(context).no_data_message;
|
||||
}
|
||||
|
||||
|
||||
String checkStateDevice(BuildContext context, int state) {
|
||||
String message = appLocalization(context).no_data_message;
|
||||
if (state == 1) {
|
||||
@@ -157,11 +161,11 @@ class DeviceUtils {
|
||||
} else if (state == 0) {
|
||||
return const Color(0xFF9EF16D);
|
||||
} else if (state == 2) {
|
||||
return const Color(0xFFF5EF44);;
|
||||
return const Color(0xFFF5EF44);
|
||||
} else if (state == -1) {
|
||||
return const Color(0xFFBBBAC2);;
|
||||
return const Color(0xFFBBBAC2);
|
||||
} else {
|
||||
return const Color(0xFFF5EF44);;
|
||||
return const Color(0xFFF5EF44);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user