455 lines
18 KiB
Dart
455 lines
18 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:double_back_to_close_app/double_back_to_close_app.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/material.dart' as td;
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
import 'package:get/get.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:IQ/app/global/converted_bytes.dart';
|
|
import 'package:IQ/app/global/global_snackbar.dart';
|
|
import 'package:IQ/app/global/static_informs.dart';
|
|
import 'package:IQ/app/global/text_widget.dart';
|
|
import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart';
|
|
import 'package:IQ/app/modules/home/models/traffic_model.dart';
|
|
import 'package:IQ/app/modules/home/providers/traffic.dart';
|
|
import 'package:IQ/app/modules/home/providers/user.dart';
|
|
import 'package:IQ/app/modules/service/api_service.dart';
|
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
|
|
|
import '../controllers/data_usage_controller.dart';
|
|
import 'dart:convert';
|
|
|
|
import 'package:IQ/app/global/snono_encrypt.dart';
|
|
|
|
class DataUsageView extends StatefulWidget {
|
|
const DataUsageView({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<DataUsageView> createState() => _DataUsageViewState();
|
|
}
|
|
|
|
DateTime monthOfData = DateTime.now();
|
|
|
|
class _DataUsageViewState extends State<DataUsageView>
|
|
with WidgetsBindingObserver {
|
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
|
bool fetchDataUsageData = false;
|
|
|
|
Future<Traffic?>? getTraffic;
|
|
bool? changeMonthLoading;
|
|
Traffic? traffic;
|
|
List<int>? list = [];
|
|
Future<Traffic?>? getTrafficInforms() async {
|
|
await getTodayTraffic();
|
|
setState(() {});
|
|
|
|
String payload = AES.encrypt(
|
|
data: jsonEncode({
|
|
"report_type": "daily",
|
|
"month": monthOfData.month,
|
|
"year": monthOfData.year,
|
|
"user_id": null,
|
|
}),
|
|
passpharse: 'abcdefghijuklmno0123456789012345',
|
|
);
|
|
var value = await APIService.post('traffic', payload);
|
|
traffic = Traffic.fromJson(jsonDecode(value));
|
|
chartData = traffic?.data?.totalReal?.map(
|
|
(e) {
|
|
DateTime lastDayOfMonth = DateTime(
|
|
monthOfData.year,
|
|
monthOfData.month + 1,
|
|
0,
|
|
);
|
|
int? day;
|
|
// ignore: unnecessary_null_comparison
|
|
if (day == null) {
|
|
day = (traffic?.data?.totalReal?.indexOf(e))! + 1;
|
|
} else {
|
|
if ((traffic?.data?.totalReal?.indexOf(e))! > 0 &&
|
|
(traffic?.data?.totalReal?.indexOf(e))! < lastDayOfMonth.day) {
|
|
day = (traffic?.data?.totalReal?.indexOf(e))! + 7;
|
|
}
|
|
}
|
|
return DataUsage(
|
|
DateTime(
|
|
monthOfData.year,
|
|
monthOfData.month,
|
|
day,
|
|
),
|
|
e.toDouble(),
|
|
);
|
|
},
|
|
).toList();
|
|
changeMonthLoading = false;
|
|
fetchDataUsageData = true;
|
|
setState(() {});
|
|
return traffic;
|
|
}
|
|
|
|
List<DataUsage>? chartData;
|
|
TooltipBehavior? tooltipBehavior;
|
|
String directionsImage =
|
|
defaultLocale == "en" ? 'assets/next.svg' : "assets/left-arrow.svg";
|
|
String directionsImage2 =
|
|
defaultLocale == "en" ? 'assets/left-arrow.svg' : "assets/next.svg";
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
super.didChangeAppLifecycleState(state);
|
|
if (state == AppLifecycleState.inactive ||
|
|
state == AppLifecycleState.detached ||
|
|
state == AppLifecycleState.paused) return;
|
|
if (state == AppLifecycleState.resumed) {
|
|
defaultLocale = Platform.localeName.split('_')[0];
|
|
directionsImage =
|
|
defaultLocale == "en" ? 'assets/next.svg' : "assets/left-arrow.svg";
|
|
directionsImage2 =
|
|
defaultLocale == "en" ? 'assets/left-arrow.svg' : "assets/next.svg";
|
|
snackBarText = 'back_twice'.tr;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
getTraffic = getTrafficInforms();
|
|
tooltipBehavior = TooltipBehavior(enable: true);
|
|
WidgetsBinding.instance.addObserver(this);
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
var stackedContainer = Container(
|
|
height: 250,
|
|
decoration: BoxDecoration(
|
|
color: brandColor,
|
|
image: const DecorationImage(
|
|
image: AssetImage('assets/background.png'),
|
|
fit: BoxFit.fill,
|
|
),
|
|
),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
SizedBox(height: MediaQuery.of(context).viewPadding.top),
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(
|
|
horizontal: 15,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
margin: const EdgeInsets.only(
|
|
top: 5,
|
|
right: 15,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
"assets/2/icon.svg",
|
|
height: 20,
|
|
width: 71.16,
|
|
),
|
|
const SizedBox(width: 10),
|
|
Image.asset("assets/logo.png"),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
user?.data?.firstname ?? ' . . . ',
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.normal,
|
|
),
|
|
),
|
|
IconButton(
|
|
onPressed: () {
|
|
scaffoldKey.currentState?.openEndDrawer();
|
|
},
|
|
icon: const Icon(
|
|
Icons.menu,
|
|
color: Colors.white,
|
|
size: 40,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
TextWidget(
|
|
text: 'data_usage_screen_title'.tr,
|
|
color: Colors.white,
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w300,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
SvgPicture.asset(
|
|
'assets/trafic.svg',
|
|
color: Colors.white,
|
|
fit: BoxFit.contain,
|
|
height: 60,
|
|
width: 60,
|
|
),
|
|
Directionality(
|
|
textDirection: defaultLocale == "en"
|
|
? td.TextDirection.ltr
|
|
: td.TextDirection.rtl,
|
|
child: TextWidget(
|
|
text: totalGBs,
|
|
// text: '$totalGBs',
|
|
color: Colors.white,
|
|
fontSize: 32,
|
|
fontWeight: FontWeight.bold,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
return Directionality(
|
|
textDirection:
|
|
defaultLocale != "en" ? td.TextDirection.ltr : td.TextDirection.rtl,
|
|
child: Scaffold(
|
|
backgroundColor: backgroundColor,
|
|
drawerScrimColor: Colors.black.withOpacity(0.7),
|
|
key: scaffoldKey,
|
|
endDrawer: const DrawerSideView(),
|
|
drawerEdgeDragWidth: widthSize(context),
|
|
body: DoubleBackToCloseApp(
|
|
snackBar: snackBar,
|
|
child: fetchDataUsageData
|
|
? Stack(
|
|
children: [
|
|
Column(
|
|
children: [
|
|
const SizedBox(height: 270),
|
|
Container(
|
|
margin: defaultLocale == "en"
|
|
? const EdgeInsets.only(
|
|
left: 15,
|
|
bottom: 10,
|
|
)
|
|
: const EdgeInsets.only(
|
|
right: 15,
|
|
bottom: 10,
|
|
),
|
|
child: Align(
|
|
alignment: defaultLocale == "en"
|
|
? Alignment.centerLeft
|
|
: Alignment.centerRight,
|
|
child: TextWidget(
|
|
text: 'data_usage_title'.tr,
|
|
fontSize: 22,
|
|
color: brandColor,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
height: 400,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: const BorderRadius.all(
|
|
Radius.circular(20),
|
|
),
|
|
border: Border.all(
|
|
color: borderColor,
|
|
width: 1,
|
|
),
|
|
),
|
|
padding: const EdgeInsets.all(20),
|
|
margin: const EdgeInsets.only(right: 10, left: 10),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
|
margin: const EdgeInsets.symmetric(vertical: 20),
|
|
child: GetBuilder(
|
|
builder: (DataUsageController c) {
|
|
return changeMonthLoading == null ||
|
|
changeMonthLoading != true
|
|
? SfCartesianChart(
|
|
tooltipBehavior: tooltipBehavior,
|
|
backgroundColor: Colors.white,
|
|
borderColor: borderColor,
|
|
borderWidth: 0,
|
|
isTransposed: false,
|
|
margin: const EdgeInsets.symmetric(
|
|
horizontal: 15),
|
|
plotAreaBackgroundColor: Colors.white,
|
|
plotAreaBorderColor: borderColor,
|
|
plotAreaBorderWidth: 0,
|
|
selectionGesture:
|
|
ActivationMode.singleTap,
|
|
selectionType: SelectionType.point,
|
|
enableAxisAnimation: true,
|
|
primaryXAxis: DateTimeAxis(
|
|
edgeLabelPlacement:
|
|
EdgeLabelPlacement.shift,
|
|
borderWidth: 1,
|
|
borderColor: Colors.white,
|
|
labelAlignment: LabelAlignment.center,
|
|
majorGridLines: const MajorGridLines(
|
|
width: 0,
|
|
color: Colors.transparent,
|
|
),
|
|
),
|
|
primaryYAxis: NumericAxis(
|
|
axisLabelFormatter:
|
|
(AxisLabelRenderDetails details) {
|
|
return ChartAxisLabel(
|
|
formatBytes(
|
|
details.value.toInt(), 0),
|
|
details.textStyle,
|
|
);
|
|
},
|
|
borderWidth: 1,
|
|
borderColor: Colors.white,
|
|
labelAlignment: LabelAlignment.center,
|
|
majorGridLines: MajorGridLines(
|
|
width: 1, color: borderColor),
|
|
),
|
|
series: <ChartSeries>[
|
|
LineSeries<DataUsage, DateTime>(
|
|
name: 'Total',
|
|
dataSource: chartData ?? [],
|
|
xValueMapper:
|
|
(DataUsage xAxis, _) =>
|
|
xAxis.monthDay,
|
|
yValueMapper:
|
|
(DataUsage yAxis, _) =>
|
|
yAxis.bytes,
|
|
color: brandColor,
|
|
enableTooltip: true,
|
|
),
|
|
],
|
|
)
|
|
: Center(
|
|
child: CircularProgressIndicator(
|
|
color: brandColor,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.only(top: 25),
|
|
child: Center(
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
TextButton(
|
|
style: ButtonStyle(
|
|
shape: MaterialStateProperty.all(
|
|
const CircleBorder(),
|
|
),
|
|
),
|
|
onPressed: () {
|
|
if (monthOfData.month > 1) {
|
|
changeMonthLoading = true;
|
|
chartData = [];
|
|
monthOfData = DateTime(
|
|
monthOfData.year,
|
|
monthOfData.month - 1,
|
|
);
|
|
getTraffic = getTrafficInforms();
|
|
setState(() {});
|
|
}
|
|
},
|
|
child: SvgPicture.asset(
|
|
directionsImage,
|
|
height: 35,
|
|
width: 35,
|
|
),
|
|
),
|
|
const SizedBox(width: 50),
|
|
GetBuilder(
|
|
builder: (DataUsageController c) {
|
|
return TextWidget(
|
|
text: DateFormat('MMMM').format(
|
|
DateTime(
|
|
monthOfData.year,
|
|
monthOfData.month,
|
|
),
|
|
),
|
|
fontSize: 22,
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w500,
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(width: 50),
|
|
TextButton(
|
|
style: ButtonStyle(
|
|
shape: MaterialStateProperty.all(
|
|
const CircleBorder(),
|
|
),
|
|
),
|
|
onPressed: () {
|
|
if (monthOfData.month < 12) {
|
|
changeMonthLoading = true;
|
|
chartData = [];
|
|
monthOfData = DateTime(
|
|
monthOfData.year,
|
|
monthOfData.month + 1,
|
|
);
|
|
getTraffic = getTrafficInforms();
|
|
setState(() {});
|
|
}
|
|
},
|
|
child: SvgPicture.asset(
|
|
directionsImage2,
|
|
height: 35,
|
|
width: 35,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
stackedContainer,
|
|
],
|
|
)
|
|
: Stack(
|
|
children: [
|
|
Center(
|
|
child: CircularProgressIndicator(
|
|
color: brandColor,
|
|
),
|
|
),
|
|
stackedContainer,
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DataUsage {
|
|
DataUsage(this.monthDay, this.bytes);
|
|
final DateTime monthDay;
|
|
final double bytes;
|
|
}
|