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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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());
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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();
}
},
);

View File

@@ -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!;

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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,
),
],
),
],
),
],
),
),
),
);

View File

@@ -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();
},

View File

@@ -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();

View File

@@ -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)),
)

View File

@@ -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,

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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!),

View File

@@ -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);
}
}

View File

@@ -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(

View File

@@ -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 = "";