Add SimDataScreen
This commit is contained in:
34
lib/bloc/sim_data_bloc.dart
Normal file
34
lib/bloc/sim_data_bloc.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../product/services/api_services.dart';
|
||||
import '../feature/devices/device_model.dart';
|
||||
import '../product/base/bloc/base_bloc.dart';
|
||||
|
||||
class SimDataBloc extends BlocBase{
|
||||
|
||||
APIServices apiServices = APIServices();
|
||||
|
||||
final devices = StreamController<List<Device>>.broadcast();
|
||||
StreamSink<List<Device>> get sinkDevices => devices.sink;
|
||||
Stream<List<Device>> get streamDevices => devices.stream;
|
||||
|
||||
@override
|
||||
void dispose() {}
|
||||
|
||||
void getOwnerDevices(BuildContext context) async {
|
||||
await apiServices.execute(context, () async {
|
||||
List<Device> devices = [];
|
||||
devices = await apiServices.getOwnerDevices();
|
||||
|
||||
List<Device> publicDevices = [];
|
||||
for (var device in devices) {
|
||||
if (device.visibility == "PUBLIC") {
|
||||
publicDevices.add(device);
|
||||
}
|
||||
}
|
||||
sinkDevices.add(publicDevices);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,6 +92,11 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
appLocalization(context).profile_setting,
|
||||
userSnapshot.data ?? user),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.sim_card,
|
||||
appLocalization(context).profile_sim_data,
|
||||
userSnapshot.data ?? user),
|
||||
SizedBox(height: context.lowValue),
|
||||
cardContent(
|
||||
Icons.logout_outlined,
|
||||
appLocalization(context).log_out,
|
||||
@@ -113,7 +118,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
changeUserPassword(context, settingsBloc);
|
||||
} else if (icon == Icons.settings_outlined) {
|
||||
context.push(ApplicationConstants.DEVICE_NOTIFICATIONS_SETTINGS);
|
||||
} else {
|
||||
} else if(icon == Icons.sim_card){
|
||||
context.push(ApplicationConstants.SIM_DATA_SETTINGS);
|
||||
}
|
||||
else {
|
||||
await apiServices.logOut(context);
|
||||
}
|
||||
},
|
||||
|
||||
170
lib/feature/settings/sim_data/shared_sim_component.dart
Normal file
170
lib/feature/settings/sim_data/shared_sim_component.dart
Normal file
@@ -0,0 +1,170 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../devices/device_model.dart';
|
||||
import '../../../product/extension/context_extension.dart';
|
||||
import '../../../product/services/language_services.dart';
|
||||
|
||||
import '../../../product/utils/device_utils.dart';
|
||||
|
||||
class SharedSimComponent extends StatelessWidget {
|
||||
|
||||
const SharedSimComponent({super.key, required this.device});
|
||||
final Device device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
double screenHeight = MediaQuery.of(context).size.height;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
width: screenWidth,
|
||||
height: screenHeight / 5.5,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
gradient: getGradientColor(getMonthLeft())
|
||||
),
|
||||
child: Padding(
|
||||
padding: context.paddingLow,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
device.name ?? "name",
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
_buildStatusChip(context,device.state ?? -1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
// Time period
|
||||
Text(
|
||||
"${appLocalization(context).time_title}: ${convertStartTime()} - ${convertExpireTime()}",
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: context.lowValue),
|
||||
_buildDurationDisplay(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatusChip(BuildContext context,int state) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.white),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.circle,
|
||||
color: DeviceUtils.instance.getTableRowColor(context, state),
|
||||
size: 12,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
DeviceUtils.instance.checkStateDevice(context, state),
|
||||
style: TextStyle(
|
||||
color: DeviceUtils.instance.getTableRowColor(context, state),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDurationDisplay(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
Text(
|
||||
"${getMonthLeft()}",
|
||||
style: const TextStyle(
|
||||
fontSize: 40,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
appLocalization(context).sim_data_month_left_message,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
String convertStartTime(){
|
||||
return DateFormat('dd/MM/yyyy').format(device.createdAt!);
|
||||
}
|
||||
|
||||
String convertExpireTime() {
|
||||
final expireDate = _calculateExpireDate();
|
||||
return DateFormat('dd/MM/yyyy').format(expireDate);
|
||||
}
|
||||
|
||||
int getMonthLeft() {
|
||||
final expireDate = _calculateExpireDate();
|
||||
final now = DateTime.now();
|
||||
|
||||
int totalMonths = (expireDate.year - now.year) * 12 + (expireDate.month - now.month);
|
||||
|
||||
if (expireDate.day < now.day) {
|
||||
totalMonths -= 1;
|
||||
}
|
||||
|
||||
return totalMonths;
|
||||
}
|
||||
|
||||
DateTime _calculateExpireDate() {
|
||||
return DateTime(
|
||||
device.createdAt!.year + 3,
|
||||
device.createdAt!.month,
|
||||
device.createdAt!.day,
|
||||
device.createdAt!.hour,
|
||||
device.createdAt!.minute,
|
||||
device.createdAt!.second,
|
||||
device.createdAt!.millisecond,
|
||||
device.createdAt!.microsecond,
|
||||
);
|
||||
}
|
||||
|
||||
LinearGradient getGradientColor(int monthLeft){
|
||||
if(monthLeft <= 3){
|
||||
return const LinearGradient(
|
||||
colors: [Color(0xFFff4b1f), Color(0xFFff9068)],
|
||||
);
|
||||
}else{
|
||||
return const LinearGradient(
|
||||
colors: [Color(0xFF56ab2f), Color(0xFFa8e063)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
55
lib/feature/settings/sim_data/sim_data_screen.dart
Normal file
55
lib/feature/settings/sim_data/sim_data_screen.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sfm_app/feature/settings/sim_data/shared_sim_component.dart';
|
||||
|
||||
import '../../../product/services/language_services.dart';
|
||||
import '../../../product/shared/shared_loading_animation.dart';
|
||||
import '../../../bloc/sim_data_bloc.dart';
|
||||
import '../../../product/base/bloc/base_bloc.dart';
|
||||
|
||||
class SimDataScreen extends StatefulWidget {
|
||||
const SimDataScreen({super.key});
|
||||
@override
|
||||
State<SimDataScreen> createState() => _SimDataScreenState();
|
||||
}
|
||||
|
||||
class _SimDataScreenState extends State<SimDataScreen> {
|
||||
late SimDataBloc simDataBloc;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
simDataBloc = BlocProvider.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(appLocalization(context).profile_sim_data),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: StreamBuilder(
|
||||
stream: simDataBloc.streamDevices,
|
||||
builder: (context, devicesSnapshot) {
|
||||
if (devicesSnapshot.data == null) {
|
||||
simDataBloc.getOwnerDevices(context);
|
||||
return const SharedLoadingAnimation();
|
||||
} else if (devicesSnapshot.data!.isEmpty) {
|
||||
return Center(
|
||||
child: Text(appLocalization(context).main_no_data),
|
||||
);
|
||||
} else {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
children: devicesSnapshot.data!.map(
|
||||
(device) {
|
||||
return SharedSimComponent(device: device,);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -7,6 +9,7 @@ import 'firebase_options.dart';
|
||||
|
||||
import 'product/lang/l10n/app_localizations.dart';
|
||||
import 'product/services/api_services.dart';
|
||||
import 'product/services/notification_services.dart';
|
||||
import 'product/services/theme_services.dart';
|
||||
import 'product/services/language_services.dart';
|
||||
import 'bloc/main_bloc.dart';
|
||||
@@ -146,7 +149,7 @@ class _MyAppState extends State<MyApp> {
|
||||
// // notificationServices.firebaseInit(context);
|
||||
// // notificationServices.setupInteractMessage();
|
||||
// notificationServices.getDeviceToken().then((token){
|
||||
// print("Firebase Token: $token");
|
||||
// log("Firebase Token: $token");
|
||||
// sendNotificationToken(token);
|
||||
// });
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ class ApplicationConstants {
|
||||
static const DEVICE_LOGS_PATH = "/device-logs";
|
||||
static const GROUP_PATH = "/groups";
|
||||
static const DEVICE_NOTIFICATIONS_SETTINGS = "/device-notifications-settings";
|
||||
static const SIM_DATA_SETTINGS = "/sim-data-settings";
|
||||
static const OWNER_GROUP = "owner";
|
||||
static const PARTICIPANT_GROUP = "participant";
|
||||
static const NO_DATA = "no_data";
|
||||
|
||||
@@ -13,4 +13,5 @@ enum AppRoutes {
|
||||
HISTORY,
|
||||
GROUPS,
|
||||
GROUP_DETAIL,
|
||||
SIM_DATA_SETTING,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../bloc/sim_data_bloc.dart';
|
||||
import '../../../feature/settings/sim_data/sim_data_screen.dart';
|
||||
import '../../../bloc/device_detail_bloc.dart';
|
||||
import '../../../feature/devices/device_detail/device_detail_screen.dart';
|
||||
import '../../../bloc/device_notification_settings_bloc.dart';
|
||||
@@ -151,6 +154,16 @@ GoRouter goRouter() {
|
||||
),
|
||||
transitionsBuilder: transitionsRightToLeft),
|
||||
),
|
||||
GoRoute(
|
||||
path: ApplicationConstants.SIM_DATA_SETTINGS,
|
||||
name: AppRoutes.SIM_DATA_SETTING.name,
|
||||
pageBuilder: (context, state) => CustomTransitionPage(
|
||||
child: BlocProvider(
|
||||
child: const SimDataScreen(),
|
||||
blocBuilder: () => SimDataBloc(),
|
||||
),
|
||||
transitionsBuilder: transitionsRightToLeft),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,10 @@
|
||||
"profile_page_title": "Settings Page",
|
||||
"profile_change_info": "Change information",
|
||||
"profile_change_pass": "Change password",
|
||||
"profile_sim_data": "Device SIM information",
|
||||
"profile_setting": "Notification Setting",
|
||||
"sim_data_month_left_message": "months left",
|
||||
"time_title": "Time",
|
||||
"change_profile_title": "Personal information",
|
||||
"change_profile_username": "Username: ",
|
||||
"change_profile_username_hint": "Enter username ",
|
||||
|
||||
@@ -770,12 +770,30 @@ abstract class AppLocalizations {
|
||||
/// **'Change password'**
|
||||
String get profile_change_pass;
|
||||
|
||||
/// No description provided for @profile_sim_data.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Device SIM information'**
|
||||
String get profile_sim_data;
|
||||
|
||||
/// No description provided for @profile_setting.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Notification Setting'**
|
||||
String get profile_setting;
|
||||
|
||||
/// No description provided for @sim_data_month_left_message.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'months left'**
|
||||
String get sim_data_month_left_message;
|
||||
|
||||
/// No description provided for @time_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Time'**
|
||||
String get time_title;
|
||||
|
||||
/// No description provided for @change_profile_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -360,9 +360,18 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get profile_change_pass => 'Change password';
|
||||
|
||||
@override
|
||||
String get profile_sim_data => 'Device SIM information';
|
||||
|
||||
@override
|
||||
String get profile_setting => 'Notification Setting';
|
||||
|
||||
@override
|
||||
String get sim_data_month_left_message => 'months left';
|
||||
|
||||
@override
|
||||
String get time_title => 'Time';
|
||||
|
||||
@override
|
||||
String get change_profile_title => 'Personal information';
|
||||
|
||||
|
||||
@@ -356,9 +356,18 @@ class AppLocalizationsVi extends AppLocalizations {
|
||||
@override
|
||||
String get profile_change_pass => 'Đổi mật khẩu';
|
||||
|
||||
@override
|
||||
String get profile_sim_data => 'Thông tin sim thiết bị';
|
||||
|
||||
@override
|
||||
String get profile_setting => 'Cài đặt thông báo';
|
||||
|
||||
@override
|
||||
String get sim_data_month_left_message => 'tháng còn lại';
|
||||
|
||||
@override
|
||||
String get time_title => 'Thời gian';
|
||||
|
||||
@override
|
||||
String get change_profile_title => 'Thông tin người dùng';
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@
|
||||
"profile_change_info": "Đổi thông tin cá nhân",
|
||||
"profile_change_pass": "Đổi mật khẩu",
|
||||
"profile_setting": "Cài đặt thông báo",
|
||||
"profile_sim_data": "Thông tin sim thiết bị",
|
||||
"sim_data_month_left_message": "tháng còn lại",
|
||||
"time_title": "Thời gian",
|
||||
"change_profile_title": "Thông tin người dùng",
|
||||
"change_profile_username": "Tên người dùng: ",
|
||||
"change_profile_username_hint": "Nhập tên ",
|
||||
|
||||
@@ -36,7 +36,7 @@ class NotificationServices {
|
||||
|
||||
Future<String> getDeviceToken() async {
|
||||
print("GET FB TOKEN");
|
||||
String? token = await messaging.getAPNSToken();
|
||||
String? token = await messaging.getToken();
|
||||
print("GET FB: ${token}");
|
||||
return token!;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user